| // Copyright 2021 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package types2 |
| |
| import ( |
| "strings" |
| "testing" |
| ) |
| |
| // maketl makes a term list from a string of the term list. |
| func maketl(s string) termlist { |
| s = strings.ReplaceAll(s, " ", "") |
| names := strings.Split(s, "∪") |
| r := make(termlist, len(names)) |
| for i, n := range names { |
| r[i] = testTerm(n) |
| } |
| return r |
| } |
| |
| func TestTermlistAll(t *testing.T) { |
| if !allTermlist.isAll() { |
| t.Errorf("allTermlist is not the set of all types") |
| } |
| } |
| |
| func TestTermlistString(t *testing.T) { |
| for _, want := range []string{ |
| "∅", |
| "𝓤", |
| "int", |
| "~int", |
| "myInt", |
| "∅ ∪ ∅", |
| "𝓤 ∪ 𝓤", |
| "∅ ∪ 𝓤 ∪ int", |
| "∅ ∪ 𝓤 ∪ int ∪ myInt", |
| } { |
| if got := maketl(want).String(); got != want { |
| t.Errorf("(%v).String() == %v", want, got) |
| } |
| } |
| } |
| |
| func TestTermlistIsEmpty(t *testing.T) { |
| for test, want := range map[string]bool{ |
| "∅": true, |
| "∅ ∪ ∅": true, |
| "∅ ∪ ∅ ∪ 𝓤": false, |
| "∅ ∪ ∅ ∪ myInt": false, |
| "𝓤": false, |
| "𝓤 ∪ int": false, |
| "𝓤 ∪ myInt ∪ ∅": false, |
| } { |
| xl := maketl(test) |
| got := xl.isEmpty() |
| if got != want { |
| t.Errorf("(%v).isEmpty() == %v; want %v", test, got, want) |
| } |
| } |
| } |
| |
| func TestTermlistIsAll(t *testing.T) { |
| for test, want := range map[string]bool{ |
| "∅": false, |
| "∅ ∪ ∅": false, |
| "int ∪ ~string": false, |
| "~int ∪ myInt": false, |
| "∅ ∪ ∅ ∪ 𝓤": true, |
| "𝓤": true, |
| "𝓤 ∪ int": true, |
| "myInt ∪ 𝓤": true, |
| } { |
| xl := maketl(test) |
| got := xl.isAll() |
| if got != want { |
| t.Errorf("(%v).isAll() == %v; want %v", test, got, want) |
| } |
| } |
| } |
| |
| func TestTermlistNorm(t *testing.T) { |
| for _, test := range []struct { |
| xl, want string |
| }{ |
| {"∅", "∅"}, |
| {"∅ ∪ ∅", "∅"}, |
| {"∅ ∪ int", "int"}, |
| {"∅ ∪ myInt", "myInt"}, |
| {"𝓤 ∪ int", "𝓤"}, |
| {"𝓤 ∪ myInt", "𝓤"}, |
| {"int ∪ myInt", "int ∪ myInt"}, |
| {"~int ∪ int", "~int"}, |
| {"~int ∪ myInt", "~int"}, |
| {"int ∪ ~string ∪ int", "int ∪ ~string"}, |
| {"~int ∪ string ∪ 𝓤 ∪ ~string ∪ int", "𝓤"}, |
| {"~int ∪ string ∪ myInt ∪ ~string ∪ int", "~int ∪ ~string"}, |
| } { |
| xl := maketl(test.xl) |
| got := maketl(test.xl).norm() |
| if got.String() != test.want { |
| t.Errorf("(%v).norm() = %v; want %v", xl, got, test.want) |
| } |
| } |
| } |
| |
| func TestTermlistStructuralType(t *testing.T) { |
| // helper to deal with nil types |
| tstring := func(typ Type) string { |
| if typ == nil { |
| return "nil" |
| } |
| return typ.String() |
| } |
| |
| for test, want := range map[string]string{ |
| "∅": "nil", |
| "𝓤": "nil", |
| "int": "int", |
| "myInt": "myInt", |
| "~int": "int", |
| "~int ∪ string": "nil", |
| "~int ∪ myInt": "int", |
| "∅ ∪ int": "int", |
| "∅ ∪ ~int": "int", |
| "∅ ∪ ~int ∪ string": "nil", |
| } { |
| xl := maketl(test) |
| got := tstring(xl.structuralType()) |
| if got != want { |
| t.Errorf("(%v).structuralType() == %v; want %v", test, got, want) |
| } |
| } |
| } |
| |
| func TestTermlistUnion(t *testing.T) { |
| for _, test := range []struct { |
| xl, yl, want string |
| }{ |
| |
| {"∅", "∅", "∅"}, |
| {"∅", "𝓤", "𝓤"}, |
| {"∅", "int", "int"}, |
| {"𝓤", "~int", "𝓤"}, |
| {"int", "~int", "~int"}, |
| {"int", "string", "int ∪ string"}, |
| {"int", "myInt", "int ∪ myInt"}, |
| {"~int", "myInt", "~int"}, |
| {"int ∪ string", "~string", "int ∪ ~string"}, |
| {"~int ∪ string", "~string ∪ int", "~int ∪ ~string"}, |
| {"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, |
| {"~int ∪ myInt ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, |
| {"~int ∪ string ∪ 𝓤", "~string ∪ int", "𝓤"}, |
| {"~int ∪ string ∪ myInt", "~string ∪ int", "~int ∪ ~string"}, |
| } { |
| xl := maketl(test.xl) |
| yl := maketl(test.yl) |
| got := xl.union(yl).String() |
| if got != test.want { |
| t.Errorf("(%v).union(%v) = %v; want %v", test.xl, test.yl, got, test.want) |
| } |
| } |
| } |
| |
| func TestTermlistIntersect(t *testing.T) { |
| for _, test := range []struct { |
| xl, yl, want string |
| }{ |
| |
| {"∅", "∅", "∅"}, |
| {"∅", "𝓤", "∅"}, |
| {"∅", "int", "∅"}, |
| {"∅", "myInt", "∅"}, |
| {"𝓤", "~int", "~int"}, |
| {"𝓤", "myInt", "myInt"}, |
| {"int", "~int", "int"}, |
| {"int", "string", "∅"}, |
| {"int", "myInt", "∅"}, |
| {"~int", "myInt", "myInt"}, |
| {"int ∪ string", "~string", "string"}, |
| {"~int ∪ string", "~string ∪ int", "int ∪ string"}, |
| {"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"}, |
| {"~int ∪ myInt ∪ ∅", "~string ∪ int", "int"}, |
| {"~int ∪ string ∪ 𝓤", "~string ∪ int", "int ∪ ~string"}, |
| {"~int ∪ string ∪ myInt", "~string ∪ int", "int ∪ string"}, |
| } { |
| xl := maketl(test.xl) |
| yl := maketl(test.yl) |
| got := xl.intersect(yl).String() |
| if got != test.want { |
| t.Errorf("(%v).intersect(%v) = %v; want %v", test.xl, test.yl, got, test.want) |
| } |
| } |
| } |
| |
| func TestTermlistEqual(t *testing.T) { |
| for _, test := range []struct { |
| xl, yl string |
| want bool |
| }{ |
| {"∅", "∅", true}, |
| {"∅", "𝓤", false}, |
| {"𝓤", "𝓤", true}, |
| {"𝓤 ∪ int", "𝓤", true}, |
| {"𝓤 ∪ int", "string ∪ 𝓤", true}, |
| {"𝓤 ∪ myInt", "string ∪ 𝓤", true}, |
| {"int ∪ ~string", "string ∪ int", false}, |
| {"~int ∪ string", "string ∪ myInt", false}, |
| {"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true}, |
| } { |
| xl := maketl(test.xl) |
| yl := maketl(test.yl) |
| got := xl.equal(yl) |
| if got != test.want { |
| t.Errorf("(%v).equal(%v) = %v; want %v", test.xl, test.yl, got, test.want) |
| } |
| } |
| } |
| |
| func TestTermlistIncludes(t *testing.T) { |
| for _, test := range []struct { |
| xl, typ string |
| want bool |
| }{ |
| {"∅", "int", false}, |
| {"𝓤", "int", true}, |
| {"~int", "int", true}, |
| {"int", "string", false}, |
| {"~int", "string", false}, |
| {"~int", "myInt", true}, |
| {"int ∪ string", "string", true}, |
| {"~int ∪ string", "int", true}, |
| {"~int ∪ string", "myInt", true}, |
| {"~int ∪ myInt ∪ ∅", "myInt", true}, |
| {"myInt ∪ ∅ ∪ 𝓤", "int", true}, |
| } { |
| xl := maketl(test.xl) |
| yl := testTerm(test.typ).typ |
| got := xl.includes(yl) |
| if got != test.want { |
| t.Errorf("(%v).includes(%v) = %v; want %v", test.xl, yl, got, test.want) |
| } |
| } |
| } |
| |
| func TestTermlistSupersetOf(t *testing.T) { |
| for _, test := range []struct { |
| xl, typ string |
| want bool |
| }{ |
| {"∅", "∅", true}, |
| {"∅", "𝓤", false}, |
| {"∅", "int", false}, |
| {"𝓤", "∅", true}, |
| {"𝓤", "𝓤", true}, |
| {"𝓤", "int", true}, |
| {"𝓤", "~int", true}, |
| {"𝓤", "myInt", true}, |
| {"~int", "int", true}, |
| {"~int", "~int", true}, |
| {"~int", "myInt", true}, |
| {"int", "~int", false}, |
| {"myInt", "~int", false}, |
| {"int", "string", false}, |
| {"~int", "string", false}, |
| {"int ∪ string", "string", true}, |
| {"int ∪ string", "~string", false}, |
| {"~int ∪ string", "int", true}, |
| {"~int ∪ string", "myInt", true}, |
| {"~int ∪ string ∪ ∅", "string", true}, |
| {"~string ∪ ∅ ∪ 𝓤", "myInt", true}, |
| } { |
| xl := maketl(test.xl) |
| y := testTerm(test.typ) |
| got := xl.supersetOf(y) |
| if got != test.want { |
| t.Errorf("(%v).supersetOf(%v) = %v; want %v", test.xl, y, got, test.want) |
| } |
| } |
| } |
| |
| func TestTermlistSubsetOf(t *testing.T) { |
| for _, test := range []struct { |
| xl, yl string |
| want bool |
| }{ |
| {"∅", "∅", true}, |
| {"∅", "𝓤", true}, |
| {"𝓤", "∅", false}, |
| {"𝓤", "𝓤", true}, |
| {"int", "int ∪ string", true}, |
| {"~int", "int ∪ string", false}, |
| {"~int", "myInt ∪ string", false}, |
| {"myInt", "~int ∪ string", true}, |
| {"~int", "string ∪ string ∪ int ∪ ~int", true}, |
| {"myInt", "string ∪ string ∪ ~int", true}, |
| {"int ∪ string", "string", false}, |
| {"int ∪ string", "string ∪ int", true}, |
| {"int ∪ ~string", "string ∪ int", false}, |
| {"myInt ∪ ~string", "string ∪ int ∪ 𝓤", true}, |
| {"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false}, |
| {"int ∪ myInt", "string ∪ ~int ∪ ∅ ∪ string", true}, |
| } { |
| xl := maketl(test.xl) |
| yl := maketl(test.yl) |
| got := xl.subsetOf(yl) |
| if got != test.want { |
| t.Errorf("(%v).subsetOf(%v) = %v; want %v", test.xl, test.yl, got, test.want) |
| } |
| } |
| } |