golang.org/x/tools@v0.21.0/internal/refactor/inline/falcon_test.go (about)

     1  // Copyright 2023 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 inline_test
     6  
     7  import "testing"
     8  
     9  // Testcases mostly come in pairs, of a success and a failure
    10  // to substitute based on specific constant argument values.
    11  
    12  func TestFalconStringIndex(t *testing.T) {
    13  	runTests(t, []testcase{
    14  		{
    15  			"Non-negative string index.",
    16  			`func f(i int) byte { return s[i] }; var s string`,
    17  			`func _() { f(0) }`,
    18  			`func _() { _ = s[0] }`,
    19  		},
    20  		{
    21  			"Negative string index.",
    22  			`func f(i int) byte { return s[i] }; var s string`,
    23  			`func _() { f(-1) }`,
    24  			`func _() {
    25  	var i int = -1
    26  	_ = s[i]
    27  }`,
    28  		},
    29  		{
    30  			"String index in range.",
    31  			`func f(s string, i int) byte { return s[i] }`,
    32  			`func _() { f("-", 0) }`,
    33  			`func _() { _ = "-"[0] }`,
    34  		},
    35  		{
    36  			"String index out of range.",
    37  			`func f(s string, i int) byte { return s[i] }`,
    38  			`func _() { f("-", 1) }`,
    39  			`func _() {
    40  	var (
    41  		s string = "-"
    42  		i int    = 1
    43  	)
    44  	_ = s[i]
    45  }`,
    46  		},
    47  		{
    48  			"Remove known prefix (OK)",
    49  			`func f(s, prefix string) string { return s[:len(prefix)] }`,
    50  			`func _() { f("", "") }`,
    51  			`func _() { _ = ""[:len("")] }`,
    52  		},
    53  		{
    54  			"Remove not-a-prefix (out of range)",
    55  			`func f(s, prefix string) string { return s[:len(prefix)] }`,
    56  			`func _() { f("", "pre") }`,
    57  			`func _() {
    58  	var s, prefix string = "", "pre"
    59  	_ = s[:len(prefix)]
    60  }`,
    61  		},
    62  	})
    63  }
    64  
    65  func TestFalconSliceIndices(t *testing.T) {
    66  	runTests(t, []testcase{
    67  		{
    68  			"Monotonic (0<=i<=j) slice indices (len unknown).",
    69  			`func f(i, j int) []int { return s[i:j] }; var s []int`,
    70  			`func _() { f(0, 1) }`,
    71  			`func _() { _ = s[0:1] }`,
    72  		},
    73  		{
    74  			"Non-monotonic slice indices (len unknown).",
    75  			`func f(i, j int) []int { return s[i:j] }; var s []int`,
    76  			`func _() { f(1, 0) }`,
    77  			`func _() {
    78  	var i, j int = 1, 0
    79  	_ = s[i:j]
    80  }`,
    81  		},
    82  		{
    83  			"Negative slice index.",
    84  			`func f(i, j int) []int { return s[i:j] }; var s []int`,
    85  			`func _() { f(-1, 1) }`,
    86  			`func _() {
    87  	var i, j int = -1, 1
    88  	_ = s[i:j]
    89  }`,
    90  		},
    91  	})
    92  }
    93  
    94  func TestFalconMapKeys(t *testing.T) {
    95  	runTests(t, []testcase{
    96  		{
    97  			"Unique map keys (int)",
    98  			`func f(x int) { _ = map[int]bool{1: true, x: true} }`,
    99  			`func _() { f(2) }`,
   100  			`func _() { _ = map[int]bool{1: true, 2: true} }`,
   101  		},
   102  		{
   103  			"Duplicate map keys (int)",
   104  			`func f(x int) { _ = map[int]bool{1: true, x: true} }`,
   105  			`func _() { f(1) }`,
   106  			`func _() {
   107  	var x int = 1
   108  	_ = map[int]bool{1: true, x: true}
   109  }`,
   110  		},
   111  		{
   112  			"Unique map keys (varied built-in types)",
   113  			`func f(x int16) { _ = map[any]bool{1: true, x: true} }`,
   114  			`func _() { f(2) }`,
   115  			`func _() { _ = map[any]bool{1: true, int16(2): true} }`,
   116  		},
   117  		{
   118  			"Duplicate map keys (varied built-in types)",
   119  			`func f(x int16) { _ = map[any]bool{1: true, x: true} }`,
   120  			`func _() { f(1) }`,
   121  			`func _() { _ = map[any]bool{1: true, int16(1): true} }`,
   122  		},
   123  		{
   124  			"Unique map keys (varied user-defined types)",
   125  			`func f(x myint) { _ = map[any]bool{1: true, x: true} }; type myint int`,
   126  			`func _() { f(2) }`,
   127  			`func _() { _ = map[any]bool{1: true, myint(2): true} }`,
   128  		},
   129  		{
   130  			"Duplicate map keys (varied user-defined types)",
   131  			`func f(x myint, y myint2) { _ = map[any]bool{x: true, y: true} }; type (myint int; myint2 int)`,
   132  			`func _() { f(1, 1) }`,
   133  			`func _() {
   134  	var (
   135  		x myint  = 1
   136  		y myint2 = 1
   137  	)
   138  	_ = map[any]bool{x: true, y: true}
   139  }`,
   140  		},
   141  		{
   142  			"Duplicate map keys (user-defined alias to built-in)",
   143  			`func f(x myint, y int) { _ = map[any]bool{x: true, y: true} }; type myint = int`,
   144  			`func _() { f(1, 1) }`,
   145  			`func _() {
   146  	var (
   147  		x myint = 1
   148  		y int   = 1
   149  	)
   150  	_ = map[any]bool{x: true, y: true}
   151  }`,
   152  		},
   153  	})
   154  }
   155  
   156  func TestFalconSwitchCases(t *testing.T) {
   157  	runTests(t, []testcase{
   158  		{
   159  			"Unique switch cases (int).",
   160  			`func f(x int) { switch 0 { case x: case 1: } }`,
   161  			`func _() { f(2) }`,
   162  			`func _() {
   163  	switch 0 {
   164  	case 2:
   165  	case 1:
   166  	}
   167  }`,
   168  		},
   169  		{
   170  			"Duplicate switch cases (int).",
   171  			`func f(x int) { switch 0 { case x: case 1: } }`,
   172  			`func _() { f(1) }`,
   173  			`func _() {
   174  	var x int = 1
   175  	switch 0 {
   176  	case x:
   177  	case 1:
   178  	}
   179  }`,
   180  		},
   181  		{
   182  			"Unique switch cases (varied built-in types).",
   183  			`func f(x int) { switch any(nil) { case x: case int16(1): } }`,
   184  			`func _() { f(2) }`,
   185  			`func _() {
   186  	switch any(nil) {
   187  	case 2:
   188  	case int16(1):
   189  	}
   190  }`,
   191  		},
   192  		{
   193  			"Duplicate switch cases (varied built-in types).",
   194  			`func f(x int) { switch any(nil) { case x: case int16(1): } }`,
   195  			`func _() { f(1) }`,
   196  			`func _() {
   197  	switch any(nil) {
   198  	case 1:
   199  	case int16(1):
   200  	}
   201  }`,
   202  		},
   203  	})
   204  }
   205  
   206  func TestFalconDivision(t *testing.T) {
   207  	runTests(t, []testcase{
   208  		{
   209  			"Division by two.",
   210  			`func f(x, y int) int { return x / y }`,
   211  			`func _() { f(1, 2) }`,
   212  			`func _() { _ = 1 / 2 }`,
   213  		},
   214  		{
   215  			"Division by zero.",
   216  			`func f(x, y int) int { return x / y }`,
   217  			`func _() { f(1, 0) }`,
   218  			`func _() {
   219  	var x, y int = 1, 0
   220  	_ = x / y
   221  }`,
   222  		},
   223  		{
   224  			"Division by two (statement).",
   225  			`func f(x, y int) { x /= y }`,
   226  			`func _() { f(1, 2) }`,
   227  			`func _() {
   228  	var x int = 1
   229  	x /= 2
   230  }`,
   231  		},
   232  		{
   233  			"Division by zero (statement).",
   234  			`func f(x, y int) { x /= y }`,
   235  			`func _() { f(1, 0) }`,
   236  			`func _() {
   237  	var x, y int = 1, 0
   238  	x /= y
   239  }`,
   240  		},
   241  		{
   242  			"Division of minint by two (ok).",
   243  			`func f(x, y int32) { _ = x / y }`,
   244  			`func _() { f(-0x80000000, 2) }`,
   245  			`func _() { _ = int32(-0x80000000) / int32(2) }`,
   246  		},
   247  		{
   248  			"Division of minint by -1 (overflow).",
   249  			`func f(x, y int32) { _ = x / y }`,
   250  			`func _() { f(-0x80000000, -1) }`,
   251  			`func _() {
   252  	var x, y int32 = -0x80000000, -1
   253  	_ = x / y
   254  }`,
   255  		},
   256  	})
   257  }
   258  
   259  func TestFalconMinusMinInt(t *testing.T) {
   260  	runTests(t, []testcase{
   261  		{
   262  			"Negation of maxint.",
   263  			`func f(x int32) int32 { return -x }`,
   264  			`func _() { f(0x7fffffff) }`,
   265  			`func _() { _ = -int32(0x7fffffff) }`,
   266  		},
   267  		{
   268  			"Negation of minint.",
   269  			`func f(x int32) int32 { return -x }`,
   270  			`func _() { f(-0x80000000) }`,
   271  			`func _() {
   272  	var x int32 = -0x80000000
   273  	_ = -x
   274  }`,
   275  		},
   276  	})
   277  }
   278  
   279  func TestFalconArithmeticOverflow(t *testing.T) {
   280  	runTests(t, []testcase{
   281  		{
   282  			"Addition without overflow.",
   283  			`func f(x, y int32) int32 { return x + y }`,
   284  			`func _() { f(100, 200) }`,
   285  			`func _() { _ = int32(100) + int32(200) }`,
   286  		},
   287  		{
   288  			"Addition with overflow.",
   289  			`func f(x, y int32) int32 { return x + y }`,
   290  			`func _() { f(1<<30, 1<<30) }`,
   291  			`func _() {
   292  	var x, y int32 = 1 << 30, 1 << 30
   293  	_ = x + y
   294  }`,
   295  		},
   296  		{
   297  			"Conversion in range.",
   298  			`func f(x int) int8 { return int8(x) }`,
   299  			`func _() { f(123) }`,
   300  			`func _() { _ = int8(123) }`,
   301  		},
   302  		{
   303  			"Conversion out of range.",
   304  			`func f(x int) int8 { return int8(x) }`,
   305  			`func _() { f(456) }`,
   306  			`func _() {
   307  	var x int = 456
   308  	_ = int8(x)
   309  }`,
   310  		},
   311  	})
   312  }
   313  
   314  func TestFalconComplex(t *testing.T) {
   315  	runTests(t, []testcase{
   316  		{
   317  			"Complex arithmetic (good).",
   318  			`func f(re, im float64, z complex128) byte { return "x"[int(real(complex(re, im)*complex(re, -im)-z))] }`,
   319  			`func _() { f(1, 2, 5+0i) }`,
   320  			`func _() { _ = "x"[int(real(complex(1, 2)*complex(1, -2)-(5+0i)))] }`,
   321  		},
   322  		{
   323  			"Complex arithmetic (bad).",
   324  			`func f(re, im float64, z complex128) byte { return "x"[int(real(complex(re, im)*complex(re, -im)-z))] }`,
   325  			`func _() { f(1, 3, 5+0i) }`,
   326  			`func _() {
   327  	var (
   328  		re, im float64    = 1, 3
   329  		z      complex128 = 5 + 0i
   330  	)
   331  	_ = "x"[int(real(complex(re, im)*complex(re, -im)-z))]
   332  }`,
   333  		},
   334  	})
   335  }
   336  func TestFalconMisc(t *testing.T) {
   337  	runTests(t, []testcase{
   338  		{
   339  			"Compound constant expression (good).",
   340  			`func f(x, y string, i, j int) byte { return x[i*len(y)+j] }`,
   341  			`func _() { f("abc", "xy", 2, -3) }`,
   342  			`func _() { _ = "abc"[2*len("xy")+-3] }`,
   343  		},
   344  		{
   345  			"Compound constant expression (index out of range).",
   346  			`func f(x, y string, i, j int) byte { return x[i*len(y)+j] }`,
   347  			`func _() { f("abc", "xy", 4, -3) }`,
   348  			`func _() {
   349  	var (
   350  		x, y string = "abc", "xy"
   351  		i, j int    = 4, -3
   352  	)
   353  	_ = x[i*len(y)+j]
   354  }`,
   355  		},
   356  		{
   357  			"Constraints within nested functions (good).",
   358  			`func f(x int) { _ = func() { _ = [1]int{}[x] } }`,
   359  			`func _() { f(0) }`,
   360  			`func _() { _ = func() { _ = [1]int{}[0] } }`,
   361  		},
   362  		{
   363  			"Constraints within nested functions (bad).",
   364  			`func f(x int) { _ = func() { _ = [1]int{}[x] } }`,
   365  			`func _() { f(1) }`,
   366  			`func _() {
   367  	var x int = 1
   368  	_ = func() { _ = [1]int{}[x] }
   369  }`,
   370  		},
   371  		{
   372  			"Falcon violation rejects only the constant arguments (x, z).",
   373  			`func f(x, y, z string) string { return x[:2] + y + z[:2] }; var b string`,
   374  			`func _() { f("a", b, "c") }`,
   375  			`func _() {
   376  	var x, z string = "a", "c"
   377  	_ = x[:2] + b + z[:2]
   378  }`,
   379  		},
   380  	})
   381  }