From b90b70eed93dc7896085baccc26ffa7611528a14 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 14 Jan 2021 22:50:49 +0100 Subject: [PATCH] Cherry-pick #22541 to 7.x: Run unit and integration tests with gotestsum (#23512) --- .ci/scripts/install-tools.bat | 2 +- NOTICE.txt | 523 ++++++++++++++++++++-- dev-tools/mage/gotest.go | 232 +++------- dev-tools/mage/gotest_test.go | 382 ++++++++++++++++ go.mod | 13 +- go.sum | 27 +- heartbeat/monitors/stdfields/stdfields.go | 2 - libbeat/common/cli/confirm.go | 8 +- libbeat/common/cli/confirm_test.go | 34 +- libbeat/common/cli/input.go | 6 +- libbeat/common/cli/input_test.go | 24 +- tools/tools.go | 1 + 12 files changed, 994 insertions(+), 260 deletions(-) create mode 100644 dev-tools/mage/gotest_test.go diff --git a/.ci/scripts/install-tools.bat b/.ci/scripts/install-tools.bat index 99dcc0006a8..1d29b548318 100755 --- a/.ci/scripts/install-tools.bat +++ b/.ci/scripts/install-tools.bat @@ -79,4 +79,4 @@ gcc --version where gcc REM Reset the USERPROFILE -SET USERPROFILE=%PREVIOUS_USERPROFILE% \ No newline at end of file +SET USERPROFILE=%PREVIOUS_USERPROFILE% diff --git a/NOTICE.txt b/NOTICE.txt index 2e70243272e..bf0cf7d8709 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -8478,11 +8478,11 @@ limitations under the License. -------------------------------------------------------------------------------- Dependency : github.com/fatih/color -Version: v1.5.0 +Version: v1.9.0 Licence type (autodetected): MIT -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/fatih/color@v1.5.0/LICENSE.md: +Contents of probable licence file $GOMODCACHE/github.com/fatih/color@v1.9.0/LICENSE.md: The MIT License (MIT) @@ -9857,11 +9857,11 @@ Contents of probable licence file $GOMODCACHE/github.com/google/flatbuffers@v1.7 -------------------------------------------------------------------------------- Dependency : github.com/google/go-cmp -Version: v0.4.0 +Version: v0.5.2 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/google/go-cmp@v0.4.0/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/google/go-cmp@v0.5.2/LICENSE: Copyright (c) 2017 The Go Authors. All rights reserved. @@ -11716,36 +11716,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------------- -Dependency : github.com/jstemmer/go-junit-report -Version: v0.9.1 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/jstemmer/go-junit-report@v0.9.1/LICENSE: - -Copyright (c) 2012 Joel Stemmer - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------------- Dependency : github.com/blakerouse/service Version: v1.1.1-0.20200924160513-057808572ffa @@ -12007,11 +11977,11 @@ Contents of probable licence file $GOMODCACHE/github.com/magefile/mage@v1.10.0/L -------------------------------------------------------------------------------- Dependency : github.com/mattn/go-colorable -Version: v0.1.4 +Version: v0.1.6 Licence type (autodetected): MIT -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/mattn/go-colorable@v0.1.4/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/mattn/go-colorable@v0.1.6/LICENSE: The MIT License (MIT) @@ -16231,11 +16201,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : golang.org/x/sys -Version: v0.0.0-20200625212154-ddb9806d33ae +Version: v0.0.0-20201009025420-dfb3f7c4e634 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20200625212154-ddb9806d33ae/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20201009025420-dfb3f7c4e634/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -17393,6 +17363,218 @@ See the License for the specific language governing permissions and limitations under the License. +-------------------------------------------------------------------------------- +Dependency : gotest.tools/gotestsum +Version: v0.6.0 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/gotest.tools/gotestsum@v0.6.0/LICENSE: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + -------------------------------------------------------------------------------- Dependency : howett.net/plist Version: v0.0.0-20181124034731-591f970eefbb @@ -30514,6 +30696,218 @@ Contents of probable licence file $GOMODCACHE/github.com/google/renameio@v0.1.0/ limitations under the License. +-------------------------------------------------------------------------------- +Dependency : github.com/google/shlex +Version: v0.0.0-20191202100458-e7afc7fbc510 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/google/shlex@v0.0.0-20191202100458-e7afc7fbc510/COPYING: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + -------------------------------------------------------------------------------- Dependency : github.com/google/subcommands Version: v1.0.1 @@ -34171,6 +34565,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- +Dependency : github.com/jstemmer/go-junit-report +Version: v0.9.1 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/jstemmer/go-junit-report@v0.9.1/LICENSE: + +Copyright (c) 2012 Joel Stemmer + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------------- Dependency : github.com/jtolds/gls Version: v4.20.0+incompatible @@ -42536,6 +42960,29 @@ See the License for the specific language governing permissions and limitations under the License. +-------------------------------------------------------------------------------- +Dependency : gotest.tools/v3 +Version: v3.0.3 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/gotest.tools/v3@v3.0.3/LICENSE: + +Copyright 2018 gotest.tools authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + -------------------------------------------------------------------------------- Dependency : honnef.co/go/tools Version: v0.0.1-2019.2.3 diff --git a/dev-tools/mage/gotest.go b/dev-tools/mage/gotest.go index 948d15c754f..a2e6582ca7e 100644 --- a/dev-tools/mage/gotest.go +++ b/dev-tools/mage/gotest.go @@ -18,7 +18,6 @@ package mage import ( - "bytes" "context" "fmt" "io" @@ -28,16 +27,14 @@ import ( "os/exec" "path" "path/filepath" - "runtime" - "sort" "strings" "time" - "github.com/jstemmer/go-junit-report/formatter" - "github.com/jstemmer/go-junit-report/parser" "github.com/magefile/mage/mg" "github.com/magefile/mage/sh" "github.com/pkg/errors" + + "github.com/elastic/beats/v7/dev-tools/mage/gotool" ) // GoTestArgs are the arguments used for the "go*Test" targets and they define @@ -52,6 +49,7 @@ type GoTestArgs struct { OutputFile string // File to write verbose test output to. JUnitReportFile string // File to write a JUnit XML test report to. CoverageProfileFile string // Test coverage profile file (enables -cover). + Output io.Writer // Write stderr and stdout to Output if set } // TestBinaryArgs are the arguments used when building binary for testing. @@ -183,40 +181,80 @@ func GoTestIntegrationForModule(ctx context.Context) error { return nil } +// InstallGoTestTools installs additional tools that are required to run unit and integration tests. +func InstallGoTestTools() { + gotool.Install( + gotool.Install.Package("gotest.tools/gotestsum"), + ) +} + // GoTest invokes "go test" and reports the results to stdout. It returns an // error if there was any failure executing the tests or if there were any // test failures. func GoTest(ctx context.Context, params GoTestArgs) error { + mg.Deps(InstallGoTestTools) + fmt.Println(">> go test:", params.TestName, "Testing") - // Build args list to Go. - args := []string{"test"} - args = append(args, "-v") + // We use gotestsum to drive the tests and produce a junit report. + // The tool runs `go test -json` in order to produce a structured log which makes it easier + // to parse the actual test output. + // Of OutputFile is given the original JSON file will be written as well. + // + // The runner needs to set CLI flags for gotestsum and for "go test". We track the different + // CLI flags in the gotestsumArgs and testArgs variables, such that we can finally produce command like: + // $ gotestsum -- + // + // The additional arguments given via GoTestArgs are applied to `go test` only. Callers can not + // modify any of the gotestsum arguments. + + gotestsumArgs := []string{"--no-color"} + if mg.Verbose() { + gotestsumArgs = append(gotestsumArgs, "-f", "standard-verbose") + } else { + gotestsumArgs = append(gotestsumArgs, "-f", "standard-quiet") + } + if params.JUnitReportFile != "" { + CreateDir(params.JUnitReportFile) + gotestsumArgs = append(gotestsumArgs, "--junitfile", params.JUnitReportFile) + } + if params.OutputFile != "" { + CreateDir(params.OutputFile) + gotestsumArgs = append(gotestsumArgs, "--jsonfile", params.OutputFile+".json") + } + + var testArgs []string // -race is only supported on */amd64 if os.Getenv("DEV_ARCH") == "amd64" { if params.Race { - args = append(args, "-race") + testArgs = append(testArgs, "-race") } } if len(params.Tags) > 0 { - args = append(args, "-tags", strings.Join(params.Tags, " ")) + params := strings.Join(params.Tags, " ") + if params != "" { + testArgs = append(testArgs, "-tags", params) + } } if params.CoverageProfileFile != "" { params.CoverageProfileFile = createDir(filepath.Clean(params.CoverageProfileFile)) - args = append(args, + testArgs = append(testArgs, "-covermode=atomic", "-coverprofile="+params.CoverageProfileFile, ) } - args = append(args, params.ExtraFlags...) - args = append(args, params.Packages...) + testArgs = append(testArgs, params.ExtraFlags...) + testArgs = append(testArgs, params.Packages...) - goTest := makeCommand(ctx, params.Env, "go", args...) + args := append(gotestsumArgs, append([]string{"--"}, testArgs...)...) + goTest := makeCommand(ctx, params.Env, "gotestsum", args...) // Wire up the outputs. - bufferOutput := new(bytes.Buffer) - outputs := []io.Writer{bufferOutput} + var outputs []io.Writer + if params.Output != nil { + outputs = append(outputs, params.Output) + } if params.OutputFile != "" { fileOutput, err := os.Create(createDir(params.OutputFile)) @@ -227,18 +265,16 @@ func GoTest(ctx context.Context, params GoTestArgs) error { outputs = append(outputs, fileOutput) } output := io.MultiWriter(outputs...) - goTest.Stdout = output - goTest.Stderr = output - - if mg.Verbose() { + if params.Output == nil { goTest.Stdout = io.MultiWriter(output, os.Stdout) goTest.Stderr = io.MultiWriter(output, os.Stderr) + } else { + goTest.Stdout = output + goTest.Stderr = output } - // Execute 'go test' and measure duration. - start := time.Now() err := goTest.Run() - duration := time.Since(start) + var goTestErr *exec.ExitError if err != nil { // Command ran. @@ -251,30 +287,11 @@ func GoTest(ctx context.Context, params GoTestArgs) error { goTestErr = exitErr } - // Parse the verbose test output. - report, err := parser.Parse(bytes.NewBuffer(bufferOutput.Bytes()), BeatName) - if err != nil { - return errors.Wrap(err, "failed to parse go test output") - } - if goTestErr != nil && len(report.Packages) == 0 { + if goTestErr != nil { // No packages were tested. Probably the code didn't compile. - fmt.Println(bytes.NewBuffer(bufferOutput.Bytes()).String()) return errors.Wrap(goTestErr, "go test returned a non-zero value") } - // Generate a JUnit XML report. - if params.JUnitReportFile != "" { - junitReport, err := os.Create(createDir(params.JUnitReportFile)) - if err != nil { - return errors.Wrap(err, "failed to create junit report") - } - defer junitReport.Close() - - if err = formatter.JUnitReportXML(report, false, runtime.Version(), junitReport); err != nil { - return errors.Wrap(err, "failed to write junit report") - } - } - // Generate a HTML code coverage report. var htmlCoverReport string if params.CoverageProfileFile != "" { @@ -288,27 +305,9 @@ func GoTest(ctx context.Context, params GoTestArgs) error { } } - // Summarize the results and log to stdout. - summary, err := NewGoTestSummary(duration, report, map[string]string{ - "Output File": params.OutputFile, - "JUnit Report": params.JUnitReportFile, - "Coverage Report": htmlCoverReport, - }) - if err != nil { - return err - } - if !mg.Verbose() && summary.Fail > 0 { - fmt.Println(summary.Failures()) - } - fmt.Println(summary.String()) - // Return an error indicating that testing failed. - if summary.Fail > 0 || goTestErr != nil { + if goTestErr != nil { fmt.Println(">> go test:", params.TestName, "Test Failed") - if summary.Fail > 0 { - return errors.Errorf("go test failed: %d test failures", summary.Fail) - } - return errors.Wrap(goTestErr, "go test returned a non-zero value") } @@ -329,117 +328,10 @@ func makeCommand(ctx context.Context, env map[string]string, cmd string, args .. c.Stderr = os.Stderr c.Stdin = os.Stdin log.Println("exec:", cmd, strings.Join(args, " ")) + fmt.Println("exec:", cmd, strings.Join(args, " ")) return c } -// GoTestSummary is a summary of test results. -type GoTestSummary struct { - *parser.Report // Report generated by parsing test output. - Pass int // Number of passing tests. - Fail int // Number of failed tests. - Skip int // Number of skipped tests. - Packages int // Number of packages tested. - Duration time.Duration // Total go test running duration. - Files map[string]string -} - -// NewGoTestSummary builds a new GoTestSummary. It returns an error if it cannot -// resolve the absolute paths to the given files. -func NewGoTestSummary(d time.Duration, r *parser.Report, outputFiles map[string]string) (*GoTestSummary, error) { - files := map[string]string{} - for name, file := range outputFiles { - if file == "" { - continue - } - absFile, err := filepath.Abs(file) - if err != nil { - return nil, errors.Wrapf(err, "failed resolving absolute path for %v", file) - } - files[name+":"] = absFile - } - - summary := &GoTestSummary{ - Report: r, - Duration: d, - Packages: len(r.Packages), - Files: files, - } - - for _, pkg := range r.Packages { - for _, t := range pkg.Tests { - switch t.Result { - case parser.PASS: - summary.Pass++ - case parser.FAIL: - summary.Fail++ - case parser.SKIP: - summary.Skip++ - default: - return nil, errors.Errorf("Unknown test result value: %v", t.Result) - } - } - } - - return summary, nil -} - -// Failures returns a string containing the list of failed test cases and their -// output. -func (s *GoTestSummary) Failures() string { - b := new(strings.Builder) - - if s.Fail > 0 { - fmt.Fprintln(b, "FAILURES:") - for _, pkg := range s.Report.Packages { - for _, t := range pkg.Tests { - if t.Result != parser.FAIL { - continue - } - fmt.Fprintln(b, "Package:", pkg.Name) - fmt.Fprintln(b, "Test: ", t.Name) - for _, line := range t.Output { - if strings.TrimSpace(line) != "" { - fmt.Fprintln(b, line) - } - } - fmt.Fprintln(b, "----") - } - } - } - - return strings.TrimRight(b.String(), "\n") -} - -// String returns a summary of the testing results (number of fail/pass/skip, -// test duration, number packages, output files). -func (s *GoTestSummary) String() string { - b := new(strings.Builder) - - fmt.Fprintln(b, "SUMMARY:") - fmt.Fprintln(b, " Fail: ", s.Fail) - fmt.Fprintln(b, " Skip: ", s.Skip) - fmt.Fprintln(b, " Pass: ", s.Pass) - fmt.Fprintln(b, " Packages:", len(s.Report.Packages)) - fmt.Fprintln(b, " Duration:", s.Duration) - - // Sort the list of files and compute the column width. - var names []string - var nameWidth int - for name := range s.Files { - if len(name) > nameWidth { - nameWidth = len(name) - } - names = append(names, name) - } - sort.Strings(names) - - for _, name := range names { - fmt.Fprintf(b, " %-*s %s\n", nameWidth, name, s.Files[name]) - } - - return strings.TrimRight(b.String(), "\n") -} - // BuildSystemTestBinary runs BuildSystemTestGoBinary with default values. func BuildSystemTestBinary() error { return BuildSystemTestGoBinary(DefaultTestBinaryArgs()) diff --git a/dev-tools/mage/gotest_test.go b/dev-tools/mage/gotest_test.go new file mode 100644 index 00000000000..24ce55614cb --- /dev/null +++ b/dev-tools/mage/gotest_test.go @@ -0,0 +1,382 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package mage + +import ( + "context" + "os" + "regexp" + "strings" + "testing" + "time" + + "github.com/magefile/mage/mg" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const envGoTestHelper = "GOTEST_WANT_HELPER" + +var gotestHelperMode = os.Getenv(envGoTestHelper) == "1" + +// TestGoTest_CaptureOutput runs different `go test` scenarios via `GoTest` and +// captures the stderr and stdout output of the test run. The output is then +// validated using a regular expression. +// +// For each scenario a GoTest helper test is defined and a regular expression +// that the test output must match. The naming convention for scenario X is: +// - TestGoTest_Helper_: the test function to be executed +// - wantTest: regular expression the output must match. +// +// TestGoTest_CaptureOutput sets the `GOTEST_WANT_HELPER` environment variable when it executes the tests. +// each test helper must check if it is driven by this function or not: +// +// func TestGoTest_Helper_X(t *testing.T) { +// if !gotestHelperMode { +// return +// } +// +// // sample test +// } +// +func TestGoTest_CaptureOutput(t *testing.T) { + errNonZero := "go test returned a non-zero value" + makeArgs := func(test string) GoTestArgs { + return GoTestArgs{ + TestName: "asserts", + Packages: []string{"."}, + Env: map[string]string{envGoTestHelper: "1"}, + ExtraFlags: []string{"-test.run", test}, + } + } + + tests := map[string]struct { + args GoTestArgs + verbose bool + wantErr string + want string + }{ + "passing test without output": { + args: makeArgs("TestGoTest_Helper_OK"), + verbose: true, + want: wantTestOK, + }, + "capture output from assert failures": { + args: makeArgs("TestGoTest_Helper_AssertOutput"), + wantErr: errNonZero, + want: wantTestAssertOutput, + }, + "capture test log output": { + args: makeArgs("TestGoTest_Helper_LogOutput"), + wantErr: errNonZero, + want: wantTestLogOutput, + }, + "capture panic": { + args: makeArgs("TestGoTest_Helper_WithPanic"), + wantErr: errNonZero, + want: wantTestWithPanic, + }, + "capture wrong panic": { + args: makeArgs("TestGoTest_Helper_WithWrongPanic"), + wantErr: errNonZero, + want: wantTestWithWrongPanic, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + oldVerboseArg := os.Getenv(mg.VerboseEnv) + defer func() { + os.Setenv(mg.VerboseEnv, oldVerboseArg) + }() + + if test.verbose { + os.Setenv(mg.VerboseEnv, "true") + } else { + os.Setenv(mg.VerboseEnv, "false") + } + + var buf strings.Builder + args := test.args + args.Output = &buf + err := GoTest(context.TODO(), args) + + if test.wantErr == "" { + if err != nil { + t.Fatalf("GoTest did return an unexpected error: %v", err) + } + } else { + if err == nil { + t.Fatalf("GoTest was expected to return an error saying '%v'", test.wantErr) + } + + errString := err.Error() + if !strings.Contains(errString, test.wantErr) { + t.Fatalf("GoTest error does not match expected error message:\nwant: '%v'\ngot: '%v'", + test.wantErr, errString) + } + } + + re, err := regexp.Compile(test.want) + if err != nil { + t.Fatalf("Failed to compile test match regex: %v", err) + } + + output := buf.String() + if !re.MatchString(output) { + t.Fatalf("GoTest output missmatch:\nwant:\n%v\n\ngot:\n%v", test.want, output) + } + }) + } +} + +func TestGoTest_Helper_OK(t *testing.T) { + if !gotestHelperMode { + return + } + + // Succeeding test without any additional output or test logs. +} + +var wantTestOK = `--- PASS: TestGoTest_Helper_OK.*` + +func TestGoTest_Helper_AssertOutput(t *testing.T) { + if !gotestHelperMode { + return + } + + t.Run("assert fails", func(t *testing.T) { + assert.True(t, false) + }) + + t.Run("assert with message", func(t *testing.T) { + assert.True(t, false, "My message") + }) + + t.Run("assert with messagef", func(t *testing.T) { + assert.True(t, false, "My message with arguments: %v", 42) + }) + + t.Run("require fails", func(t *testing.T) { + require.True(t, false) + }) + + t.Run("require with message", func(t *testing.T) { + require.True(t, false, "My message") + }) + + t.Run("require with messagef", func(t *testing.T) { + require.True(t, false, "My message with arguments: %v", 42) + }) + + t.Run("equals map", func(t *testing.T) { + want := map[string]interface{}{ + "a": 1, + "b": true, + "c": "test", + "e": map[string]interface{}{ + "x": "y", + }, + } + + got := map[string]interface{}{ + "a": 42, + "b": false, + "c": "test", + } + + assert.Equal(t, want, got) + }) +} + +var wantTestAssertOutput = `(?sm: +=== Failed +=== FAIL: dev-tools/mage TestGoTest_Helper_AssertOutput/assert_fails.* + gotest_test.go:\d+:.* + Error Trace: gotest_test.go:\d+.* + Error: Should be true.* + Test: TestGoTest_Helper_AssertOutput/assert_fails.* + --- FAIL: TestGoTest_Helper_AssertOutput/assert_fails .* +=== FAIL: dev-tools/mage TestGoTest_Helper_AssertOutput/assert_with_message .* + gotest_test.go:\d+:.* + Error Trace: gotest_test.go:\d+.* + Error: Should be true.* + Test: TestGoTest_Helper_AssertOutput/assert_with_message.* + Messages: My message.* + --- FAIL: TestGoTest_Helper_AssertOutput/assert_with_message .* +=== FAIL: dev-tools/mage TestGoTest_Helper_AssertOutput/assert_with_messagef .* + gotest_test.go:\d+:.* + Error Trace: gotest_test.go:\d+.* + Error: Should be true.* + Test: TestGoTest_Helper_AssertOutput/assert_with_messagef.* + Messages: My message with arguments: 42.* + --- FAIL: TestGoTest_Helper_AssertOutput/assert_with_messagef .* +=== FAIL: dev-tools/mage TestGoTest_Helper_AssertOutput/require_fails .* + gotest_test.go:\d+:.* + Error Trace: gotest_test.go:\d+.* + Error: Should be true.* + Test: TestGoTest_Helper_AssertOutput/require_fails.* + --- FAIL: TestGoTest_Helper_AssertOutput/require_fails .* +=== FAIL: dev-tools/mage TestGoTest_Helper_AssertOutput/require_with_message .* + gotest_test.go:\d+:.* + Error Trace: gotest_test.go:\d+.* + Error: Should be true.* + Test: TestGoTest_Helper_AssertOutput/require_with_message.* + Messages: My message.* + --- FAIL: TestGoTest_Helper_AssertOutput/require_with_message .* +=== FAIL: dev-tools/mage TestGoTest_Helper_AssertOutput/require_with_messagef .* + gotest_test.go:\d+:.* + Error Trace: gotest_test.go:\d+.* + Error: Should be true.* + Test: TestGoTest_Helper_AssertOutput/require_with_messagef.* + Messages: My message with arguments: 42.* + --- FAIL: TestGoTest_Helper_AssertOutput/require_with_messagef .* +=== FAIL: dev-tools/mage TestGoTest_Helper_AssertOutput/equals_map .* + gotest_test.go:\d+:.* + Error Trace: gotest_test.go:\d+.* + Error: Not equal:.* +\s+expected: map\[string\]interface \{\}\{"a":1, "b":true, "c":"test", "e":map\[string\]interface \{\}\{"x":"y"\}\}.* +\s+actual : map\[string\]interface \{\}\{"a":42, "b":false, "c":"test"\}.* +\s+Diff:.* +\s+--- Expected.* +\s+\+\+\+ Actual.* +\s+-\(map\[string\]interface \{\}\) \(len=4\) \{.* +\s+- \(string\) \(len=1\) "a": \(int\) 1,.* +\s+- \(string\) \(len=1\) "b": \(bool\) true,.* +\s+- \(string\) \(len=1\) "c": \(string\) \(len=4\) "test",.* +\s+- \(string\) \(len=1\) "e": \(map\[string\]interface \{\}\) \(len=1\) \{.* +\s+- \(string\) \(len=1\) "x": \(string\) \(len=1\) "y".* +\s+- }.* +\s+\+\(map\[string\]interface \{\}\) \(len=3\) \{.* +\s+\+ \(string\) \(len=1\) "a": \(int\) 42,.* +\s+\+ \(string\) \(len=1\) "b": \(bool\) false,.* +\s+\+ \(string\) \(len=1\) "c": \(string\) \(len=4\) "test".* +\s+\}.* +)` + +func TestGoTest_Helper_LogOutput(t *testing.T) { + if !gotestHelperMode { + return + } + + t.Run("on error", func(t *testing.T) { + t.Log("Log message should be printed") + t.Logf("printf style log message: %v", 42) + t.Error("Log should fail") + t.Errorf("Log should fail with printf style log: %v", 23) + }) + + t.Run("on fatal", func(t *testing.T) { + t.Log("Log message should be printed") + t.Logf("printf style log message: %v", 42) + t.Fatal("Log should fail") + }) + + t.Run("on fatalf", func(t *testing.T) { + t.Log("Log message should be printed") + t.Logf("printf style log message: %v", 42) + t.Fatalf("Log should fail with printf style log: %v", 42) + }) + + t.Run("with newlines", func(t *testing.T) { + t.Log("Log\nmessage\nshould\nbe\nprinted") + t.Logf("printf\nstyle\nlog\nmessage:\n%v", 42) + t.Fatalf("Log\nshould\nfail\nwith\nprintf\nstyle\nlog:\n%v", 42) + }) +} + +var wantTestLogOutput = `(?sm: +=== Failed.* +=== FAIL: dev-tools/mage TestGoTest_Helper_LogOutput/on_error.* + gotest_test.go:\d+: Log message should be printed.* + gotest_test.go:\d+: printf style log message: 42.* + gotest_test.go:\d+: Log should fail.* + gotest_test.go:\d+: Log should fail with printf style log: 23.* + --- FAIL: TestGoTest_Helper_LogOutput/on_error.* +=== FAIL: dev-tools/mage TestGoTest_Helper_LogOutput/on_fatal.* + gotest_test.go:\d+: Log message should be printed.* + gotest_test.go:\d+: printf style log message: 42.* + gotest_test.go:\d+: Log should fail.* + --- FAIL: TestGoTest_Helper_LogOutput/on_fatal.* +=== FAIL: dev-tools/mage TestGoTest_Helper_LogOutput/on_fatalf.* + gotest_test.go:\d+: Log message should be printed.* + gotest_test.go:\d+: printf style log message: 42.* + gotest_test.go:\d+: Log should fail with printf style log: 42.* + --- FAIL: TestGoTest_Helper_LogOutput/on_fatalf.* +=== FAIL: dev-tools/mage TestGoTest_Helper_LogOutput/with_newlines.* + gotest_test.go:\d+: Log.* + message.* + should.* + be.* + printed.* + gotest_test.go:\d+: printf.* + style.* + log.* + message:.* + 42.* + gotest_test.go:\d+: Log.* + should.* + fail.* + with.* + printf.* + style.* + log:.* + 42.* + --- FAIL: TestGoTest_Helper_LogOutput/with_newlines.* +=== FAIL: dev-tools/mage TestGoTest_Helper_LogOutput.* +DONE 5 tests, 5 failures in.* +)` + +func TestGoTest_Helper_WithPanic(t *testing.T) { + if !gotestHelperMode { + return + } + + panic("Kaputt.") +} + +var wantTestWithPanic = `(?sm: +=== FAIL: dev-tools/mage TestGoTest_Helper_WithPanic.* +panic: Kaputt. \[recovered\].* + panic: Kaputt.* +)` + +func TestGoTest_Helper_WithWrongPanic(t *testing.T) { + if !gotestHelperMode { + return + } + + t.Run("setup failing go-routine", func(t *testing.T) { + go func() { + time.Sleep(1 * time.Second) + t.Fatal("oops") + }() + }) + + t.Run("false positive failure", func(t *testing.T) { + time.Sleep(10 * time.Second) + }) +} + +// The regular expression must very forgiving. Unfortunately the order of the +// tests and log lines can differ per run. +var wantTestWithWrongPanic = `(?sm: +=== FAIL: dev-tools/mage TestGoTest_Helper_WithWrongPanic.* +.* +panic: Fail in goroutine after TestGoTest_Helper_WithWrongPanic/setup_failing_go-routine has completed.* +)` diff --git a/go.mod b/go.mod index 0480ddac02b..450def63d6b 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/elastic/go-ucfg v0.8.3 github.com/elastic/go-windows v1.0.1 // indirect github.com/elastic/gosigar v0.13.0 - github.com/fatih/color v1.5.0 + github.com/fatih/color v1.9.0 github.com/fsnotify/fsevents v0.1.1 github.com/fsnotify/fsnotify v1.4.9 github.com/go-ole/go-ole v1.2.5-0.20190920104607-14974a1cf647 // indirect @@ -89,7 +89,7 @@ require ( github.com/golang/snappy v0.0.1 github.com/gomodule/redigo v1.8.3 github.com/google/flatbuffers v1.7.2-0.20170925184458-7a6b2bf521e9 - github.com/google/go-cmp v0.4.0 + github.com/google/go-cmp v0.5.2 github.com/google/gopacket v1.1.18-0.20191009163724-0ad7f2610e34 github.com/google/uuid v1.1.2-0.20190416172445-c2e93f3ae59f github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 @@ -108,15 +108,13 @@ require ( github.com/jonboulle/clockwork v0.2.2 github.com/josephspurrier/goversioninfo v0.0.0-20190209210621-63e6d1acd3dd github.com/jpillora/backoff v1.0.0 // indirect - github.com/jstemmer/go-junit-report v0.9.1 github.com/kardianos/service v1.1.0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/lib/pq v1.1.2-0.20190507191818-2ff3cb3adc01 github.com/magefile/mage v1.10.0 github.com/mailru/easyjson v0.7.1 // indirect - github.com/mattn/go-colorable v0.1.4 + github.com/mattn/go-colorable v0.1.6 github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe // indirect - github.com/mattn/go-isatty v0.0.12 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/miekg/dns v1.1.15 github.com/mitchellh/gox v1.0.1 @@ -142,7 +140,7 @@ require ( github.com/samuel/go-thrift v0.0.0-20140522043831-2187045faa54 github.com/sanathkr/yaml v1.0.1-0.20170819201035-0056894fa522 // indirect github.com/satori/go.uuid v1.2.0 // indirect - github.com/shirou/gopsutil v2.19.11+incompatible + github.com/shirou/gopsutil v3.20.12+incompatible github.com/shopspring/decimal v1.2.0 github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.5 @@ -169,7 +167,7 @@ require ( golang.org/x/net v0.0.0-20200707034311-ab3426394381 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a - golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae + golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 golang.org/x/text v0.3.3 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/tools v0.0.0-20200904185747-39188db58858 @@ -182,6 +180,7 @@ require ( gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528 gopkg.in/yaml.v2 v2.3.0 gotest.tools v2.2.0+incompatible + gotest.tools/gotestsum v0.6.0 howett.net/plist v0.0.0-20181124034731-591f970eefbb k8s.io/api v0.19.4 k8s.io/apimachinery v0.19.4 diff --git a/go.sum b/go.sum index 201f0d01fed..726066a7fc9 100644 --- a/go.sum +++ b/go.sum @@ -292,8 +292,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.5.0 h1:vBh+kQp8lg9XPr56u1CPrWjFXtdphMoGWVHr9/1c+A0= -github.com/fatih/color v1.5.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.7.2 h1:2QxQoC1TS09S7fhCPsrvqYdvP1H5M1P1ih5ABm3BTYk= @@ -378,6 +378,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo= github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= github.com/google/go-github/v29 v29.0.2 h1:opYN6Wc7DOz7Ku3Oh4l7prmkOMwEcQxpFtxdU8N8Pts= @@ -395,6 +397,8 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2-0.20190416172445-c2e93f3ae59f h1:XXzyYlFbxK3kWfcmu3Wc+Tv8/QQl/VqwsWuSYF1Rj0s= @@ -469,6 +473,7 @@ github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8 github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josephspurrier/goversioninfo v0.0.0-20190209210621-63e6d1acd3dd h1:KikNiFwUO3QLyeKyN4k9yBH9Pcu/gU/yficWi61cJIw= @@ -521,12 +526,14 @@ github.com/markbates/pkger v0.17.0 h1:RFfyBPufP2V6cddUyyEVSHBpaAnM1WzaMNyqomeT+i github.com/markbates/pkger v0.17.0/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw= github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe h1:YioO2TiJyAHWHyCRQCP8jk5IzTqmsbGc5qQPIhHo6xs= github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-shellwords v1.0.7 h1:KqhVjVZomx2puPACkj9vrGFqnp42Htvo9SEAWePHKOs= @@ -661,8 +668,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shirou/gopsutil v2.19.11+incompatible h1:lJHR0foqAjI4exXqWsU3DbH7bX1xvdhGdnXTIARA9W4= -github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.20.12+incompatible h1:6VEGkOXP/eP4o2Ilk8cSsX0PhOEfX6leqAnD+urrp9M= +github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -875,6 +882,7 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -882,11 +890,12 @@ golang.org/x/sys v0.0.0-20200102141924-c96a22e43c9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -988,6 +997,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/gotestsum v0.6.0 h1:0zIxynXq9gkAcRpboAi3qOQIkZkCt/stfQzd7ab7Czs= +gotest.tools/gotestsum v0.6.0/go.mod h1:LEX+ioCVdeWhZc8GYfiBRag360eBhwixWJ62R9eDQtI= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/heartbeat/monitors/stdfields/stdfields.go b/heartbeat/monitors/stdfields/stdfields.go index 433f6223863..26b28628fc3 100644 --- a/heartbeat/monitors/stdfields/stdfields.go +++ b/heartbeat/monitors/stdfields/stdfields.go @@ -18,7 +18,6 @@ package stdfields import ( - "fmt" "time" "github.com/pkg/errors" @@ -50,7 +49,6 @@ func ConfigToStdMonitorFields(config *common.Config) (StdMonitorFields, error) { mpi := StdMonitorFields{Enabled: true} if err := config.Unpack(&mpi); err != nil { - fmt.Printf("HIER %s", err) return mpi, errors.Wrap(err, "error unpacking monitor plugin config") } diff --git a/libbeat/common/cli/confirm.go b/libbeat/common/cli/confirm.go index 4beaa95bac9..5129071a7fa 100644 --- a/libbeat/common/cli/confirm.go +++ b/libbeat/common/cli/confirm.go @@ -32,10 +32,10 @@ import ( // returns true for yes, false for no func Confirm(prompt string, def bool) (bool, error) { reader := bufio.NewReader(os.Stdin) - return confirm(reader, prompt, def) + return confirm(reader, os.Stdout, prompt, def) } -func confirm(r io.Reader, prompt string, def bool) (bool, error) { +func confirm(r io.Reader, out io.Writer, prompt string, def bool) (bool, error) { options := " [Y/n]" if !def { options = " [y/N]" @@ -43,7 +43,7 @@ func confirm(r io.Reader, prompt string, def bool) (bool, error) { reader := bufio.NewScanner(r) for { - fmt.Print(prompt + options + ":") + fmt.Fprintf(out, prompt+options+":") if !reader.Scan() { break @@ -56,7 +56,7 @@ func confirm(r io.Reader, prompt string, def bool) (bool, error) { case "n", "no": return false, nil default: - fmt.Println("Please write 'y' or 'n'") + fmt.Fprintln(out, "Please write 'y' or 'n'") } } diff --git a/libbeat/common/cli/confirm_test.go b/libbeat/common/cli/confirm_test.go index 97a9475b332..dca2064aaa1 100644 --- a/libbeat/common/cli/confirm_test.go +++ b/libbeat/common/cli/confirm_test.go @@ -25,49 +25,51 @@ import ( ) func TestConfirm(t *testing.T) { - tests := []struct { - name string + tests := map[string]struct { input string + prompt string def bool result bool error bool }{ - { - name: "Test default yes", + "Test default yes": { input: "\n", + prompt: "> [Y/n]:", def: true, result: true, }, - { - name: "Test default no", + "Test default no": { input: "\n", + prompt: "> [y/N]:", def: false, result: false, }, - { - name: "Test YeS", + "Test YeS": { input: "YeS\n", + prompt: "> [y/N]:", def: false, result: true, }, - { - name: "Test Y", + "Test Y": { input: "Y\n", + prompt: "> [y/N]:", def: false, result: true, }, - { - name: "Test No", + "Test No": { input: "No\n", def: true, + prompt: "> [Y/n]:", result: false, }, } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { + for name, test := range tests { + t.Run(name, func(t *testing.T) { + var buf strings.Builder r := strings.NewReader(test.input) - result, err := confirm(r, "prompt", test.def) + + result, err := confirm(r, &buf, ">", test.def) assert.Equal(t, test.result, result) if test.error { @@ -75,6 +77,8 @@ func TestConfirm(t *testing.T) { } else { assert.NoError(t, err) } + + assert.Equal(t, test.prompt, buf.String()) }) } } diff --git a/libbeat/common/cli/input.go b/libbeat/common/cli/input.go index a6a516fd3d4..7025f63f2aa 100644 --- a/libbeat/common/cli/input.go +++ b/libbeat/common/cli/input.go @@ -29,12 +29,12 @@ import ( // ReadInput shows the text and ask the user to provide input. func ReadInput(prompt string) (string, error) { reader := bufio.NewReader(os.Stdin) - return input(reader, prompt) + return input(reader, os.Stdout, prompt) } -func input(r io.Reader, prompt string) (string, error) { +func input(r io.Reader, out io.Writer, prompt string) (string, error) { reader := bufio.NewScanner(r) - fmt.Print(prompt + " ") + fmt.Fprintf(out, prompt+" ") if !reader.Scan() { return "", errors.New("error reading user input") diff --git a/libbeat/common/cli/input_test.go b/libbeat/common/cli/input_test.go index de87b5efe2a..94c1d26bb7c 100644 --- a/libbeat/common/cli/input_test.go +++ b/libbeat/common/cli/input_test.go @@ -25,39 +25,37 @@ import ( ) func TestReadInput(t *testing.T) { - tests := []struct { - name string + tests := map[string]struct { input string res string }{ - { - name: "Question 1?", + "Question 1?": { input: "\n", res: "", }, - { - name: "Question 2?", + "Question 2?": { input: "full string input\n", res: "full string input", }, - { - name: "Question 3?", + + "Question 3?": { input: "123456789\n", res: "123456789", }, - { - name: "Question 4?", + "Question 4?": { input: "false\n", res: "false", }, } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { + for name, test := range tests { + t.Run(name, func(t *testing.T) { + var buf strings.Builder r := strings.NewReader(test.input) - result, err := input(r, test.name) + result, err := input(r, &buf, name) assert.NoError(t, err) assert.Equal(t, test.res, result) + assert.Equal(t, name+" ", buf.String()) }) } } diff --git a/tools/tools.go b/tools/tools.go index 707fdb559d6..7708afedfc4 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -28,6 +28,7 @@ import ( _ "github.com/tsg/go-daemon" _ "golang.org/x/tools/cmd/goimports" _ "golang.org/x/tools/cmd/stringer" + _ "gotest.tools/gotestsum/cmd" _ "github.com/mitchellh/gox" _ "github.com/reviewdog/reviewdog/cmd/reviewdog"