1// Copyright 2021 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
5package types2
6
7import (
8	"strings"
9	"testing"
10)
11
12// maketl makes a term list from a string of the term list.
13func maketl(s string) termlist {
14	s = strings.ReplaceAll(s, " ", "")
15	names := strings.Split(s, "∪")
16	r := make(termlist, len(names))
17	for i, n := range names {
18		r[i] = testTerm(n)
19	}
20	return r
21}
22
23func TestTermlistAll(t *testing.T) {
24	if !allTermlist.isAll() {
25		t.Errorf("allTermlist is not the set of all types")
26	}
27}
28
29func TestTermlistString(t *testing.T) {
30	for _, want := range []string{
31		"∅",
32		"��",
33		"int",
34		"~int",
35		"myInt",
36		"∅ ∪ ∅",
37		"�� ∪ ��",
38		"∅ ∪ �� ∪ int",
39		"∅ ∪ �� ∪ int ∪ myInt",
40	} {
41		if got := maketl(want).String(); got != want {
42			t.Errorf("(%v).String() == %v", want, got)
43		}
44	}
45}
46
47func TestTermlistIsEmpty(t *testing.T) {
48	for test, want := range map[string]bool{
49		"∅":             true,
50		"∅ ∪ ∅":         true,
51		"∅ ∪ ∅ ∪ ��":     false,
52		"∅ ∪ ∅ ∪ myInt": false,
53		"��":             false,
54		"�� ∪ int":       false,
55		"�� ∪ myInt ∪ ∅": false,
56	} {
57		xl := maketl(test)
58		got := xl.isEmpty()
59		if got != want {
60			t.Errorf("(%v).isEmpty() == %v; want %v", test, got, want)
61		}
62	}
63}
64
65func TestTermlistIsAll(t *testing.T) {
66	for test, want := range map[string]bool{
67		"∅":             false,
68		"∅ ∪ ∅":         false,
69		"int ∪ ~string": false,
70		"~int ∪ myInt":  false,
71		"∅ ∪ ∅ ∪ ��":     true,
72		"��":             true,
73		"�� ∪ int":       true,
74		"myInt ∪ ��":     true,
75	} {
76		xl := maketl(test)
77		got := xl.isAll()
78		if got != want {
79			t.Errorf("(%v).isAll() == %v; want %v", test, got, want)
80		}
81	}
82}
83
84func TestTermlistNorm(t *testing.T) {
85	for _, test := range []struct {
86		xl, want string
87	}{
88		{"∅", "∅"},
89		{"∅ ∪ ∅", "∅"},
90		{"∅ ∪ int", "int"},
91		{"∅ ∪ myInt", "myInt"},
92		{"�� ∪ int", "��"},
93		{"�� ∪ myInt", "��"},
94		{"int ∪ myInt", "int ∪ myInt"},
95		{"~int ∪ int", "~int"},
96		{"~int ∪ myInt", "~int"},
97		{"int ∪ ~string ∪ int", "int ∪ ~string"},
98		{"~int ∪ string ∪ �� ∪ ~string ∪ int", "��"},
99		{"~int ∪ string ∪ myInt ∪ ~string ∪ int", "~int ∪ ~string"},
100	} {
101		xl := maketl(test.xl)
102		got := maketl(test.xl).norm()
103		if got.String() != test.want {
104			t.Errorf("(%v).norm() = %v; want %v", xl, got, test.want)
105		}
106	}
107}
108
109func TestTermlistSingleType(t *testing.T) {
110	// helper to deal with nil types
111	tstring := func(typ Type) string {
112		if typ == nil {
113			return "nil"
114		}
115		return typ.String()
116	}
117
118	for test, want := range map[string]string{
119		"∅":                 "nil",
120		"��":                 "nil",
121		"int":               "int",
122		"myInt":             "myInt",
123		"~int":              "int",
124		"~int ∪ string":     "nil",
125		"~int ∪ myInt":      "int",
126		"∅ ∪ int":           "int",
127		"∅ ∪ ~int":          "int",
128		"∅ ∪ ~int ∪ string": "nil",
129	} {
130		xl := maketl(test)
131		got := tstring(xl.singleType())
132		if got != want {
133			t.Errorf("(%v).singleType() == %v; want %v", test, got, want)
134		}
135	}
136}
137
138func TestTermlistUnion(t *testing.T) {
139	for _, test := range []struct {
140		xl, yl, want string
141	}{
142
143		{"∅", "∅", "∅"},
144		{"∅", "��", "��"},
145		{"∅", "int", "int"},
146		{"��", "~int", "��"},
147		{"int", "~int", "~int"},
148		{"int", "string", "int ∪ string"},
149		{"int", "myInt", "int ∪ myInt"},
150		{"~int", "myInt", "~int"},
151		{"int ∪ string", "~string", "int ∪ ~string"},
152		{"~int ∪ string", "~string ∪ int", "~int ∪ ~string"},
153		{"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"},
154		{"~int ∪ myInt ∪ ∅", "~string ∪ int", "~int ∪ ~string"},
155		{"~int ∪ string ∪ ��", "~string ∪ int", "��"},
156		{"~int ∪ string ∪ myInt", "~string ∪ int", "~int ∪ ~string"},
157	} {
158		xl := maketl(test.xl)
159		yl := maketl(test.yl)
160		got := xl.union(yl).String()
161		if got != test.want {
162			t.Errorf("(%v).union(%v) = %v; want %v", test.xl, test.yl, got, test.want)
163		}
164	}
165}
166
167func TestTermlistIntersect(t *testing.T) {
168	for _, test := range []struct {
169		xl, yl, want string
170	}{
171
172		{"∅", "∅", "∅"},
173		{"∅", "��", "∅"},
174		{"∅", "int", "∅"},
175		{"∅", "myInt", "∅"},
176		{"��", "~int", "~int"},
177		{"��", "myInt", "myInt"},
178		{"int", "~int", "int"},
179		{"int", "string", "∅"},
180		{"int", "myInt", "∅"},
181		{"~int", "myInt", "myInt"},
182		{"int ∪ string", "~string", "string"},
183		{"~int ∪ string", "~string ∪ int", "int ∪ string"},
184		{"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"},
185		{"~int ∪ myInt ∪ ∅", "~string ∪ int", "int"},
186		{"~int ∪ string ∪ ��", "~string ∪ int", "int ∪ ~string"},
187		{"~int ∪ string ∪ myInt", "~string ∪ int", "int ∪ string"},
188	} {
189		xl := maketl(test.xl)
190		yl := maketl(test.yl)
191		got := xl.intersect(yl).String()
192		if got != test.want {
193			t.Errorf("(%v).intersect(%v) = %v; want %v", test.xl, test.yl, got, test.want)
194		}
195	}
196}
197
198func TestTermlistEqual(t *testing.T) {
199	for _, test := range []struct {
200		xl, yl string
201		want   bool
202	}{
203		{"∅", "∅", true},
204		{"∅", "��", false},
205		{"��", "��", true},
206		{"�� ∪ int", "��", true},
207		{"�� ∪ int", "string ∪ ��", true},
208		{"�� ∪ myInt", "string ∪ ��", true},
209		{"int ∪ ~string", "string ∪ int", false},
210		{"~int ∪ string", "string ∪ myInt", false},
211		{"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true},
212	} {
213		xl := maketl(test.xl)
214		yl := maketl(test.yl)
215		got := xl.equal(yl)
216		if got != test.want {
217			t.Errorf("(%v).equal(%v) = %v; want %v", test.xl, test.yl, got, test.want)
218		}
219	}
220}
221
222func TestTermlistIncludes(t *testing.T) {
223	for _, test := range []struct {
224		xl, typ string
225		want    bool
226	}{
227		{"∅", "int", false},
228		{"��", "int", true},
229		{"~int", "int", true},
230		{"int", "string", false},
231		{"~int", "string", false},
232		{"~int", "myInt", true},
233		{"int ∪ string", "string", true},
234		{"~int ∪ string", "int", true},
235		{"~int ∪ string", "myInt", true},
236		{"~int ∪ myInt ∪ ∅", "myInt", true},
237		{"myInt ∪ ∅ ∪ ��", "int", true},
238	} {
239		xl := maketl(test.xl)
240		yl := testTerm(test.typ).typ
241		got := xl.includes(yl)
242		if got != test.want {
243			t.Errorf("(%v).includes(%v) = %v; want %v", test.xl, yl, got, test.want)
244		}
245	}
246}
247
248func TestTermlistSupersetOf(t *testing.T) {
249	for _, test := range []struct {
250		xl, typ string
251		want    bool
252	}{
253		{"∅", "∅", true},
254		{"∅", "��", false},
255		{"∅", "int", false},
256		{"��", "∅", true},
257		{"��", "��", true},
258		{"��", "int", true},
259		{"��", "~int", true},
260		{"��", "myInt", true},
261		{"~int", "int", true},
262		{"~int", "~int", true},
263		{"~int", "myInt", true},
264		{"int", "~int", false},
265		{"myInt", "~int", false},
266		{"int", "string", false},
267		{"~int", "string", false},
268		{"int ∪ string", "string", true},
269		{"int ∪ string", "~string", false},
270		{"~int ∪ string", "int", true},
271		{"~int ∪ string", "myInt", true},
272		{"~int ∪ string ∪ ∅", "string", true},
273		{"~string ∪ ∅ ∪ ��", "myInt", true},
274	} {
275		xl := maketl(test.xl)
276		y := testTerm(test.typ)
277		got := xl.supersetOf(y)
278		if got != test.want {
279			t.Errorf("(%v).supersetOf(%v) = %v; want %v", test.xl, y, got, test.want)
280		}
281	}
282}
283
284func TestTermlistSubsetOf(t *testing.T) {
285	for _, test := range []struct {
286		xl, yl string
287		want   bool
288	}{
289		{"∅", "∅", true},
290		{"∅", "��", true},
291		{"��", "∅", false},
292		{"��", "��", true},
293		{"int", "int ∪ string", true},
294		{"~int", "int ∪ string", false},
295		{"~int", "myInt ∪ string", false},
296		{"myInt", "~int ∪ string", true},
297		{"~int", "string ∪ string ∪ int ∪ ~int", true},
298		{"myInt", "string ∪ string ∪ ~int", true},
299		{"int ∪ string", "string", false},
300		{"int ∪ string", "string ∪ int", true},
301		{"int ∪ ~string", "string ∪ int", false},
302		{"myInt ∪ ~string", "string ∪ int ∪ ��", true},
303		{"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false},
304		{"int ∪ myInt", "string ∪ ~int ∪ ∅ ∪ string", true},
305	} {
306		xl := maketl(test.xl)
307		yl := maketl(test.yl)
308		got := xl.subsetOf(yl)
309		if got != test.want {
310			t.Errorf("(%v).subsetOf(%v) = %v; want %v", test.xl, test.yl, got, test.want)
311		}
312	}
313}
314