Source file src/go/constant/value_test.go

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package constant
     6  
     7  import (
     8  	"fmt"
     9  	"go/token"
    10  	"math"
    11  	"math/big"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  var intTests = []string{
    17  	// 0-octals
    18  	`0_123 = 0123`,
    19  	`0123_456 = 0123456`,
    20  
    21  	// decimals
    22  	`1_234 = 1234`,
    23  	`1_234_567 = 1234567`,
    24  
    25  	// hexadecimals
    26  	`0X_0 = 0`,
    27  	`0X_1234 = 0x1234`,
    28  	`0X_CAFE_f00d = 0xcafef00d`,
    29  
    30  	// octals
    31  	`0o0 = 0`,
    32  	`0o1234 = 01234`,
    33  	`0o01234567 = 01234567`,
    34  
    35  	`0O0 = 0`,
    36  	`0O1234 = 01234`,
    37  	`0O01234567 = 01234567`,
    38  
    39  	`0o_0 = 0`,
    40  	`0o_1234 = 01234`,
    41  	`0o0123_4567 = 01234567`,
    42  
    43  	`0O_0 = 0`,
    44  	`0O_1234 = 01234`,
    45  	`0O0123_4567 = 01234567`,
    46  
    47  	// binaries
    48  	`0b0 = 0`,
    49  	`0b1011 = 0xb`,
    50  	`0b00101101 = 0x2d`,
    51  
    52  	`0B0 = 0`,
    53  	`0B1011 = 0xb`,
    54  	`0B00101101 = 0x2d`,
    55  
    56  	`0b_0 = 0`,
    57  	`0b10_11 = 0xb`,
    58  	`0b_0010_1101 = 0x2d`,
    59  }
    60  
    61  // The RHS operand may be a floating-point quotient n/d of two integer values n and d.
    62  var floatTests = []string{
    63  	// decimal floats
    64  	`1_2_3. = 123.`,
    65  	`0_123. = 123.`,
    66  
    67  	`0_0e0 = 0.`,
    68  	`1_2_3e0 = 123.`,
    69  	`0_123e0 = 123.`,
    70  
    71  	`0e-0_0 = 0.`,
    72  	`1_2_3E+0 = 123.`,
    73  	`0123E1_2_3 = 123e123`,
    74  
    75  	`0.e+1 = 0.`,
    76  	`123.E-1_0 = 123e-10`,
    77  	`01_23.e123 = 123e123`,
    78  
    79  	`.0e-1 = .0`,
    80  	`.123E+10 = .123e10`,
    81  	`.0123E123 = .0123e123`,
    82  
    83  	`1_2_3.123 = 123.123`,
    84  	`0123.01_23 = 123.0123`,
    85  
    86  	`1e-1000000000 = 0`,
    87  	`1e+1000000000 = ?`,
    88  	`6e5518446744 = ?`,
    89  	`-6e5518446744 = ?`,
    90  
    91  	// hexadecimal floats
    92  	`0x0.p+0 = 0.`,
    93  	`0Xdeadcafe.p-10 = 0xdeadcafe/1024`,
    94  	`0x1234.P84 = 0x1234000000000000000000000`,
    95  
    96  	`0x.1p-0 = 1/16`,
    97  	`0X.deadcafep4 = 0xdeadcafe/0x10000000`,
    98  	`0x.1234P+12 = 0x1234/0x10`,
    99  
   100  	`0x0p0 = 0.`,
   101  	`0Xdeadcafep+1 = 0x1bd5b95fc`,
   102  	`0x1234P-10 = 0x1234/1024`,
   103  
   104  	`0x0.0p0 = 0.`,
   105  	`0Xdead.cafep+1 = 0x1bd5b95fc/0x10000`,
   106  	`0x12.34P-10 = 0x1234/0x40000`,
   107  
   108  	`0Xdead_cafep+1 = 0xdeadcafep+1`,
   109  	`0x_1234P-10 = 0x1234p-10`,
   110  
   111  	`0X_dead_cafe.p-10 = 0xdeadcafe.p-10`,
   112  	`0x12_34.P1_2_3 = 0x1234.p123`,
   113  }
   114  
   115  var imagTests = []string{
   116  	`1_234i = 1234i`,
   117  	`1_234_567i = 1234567i`,
   118  
   119  	`0.i = 0i`,
   120  	`123.i = 123i`,
   121  	`0123.i = 123i`,
   122  
   123  	`0.e+1i = 0i`,
   124  	`123.E-1_0i = 123e-10i`,
   125  	`01_23.e123i = 123e123i`,
   126  
   127  	`1e-1000000000i = 0i`,
   128  	`1e+1000000000i = ?`,
   129  	`6e5518446744i = ?`,
   130  	`-6e5518446744i = ?`,
   131  }
   132  
   133  func testNumbers(t *testing.T, kind token.Token, tests []string) {
   134  	for _, test := range tests {
   135  		a := strings.Split(test, " = ")
   136  		if len(a) != 2 {
   137  			t.Errorf("invalid test case: %s", test)
   138  			continue
   139  		}
   140  
   141  		x := MakeFromLiteral(a[0], kind, 0)
   142  		var y Value
   143  		if a[1] == "?" {
   144  			y = MakeUnknown()
   145  		} else {
   146  			if ns, ds, ok := strings.Cut(a[1], "/"); ok && kind == token.FLOAT {
   147  				n := MakeFromLiteral(ns, token.INT, 0)
   148  				d := MakeFromLiteral(ds, token.INT, 0)
   149  				y = BinaryOp(n, token.QUO, d)
   150  			} else {
   151  				y = MakeFromLiteral(a[1], kind, 0)
   152  			}
   153  			if y.Kind() == Unknown {
   154  				panic(fmt.Sprintf("invalid test case: %s %d", test, y.Kind()))
   155  			}
   156  		}
   157  
   158  		xk := x.Kind()
   159  		yk := y.Kind()
   160  		if xk != yk {
   161  			t.Errorf("%s: got kind %d != %d", test, xk, yk)
   162  			continue
   163  		}
   164  
   165  		if yk == Unknown {
   166  			continue
   167  		}
   168  
   169  		if !Compare(x, token.EQL, y) {
   170  			t.Errorf("%s: %s != %s", test, x, y)
   171  		}
   172  	}
   173  }
   174  
   175  // TestNumbers verifies that differently written literals
   176  // representing the same number do have the same value.
   177  func TestNumbers(t *testing.T) {
   178  	testNumbers(t, token.INT, intTests)
   179  	testNumbers(t, token.FLOAT, floatTests)
   180  	testNumbers(t, token.IMAG, imagTests)
   181  }
   182  
   183  var opTests = []string{
   184  	// unary operations
   185  	`+ 0 = 0`,
   186  	`+ ? = ?`,
   187  	`- 1 = -1`,
   188  	`- ? = ?`,
   189  	`^ 0 = -1`,
   190  	`^ ? = ?`,
   191  
   192  	`! true = false`,
   193  	`! false = true`,
   194  	`! ? = ?`,
   195  
   196  	// etc.
   197  
   198  	// binary operations
   199  	`"" + "" = ""`,
   200  	`"foo" + "" = "foo"`,
   201  	`"" + "bar" = "bar"`,
   202  	`"foo" + "bar" = "foobar"`,
   203  
   204  	`0 + 0 = 0`,
   205  	`0 + 0.1 = 0.1`,
   206  	`0 + 0.1i = 0.1i`,
   207  	`0.1 + 0.9 = 1`,
   208  	`1e100 + 1e100 = 2e100`,
   209  	`? + 0 = ?`,
   210  	`0 + ? = ?`,
   211  
   212  	`0 - 0 = 0`,
   213  	`0 - 0.1 = -0.1`,
   214  	`0 - 0.1i = -0.1i`,
   215  	`1e100 - 1e100 = 0`,
   216  	`? - 0 = ?`,
   217  	`0 - ? = ?`,
   218  
   219  	`0 * 0 = 0`,
   220  	`1 * 0.1 = 0.1`,
   221  	`1 * 0.1i = 0.1i`,
   222  	`1i * 1i = -1`,
   223  	`? * 0 = ?`,
   224  	`0 * ? = ?`,
   225  	`0 * 1e+1000000000 = ?`,
   226  
   227  	`0 / 0 = "division_by_zero"`,
   228  	`10 / 2 = 5`,
   229  	`5 / 3 = 5/3`,
   230  	`5i / 3i = 5/3`,
   231  	`? / 0 = ?`,
   232  	`0 / ? = ?`,
   233  	`0 * 1e+1000000000i = ?`,
   234  
   235  	`0 % 0 = "runtime_error:_integer_divide_by_zero"`, // TODO(gri) should be the same as for /
   236  	`10 % 3 = 1`,
   237  	`? % 0 = ?`,
   238  	`0 % ? = ?`,
   239  
   240  	`0 & 0 = 0`,
   241  	`12345 & 0 = 0`,
   242  	`0xff & 0xf = 0xf`,
   243  	`? & 0 = ?`,
   244  	`0 & ? = ?`,
   245  
   246  	`0 | 0 = 0`,
   247  	`12345 | 0 = 12345`,
   248  	`0xb | 0xa0 = 0xab`,
   249  	`? | 0 = ?`,
   250  	`0 | ? = ?`,
   251  
   252  	`0 ^ 0 = 0`,
   253  	`1 ^ -1 = -2`,
   254  	`? ^ 0 = ?`,
   255  	`0 ^ ? = ?`,
   256  
   257  	`0 &^ 0 = 0`,
   258  	`0xf &^ 1 = 0xe`,
   259  	`1 &^ 0xf = 0`,
   260  	// etc.
   261  
   262  	// shifts
   263  	`0 << 0 = 0`,
   264  	`1 << 10 = 1024`,
   265  	`0 >> 0 = 0`,
   266  	`1024 >> 10 == 1`,
   267  	`? << 0 == ?`,
   268  	`? >> 10 == ?`,
   269  	// etc.
   270  
   271  	// comparisons
   272  	`false == false = true`,
   273  	`false == true = false`,
   274  	`true == false = false`,
   275  	`true == true = true`,
   276  
   277  	`false != false = false`,
   278  	`false != true = true`,
   279  	`true != false = true`,
   280  	`true != true = false`,
   281  
   282  	`"foo" == "bar" = false`,
   283  	`"foo" != "bar" = true`,
   284  	`"foo" < "bar" = false`,
   285  	`"foo" <= "bar" = false`,
   286  	`"foo" > "bar" = true`,
   287  	`"foo" >= "bar" = true`,
   288  
   289  	`0 == 0 = true`,
   290  	`0 != 0 = false`,
   291  	`0 < 10 = true`,
   292  	`10 <= 10 = true`,
   293  	`0 > 10 = false`,
   294  	`10 >= 10 = true`,
   295  
   296  	`1/123456789 == 1/123456789 == true`,
   297  	`1/123456789 != 1/123456789 == false`,
   298  	`1/123456789 < 1/123456788 == true`,
   299  	`1/123456788 <= 1/123456789 == false`,
   300  	`0.11 > 0.11 = false`,
   301  	`0.11 >= 0.11 = true`,
   302  
   303  	`? == 0 = false`,
   304  	`? != 0 = false`,
   305  	`? < 10 = false`,
   306  	`? <= 10 = false`,
   307  	`? > 10 = false`,
   308  	`? >= 10 = false`,
   309  
   310  	`0 == ? = false`,
   311  	`0 != ? = false`,
   312  	`0 < ? = false`,
   313  	`10 <= ? = false`,
   314  	`0 > ? = false`,
   315  	`10 >= ? = false`,
   316  
   317  	// etc.
   318  }
   319  
   320  func TestOps(t *testing.T) {
   321  	for _, test := range opTests {
   322  		a := strings.Split(test, " ")
   323  		i := 0 // operator index
   324  
   325  		var x, x0 Value
   326  		switch len(a) {
   327  		case 4:
   328  			// unary operation
   329  		case 5:
   330  			// binary operation
   331  			x, x0 = val(a[0]), val(a[0])
   332  			i = 1
   333  		default:
   334  			t.Errorf("invalid test case: %s", test)
   335  			continue
   336  		}
   337  
   338  		op, ok := optab[a[i]]
   339  		if !ok {
   340  			panic("missing optab entry for " + a[i])
   341  		}
   342  
   343  		y, y0 := val(a[i+1]), val(a[i+1])
   344  
   345  		got := doOp(x, op, y)
   346  		want := val(a[i+3])
   347  		if !eql(got, want) {
   348  			t.Errorf("%s: got %s; want %s", test, got, want)
   349  			continue
   350  		}
   351  
   352  		if x0 != nil && !eql(x, x0) {
   353  			t.Errorf("%s: x changed to %s", test, x)
   354  			continue
   355  		}
   356  
   357  		if !eql(y, y0) {
   358  			t.Errorf("%s: y changed to %s", test, y)
   359  			continue
   360  		}
   361  	}
   362  }
   363  
   364  func eql(x, y Value) bool {
   365  	_, ux := x.(unknownVal)
   366  	_, uy := y.(unknownVal)
   367  	if ux || uy {
   368  		return ux == uy
   369  	}
   370  	return Compare(x, token.EQL, y)
   371  }
   372  
   373  // ----------------------------------------------------------------------------
   374  // String tests
   375  
   376  var xxx = strings.Repeat("x", 68)
   377  var issue14262 = `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).  المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد لهذا الترخيص."`
   378  
   379  var stringTests = []struct {
   380  	input, short, exact string
   381  }{
   382  	// Unknown
   383  	{"", "unknown", "unknown"},
   384  	{"0x", "unknown", "unknown"},
   385  	{"'", "unknown", "unknown"},
   386  	{"1f0", "unknown", "unknown"},
   387  	{"unknown", "unknown", "unknown"},
   388  
   389  	// Bool
   390  	{"true", "true", "true"},
   391  	{"false", "false", "false"},
   392  
   393  	// String
   394  	{`""`, `""`, `""`},
   395  	{`"foo"`, `"foo"`, `"foo"`},
   396  	{`"` + xxx + `xx"`, `"` + xxx + `xx"`, `"` + xxx + `xx"`},
   397  	{`"` + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + `xxx"`},
   398  	{`"` + xxx + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + xxx + `xxx"`},
   399  	{issue14262, `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة ال...`, issue14262},
   400  
   401  	// Int
   402  	{"0", "0", "0"},
   403  	{"-1", "-1", "-1"},
   404  	{"12345", "12345", "12345"},
   405  	{"-12345678901234567890", "-12345678901234567890", "-12345678901234567890"},
   406  	{"12345678901234567890", "12345678901234567890", "12345678901234567890"},
   407  
   408  	// Float
   409  	{"0.", "0", "0"},
   410  	{"-0.0", "0", "0"},
   411  	{"10.0", "10", "10"},
   412  	{"2.1", "2.1", "21/10"},
   413  	{"-2.1", "-2.1", "-21/10"},
   414  	{"1e9999", "1e+9999", "0x.f8d4a9da224650a8cb2959e10d985ad92adbd44c62917e608b1f24c0e1b76b6f61edffeb15c135a4b601637315f7662f325f82325422b244286a07663c9415d2p+33216"},
   415  	{"1e-9999", "1e-9999", "0x.83b01ba6d8c0425eec1b21e96f7742d63c2653ed0a024cf8a2f9686df578d7b07d7a83d84df6a2ec70a921d1f6cd5574893a7eda4d28ee719e13a5dce2700759p-33215"},
   416  	{"2.71828182845904523536028747135266249775724709369995957496696763", "2.71828", "271828182845904523536028747135266249775724709369995957496696763/100000000000000000000000000000000000000000000000000000000000000"},
   417  	{"0e9999999999", "0", "0"},   // issue #16176
   418  	{"-6e-1886451601", "0", "0"}, // issue #20228
   419  
   420  	// Complex
   421  	{"0i", "(0 + 0i)", "(0 + 0i)"},
   422  	{"-0i", "(0 + 0i)", "(0 + 0i)"},
   423  	{"10i", "(0 + 10i)", "(0 + 10i)"},
   424  	{"-10i", "(0 + -10i)", "(0 + -10i)"},
   425  	{"1e9999i", "(0 + 1e+9999i)", "(0 + 0x.f8d4a9da224650a8cb2959e10d985ad92adbd44c62917e608b1f24c0e1b76b6f61edffeb15c135a4b601637315f7662f325f82325422b244286a07663c9415d2p+33216i)"},
   426  }
   427  
   428  func TestString(t *testing.T) {
   429  	for _, test := range stringTests {
   430  		x := val(test.input)
   431  		if got := x.String(); got != test.short {
   432  			t.Errorf("%s: got %q; want %q as short string", test.input, got, test.short)
   433  		}
   434  		if got := x.ExactString(); got != test.exact {
   435  			t.Errorf("%s: got %q; want %q as exact string", test.input, got, test.exact)
   436  		}
   437  	}
   438  }
   439  
   440  // ----------------------------------------------------------------------------
   441  // Support functions
   442  
   443  func val(lit string) Value {
   444  	if len(lit) == 0 {
   445  		return MakeUnknown()
   446  	}
   447  
   448  	switch lit {
   449  	case "?":
   450  		return MakeUnknown()
   451  	case "true":
   452  		return MakeBool(true)
   453  	case "false":
   454  		return MakeBool(false)
   455  	}
   456  
   457  	if as, bs, ok := strings.Cut(lit, "/"); ok {
   458  		// assume fraction
   459  		a := MakeFromLiteral(as, token.INT, 0)
   460  		b := MakeFromLiteral(bs, token.INT, 0)
   461  		return BinaryOp(a, token.QUO, b)
   462  	}
   463  
   464  	tok := token.INT
   465  	switch first, last := lit[0], lit[len(lit)-1]; {
   466  	case first == '"' || first == '`':
   467  		tok = token.STRING
   468  		lit = strings.ReplaceAll(lit, "_", " ")
   469  	case first == '\'':
   470  		tok = token.CHAR
   471  	case last == 'i':
   472  		tok = token.IMAG
   473  	default:
   474  		if !strings.HasPrefix(lit, "0x") && strings.ContainsAny(lit, "./Ee") {
   475  			tok = token.FLOAT
   476  		}
   477  	}
   478  
   479  	return MakeFromLiteral(lit, tok, 0)
   480  }
   481  
   482  var optab = map[string]token.Token{
   483  	"!": token.NOT,
   484  
   485  	"+": token.ADD,
   486  	"-": token.SUB,
   487  	"*": token.MUL,
   488  	"/": token.QUO,
   489  	"%": token.REM,
   490  
   491  	"<<": token.SHL,
   492  	">>": token.SHR,
   493  
   494  	"&":  token.AND,
   495  	"|":  token.OR,
   496  	"^":  token.XOR,
   497  	"&^": token.AND_NOT,
   498  
   499  	"==": token.EQL,
   500  	"!=": token.NEQ,
   501  	"<":  token.LSS,
   502  	"<=": token.LEQ,
   503  	">":  token.GTR,
   504  	">=": token.GEQ,
   505  }
   506  
   507  func panicHandler(v *Value) {
   508  	switch p := recover().(type) {
   509  	case nil:
   510  		// nothing to do
   511  	case string:
   512  		*v = MakeString(p)
   513  	case error:
   514  		*v = MakeString(p.Error())
   515  	default:
   516  		panic(p)
   517  	}
   518  }
   519  
   520  func doOp(x Value, op token.Token, y Value) (z Value) {
   521  	defer panicHandler(&z)
   522  
   523  	if x == nil {
   524  		return UnaryOp(op, y, 0)
   525  	}
   526  
   527  	switch op {
   528  	case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
   529  		return MakeBool(Compare(x, op, y))
   530  	case token.SHL, token.SHR:
   531  		s, _ := Int64Val(y)
   532  		return Shift(x, op, uint(s))
   533  	default:
   534  		return BinaryOp(x, op, y)
   535  	}
   536  }
   537  
   538  // ----------------------------------------------------------------------------
   539  // Other tests
   540  
   541  var fracTests = []string{
   542  	"0",
   543  	"1",
   544  	"-1",
   545  	"1.2",
   546  	"-0.991",
   547  	"2.718281828",
   548  	"3.14159265358979323e-10",
   549  	"1e100",
   550  	"1e1000",
   551  }
   552  
   553  func TestFractions(t *testing.T) {
   554  	for _, test := range fracTests {
   555  		x := val(test)
   556  		// We don't check the actual numerator and denominator because they
   557  		// are unlikely to be 100% correct due to floatVal rounding errors.
   558  		// Instead, we compute the fraction again and compare the rounded
   559  		// result.
   560  		q := BinaryOp(Num(x), token.QUO, Denom(x))
   561  		got := q.String()
   562  		want := x.String()
   563  		if got != want {
   564  			t.Errorf("%s: got quotient %s, want %s", x, got, want)
   565  		}
   566  	}
   567  }
   568  
   569  var bytesTests = []string{
   570  	"0",
   571  	"1",
   572  	"123456789",
   573  	"123456789012345678901234567890123456789012345678901234567890",
   574  }
   575  
   576  func TestBytes(t *testing.T) {
   577  	for _, test := range bytesTests {
   578  		x := val(test)
   579  		bytes := Bytes(x)
   580  
   581  		// special case 0
   582  		if Sign(x) == 0 && len(bytes) != 0 {
   583  			t.Errorf("%s: got %v; want empty byte slice", test, bytes)
   584  		}
   585  
   586  		if n := len(bytes); n > 0 && bytes[n-1] == 0 {
   587  			t.Errorf("%s: got %v; want no leading 0 byte", test, bytes)
   588  		}
   589  
   590  		if got := MakeFromBytes(bytes); !eql(got, x) {
   591  			t.Errorf("%s: got %s; want %s (bytes = %v)", test, got, x, bytes)
   592  		}
   593  	}
   594  }
   595  
   596  func TestUnknown(t *testing.T) {
   597  	u := MakeUnknown()
   598  	var values = []Value{
   599  		u,
   600  		MakeBool(false), // token.ADD ok below, operation is never considered
   601  		MakeString(""),
   602  		MakeInt64(1),
   603  		MakeFromLiteral("''", token.CHAR, 0),
   604  		MakeFromLiteral("-1234567890123456789012345678901234567890", token.INT, 0),
   605  		MakeFloat64(1.2),
   606  		MakeImag(MakeFloat64(1.2)),
   607  	}
   608  	for _, val := range values {
   609  		x, y := val, u
   610  		for i := range [2]int{} {
   611  			if i == 1 {
   612  				x, y = y, x
   613  			}
   614  			if got := BinaryOp(x, token.ADD, y); got.Kind() != Unknown {
   615  				t.Errorf("%s + %s: got %s; want %s", x, y, got, u)
   616  			}
   617  			if got := Compare(x, token.EQL, y); got {
   618  				t.Errorf("%s == %s: got true; want false", x, y)
   619  			}
   620  		}
   621  	}
   622  }
   623  
   624  func TestMakeFloat64(t *testing.T) {
   625  	var zero float64
   626  	for _, arg := range []float64{
   627  		-math.MaxFloat32,
   628  		-10,
   629  		-0.5,
   630  		-zero,
   631  		zero,
   632  		1,
   633  		10,
   634  		123456789.87654321e-23,
   635  		1e10,
   636  		math.MaxFloat64,
   637  	} {
   638  		val := MakeFloat64(arg)
   639  		if val.Kind() != Float {
   640  			t.Errorf("%v: got kind = %d; want %d", arg, val.Kind(), Float)
   641  		}
   642  
   643  		// -0.0 is mapped to 0.0
   644  		got, exact := Float64Val(val)
   645  		if !exact || math.Float64bits(got) != math.Float64bits(arg+0) {
   646  			t.Errorf("%v: got %v (exact = %v)", arg, got, exact)
   647  		}
   648  	}
   649  
   650  	// infinity
   651  	for sign := range []int{-1, 1} {
   652  		arg := math.Inf(sign)
   653  		val := MakeFloat64(arg)
   654  		if val.Kind() != Unknown {
   655  			t.Errorf("%v: got kind = %d; want %d", arg, val.Kind(), Unknown)
   656  		}
   657  	}
   658  }
   659  
   660  type makeTestCase struct {
   661  	kind      Kind
   662  	arg, want any
   663  }
   664  
   665  func dup(k Kind, x any) makeTestCase { return makeTestCase{k, x, x} }
   666  
   667  func TestMake(t *testing.T) {
   668  	for _, test := range []makeTestCase{
   669  		{Bool, false, false},
   670  		{String, "hello", "hello"},
   671  
   672  		{Int, int64(1), int64(1)},
   673  		{Int, big.NewInt(10), int64(10)},
   674  		{Int, new(big.Int).Lsh(big.NewInt(1), 62), int64(1 << 62)},
   675  		dup(Int, new(big.Int).Lsh(big.NewInt(1), 63)),
   676  
   677  		{Float, big.NewFloat(0), floatVal0.val},
   678  		dup(Float, big.NewFloat(2.0)),
   679  		dup(Float, big.NewRat(1, 3)),
   680  	} {
   681  		val := Make(test.arg)
   682  		got := Val(val)
   683  		if val.Kind() != test.kind || got != test.want {
   684  			t.Errorf("got %v (%T, kind = %d); want %v (%T, kind = %d)",
   685  				got, got, val.Kind(), test.want, test.want, test.kind)
   686  		}
   687  	}
   688  }
   689  
   690  func BenchmarkStringAdd(b *testing.B) {
   691  	for size := 1; size <= 65536; size *= 4 {
   692  		b.Run(fmt.Sprint(size), func(b *testing.B) {
   693  			b.ReportAllocs()
   694  			n := int64(0)
   695  			for i := 0; i < b.N; i++ {
   696  				x := MakeString(strings.Repeat("x", 100))
   697  				y := x
   698  				for j := 0; j < size-1; j++ {
   699  					y = BinaryOp(y, token.ADD, x)
   700  				}
   701  				n += int64(len(StringVal(y)))
   702  			}
   703  			if n != int64(b.N)*int64(size)*100 {
   704  				b.Fatalf("bad string %d != %d", n, int64(b.N)*int64(size)*100)
   705  			}
   706  		})
   707  	}
   708  }
   709  
   710  var bitLenTests = []struct {
   711  	val  int64
   712  	want int
   713  }{
   714  	{0, 0},
   715  	{1, 1},
   716  	{-16, 5},
   717  	{1 << 61, 62},
   718  	{1 << 62, 63},
   719  	{-1 << 62, 63},
   720  	{-1 << 63, 64},
   721  }
   722  
   723  func TestBitLen(t *testing.T) {
   724  	for _, test := range bitLenTests {
   725  		if got := BitLen(MakeInt64(test.val)); got != test.want {
   726  			t.Errorf("%v: got %v, want %v", test.val, got, test.want)
   727  		}
   728  	}
   729  }
   730  

View as plain text