Skip to content

Commit eece582

Browse files
authored
Fixed compiler output capture in JSON mode (arduino#2078)
* Added integration test for arduino#1698 * Added helper functions to handle concurrent writes to ctx.Stdout/Stderr * Do not alter ctx.Stderr/Stdout in ExecCommand Some instances of ctx.Stdout may now contains nil since it's no more altered during ExecCommand. * Handle multi-threaded compile streams
1 parent 6992de7 commit eece582

File tree

9 files changed

+65
-15
lines changed

9 files changed

+65
-15
lines changed

Diff for: internal/integrationtest/compile_3/compile_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/arduino/go-paths-helper"
2323
"github.com/arduino/go-properties-orderedmap"
2424
"github.com/stretchr/testify/require"
25+
"go.bug.st/testifyjson/requirejson"
2526
)
2627

2728
func TestRuntimeToolPropertiesGeneration(t *testing.T) {
@@ -96,3 +97,22 @@ func TestCompileBuildPathInsideSketch(t *testing.T) {
9697
_, _, err = cli.Run("compile", "-b", "arduino:avr:mega", "--build-path", "build-mega")
9798
require.NoError(t, err)
9899
}
100+
101+
func TestCompilerErrOutput(t *testing.T) {
102+
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
103+
defer env.CleanUp()
104+
105+
// Run update-index with our test index
106+
_, _, err := cli.Run("core", "install", "arduino:[email protected]")
107+
require.NoError(t, err)
108+
109+
// prepare sketch
110+
sketch, err := paths.New("testdata", "blink_with_wrong_cpp").Abs()
111+
require.NoError(t, err)
112+
113+
// Run compile and catch err stream
114+
out, _, err := cli.Run("compile", "-b", "arduino:avr:uno", "--format", "json", sketch.String())
115+
require.Error(t, err)
116+
compilerErr := requirejson.Parse(t, out).Query(".compiler_err")
117+
compilerErr.MustContain(`"error"`)
118+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void setup() {}
2+
void loop() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void wrong() {

Diff for: legacy/builder/builder.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func (s *Preprocess) Run(ctx *types.Context) error {
152152
}
153153

154154
// Output arduino-preprocessed source
155-
ctx.Stdout.Write([]byte(ctx.Source))
155+
ctx.WriteStdout([]byte(ctx.Source))
156156
return nil
157157
}
158158

Diff for: legacy/builder/builder_utils/utils.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,15 @@ func compileFileWithRecipe(ctx *types.Context, sourcePath *paths.Path, source *p
190190
ctx.CompilationDatabase.Add(source, command)
191191
}
192192
if !objIsUpToDate && !ctx.OnlyUpdateCompilationDatabase {
193-
_, _, err = utils.ExecCommand(ctx, command, utils.ShowIfVerbose /* stdout */, utils.Show /* stderr */)
193+
// Since this compile could be multithreaded, we first capture the command output
194+
stdout, stderr, err := utils.ExecCommand(ctx, command, utils.Capture, utils.Capture)
195+
// and transfer all at once at the end...
196+
if ctx.Verbose {
197+
ctx.WriteStdout(stdout)
198+
}
199+
ctx.WriteStderr(stderr)
200+
201+
// ...and then return the error
194202
if err != nil {
195203
return nil, errors.WithStack(err)
196204
}

Diff for: legacy/builder/container_find_includes.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile t
408408
return errors.New(tr("Internal error in cache"))
409409
}
410410
}
411-
ctx.Stderr.Write(preproc_stderr)
411+
ctx.WriteStderr(preproc_stderr)
412412
return errors.WithStack(preproc_err)
413413
}
414414

Diff for: legacy/builder/preprocess_sketch.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,6 @@ func (s *OutputCodeCompletions) Run(ctx *types.Context) error {
146146
// we assume it is a json, let's make it compliant at least
147147
ctx.CodeCompletions = "[]"
148148
}
149-
fmt.Fprintln(ctx.Stdout, ctx.CodeCompletions)
149+
ctx.WriteStdout([]byte(ctx.CodeCompletions))
150150
return nil
151151
}

Diff for: legacy/builder/types/context.go

+18
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,21 @@ func (ctx *Context) Warn(msg string) {
249249
}
250250
ctx.stdLock.Unlock()
251251
}
252+
253+
func (ctx *Context) WriteStdout(data []byte) (int, error) {
254+
ctx.stdLock.Lock()
255+
defer ctx.stdLock.Unlock()
256+
if ctx.Stdout == nil {
257+
return os.Stdout.Write(data)
258+
}
259+
return ctx.Stdout.Write(data)
260+
}
261+
262+
func (ctx *Context) WriteStderr(data []byte) (int, error) {
263+
ctx.stdLock.Lock()
264+
defer ctx.stdLock.Unlock()
265+
if ctx.Stderr == nil {
266+
return os.Stderr.Write(data)
267+
}
268+
return ctx.Stderr.Write(data)
269+
}

Diff for: legacy/builder/utils/utils.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -184,29 +184,30 @@ const (
184184
)
185185

186186
func ExecCommand(ctx *types.Context, command *exec.Cmd, stdout int, stderr int) ([]byte, []byte, error) {
187-
if ctx.Stdout == nil {
188-
ctx.Stdout = os.Stdout
189-
}
190-
if ctx.Stderr == nil {
191-
ctx.Stderr = os.Stderr
192-
}
193-
194187
if ctx.Verbose {
195188
ctx.Info(PrintableCommand(command.Args))
196189
}
197190

198191
if stdout == Capture {
199192
buffer := &bytes.Buffer{}
200193
command.Stdout = buffer
201-
} else if stdout == Show || stdout == ShowIfVerbose && ctx.Verbose {
202-
command.Stdout = ctx.Stdout
194+
} else if stdout == Show || (stdout == ShowIfVerbose && ctx.Verbose) {
195+
if ctx.Stdout != nil {
196+
command.Stdout = ctx.Stdout
197+
} else {
198+
command.Stdout = os.Stdout
199+
}
203200
}
204201

205202
if stderr == Capture {
206203
buffer := &bytes.Buffer{}
207204
command.Stderr = buffer
208-
} else if stderr == Show || stderr == ShowIfVerbose && ctx.Verbose {
209-
command.Stderr = ctx.Stderr
205+
} else if stderr == Show || (stderr == ShowIfVerbose && ctx.Verbose) {
206+
if ctx.Stderr != nil {
207+
command.Stderr = ctx.Stderr
208+
} else {
209+
command.Stderr = os.Stderr
210+
}
210211
}
211212

212213
err := command.Start()

0 commit comments

Comments
 (0)