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  }