github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/test/go-spew/spew/spew_test.go (about)

     1  /*
     2   * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
     3   *
     4   * Permission to use, copy, modify, and distribute this software for any
     5   * purpose with or without fee is hereby granted, provided that the above
     6   * copyright notice and this permission notice appear in all copies.
     7   *
     8   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     9   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    10   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    11   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    12   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    13   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    14   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    15   */
    16  
    17  package spew_test
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"testing"
    25  
    26  	"github.com/davecgh/go-spew/spew"
    27  )
    28  
    29  // spewFunc is used to identify which public function of the spew package or
    30  // ConfigState a test applies to.
    31  type spewFunc int
    32  
    33  const (
    34  	fCSFdump spewFunc = iota
    35  	fCSFprint
    36  	fCSFprintf
    37  	fCSFprintln
    38  	fCSPrint
    39  	fCSPrintln
    40  	fCSSdump
    41  	fCSSprint
    42  	fCSSprintf
    43  	fCSSprintln
    44  	fCSErrorf
    45  	fCSNewFormatter
    46  	fErrorf
    47  	fFprint
    48  	fFprintln
    49  	fPrint
    50  	fPrintln
    51  	fSdump
    52  	fSprint
    53  	fSprintf
    54  	fSprintln
    55  )
    56  
    57  // Map of spewFunc values to names for pretty printing.
    58  var spewFuncStrings = map[spewFunc]string{
    59  	fCSFdump:        "ConfigState.Fdump",
    60  	fCSFprint:       "ConfigState.Fprint",
    61  	fCSFprintf:      "ConfigState.Fprintf",
    62  	fCSFprintln:     "ConfigState.Fprintln",
    63  	fCSSdump:        "ConfigState.Sdump",
    64  	fCSPrint:        "ConfigState.Print",
    65  	fCSPrintln:      "ConfigState.Println",
    66  	fCSSprint:       "ConfigState.Sprint",
    67  	fCSSprintf:      "ConfigState.Sprintf",
    68  	fCSSprintln:     "ConfigState.Sprintln",
    69  	fCSErrorf:       "ConfigState.Errorf",
    70  	fCSNewFormatter: "ConfigState.NewFormatter",
    71  	fErrorf:         "spew.Errorf",
    72  	fFprint:         "spew.Fprint",
    73  	fFprintln:       "spew.Fprintln",
    74  	fPrint:          "spew.Print",
    75  	fPrintln:        "spew.Println",
    76  	fSdump:          "spew.Sdump",
    77  	fSprint:         "spew.Sprint",
    78  	fSprintf:        "spew.Sprintf",
    79  	fSprintln:       "spew.Sprintln",
    80  }
    81  
    82  func (f spewFunc) String() string {
    83  	if s, ok := spewFuncStrings[f]; ok {
    84  		return s
    85  	}
    86  	return fmt.Sprintf("Unknown spewFunc (%d)", int(f))
    87  }
    88  
    89  // spewTest is used to describe a test to be performed against the public
    90  // functions of the spew package or ConfigState.
    91  type spewTest struct {
    92  	cs     *spew.ConfigState
    93  	f      spewFunc
    94  	format string
    95  	in     interface{}
    96  	want   string
    97  }
    98  
    99  // spewTests houses the tests to be performed against the public functions of
   100  // the spew package and ConfigState.
   101  //
   102  // These tests are only intended to ensure the public functions are exercised
   103  // and are intentionally not exhaustive of types.  The exhaustive type
   104  // tests are handled in the dump and format tests.
   105  var spewTests []spewTest
   106  
   107  // redirStdout is a helper function to return the standard output from f as a
   108  // byte slice.
   109  func redirStdout(f func()) ([]byte, error) {
   110  	tempFile, err := ioutil.TempFile("", "ss-test")
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	fileName := tempFile.Name()
   115  	defer os.Remove(fileName) // Ignore error
   116  
   117  	origStdout := os.Stdout
   118  	os.Stdout = tempFile
   119  	f()
   120  	os.Stdout = origStdout
   121  	tempFile.Close()
   122  
   123  	return ioutil.ReadFile(fileName)
   124  }
   125  
   126  func initSpewTests() {
   127  	// Config states with various settings.
   128  	scsDefault := spew.NewDefaultConfig()
   129  	scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true}
   130  	scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true}
   131  	scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1}
   132  	scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true}
   133  	scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true}
   134  	scsNoCap := &spew.ConfigState{DisableCapacities: true}
   135  
   136  	// Variables for tests on types which implement Stringer interface with and
   137  	// without a pointer receiver.
   138  	ts := stringer("test")
   139  	tps := pstringer("test")
   140  
   141  	type ptrTester struct {
   142  		s *struct{}
   143  	}
   144  	tptr := &ptrTester{s: &struct{}{}}
   145  
   146  	// depthTester is used to test max depth handling for structs, array, slices
   147  	// and maps.
   148  	type depthTester struct {
   149  		ic    indirCir1
   150  		arr   [1]string
   151  		slice []string
   152  		m     map[string]int
   153  	}
   154  	dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"},
   155  		map[string]int{"one": 1}}
   156  
   157  	// Variable for tests on types which implement error interface.
   158  	te := customError(10)
   159  
   160  	spewTests = []spewTest{
   161  		{scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"},
   162  		{scsDefault, fCSFprint, "", int16(32767), "32767"},
   163  		{scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"},
   164  		{scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"},
   165  		{scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"},
   166  		{scsDefault, fCSPrintln, "", uint8(255), "255\n"},
   167  		{scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"},
   168  		{scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"},
   169  		{scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"},
   170  		{scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"},
   171  		{scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"},
   172  		{scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"},
   173  		{scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"},
   174  		{scsDefault, fFprint, "", float32(3.14), "3.14"},
   175  		{scsDefault, fFprintln, "", float64(6.28), "6.28\n"},
   176  		{scsDefault, fPrint, "", true, "true"},
   177  		{scsDefault, fPrintln, "", false, "false\n"},
   178  		{scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"},
   179  		{scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"},
   180  		{scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"},
   181  		{scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"},
   182  		{scsNoMethods, fCSFprint, "", ts, "test"},
   183  		{scsNoMethods, fCSFprint, "", &ts, "<*>test"},
   184  		{scsNoMethods, fCSFprint, "", tps, "test"},
   185  		{scsNoMethods, fCSFprint, "", &tps, "<*>test"},
   186  		{scsNoPmethods, fCSFprint, "", ts, "stringer test"},
   187  		{scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"},
   188  		{scsNoPmethods, fCSFprint, "", tps, "test"},
   189  		{scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"},
   190  		{scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"},
   191  		{scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" +
   192  			" ic: (spew_test.indirCir1) {\n  <max depth reached>\n },\n" +
   193  			" arr: ([1]string) (len=1 cap=1) {\n  <max depth reached>\n },\n" +
   194  			" slice: ([]string) (len=1 cap=1) {\n  <max depth reached>\n },\n" +
   195  			" m: (map[string]int) (len=1) {\n  <max depth reached>\n }\n}\n"},
   196  		{scsContinue, fCSFprint, "", ts, "(stringer test) test"},
   197  		{scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " +
   198  			"(len=4) (stringer test) \"test\"\n"},
   199  		{scsContinue, fCSFprint, "", te, "(error: 10) 10"},
   200  		{scsContinue, fCSFdump, "", te, "(spew_test.customError) " +
   201  			"(error: 10) 10\n"},
   202  		{scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"},
   203  		{scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"},
   204  		{scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"},
   205  		{scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"},
   206  	}
   207  }
   208  
   209  // TestSpew executes all of the tests described by spewTests.
   210  func TestSpew(t *testing.T) {
   211  	initSpewTests()
   212  
   213  	t.Logf("Running %d tests", len(spewTests))
   214  	for i, test := range spewTests {
   215  		buf := new(bytes.Buffer)
   216  		switch test.f {
   217  		case fCSFdump:
   218  			test.cs.Fdump(buf, test.in)
   219  
   220  		case fCSFprint:
   221  			test.cs.Fprint(buf, test.in)
   222  
   223  		case fCSFprintf:
   224  			test.cs.Fprintf(buf, test.format, test.in)
   225  
   226  		case fCSFprintln:
   227  			test.cs.Fprintln(buf, test.in)
   228  
   229  		case fCSPrint:
   230  			b, err := redirStdout(func() { test.cs.Print(test.in) })
   231  			if err != nil {
   232  				t.Errorf("%v #%d %v", test.f, i, err)
   233  				continue
   234  			}
   235  			buf.Write(b)
   236  
   237  		case fCSPrintln:
   238  			b, err := redirStdout(func() { test.cs.Println(test.in) })
   239  			if err != nil {
   240  				t.Errorf("%v #%d %v", test.f, i, err)
   241  				continue
   242  			}
   243  			buf.Write(b)
   244  
   245  		case fCSSdump:
   246  			str := test.cs.Sdump(test.in)
   247  			buf.WriteString(str)
   248  
   249  		case fCSSprint:
   250  			str := test.cs.Sprint(test.in)
   251  			buf.WriteString(str)
   252  
   253  		case fCSSprintf:
   254  			str := test.cs.Sprintf(test.format, test.in)
   255  			buf.WriteString(str)
   256  
   257  		case fCSSprintln:
   258  			str := test.cs.Sprintln(test.in)
   259  			buf.WriteString(str)
   260  
   261  		case fCSErrorf:
   262  			err := test.cs.Errorf(test.format, test.in)
   263  			buf.WriteString(err.Error())
   264  
   265  		case fCSNewFormatter:
   266  			fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in))
   267  
   268  		case fErrorf:
   269  			err := spew.Errorf(test.format, test.in)
   270  			buf.WriteString(err.Error())
   271  
   272  		case fFprint:
   273  			spew.Fprint(buf, test.in)
   274  
   275  		case fFprintln:
   276  			spew.Fprintln(buf, test.in)
   277  
   278  		case fPrint:
   279  			b, err := redirStdout(func() { spew.Print(test.in) })
   280  			if err != nil {
   281  				t.Errorf("%v #%d %v", test.f, i, err)
   282  				continue
   283  			}
   284  			buf.Write(b)
   285  
   286  		case fPrintln:
   287  			b, err := redirStdout(func() { spew.Println(test.in) })
   288  			if err != nil {
   289  				t.Errorf("%v #%d %v", test.f, i, err)
   290  				continue
   291  			}
   292  			buf.Write(b)
   293  
   294  		case fSdump:
   295  			str := spew.Sdump(test.in)
   296  			buf.WriteString(str)
   297  
   298  		case fSprint:
   299  			str := spew.Sprint(test.in)
   300  			buf.WriteString(str)
   301  
   302  		case fSprintf:
   303  			str := spew.Sprintf(test.format, test.in)
   304  			buf.WriteString(str)
   305  
   306  		case fSprintln:
   307  			str := spew.Sprintln(test.in)
   308  			buf.WriteString(str)
   309  
   310  		default:
   311  			t.Errorf("%v #%d unrecognized function", test.f, i)
   312  			continue
   313  		}
   314  		s := buf.String()
   315  		if test.want != s {
   316  			t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want)
   317  			continue
   318  		}
   319  	}
   320  }