objects_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. package tengo_test
  2. import (
  3. "testing"
  4. "github.com/d5/tengo/v2"
  5. "github.com/d5/tengo/v2/require"
  6. "github.com/d5/tengo/v2/token"
  7. )
  8. func TestObject_TypeName(t *testing.T) {
  9. var o tengo.Object = &tengo.Int{}
  10. require.Equal(t, "int", o.TypeName())
  11. o = &tengo.Float{}
  12. require.Equal(t, "float", o.TypeName())
  13. o = &tengo.Char{}
  14. require.Equal(t, "char", o.TypeName())
  15. o = &tengo.String{}
  16. require.Equal(t, "string", o.TypeName())
  17. o = &tengo.Bool{}
  18. require.Equal(t, "bool", o.TypeName())
  19. o = &tengo.Array{}
  20. require.Equal(t, "array", o.TypeName())
  21. o = &tengo.Map{}
  22. require.Equal(t, "map", o.TypeName())
  23. o = &tengo.ArrayIterator{}
  24. require.Equal(t, "array-iterator", o.TypeName())
  25. o = &tengo.StringIterator{}
  26. require.Equal(t, "string-iterator", o.TypeName())
  27. o = &tengo.MapIterator{}
  28. require.Equal(t, "map-iterator", o.TypeName())
  29. o = &tengo.BuiltinFunction{Name: "fn"}
  30. require.Equal(t, "builtin-function:fn", o.TypeName())
  31. o = &tengo.UserFunction{Name: "fn"}
  32. require.Equal(t, "user-function:fn", o.TypeName())
  33. o = &tengo.CompiledFunction{}
  34. require.Equal(t, "compiled-function", o.TypeName())
  35. o = &tengo.Undefined{}
  36. require.Equal(t, "undefined", o.TypeName())
  37. o = &tengo.Error{}
  38. require.Equal(t, "error", o.TypeName())
  39. o = &tengo.Bytes{}
  40. require.Equal(t, "bytes", o.TypeName())
  41. }
  42. func TestObject_IsFalsy(t *testing.T) {
  43. var o tengo.Object = &tengo.Int{Value: 0}
  44. require.True(t, o.IsFalsy())
  45. o = &tengo.Int{Value: 1}
  46. require.False(t, o.IsFalsy())
  47. o = &tengo.Float{Value: 0}
  48. require.False(t, o.IsFalsy())
  49. o = &tengo.Float{Value: 1}
  50. require.False(t, o.IsFalsy())
  51. o = &tengo.Char{Value: ' '}
  52. require.False(t, o.IsFalsy())
  53. o = &tengo.Char{Value: 'T'}
  54. require.False(t, o.IsFalsy())
  55. o = &tengo.String{Value: ""}
  56. require.True(t, o.IsFalsy())
  57. o = &tengo.String{Value: " "}
  58. require.False(t, o.IsFalsy())
  59. o = &tengo.Array{Value: nil}
  60. require.True(t, o.IsFalsy())
  61. o = &tengo.Array{Value: []tengo.Object{nil}} // nil is not valid but still count as 1 element
  62. require.False(t, o.IsFalsy())
  63. o = &tengo.Map{Value: nil}
  64. require.True(t, o.IsFalsy())
  65. o = &tengo.Map{Value: map[string]tengo.Object{"a": nil}} // nil is not valid but still count as 1 element
  66. require.False(t, o.IsFalsy())
  67. o = &tengo.StringIterator{}
  68. require.True(t, o.IsFalsy())
  69. o = &tengo.ArrayIterator{}
  70. require.True(t, o.IsFalsy())
  71. o = &tengo.MapIterator{}
  72. require.True(t, o.IsFalsy())
  73. o = &tengo.BuiltinFunction{}
  74. require.False(t, o.IsFalsy())
  75. o = &tengo.CompiledFunction{}
  76. require.False(t, o.IsFalsy())
  77. o = &tengo.Undefined{}
  78. require.True(t, o.IsFalsy())
  79. o = &tengo.Error{}
  80. require.True(t, o.IsFalsy())
  81. o = &tengo.Bytes{}
  82. require.True(t, o.IsFalsy())
  83. o = &tengo.Bytes{Value: []byte{1, 2}}
  84. require.False(t, o.IsFalsy())
  85. }
  86. func TestObject_String(t *testing.T) {
  87. var o tengo.Object = &tengo.Int{Value: 0}
  88. require.Equal(t, "0", o.String())
  89. o = &tengo.Int{Value: 1}
  90. require.Equal(t, "1", o.String())
  91. o = &tengo.Float{Value: 0}
  92. require.Equal(t, "0", o.String())
  93. o = &tengo.Float{Value: 1}
  94. require.Equal(t, "1", o.String())
  95. o = &tengo.Char{Value: ' '}
  96. require.Equal(t, " ", o.String())
  97. o = &tengo.Char{Value: 'T'}
  98. require.Equal(t, "T", o.String())
  99. o = &tengo.String{Value: ""}
  100. require.Equal(t, `""`, o.String())
  101. o = &tengo.String{Value: " "}
  102. require.Equal(t, `" "`, o.String())
  103. o = &tengo.Array{Value: nil}
  104. require.Equal(t, "[]", o.String())
  105. o = &tengo.Map{Value: nil}
  106. require.Equal(t, "{}", o.String())
  107. o = &tengo.Error{Value: nil}
  108. require.Equal(t, "error", o.String())
  109. o = &tengo.Error{Value: &tengo.String{Value: "error 1"}}
  110. require.Equal(t, `error: "error 1"`, o.String())
  111. o = &tengo.StringIterator{}
  112. require.Equal(t, "<string-iterator>", o.String())
  113. o = &tengo.ArrayIterator{}
  114. require.Equal(t, "<array-iterator>", o.String())
  115. o = &tengo.MapIterator{}
  116. require.Equal(t, "<map-iterator>", o.String())
  117. o = &tengo.Undefined{}
  118. require.Equal(t, "<undefined>", o.String())
  119. o = &tengo.Bytes{}
  120. require.Equal(t, "", o.String())
  121. o = &tengo.Bytes{Value: []byte("foo")}
  122. require.Equal(t, "foo", o.String())
  123. }
  124. func TestObject_BinaryOp(t *testing.T) {
  125. var o tengo.Object = &tengo.Char{}
  126. _, err := o.BinaryOp(token.Add, tengo.UndefinedValue)
  127. require.Error(t, err)
  128. o = &tengo.Bool{}
  129. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  130. require.Error(t, err)
  131. o = &tengo.Map{}
  132. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  133. require.Error(t, err)
  134. o = &tengo.ArrayIterator{}
  135. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  136. require.Error(t, err)
  137. o = &tengo.StringIterator{}
  138. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  139. require.Error(t, err)
  140. o = &tengo.MapIterator{}
  141. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  142. require.Error(t, err)
  143. o = &tengo.BuiltinFunction{}
  144. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  145. require.Error(t, err)
  146. o = &tengo.CompiledFunction{}
  147. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  148. require.Error(t, err)
  149. o = &tengo.Undefined{}
  150. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  151. require.Error(t, err)
  152. o = &tengo.Error{}
  153. _, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
  154. require.Error(t, err)
  155. }
  156. func TestArray_BinaryOp(t *testing.T) {
  157. testBinaryOp(t, &tengo.Array{Value: nil}, token.Add,
  158. &tengo.Array{Value: nil}, &tengo.Array{Value: nil})
  159. testBinaryOp(t, &tengo.Array{Value: nil}, token.Add,
  160. &tengo.Array{Value: []tengo.Object{}}, &tengo.Array{Value: nil})
  161. testBinaryOp(t, &tengo.Array{Value: []tengo.Object{}}, token.Add,
  162. &tengo.Array{Value: nil}, &tengo.Array{Value: []tengo.Object{}})
  163. testBinaryOp(t, &tengo.Array{Value: []tengo.Object{}}, token.Add,
  164. &tengo.Array{Value: []tengo.Object{}},
  165. &tengo.Array{Value: []tengo.Object{}})
  166. testBinaryOp(t, &tengo.Array{Value: nil}, token.Add,
  167. &tengo.Array{Value: []tengo.Object{
  168. &tengo.Int{Value: 1},
  169. }}, &tengo.Array{Value: []tengo.Object{
  170. &tengo.Int{Value: 1},
  171. }})
  172. testBinaryOp(t, &tengo.Array{Value: nil}, token.Add,
  173. &tengo.Array{Value: []tengo.Object{
  174. &tengo.Int{Value: 1},
  175. &tengo.Int{Value: 2},
  176. &tengo.Int{Value: 3},
  177. }}, &tengo.Array{Value: []tengo.Object{
  178. &tengo.Int{Value: 1},
  179. &tengo.Int{Value: 2},
  180. &tengo.Int{Value: 3},
  181. }})
  182. testBinaryOp(t, &tengo.Array{Value: []tengo.Object{
  183. &tengo.Int{Value: 1},
  184. &tengo.Int{Value: 2},
  185. &tengo.Int{Value: 3},
  186. }}, token.Add, &tengo.Array{Value: nil},
  187. &tengo.Array{Value: []tengo.Object{
  188. &tengo.Int{Value: 1},
  189. &tengo.Int{Value: 2},
  190. &tengo.Int{Value: 3},
  191. }})
  192. testBinaryOp(t, &tengo.Array{Value: []tengo.Object{
  193. &tengo.Int{Value: 1},
  194. &tengo.Int{Value: 2},
  195. &tengo.Int{Value: 3},
  196. }}, token.Add, &tengo.Array{Value: []tengo.Object{
  197. &tengo.Int{Value: 4},
  198. &tengo.Int{Value: 5},
  199. &tengo.Int{Value: 6},
  200. }}, &tengo.Array{Value: []tengo.Object{
  201. &tengo.Int{Value: 1},
  202. &tengo.Int{Value: 2},
  203. &tengo.Int{Value: 3},
  204. &tengo.Int{Value: 4},
  205. &tengo.Int{Value: 5},
  206. &tengo.Int{Value: 6},
  207. }})
  208. }
  209. func TestError_Equals(t *testing.T) {
  210. err1 := &tengo.Error{Value: &tengo.String{Value: "some error"}}
  211. err2 := err1
  212. require.True(t, err1.Equals(err2))
  213. require.True(t, err2.Equals(err1))
  214. err2 = &tengo.Error{Value: &tengo.String{Value: "some error"}}
  215. require.False(t, err1.Equals(err2))
  216. require.False(t, err2.Equals(err1))
  217. }
  218. func TestFloat_BinaryOp(t *testing.T) {
  219. // float + float
  220. for l := float64(-2); l <= 2.1; l += 0.4 {
  221. for r := float64(-2); r <= 2.1; r += 0.4 {
  222. testBinaryOp(t, &tengo.Float{Value: l}, token.Add,
  223. &tengo.Float{Value: r}, &tengo.Float{Value: l + r})
  224. }
  225. }
  226. // float - float
  227. for l := float64(-2); l <= 2.1; l += 0.4 {
  228. for r := float64(-2); r <= 2.1; r += 0.4 {
  229. testBinaryOp(t, &tengo.Float{Value: l}, token.Sub,
  230. &tengo.Float{Value: r}, &tengo.Float{Value: l - r})
  231. }
  232. }
  233. // float * float
  234. for l := float64(-2); l <= 2.1; l += 0.4 {
  235. for r := float64(-2); r <= 2.1; r += 0.4 {
  236. testBinaryOp(t, &tengo.Float{Value: l}, token.Mul,
  237. &tengo.Float{Value: r}, &tengo.Float{Value: l * r})
  238. }
  239. }
  240. // float / float
  241. for l := float64(-2); l <= 2.1; l += 0.4 {
  242. for r := float64(-2); r <= 2.1; r += 0.4 {
  243. if r != 0 {
  244. testBinaryOp(t, &tengo.Float{Value: l}, token.Quo,
  245. &tengo.Float{Value: r}, &tengo.Float{Value: l / r})
  246. }
  247. }
  248. }
  249. // float < float
  250. for l := float64(-2); l <= 2.1; l += 0.4 {
  251. for r := float64(-2); r <= 2.1; r += 0.4 {
  252. testBinaryOp(t, &tengo.Float{Value: l}, token.Less,
  253. &tengo.Float{Value: r}, boolValue(l < r))
  254. }
  255. }
  256. // float > float
  257. for l := float64(-2); l <= 2.1; l += 0.4 {
  258. for r := float64(-2); r <= 2.1; r += 0.4 {
  259. testBinaryOp(t, &tengo.Float{Value: l}, token.Greater,
  260. &tengo.Float{Value: r}, boolValue(l > r))
  261. }
  262. }
  263. // float <= float
  264. for l := float64(-2); l <= 2.1; l += 0.4 {
  265. for r := float64(-2); r <= 2.1; r += 0.4 {
  266. testBinaryOp(t, &tengo.Float{Value: l}, token.LessEq,
  267. &tengo.Float{Value: r}, boolValue(l <= r))
  268. }
  269. }
  270. // float >= float
  271. for l := float64(-2); l <= 2.1; l += 0.4 {
  272. for r := float64(-2); r <= 2.1; r += 0.4 {
  273. testBinaryOp(t, &tengo.Float{Value: l}, token.GreaterEq,
  274. &tengo.Float{Value: r}, boolValue(l >= r))
  275. }
  276. }
  277. // float + int
  278. for l := float64(-2); l <= 2.1; l += 0.4 {
  279. for r := int64(-2); r <= 2; r++ {
  280. testBinaryOp(t, &tengo.Float{Value: l}, token.Add,
  281. &tengo.Int{Value: r}, &tengo.Float{Value: l + float64(r)})
  282. }
  283. }
  284. // float - int
  285. for l := float64(-2); l <= 2.1; l += 0.4 {
  286. for r := int64(-2); r <= 2; r++ {
  287. testBinaryOp(t, &tengo.Float{Value: l}, token.Sub,
  288. &tengo.Int{Value: r}, &tengo.Float{Value: l - float64(r)})
  289. }
  290. }
  291. // float * int
  292. for l := float64(-2); l <= 2.1; l += 0.4 {
  293. for r := int64(-2); r <= 2; r++ {
  294. testBinaryOp(t, &tengo.Float{Value: l}, token.Mul,
  295. &tengo.Int{Value: r}, &tengo.Float{Value: l * float64(r)})
  296. }
  297. }
  298. // float / int
  299. for l := float64(-2); l <= 2.1; l += 0.4 {
  300. for r := int64(-2); r <= 2; r++ {
  301. if r != 0 {
  302. testBinaryOp(t, &tengo.Float{Value: l}, token.Quo,
  303. &tengo.Int{Value: r},
  304. &tengo.Float{Value: l / float64(r)})
  305. }
  306. }
  307. }
  308. // float < int
  309. for l := float64(-2); l <= 2.1; l += 0.4 {
  310. for r := int64(-2); r <= 2; r++ {
  311. testBinaryOp(t, &tengo.Float{Value: l}, token.Less,
  312. &tengo.Int{Value: r}, boolValue(l < float64(r)))
  313. }
  314. }
  315. // float > int
  316. for l := float64(-2); l <= 2.1; l += 0.4 {
  317. for r := int64(-2); r <= 2; r++ {
  318. testBinaryOp(t, &tengo.Float{Value: l}, token.Greater,
  319. &tengo.Int{Value: r}, boolValue(l > float64(r)))
  320. }
  321. }
  322. // float <= int
  323. for l := float64(-2); l <= 2.1; l += 0.4 {
  324. for r := int64(-2); r <= 2; r++ {
  325. testBinaryOp(t, &tengo.Float{Value: l}, token.LessEq,
  326. &tengo.Int{Value: r}, boolValue(l <= float64(r)))
  327. }
  328. }
  329. // float >= int
  330. for l := float64(-2); l <= 2.1; l += 0.4 {
  331. for r := int64(-2); r <= 2; r++ {
  332. testBinaryOp(t, &tengo.Float{Value: l}, token.GreaterEq,
  333. &tengo.Int{Value: r}, boolValue(l >= float64(r)))
  334. }
  335. }
  336. }
  337. func TestInt_BinaryOp(t *testing.T) {
  338. // int + int
  339. for l := int64(-2); l <= 2; l++ {
  340. for r := int64(-2); r <= 2; r++ {
  341. testBinaryOp(t, &tengo.Int{Value: l}, token.Add,
  342. &tengo.Int{Value: r}, &tengo.Int{Value: l + r})
  343. }
  344. }
  345. // int - int
  346. for l := int64(-2); l <= 2; l++ {
  347. for r := int64(-2); r <= 2; r++ {
  348. testBinaryOp(t, &tengo.Int{Value: l}, token.Sub,
  349. &tengo.Int{Value: r}, &tengo.Int{Value: l - r})
  350. }
  351. }
  352. // int * int
  353. for l := int64(-2); l <= 2; l++ {
  354. for r := int64(-2); r <= 2; r++ {
  355. testBinaryOp(t, &tengo.Int{Value: l}, token.Mul,
  356. &tengo.Int{Value: r}, &tengo.Int{Value: l * r})
  357. }
  358. }
  359. // int / int
  360. for l := int64(-2); l <= 2; l++ {
  361. for r := int64(-2); r <= 2; r++ {
  362. if r != 0 {
  363. testBinaryOp(t, &tengo.Int{Value: l}, token.Quo,
  364. &tengo.Int{Value: r}, &tengo.Int{Value: l / r})
  365. }
  366. }
  367. }
  368. // int % int
  369. for l := int64(-4); l <= 4; l++ {
  370. for r := -int64(-4); r <= 4; r++ {
  371. if r == 0 {
  372. testBinaryOp(t, &tengo.Int{Value: l}, token.Rem,
  373. &tengo.Int{Value: r}, &tengo.Int{Value: l % r})
  374. }
  375. }
  376. }
  377. // int & int
  378. testBinaryOp(t,
  379. &tengo.Int{Value: 0}, token.And, &tengo.Int{Value: 0},
  380. &tengo.Int{Value: int64(0)})
  381. testBinaryOp(t,
  382. &tengo.Int{Value: 1}, token.And, &tengo.Int{Value: 0},
  383. &tengo.Int{Value: int64(1) & int64(0)})
  384. testBinaryOp(t,
  385. &tengo.Int{Value: 0}, token.And, &tengo.Int{Value: 1},
  386. &tengo.Int{Value: int64(0) & int64(1)})
  387. testBinaryOp(t,
  388. &tengo.Int{Value: 1}, token.And, &tengo.Int{Value: 1},
  389. &tengo.Int{Value: int64(1)})
  390. testBinaryOp(t,
  391. &tengo.Int{Value: 0}, token.And, &tengo.Int{Value: int64(0xffffffff)},
  392. &tengo.Int{Value: int64(0) & int64(0xffffffff)})
  393. testBinaryOp(t,
  394. &tengo.Int{Value: 1}, token.And, &tengo.Int{Value: int64(0xffffffff)},
  395. &tengo.Int{Value: int64(1) & int64(0xffffffff)})
  396. testBinaryOp(t,
  397. &tengo.Int{Value: int64(0xffffffff)}, token.And,
  398. &tengo.Int{Value: int64(0xffffffff)},
  399. &tengo.Int{Value: int64(0xffffffff)})
  400. testBinaryOp(t,
  401. &tengo.Int{Value: 1984}, token.And,
  402. &tengo.Int{Value: int64(0xffffffff)},
  403. &tengo.Int{Value: int64(1984) & int64(0xffffffff)})
  404. testBinaryOp(t, &tengo.Int{Value: -1984}, token.And,
  405. &tengo.Int{Value: int64(0xffffffff)},
  406. &tengo.Int{Value: int64(-1984) & int64(0xffffffff)})
  407. // int | int
  408. testBinaryOp(t,
  409. &tengo.Int{Value: 0}, token.Or, &tengo.Int{Value: 0},
  410. &tengo.Int{Value: int64(0)})
  411. testBinaryOp(t,
  412. &tengo.Int{Value: 1}, token.Or, &tengo.Int{Value: 0},
  413. &tengo.Int{Value: int64(1) | int64(0)})
  414. testBinaryOp(t,
  415. &tengo.Int{Value: 0}, token.Or, &tengo.Int{Value: 1},
  416. &tengo.Int{Value: int64(0) | int64(1)})
  417. testBinaryOp(t,
  418. &tengo.Int{Value: 1}, token.Or, &tengo.Int{Value: 1},
  419. &tengo.Int{Value: int64(1)})
  420. testBinaryOp(t,
  421. &tengo.Int{Value: 0}, token.Or, &tengo.Int{Value: int64(0xffffffff)},
  422. &tengo.Int{Value: int64(0) | int64(0xffffffff)})
  423. testBinaryOp(t,
  424. &tengo.Int{Value: 1}, token.Or, &tengo.Int{Value: int64(0xffffffff)},
  425. &tengo.Int{Value: int64(1) | int64(0xffffffff)})
  426. testBinaryOp(t,
  427. &tengo.Int{Value: int64(0xffffffff)}, token.Or,
  428. &tengo.Int{Value: int64(0xffffffff)},
  429. &tengo.Int{Value: int64(0xffffffff)})
  430. testBinaryOp(t,
  431. &tengo.Int{Value: 1984}, token.Or,
  432. &tengo.Int{Value: int64(0xffffffff)},
  433. &tengo.Int{Value: int64(1984) | int64(0xffffffff)})
  434. testBinaryOp(t,
  435. &tengo.Int{Value: -1984}, token.Or,
  436. &tengo.Int{Value: int64(0xffffffff)},
  437. &tengo.Int{Value: int64(-1984) | int64(0xffffffff)})
  438. // int ^ int
  439. testBinaryOp(t,
  440. &tengo.Int{Value: 0}, token.Xor, &tengo.Int{Value: 0},
  441. &tengo.Int{Value: int64(0)})
  442. testBinaryOp(t,
  443. &tengo.Int{Value: 1}, token.Xor, &tengo.Int{Value: 0},
  444. &tengo.Int{Value: int64(1) ^ int64(0)})
  445. testBinaryOp(t,
  446. &tengo.Int{Value: 0}, token.Xor, &tengo.Int{Value: 1},
  447. &tengo.Int{Value: int64(0) ^ int64(1)})
  448. testBinaryOp(t,
  449. &tengo.Int{Value: 1}, token.Xor, &tengo.Int{Value: 1},
  450. &tengo.Int{Value: int64(0)})
  451. testBinaryOp(t,
  452. &tengo.Int{Value: 0}, token.Xor, &tengo.Int{Value: int64(0xffffffff)},
  453. &tengo.Int{Value: int64(0) ^ int64(0xffffffff)})
  454. testBinaryOp(t,
  455. &tengo.Int{Value: 1}, token.Xor, &tengo.Int{Value: int64(0xffffffff)},
  456. &tengo.Int{Value: int64(1) ^ int64(0xffffffff)})
  457. testBinaryOp(t,
  458. &tengo.Int{Value: int64(0xffffffff)}, token.Xor,
  459. &tengo.Int{Value: int64(0xffffffff)},
  460. &tengo.Int{Value: int64(0)})
  461. testBinaryOp(t,
  462. &tengo.Int{Value: 1984}, token.Xor,
  463. &tengo.Int{Value: int64(0xffffffff)},
  464. &tengo.Int{Value: int64(1984) ^ int64(0xffffffff)})
  465. testBinaryOp(t,
  466. &tengo.Int{Value: -1984}, token.Xor,
  467. &tengo.Int{Value: int64(0xffffffff)},
  468. &tengo.Int{Value: int64(-1984) ^ int64(0xffffffff)})
  469. // int &^ int
  470. testBinaryOp(t,
  471. &tengo.Int{Value: 0}, token.AndNot, &tengo.Int{Value: 0},
  472. &tengo.Int{Value: int64(0)})
  473. testBinaryOp(t,
  474. &tengo.Int{Value: 1}, token.AndNot, &tengo.Int{Value: 0},
  475. &tengo.Int{Value: int64(1) &^ int64(0)})
  476. testBinaryOp(t,
  477. &tengo.Int{Value: 0}, token.AndNot,
  478. &tengo.Int{Value: 1}, &tengo.Int{Value: int64(0) &^ int64(1)})
  479. testBinaryOp(t,
  480. &tengo.Int{Value: 1}, token.AndNot, &tengo.Int{Value: 1},
  481. &tengo.Int{Value: int64(0)})
  482. testBinaryOp(t,
  483. &tengo.Int{Value: 0}, token.AndNot,
  484. &tengo.Int{Value: int64(0xffffffff)},
  485. &tengo.Int{Value: int64(0) &^ int64(0xffffffff)})
  486. testBinaryOp(t,
  487. &tengo.Int{Value: 1}, token.AndNot,
  488. &tengo.Int{Value: int64(0xffffffff)},
  489. &tengo.Int{Value: int64(1) &^ int64(0xffffffff)})
  490. testBinaryOp(t,
  491. &tengo.Int{Value: int64(0xffffffff)}, token.AndNot,
  492. &tengo.Int{Value: int64(0xffffffff)},
  493. &tengo.Int{Value: int64(0)})
  494. testBinaryOp(t,
  495. &tengo.Int{Value: 1984}, token.AndNot,
  496. &tengo.Int{Value: int64(0xffffffff)},
  497. &tengo.Int{Value: int64(1984) &^ int64(0xffffffff)})
  498. testBinaryOp(t,
  499. &tengo.Int{Value: -1984}, token.AndNot,
  500. &tengo.Int{Value: int64(0xffffffff)},
  501. &tengo.Int{Value: int64(-1984) &^ int64(0xffffffff)})
  502. // int << int
  503. for s := int64(0); s < 64; s++ {
  504. testBinaryOp(t,
  505. &tengo.Int{Value: 0}, token.Shl, &tengo.Int{Value: s},
  506. &tengo.Int{Value: int64(0) << uint(s)})
  507. testBinaryOp(t,
  508. &tengo.Int{Value: 1}, token.Shl, &tengo.Int{Value: s},
  509. &tengo.Int{Value: int64(1) << uint(s)})
  510. testBinaryOp(t,
  511. &tengo.Int{Value: 2}, token.Shl, &tengo.Int{Value: s},
  512. &tengo.Int{Value: int64(2) << uint(s)})
  513. testBinaryOp(t,
  514. &tengo.Int{Value: -1}, token.Shl, &tengo.Int{Value: s},
  515. &tengo.Int{Value: int64(-1) << uint(s)})
  516. testBinaryOp(t,
  517. &tengo.Int{Value: -2}, token.Shl, &tengo.Int{Value: s},
  518. &tengo.Int{Value: int64(-2) << uint(s)})
  519. testBinaryOp(t,
  520. &tengo.Int{Value: int64(0xffffffff)}, token.Shl,
  521. &tengo.Int{Value: s},
  522. &tengo.Int{Value: int64(0xffffffff) << uint(s)})
  523. }
  524. // int >> int
  525. for s := int64(0); s < 64; s++ {
  526. testBinaryOp(t,
  527. &tengo.Int{Value: 0}, token.Shr, &tengo.Int{Value: s},
  528. &tengo.Int{Value: int64(0) >> uint(s)})
  529. testBinaryOp(t,
  530. &tengo.Int{Value: 1}, token.Shr, &tengo.Int{Value: s},
  531. &tengo.Int{Value: int64(1) >> uint(s)})
  532. testBinaryOp(t,
  533. &tengo.Int{Value: 2}, token.Shr, &tengo.Int{Value: s},
  534. &tengo.Int{Value: int64(2) >> uint(s)})
  535. testBinaryOp(t,
  536. &tengo.Int{Value: -1}, token.Shr, &tengo.Int{Value: s},
  537. &tengo.Int{Value: int64(-1) >> uint(s)})
  538. testBinaryOp(t,
  539. &tengo.Int{Value: -2}, token.Shr, &tengo.Int{Value: s},
  540. &tengo.Int{Value: int64(-2) >> uint(s)})
  541. testBinaryOp(t,
  542. &tengo.Int{Value: int64(0xffffffff)}, token.Shr,
  543. &tengo.Int{Value: s},
  544. &tengo.Int{Value: int64(0xffffffff) >> uint(s)})
  545. }
  546. // int < int
  547. for l := int64(-2); l <= 2; l++ {
  548. for r := int64(-2); r <= 2; r++ {
  549. testBinaryOp(t, &tengo.Int{Value: l}, token.Less,
  550. &tengo.Int{Value: r}, boolValue(l < r))
  551. }
  552. }
  553. // int > int
  554. for l := int64(-2); l <= 2; l++ {
  555. for r := int64(-2); r <= 2; r++ {
  556. testBinaryOp(t, &tengo.Int{Value: l}, token.Greater,
  557. &tengo.Int{Value: r}, boolValue(l > r))
  558. }
  559. }
  560. // int <= int
  561. for l := int64(-2); l <= 2; l++ {
  562. for r := int64(-2); r <= 2; r++ {
  563. testBinaryOp(t, &tengo.Int{Value: l}, token.LessEq,
  564. &tengo.Int{Value: r}, boolValue(l <= r))
  565. }
  566. }
  567. // int >= int
  568. for l := int64(-2); l <= 2; l++ {
  569. for r := int64(-2); r <= 2; r++ {
  570. testBinaryOp(t, &tengo.Int{Value: l}, token.GreaterEq,
  571. &tengo.Int{Value: r}, boolValue(l >= r))
  572. }
  573. }
  574. // int + float
  575. for l := int64(-2); l <= 2; l++ {
  576. for r := float64(-2); r <= 2.1; r += 0.5 {
  577. testBinaryOp(t, &tengo.Int{Value: l}, token.Add,
  578. &tengo.Float{Value: r},
  579. &tengo.Float{Value: float64(l) + r})
  580. }
  581. }
  582. // int - float
  583. for l := int64(-2); l <= 2; l++ {
  584. for r := float64(-2); r <= 2.1; r += 0.5 {
  585. testBinaryOp(t, &tengo.Int{Value: l}, token.Sub,
  586. &tengo.Float{Value: r},
  587. &tengo.Float{Value: float64(l) - r})
  588. }
  589. }
  590. // int * float
  591. for l := int64(-2); l <= 2; l++ {
  592. for r := float64(-2); r <= 2.1; r += 0.5 {
  593. testBinaryOp(t, &tengo.Int{Value: l}, token.Mul,
  594. &tengo.Float{Value: r},
  595. &tengo.Float{Value: float64(l) * r})
  596. }
  597. }
  598. // int / float
  599. for l := int64(-2); l <= 2; l++ {
  600. for r := float64(-2); r <= 2.1; r += 0.5 {
  601. if r != 0 {
  602. testBinaryOp(t, &tengo.Int{Value: l}, token.Quo,
  603. &tengo.Float{Value: r},
  604. &tengo.Float{Value: float64(l) / r})
  605. }
  606. }
  607. }
  608. // int < float
  609. for l := int64(-2); l <= 2; l++ {
  610. for r := float64(-2); r <= 2.1; r += 0.5 {
  611. testBinaryOp(t, &tengo.Int{Value: l}, token.Less,
  612. &tengo.Float{Value: r}, boolValue(float64(l) < r))
  613. }
  614. }
  615. // int > float
  616. for l := int64(-2); l <= 2; l++ {
  617. for r := float64(-2); r <= 2.1; r += 0.5 {
  618. testBinaryOp(t, &tengo.Int{Value: l}, token.Greater,
  619. &tengo.Float{Value: r}, boolValue(float64(l) > r))
  620. }
  621. }
  622. // int <= float
  623. for l := int64(-2); l <= 2; l++ {
  624. for r := float64(-2); r <= 2.1; r += 0.5 {
  625. testBinaryOp(t, &tengo.Int{Value: l}, token.LessEq,
  626. &tengo.Float{Value: r}, boolValue(float64(l) <= r))
  627. }
  628. }
  629. // int >= float
  630. for l := int64(-2); l <= 2; l++ {
  631. for r := float64(-2); r <= 2.1; r += 0.5 {
  632. testBinaryOp(t, &tengo.Int{Value: l}, token.GreaterEq,
  633. &tengo.Float{Value: r}, boolValue(float64(l) >= r))
  634. }
  635. }
  636. }
  637. func TestMap_Index(t *testing.T) {
  638. m := &tengo.Map{Value: make(map[string]tengo.Object)}
  639. k := &tengo.Int{Value: 1}
  640. v := &tengo.String{Value: "abcdef"}
  641. err := m.IndexSet(k, v)
  642. require.NoError(t, err)
  643. res, err := m.IndexGet(k)
  644. require.NoError(t, err)
  645. require.Equal(t, v, res)
  646. }
  647. func TestString_BinaryOp(t *testing.T) {
  648. lstr := "abcde"
  649. rstr := "01234"
  650. for l := 0; l < len(lstr); l++ {
  651. for r := 0; r < len(rstr); r++ {
  652. ls := lstr[l:]
  653. rs := rstr[r:]
  654. testBinaryOp(t, &tengo.String{Value: ls}, token.Add,
  655. &tengo.String{Value: rs},
  656. &tengo.String{Value: ls + rs})
  657. rc := []rune(rstr)[r]
  658. testBinaryOp(t, &tengo.String{Value: ls}, token.Add,
  659. &tengo.Char{Value: rc},
  660. &tengo.String{Value: ls + string(rc)})
  661. }
  662. }
  663. }
  664. func testBinaryOp(
  665. t *testing.T,
  666. lhs tengo.Object,
  667. op token.Token,
  668. rhs tengo.Object,
  669. expected tengo.Object,
  670. ) {
  671. t.Helper()
  672. actual, err := lhs.BinaryOp(op, rhs)
  673. require.NoError(t, err)
  674. require.Equal(t, expected, actual)
  675. }
  676. func boolValue(b bool) tengo.Object {
  677. if b {
  678. return tengo.TrueValue
  679. }
  680. return tengo.FalseValue
  681. }