Skip to content

Commit 2270c19

Browse files
authored
Merge pull request #15 from arduino/scerza/fix-quit-message
Fix `quit` message not being printed
2 parents 410dd27 + 91f7240 commit 2270c19

File tree

12 files changed

+922
-15
lines changed

12 files changed

+922
-15
lines changed

.github/workflows/test-go-task.yml

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/test-go-task.md
2+
name: Test Go
3+
4+
env:
5+
# See: https://github.com/actions/setup-go/tree/v2#readme
6+
GO_VERSION: "1.16"
7+
8+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
9+
on:
10+
create:
11+
push:
12+
paths:
13+
- ".github/workflows/test-go-task.ya?ml"
14+
- "codecov.ya?ml"
15+
- "**/go.mod"
16+
- "**/go.sum"
17+
- "Taskfile.ya?ml"
18+
- "**.go"
19+
- "**/testdata/**"
20+
pull_request:
21+
paths:
22+
- ".github/workflows/test-go-task.ya?ml"
23+
- "codecov.ya?ml"
24+
- "**/go.mod"
25+
- "**/go.sum"
26+
- "Taskfile.ya?ml"
27+
- "**.go"
28+
- "**/testdata/**"
29+
workflow_dispatch:
30+
repository_dispatch:
31+
32+
jobs:
33+
run-determination:
34+
runs-on: ubuntu-latest
35+
outputs:
36+
result: ${{ steps.determination.outputs.result }}
37+
steps:
38+
- name: Determine if the rest of the workflow should run
39+
id: determination
40+
run: |
41+
RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x"
42+
# The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead.
43+
if [[ \
44+
"${{ github.event_name }}" != "create" || \
45+
"${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX \
46+
]]; then
47+
# Run the other jobs.
48+
RESULT="true"
49+
else
50+
# There is no need to run the other jobs.
51+
RESULT="false"
52+
fi
53+
54+
echo "::set-output name=result::$RESULT"
55+
56+
test:
57+
name: test (${{ matrix.module.path }} - ${{ matrix.operating-system }})
58+
needs: run-determination
59+
if: needs.run-determination.outputs.result == 'true'
60+
61+
strategy:
62+
fail-fast: false
63+
64+
matrix:
65+
operating-system:
66+
- ubuntu-latest
67+
- windows-latest
68+
- macos-latest
69+
module:
70+
- path: ./
71+
codecov-flags: unit
72+
73+
runs-on: ${{ matrix.operating-system }}
74+
75+
steps:
76+
- name: Checkout repository
77+
uses: actions/checkout@v2
78+
79+
- name: Install Go
80+
uses: actions/setup-go@v2
81+
with:
82+
go-version: ${{ env.GO_VERSION }}
83+
84+
- name: Install Task
85+
uses: arduino/setup-task@v1
86+
with:
87+
repo-token: ${{ secrets.GITHUB_TOKEN }}
88+
version: 3.x
89+
90+
- name: Run tests
91+
env:
92+
GO_MODULE_PATH: ${{ matrix.module.path }}
93+
run: task go:test
94+
95+
- name: Send unit tests coverage to Codecov
96+
if: runner.os == 'Linux'
97+
uses: codecov/codecov-action@v2
98+
with:
99+
file: ${{ matrix.module.path }}coverage_unit.txt
100+
flags: ${{ matrix.module.codecov-flags }}
101+
fail_ci_if_error: ${{ github.repository == 'arduino/pluggable-discovery-protocol-handler' }}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
dist/
22

3+
coverage_*.txt

.licenses/pluggable-discovery-protocol-handler/go/github.com/arduino/go-paths-helper.dep.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
22
name: github.com/arduino/go-paths-helper
3-
version: v1.0.1
3+
version: v1.6.1
44
type: go
5-
summary:
5+
summary:
66
homepage: https://pkg.go.dev/github.com/arduino/go-paths-helper
77
license: gpl-2.0-or-later
88
licenses:

.licenses/pluggable-discovery-protocol-handler/go/github.com/arduino/go-properties-orderedmap.dep.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: github.com/arduino/go-properties-orderedmap
3-
version: v1.4.0
3+
version: v1.6.0
44
type: go
55
summary: Package properties is a library for handling maps of hierarchical properties.
66
homepage: https://pkg.go.dev/github.com/arduino/go-properties-orderedmap
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
name: github.com/pkg/errors
3+
version: v0.9.1
4+
type: go
5+
summary: Package errors provides simple error handling primitives.
6+
homepage: https://pkg.go.dev/github.com/pkg/errors
7+
license: bsd-2-clause
8+
licenses:
9+
- sources: LICENSE
10+
text: |
11+
Copyright (c) 2015, Dave Cheney <[email protected]>
12+
All rights reserved.
13+
14+
Redistribution and use in source and binary forms, with or without
15+
modification, are permitted provided that the following conditions are met:
16+
17+
* Redistributions of source code must retain the above copyright notice, this
18+
list of conditions and the following disclaimer.
19+
20+
* Redistributions in binary form must reproduce the above copyright notice,
21+
this list of conditions and the following disclaimer in the documentation
22+
and/or other materials provided with the distribution.
23+
24+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
28+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34+
- sources: README.md
35+
text: BSD-2-Clause
36+
notices: []

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
<!-- NOTE: update the pkg.go.dev badge URL on each major release -->
44

55
[![Go Reference](https://pkg.go.dev/badge/github.com/arduino/pluggable-discovery-protocol-handler.svg)](https://pkg.go.dev/github.com/arduino/pluggable-discovery-protocol-handler/v2)
6+
[![Test Go status](https://github.com/arduino/pluggable-discovery-protocol-handler/actions/workflows/test-go-task.yml/badge.svg)](https://github.com/arduino/pluggable-discovery-protocol-handler/actions/workflows/test-go-task.yml)
7+
[![Codecov](https://codecov.io/gh/arduino/pluggable-discovery-protocol-handler/branch/main/graph/badge.svg)](https://codecov.io/gh/arduino/pluggable-discovery-protocol-handler)
68

79
This project is a library to ease implementation of pluggable discoveries for the [Arduino CLI](https://github.com/arduino/arduino-cli)
810
following the [official specification](https://arduino.github.io/arduino-cli/latest/platform-specification/#pluggable-discovery).

Taskfile.yml

+21-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ vars:
99
DUMMY_DISCOVERY_LDFLAGS: >
1010
-X github.com/arduino/pluggable-discovery-protocol-handler/dummy-discovery/args.Tag={{.DUMMY_DISCOVERY_VERSION}}
1111
-X github.com/arduino/pluggable-discovery-protocol-handler/dummy-discovery/args.Timestamp={{.DUMMY_DISCOVERY_TIMESTAMP}}
12+
# Path of the project's primary Go module:
13+
DEFAULT_GO_MODULE_PATH: ./
1214
DEFAULT_GO_PACKAGES:
13-
sh: echo $(go list ./... | tr '\n' ' ')
15+
sh: |
16+
echo $(cd {{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}} && go list ./... | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"')
17+
# `-ldflags` flag to use for `go test` command
18+
TEST_LDFLAGS:
1419

1520
tasks:
1621
build-dummy-discovery:
@@ -20,6 +25,21 @@ tasks:
2025
cmds:
2126
- go build -o dist/{{.EXECUTABLE}} -v -ldflags '{{.DUMMY_DISCOVERY_LDFLAGS}}' ./dummy-discovery
2227

28+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-go-task/Taskfile.yml
29+
go:test:
30+
desc: Run unit tests
31+
dir: "{{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}}"
32+
cmds:
33+
- |
34+
go test \
35+
-v \
36+
-short \
37+
-run '{{default ".*" .GO_TEST_REGEX}}' \
38+
{{default "-timeout 10m -coverpkg=./... -covermode=atomic" .GO_TEST_FLAGS}} \
39+
-coverprofile=coverage_unit.txt \
40+
{{.TEST_LDFLAGS}} \
41+
{{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}}
42+
2343
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-workflows-task/Taskfile.yml
2444
ci:validate:
2545
desc: Validate GitHub Actions workflows against their JSON schema

discovery.go

+22-5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"regexp"
3535
"strconv"
3636
"strings"
37+
"sync"
3738

3839
"github.com/arduino/go-properties-orderedmap"
3940
)
@@ -86,6 +87,7 @@ type ErrorCallback func(err string)
8687
type Server struct {
8788
impl Discovery
8889
outputChan chan *message
90+
outputWaiter sync.WaitGroup
8991
userAgent string
9092
reqProtocolVersion int
9193
initialized bool
@@ -111,8 +113,7 @@ func NewServer(impl Discovery) *Server {
111113
// the input stream is closed. In case of IO error the error is
112114
// returned.
113115
func (d *Server) Run(in io.Reader, out io.Writer) error {
114-
go d.outputProcessor(out)
115-
defer close(d.outputChan)
116+
d.startOutputProcessor(out)
116117
reader := bufio.NewReader(in)
117118
for {
118119
fullCmd, err := reader.ReadString('\n')
@@ -141,8 +142,7 @@ func (d *Server) Run(in io.Reader, out io.Writer) error {
141142
case "STOP":
142143
d.stop()
143144
case "QUIT":
144-
d.impl.Quit()
145-
d.outputChan <- messageOk("quit")
145+
d.quit()
146146
return nil
147147
default:
148148
d.outputChan <- messageError("command_error", fmt.Sprintf("Command %s not supported", cmd))
@@ -276,12 +276,26 @@ func (d *Server) syncEvent(event string, port *Port) {
276276
}
277277
}
278278

279+
func (d *Server) quit() {
280+
d.impl.Quit()
281+
d.outputChan <- messageOk("quit")
282+
close(d.outputChan)
283+
// If we don't wait for all messages
284+
// to be consumed by the output processor
285+
// we risk not printing the "quit" message.
286+
// This may cause issues to consumers of
287+
// the discovery since they expect a message
288+
// that is never sent.
289+
d.outputWaiter.Wait()
290+
}
291+
279292
func (d *Server) errorEvent(msg string) {
280293
d.outputChan <- messageError("start_sync", msg)
281294
}
282295

283-
func (d *Server) outputProcessor(outWriter io.Writer) {
296+
func (d *Server) startOutputProcessor(outWriter io.Writer) {
284297
// Start go routine to serialize messages printing
298+
d.outputWaiter.Add(1)
285299
go func() {
286300
for msg := range d.outputChan {
287301
data, err := json.MarshalIndent(msg, "", " ")
@@ -292,5 +306,8 @@ func (d *Server) outputProcessor(outWriter io.Writer) {
292306
}
293307
fmt.Fprintln(outWriter, string(data))
294308
}
309+
// We finished consuming all messages, now
310+
// we can exit for real
311+
d.outputWaiter.Done()
295312
}()
296313
}

discovery_test.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//
2+
// This file is part of dummy-discovery.
3+
//
4+
// Copyright 2021 ARDUINO SA (http://www.arduino.cc/)
5+
//
6+
// This software is released under the GNU General Public License version 3,
7+
// which covers the main part of arduino-cli.
8+
// The terms of this license can be found at:
9+
// https://www.gnu.org/licenses/gpl-3.0.en.html
10+
//
11+
// You can be released from the requirements of the above licenses by purchasing
12+
// a commercial license. Buying such a license is mandatory if you want to modify or
13+
// otherwise use the software for commercial activities involving the Arduino
14+
// software without disclosing the source code of your own applications. To purchase
15+
// a commercial license, send an email to [email protected].
16+
//
17+
18+
package discovery
19+
20+
import (
21+
"testing"
22+
23+
"github.com/arduino/arduino-cli/executils"
24+
"github.com/stretchr/testify/require"
25+
)
26+
27+
func runDummyDiscovery(t *testing.T) *executils.Process {
28+
discoveryDir := "dummy-discovery"
29+
// Build dummy-discovery for testing
30+
builder, err := executils.NewProcess("go", "build")
31+
require.NoError(t, err)
32+
builder.SetDir(discoveryDir)
33+
require.NoError(t, builder.Run())
34+
discovery, err := executils.NewProcess("./dummy-discovery")
35+
require.NoError(t, err)
36+
discovery.SetDir(discoveryDir)
37+
return discovery
38+
}
39+
40+
func TestDiscoveryStdioHandling(t *testing.T) {
41+
discovery := runDummyDiscovery(t)
42+
43+
stdout, err := discovery.StdoutPipe()
44+
require.NoError(t, err)
45+
stdin, err := discovery.StdinPipe()
46+
require.NoError(t, err)
47+
48+
require.NoError(t, discovery.Start())
49+
defer discovery.Kill()
50+
51+
n, err := stdin.Write([]byte("quit\n"))
52+
require.Greater(t, n, 0)
53+
require.NoError(t, err)
54+
output := [1024]byte{}
55+
// require.NoError(t, discovery.Wait())
56+
n, err = stdout.Read(output[:])
57+
require.Greater(t, n, 0)
58+
require.NoError(t, err)
59+
60+
expectedOutput := "{\n \"eventType\": \"quit\",\n \"message\": \"OK\"\n}\n"
61+
require.Equal(t, expectedOutput, string(output[:n]))
62+
}

dummy-discovery/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dummy-discovery
2+
dummy-discovery.exe

go.mod

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@ module github.com/arduino/pluggable-discovery-protocol-handler/v2
22

33
go 1.16
44

5-
require github.com/arduino/go-properties-orderedmap v1.4.0
5+
require (
6+
github.com/arduino/arduino-cli v0.0.0-20211123110800-c756a0f1305d
7+
github.com/arduino/go-properties-orderedmap v1.6.0
8+
github.com/stretchr/testify v1.7.0
9+
)

0 commit comments

Comments
 (0)