github.com/opentofu/opentofu@v1.7.1/internal/lang/funcs/number_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package funcs 7 8 import ( 9 "fmt" 10 "testing" 11 12 "github.com/opentofu/opentofu/internal/lang/marks" 13 "github.com/zclconf/go-cty/cty" 14 ) 15 16 func TestLog(t *testing.T) { 17 tests := []struct { 18 Num cty.Value 19 Base cty.Value 20 Want cty.Value 21 Err bool 22 }{ 23 { 24 cty.NumberFloatVal(1), 25 cty.NumberFloatVal(10), 26 cty.NumberFloatVal(0), 27 false, 28 }, 29 { 30 cty.NumberFloatVal(10), 31 cty.NumberFloatVal(10), 32 cty.NumberFloatVal(1), 33 false, 34 }, 35 36 { 37 cty.NumberFloatVal(0), 38 cty.NumberFloatVal(10), 39 cty.NegativeInfinity, 40 false, 41 }, 42 { 43 cty.NumberFloatVal(10), 44 cty.NumberFloatVal(0), 45 cty.NumberFloatVal(-0), 46 false, 47 }, 48 } 49 50 for _, test := range tests { 51 t.Run(fmt.Sprintf("log(%#v, %#v)", test.Num, test.Base), func(t *testing.T) { 52 got, err := Log(test.Num, test.Base) 53 54 if test.Err { 55 if err == nil { 56 t.Fatal("succeeded; want error") 57 } 58 return 59 } else if err != nil { 60 t.Fatalf("unexpected error: %s", err) 61 } 62 63 if !got.RawEquals(test.Want) { 64 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 65 } 66 }) 67 } 68 } 69 70 func TestPow(t *testing.T) { 71 tests := []struct { 72 Num cty.Value 73 Power cty.Value 74 Want cty.Value 75 Err bool 76 }{ 77 { 78 cty.NumberFloatVal(1), 79 cty.NumberFloatVal(0), 80 cty.NumberFloatVal(1), 81 false, 82 }, 83 { 84 cty.NumberFloatVal(1), 85 cty.NumberFloatVal(1), 86 cty.NumberFloatVal(1), 87 false, 88 }, 89 90 { 91 cty.NumberFloatVal(2), 92 cty.NumberFloatVal(0), 93 cty.NumberFloatVal(1), 94 false, 95 }, 96 { 97 cty.NumberFloatVal(2), 98 cty.NumberFloatVal(1), 99 cty.NumberFloatVal(2), 100 false, 101 }, 102 { 103 cty.NumberFloatVal(3), 104 cty.NumberFloatVal(2), 105 cty.NumberFloatVal(9), 106 false, 107 }, 108 { 109 cty.NumberFloatVal(-3), 110 cty.NumberFloatVal(2), 111 cty.NumberFloatVal(9), 112 false, 113 }, 114 { 115 cty.NumberFloatVal(2), 116 cty.NumberFloatVal(-2), 117 cty.NumberFloatVal(0.25), 118 false, 119 }, 120 { 121 cty.NumberFloatVal(0), 122 cty.NumberFloatVal(2), 123 cty.NumberFloatVal(0), 124 false, 125 }, 126 } 127 128 for _, test := range tests { 129 t.Run(fmt.Sprintf("pow(%#v, %#v)", test.Num, test.Power), func(t *testing.T) { 130 got, err := Pow(test.Num, test.Power) 131 132 if test.Err { 133 if err == nil { 134 t.Fatal("succeeded; want error") 135 } 136 return 137 } else if err != nil { 138 t.Fatalf("unexpected error: %s", err) 139 } 140 141 if !got.RawEquals(test.Want) { 142 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 143 } 144 }) 145 } 146 } 147 148 func TestSignum(t *testing.T) { 149 tests := []struct { 150 Num cty.Value 151 Want cty.Value 152 Err bool 153 }{ 154 { 155 cty.NumberFloatVal(0), 156 cty.NumberFloatVal(0), 157 false, 158 }, 159 { 160 cty.NumberFloatVal(12), 161 cty.NumberFloatVal(1), 162 false, 163 }, 164 { 165 cty.NumberFloatVal(-29), 166 cty.NumberFloatVal(-1), 167 false, 168 }, 169 } 170 171 for _, test := range tests { 172 t.Run(fmt.Sprintf("signum(%#v)", test.Num), func(t *testing.T) { 173 got, err := Signum(test.Num) 174 175 if test.Err { 176 if err == nil { 177 t.Fatal("succeeded; want error") 178 } 179 return 180 } else if err != nil { 181 t.Fatalf("unexpected error: %s", err) 182 } 183 184 if !got.RawEquals(test.Want) { 185 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 186 } 187 }) 188 } 189 } 190 191 func TestParseInt(t *testing.T) { 192 tests := []struct { 193 Num cty.Value 194 Base cty.Value 195 Want cty.Value 196 Err string 197 }{ 198 { 199 cty.StringVal("128"), 200 cty.NumberIntVal(10), 201 cty.NumberIntVal(128), 202 ``, 203 }, 204 { 205 cty.StringVal("128").Mark(marks.Sensitive), 206 cty.NumberIntVal(10), 207 cty.NumberIntVal(128).Mark(marks.Sensitive), 208 ``, 209 }, 210 { 211 cty.StringVal("128"), 212 cty.NumberIntVal(10).Mark(marks.Sensitive), 213 cty.NumberIntVal(128).Mark(marks.Sensitive), 214 ``, 215 }, 216 { 217 cty.StringVal("128").Mark(marks.Sensitive), 218 cty.NumberIntVal(10).Mark(marks.Sensitive), 219 cty.NumberIntVal(128).Mark(marks.Sensitive), 220 ``, 221 }, 222 { 223 cty.StringVal("128").Mark("boop"), 224 cty.NumberIntVal(10).Mark(marks.Sensitive), 225 cty.NumberIntVal(128).WithMarks(cty.NewValueMarks("boop", marks.Sensitive)), 226 ``, 227 }, 228 { 229 cty.StringVal("-128"), 230 cty.NumberIntVal(10), 231 cty.NumberIntVal(-128), 232 ``, 233 }, 234 { 235 cty.StringVal("00128"), 236 cty.NumberIntVal(10), 237 cty.NumberIntVal(128), 238 ``, 239 }, 240 { 241 cty.StringVal("-00128"), 242 cty.NumberIntVal(10), 243 cty.NumberIntVal(-128), 244 ``, 245 }, 246 { 247 cty.StringVal("FF00"), 248 cty.NumberIntVal(16), 249 cty.NumberIntVal(65280), 250 ``, 251 }, 252 { 253 cty.StringVal("ff00"), 254 cty.NumberIntVal(16), 255 cty.NumberIntVal(65280), 256 ``, 257 }, 258 { 259 cty.StringVal("-FF00"), 260 cty.NumberIntVal(16), 261 cty.NumberIntVal(-65280), 262 ``, 263 }, 264 { 265 cty.StringVal("00FF00"), 266 cty.NumberIntVal(16), 267 cty.NumberIntVal(65280), 268 ``, 269 }, 270 { 271 cty.StringVal("-00FF00"), 272 cty.NumberIntVal(16), 273 cty.NumberIntVal(-65280), 274 ``, 275 }, 276 { 277 cty.StringVal("1011111011101111"), 278 cty.NumberIntVal(2), 279 cty.NumberIntVal(48879), 280 ``, 281 }, 282 { 283 cty.StringVal("aA"), 284 cty.NumberIntVal(62), 285 cty.NumberIntVal(656), 286 ``, 287 }, 288 { 289 cty.StringVal("Aa"), 290 cty.NumberIntVal(62), 291 cty.NumberIntVal(2242), 292 ``, 293 }, 294 { 295 cty.StringVal("999999999999999999999999999999999999999999999999999999999999"), 296 cty.NumberIntVal(10), 297 cty.MustParseNumberVal("999999999999999999999999999999999999999999999999999999999999"), 298 ``, 299 }, 300 { 301 cty.StringVal("FF"), 302 cty.NumberIntVal(10), 303 cty.UnknownVal(cty.Number), 304 `cannot parse "FF" as a base 10 integer`, 305 }, 306 { 307 cty.StringVal("FF").Mark(marks.Sensitive), 308 cty.NumberIntVal(10), 309 cty.UnknownVal(cty.Number), 310 `cannot parse (sensitive value) as a base 10 integer`, 311 }, 312 { 313 cty.StringVal("FF").Mark(marks.Sensitive), 314 cty.NumberIntVal(10).Mark(marks.Sensitive), 315 cty.UnknownVal(cty.Number), 316 `cannot parse (sensitive value) as a base (sensitive value) integer`, 317 }, 318 { 319 cty.StringVal("00FF"), 320 cty.NumberIntVal(10), 321 cty.UnknownVal(cty.Number), 322 `cannot parse "00FF" as a base 10 integer`, 323 }, 324 { 325 cty.StringVal("-00FF"), 326 cty.NumberIntVal(10), 327 cty.UnknownVal(cty.Number), 328 `cannot parse "-00FF" as a base 10 integer`, 329 }, 330 { 331 cty.NumberIntVal(2), 332 cty.NumberIntVal(10), 333 cty.UnknownVal(cty.Number), 334 `first argument must be a string, not number`, 335 }, 336 { 337 cty.StringVal("1"), 338 cty.NumberIntVal(63), 339 cty.UnknownVal(cty.Number), 340 `base must be a whole number between 2 and 62 inclusive`, 341 }, 342 { 343 cty.StringVal("1"), 344 cty.NumberIntVal(-1), 345 cty.UnknownVal(cty.Number), 346 `base must be a whole number between 2 and 62 inclusive`, 347 }, 348 { 349 cty.StringVal("1"), 350 cty.NumberIntVal(1), 351 cty.UnknownVal(cty.Number), 352 `base must be a whole number between 2 and 62 inclusive`, 353 }, 354 { 355 cty.StringVal("1"), 356 cty.NumberIntVal(0), 357 cty.UnknownVal(cty.Number), 358 `base must be a whole number between 2 and 62 inclusive`, 359 }, 360 { 361 cty.StringVal("1.2"), 362 cty.NumberIntVal(10), 363 cty.UnknownVal(cty.Number), 364 `cannot parse "1.2" as a base 10 integer`, 365 }, 366 } 367 368 for _, test := range tests { 369 t.Run(fmt.Sprintf("parseint(%#v, %#v)", test.Num, test.Base), func(t *testing.T) { 370 got, err := ParseInt(test.Num, test.Base) 371 372 if test.Err != "" { 373 if err == nil { 374 t.Fatal("succeeded; want error") 375 } 376 if got, want := err.Error(), test.Err; got != want { 377 t.Errorf("wrong error\ngot: %s\nwant: %s", got, want) 378 } 379 return 380 } else if err != nil { 381 t.Fatalf("unexpected error: %s", err) 382 } 383 384 if !got.RawEquals(test.Want) { 385 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 386 } 387 }) 388 } 389 }