...

Source file src/go/constant/value_test.go

Documentation: go/constant

		 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 i := strings.Index(a[1], "/"); i >= 0 && kind == token.FLOAT {
	 147  				n := MakeFromLiteral(a[1][:i], token.INT, 0)
	 148  				d := MakeFromLiteral(a[1][i+1:], 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 i := strings.IndexByte(lit, '/'); i >= 0 {
	 458  		// assume fraction
	 459  		a := MakeFromLiteral(lit[:i], token.INT, 0)
	 460  		b := MakeFromLiteral(lit[i+1:], 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 interface{}
	 663  }
	 664  
	 665  func dup(k Kind, x interface{}) 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