1// Copyright 2017 Istio Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package il
16
17import (
18	"testing"
19)
20
21type builderTest struct {
22	n string
23	i func(*Builder)
24	e []uint32
25}
26
27var builderTests = []builderTest{
28	{
29		n: "and",
30		i: func(b *Builder) {
31			b.And()
32		},
33		e: []uint32{
34			uint32(And),
35		},
36	},
37	{
38		n: "xor",
39		i: func(b *Builder) {
40			b.Xor()
41		},
42		e: []uint32{
43			uint32(Xor),
44		},
45	},
46	{
47		n: "not",
48		i: func(b *Builder) {
49			b.Not()
50		},
51		e: []uint32{
52			uint32(Not),
53		},
54	},
55	{
56		n: "or",
57		i: func(b *Builder) {
58			b.Or()
59		},
60		e: []uint32{
61			uint32(Or),
62		},
63	},
64	{
65		n: "eqstring",
66		i: func(b *Builder) {
67			b.EQString()
68		},
69		e: []uint32{
70			uint32(EqS),
71		},
72	},
73	{
74		n: "aeqstring",
75		i: func(b *Builder) {
76			b.AEQString("abv")
77		},
78		e: []uint32{
79			uint32(AEqS),
80			1, //str index
81		},
82	},
83	{
84		n: "eqinteger",
85		i: func(b *Builder) {
86			b.EQInteger()
87		},
88		e: []uint32{
89			uint32(EqI),
90		},
91	},
92	{
93		n: "aeqinteger",
94		i: func(b *Builder) {
95			b.AEQInteger(345)
96		},
97		e: []uint32{
98			uint32(AEqI),
99			345,
100			0,
101		},
102	},
103	{
104		n: "eqbool",
105		i: func(b *Builder) {
106			b.EQBool()
107		},
108		e: []uint32{
109			uint32(EqB),
110		},
111	},
112	{
113		n: "aeqbool",
114		i: func(b *Builder) {
115			b.AEQBool(true)
116		},
117		e: []uint32{
118			uint32(AEqB),
119			1,
120		},
121	},
122	{
123		n: "eqdouble",
124		i: func(b *Builder) {
125			b.EQDouble()
126		},
127		e: []uint32{
128			uint32(EqD),
129		},
130	},
131	{
132		n: "aeqdouble",
133		i: func(b *Builder) {
134			b.AEQDouble(10.123)
135		},
136		e: []uint32{
137			uint32(AEqD),
138			3676492005,
139			1076117241,
140		},
141	},
142	{
143		n: "ret",
144		i: func(b *Builder) {
145			b.Ret()
146		},
147		e: []uint32{
148			uint32(Ret),
149		},
150	},
151	{
152		n: "call",
153		i: func(b *Builder) {
154			b.Call("foo")
155		},
156		e: []uint32{
157			uint32(Call),
158			1, //str index
159		},
160	},
161	{
162		n: "resolveint",
163		i: func(b *Builder) {
164			b.ResolveInt("foo")
165		},
166		e: []uint32{
167			uint32(ResolveI),
168			1, //str index
169		},
170	},
171	{
172		n: "tresolveint",
173		i: func(b *Builder) {
174			b.TResolveInt("foo")
175		},
176		e: []uint32{
177			uint32(TResolveI),
178			1, //str index
179		},
180	},
181	{
182		n: "resolvebool",
183		i: func(b *Builder) {
184			b.ResolveBool("foo")
185		},
186		e: []uint32{
187			uint32(ResolveB),
188			1, //str index
189		},
190	},
191	{
192		n: "tresolvebool",
193		i: func(b *Builder) {
194			b.TResolveBool("foo")
195		},
196		e: []uint32{
197			uint32(TResolveB),
198			1, //str index
199		},
200	},
201	{
202		n: "resolvestring",
203		i: func(b *Builder) {
204			b.ResolveString("foo")
205		},
206		e: []uint32{
207			uint32(ResolveS),
208			1, //str index
209		},
210	},
211	{
212		n: "tresolvestring",
213		i: func(b *Builder) {
214			b.TResolveString("foo")
215		},
216		e: []uint32{
217			uint32(TResolveS),
218			1, //str index
219		},
220	},
221	{
222		n: "resolvedouble",
223		i: func(b *Builder) {
224			b.ResolveDouble("foo")
225		},
226		e: []uint32{
227			uint32(ResolveD),
228			1, //str index
229		},
230	},
231	{
232		n: "tresolvedouble",
233		i: func(b *Builder) {
234			b.TResolveDouble("foo")
235		},
236		e: []uint32{
237			uint32(TResolveD),
238			1, //str index
239		},
240	},
241	{
242		n: "resolveinterface",
243		i: func(b *Builder) {
244			b.ResolveInterface("foo")
245		},
246		e: []uint32{
247			uint32(ResolveF),
248			1, //str index
249		},
250	},
251	{
252		n: "tresolveinterface",
253		i: func(b *Builder) {
254			b.TResolveInterface("foo")
255		},
256		e: []uint32{
257			uint32(TResolveF),
258			1, //str index
259		},
260	},
261	{
262		n: "apushbool",
263		i: func(b *Builder) {
264			b.APushBool(true)
265		},
266		e: []uint32{
267			uint32(APushB),
268			1,
269		},
270	},
271	{
272		n: "apushstr",
273		i: func(b *Builder) {
274			b.APushStr("ABV")
275		},
276		e: []uint32{
277			uint32(APushS),
278			1, //str index
279		},
280	},
281	{
282		n: "apushdouble",
283		i: func(b *Builder) {
284			b.APushDouble(123.456)
285		},
286		e: []uint32{
287			uint32(APushD),
288			446676599,
289			1079958831,
290		},
291	},
292	{
293		n: "apushint",
294		i: func(b *Builder) {
295			b.APushInt(456)
296		},
297		e: []uint32{
298			uint32(APushI),
299			456,
300			0,
301		},
302	},
303	{
304		n: "lookup",
305		i: func(b *Builder) {
306			b.Lookup()
307		},
308		e: []uint32{
309			uint32(Lookup),
310		},
311	},
312	{
313		n: "nlookup",
314		i: func(b *Builder) {
315			b.NLookup()
316		},
317		e: []uint32{
318			uint32(NLookup),
319		},
320	},
321	{
322		n: "alookup",
323		i: func(b *Builder) {
324			b.ALookup("abc")
325		},
326		e: []uint32{
327			uint32(ALookup),
328			1, //str index
329		},
330	},
331	{
332		n: "anlookup",
333		i: func(b *Builder) {
334			b.ANLookup("abc")
335		},
336		e: []uint32{
337			uint32(ANLookup),
338			1, //str index
339		},
340	},
341	{
342		n: "tlookup",
343		i: func(b *Builder) {
344			b.TLookup()
345		},
346		e: []uint32{
347			uint32(TLookup),
348		},
349	},
350	{
351		n: "adds",
352		i: func(b *Builder) {
353			b.AddString()
354		},
355		e: []uint32{
356			uint32(AddS),
357		},
358	},
359	{
360		n: "addi",
361		i: func(b *Builder) {
362			b.AddInteger()
363		},
364		e: []uint32{
365			uint32(AddI),
366		},
367	},
368	{
369		n: "addd",
370		i: func(b *Builder) {
371			b.AddDouble()
372		},
373		e: []uint32{
374			uint32(AddD),
375		},
376	},
377	{
378		n: "labels",
379		i: func(b *Builder) {
380			l := b.AllocateLabel()
381			b.Nop()
382			b.Jmp(l)
383			b.Nop()
384			b.Jnz(l)
385			b.Nop()
386			b.Jz(l)
387			b.Nop()
388			b.SetLabelPos(l)
389			b.Nop()
390			b.Jmp(l)
391			b.Nop()
392			b.Jnz(l)
393			b.Nop()
394			b.Jz(l)
395			b.Nop()
396			b.Jmp("LLL")
397			b.SetLabelPos("LLL")
398			b.Nop()
399		},
400		e: []uint32{
401			uint32(Nop),
402			uint32(Jmp),
403			10, // label address
404			uint32(Nop),
405			uint32(Jnz),
406			10, // label address
407			uint32(Nop),
408			uint32(Jz),
409			10, // label address
410			uint32(Nop),
411			uint32(Nop), // label points to here
412			uint32(Jmp),
413			10, // label address
414			uint32(Nop),
415			uint32(Jnz),
416			10, // label address
417			uint32(Nop),
418			uint32(Jz),
419			10, // label address
420			uint32(Nop),
421			uint32(Jmp),
422			22,
423			uint32(Nop),
424		},
425	},
426}
427
428func Test(t *testing.T) {
429	for _, test := range builderTests {
430		t.Run(test.n, func(tt *testing.T) {
431			p := NewProgram()
432			b := NewBuilder(p.strings)
433			test.i(b)
434			body := b.Build()
435
436			same := (len(body) == len(test.e))
437			if same {
438				for i := 0; i < len(body); i++ {
439					if body[i] != test.e[i] {
440						same = false
441						break
442					}
443				}
444			}
445
446			if !same {
447				tt.Logf("Expected:\n%v\n", test.e)
448				tt.Logf("Actual:\n%v\n", body)
449				tt.Fatal()
450			}
451		})
452	}
453}
454
455func TestSetLabelPosTwicePanics(t *testing.T) {
456	defer func() {
457		if r := recover(); r == nil {
458			t.Error("The code did not panic")
459		}
460	}()
461
462	p := NewProgram()
463	b := NewBuilder(p.strings)
464	b.SetLabelPos("l")
465	b.SetLabelPos("l") // Try setting again.
466}
467