github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/goutils/testingu/root_test_case.go (about) 1 /* 2 * Copyright (c) 2023-present unTill Pro, Ltd. 3 * @author Maxim Geraskin 4 */ 5 6 package testingu 7 8 import ( 9 "bytes" 10 "errors" 11 "io" 12 "os" 13 "strings" 14 "sync" 15 "testing" 16 ) 17 18 type RootTestCase struct { 19 Name string 20 Args []string 21 Version string 22 ExpectedErr error 23 ExpectedErrPattern string 24 } 25 26 func RunRootTestCases(t *testing.T, execute func(args []string, version string) error, testCases []RootTestCase) { 27 // notestdept 28 t.Helper() 29 for _, tc := range testCases { 30 t.Run(tc.Name, func(t *testing.T) { 31 t.Helper() 32 f := func() error { 33 return execute(tc.Args, tc.Version) 34 } 35 36 _, _, err := CaptureStdoutStderr(f) 37 38 checkError(t, tc.ExpectedErr, tc.ExpectedErrPattern, err) 39 }) 40 } 41 } 42 43 func checkError(t *testing.T, expectedErr error, expectedErrPattern string, actualErr error) { 44 // notestdept 45 t.Helper() 46 if expectedErr != nil || len(expectedErrPattern) > 0 { 47 if actualErr == nil { 48 t.Errorf("error was not returned as expected") 49 return 50 } 51 if expectedErr != nil && !errors.Is(actualErr, expectedErr) { 52 t.Errorf("wrong error was returned: expected `%v`, got `%v`", expectedErr, actualErr) 53 return 54 } 55 if len(expectedErrPattern) > 0 && !strings.Contains(actualErr.Error(), expectedErrPattern) { 56 t.Errorf("wrong error was returned: expected pattern `%v`, got `%v`", expectedErrPattern, actualErr.Error()) 57 return 58 } 59 } else if actualErr != nil { 60 t.Errorf("unexpected error was returned: %v", actualErr) 61 } 62 } 63 64 // https://go.dev/play/p/Fzj1k7jul7z 65 66 func CaptureStdoutStderr(f func() error) (stdout string, stderr string, err error) { 67 68 stdoutReader, stdoutWriter, err := os.Pipe() 69 if err != nil { 70 // notestdept 71 return 72 } 73 stderrReader, stderrWriter, err := os.Pipe() 74 if err != nil { 75 // notestdept 76 return 77 } 78 79 { 80 origStdout := os.Stdout 81 os.Stdout = stdoutWriter 82 defer func() { os.Stdout = origStdout }() 83 } 84 { 85 origStderr := os.Stderr 86 os.Stderr = stderrWriter 87 defer func() { os.Stderr = origStderr }() 88 } 89 90 wg := sync.WaitGroup{} 91 92 wg.Add(1) 93 go func() { 94 var b bytes.Buffer 95 defer wg.Done() 96 _, _ = io.Copy(&b, stdoutReader) 97 stdout = b.String() 98 }() 99 wg.Add(1) 100 go func() { 101 var b bytes.Buffer 102 defer wg.Done() 103 _, _ = io.Copy(&b, stderrReader) 104 stderr = b.String() 105 }() 106 107 err = f() 108 stderrWriter.Close() 109 stdoutWriter.Close() 110 wg.Wait() 111 return 112 113 }