Skip to content

Commit 99b9ba6

Browse files
add complex integration test
1 parent 9eb1c70 commit 99b9ba6

File tree

7 files changed

+156
-0
lines changed

7 files changed

+156
-0
lines changed

tests/gencircle_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ func Test_GenCircle_Burninate(t *testing.T) { runGenCircleTest(t, `burninate`) }
2020

2121
func Test_GenCircle_CatBox(t *testing.T) { runGenCircleTest(t, `catbox`) }
2222

23+
func Test_GenCircle_Trammel(t *testing.T) { runGenCircleTest(t, `trammel`) }
24+
2325
// Cache buster: Keeping the tests from using cached results when only
2426
// the test application files are changed.
2527
//
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package cmp
2+
3+
// Barrowed from the cmp package in the Go standard library
4+
// that isn't available until go1.21.
5+
type Ordered interface {
6+
~int | ~int8 | ~int16 | ~int32 | ~int64 |
7+
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
8+
~float32 | ~float64 |
9+
~string
10+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package collections
2+
3+
func Populate[K comparable, V any, SK ~[]K, SV ~[]V, M ~map[K]V](m M, keys SK, values SV) {
4+
// Lots of type parameters with parameters referencing each other.
5+
for i, k := range keys {
6+
if i < len(values) {
7+
m[k] = values[i]
8+
} else {
9+
var zero V
10+
m[k] = zero
11+
}
12+
}
13+
}
14+
15+
func KeysAndValues[K comparable, V any, M ~map[K]V](m M) struct {
16+
Keys []K
17+
Values []V
18+
} {
19+
keys := make([]K, 0, len(m))
20+
values := make([]V, 0, len(m))
21+
for k, v := range m {
22+
keys = append(keys, k)
23+
values = append(values, v)
24+
}
25+
// nested generic type that has a type parameter and nest type parameter.
26+
type result[T any] struct {
27+
Keys []T
28+
Values []V
29+
}
30+
return result[K]{Keys: keys, Values: values}
31+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// This is a test of several different kinds of generics.
2+
// It is purposefully overly complecated for testing purposes.
3+
// This integration test is similar to `compiler.Test_CrossPackageAnalysis`.
4+
5+
package main
6+
7+
import (
8+
"fmt"
9+
10+
"github.com/gopherjs/gopherjs/tests/testdata/gencircle/trammel/cmp"
11+
"github.com/gopherjs/gopherjs/tests/testdata/gencircle/trammel/collections"
12+
"github.com/gopherjs/gopherjs/tests/testdata/gencircle/trammel/stable"
13+
)
14+
15+
type StableMap[K cmp.Ordered, V any] map[K]V
16+
17+
func (m StableMap[K, V]) String() string {
18+
return stable.MapString(m, func(k K, v V) string {
19+
return fmt.Sprintf(`%v: %v`, k, v)
20+
})
21+
}
22+
23+
type SIMap = StableMap[string, int]
24+
type ISMap = StableMap[int, string]
25+
26+
func main() {
27+
m1 := SIMap{}
28+
collections.Populate(m1,
29+
[]string{"one", "two", "three"},
30+
[]int{1, 2, 3})
31+
println(m1.String())
32+
33+
m2 := ISMap{}
34+
collections.Populate(m2,
35+
[]int{4, 5, 6},
36+
[]string{"four", "five", "six"})
37+
println(m2.String())
38+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{one: 1, three: 3, two: 2}
2+
{4: four, 5: five, 6: six}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package sorts
2+
3+
import "github.com/gopherjs/gopherjs/tests/testdata/gencircle/trammel/cmp"
4+
5+
func Pair[K cmp.Ordered, V any, SK ~[]K, SV ~[]V](k SK, v SV) {
6+
Bubble(struct { // non-generic struct in a generic context.
7+
len func() int
8+
less func(i, j int) bool
9+
swap func(i, j int)
10+
}{
11+
len: func() int { return len(k) },
12+
less: func(i, j int) bool { return k[i] < k[j] },
13+
swap: func(i, j int) { k[i], v[i], k[j], v[j] = k[j], v[j], k[i], v[i] },
14+
})
15+
}
16+
17+
func Bubble(f struct {
18+
len func() int
19+
less func(i, j int) bool
20+
swap func(i, j int)
21+
}) {
22+
length := f.len()
23+
for i := 0; i < length; i++ {
24+
for j := i + 1; j < length; j++ {
25+
if f.less(j, i) {
26+
f.swap(i, j)
27+
}
28+
}
29+
}
30+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package stable
2+
3+
import (
4+
"strings"
5+
6+
"github.com/gopherjs/gopherjs/tests/testdata/gencircle/trammel/cmp"
7+
"github.com/gopherjs/gopherjs/tests/testdata/gencircle/trammel/collections"
8+
"github.com/gopherjs/gopherjs/tests/testdata/gencircle/trammel/sorts"
9+
)
10+
11+
func MapString[K cmp.Ordered, V any, M ~map[K]V](m M, stringer func(K, V) string) string {
12+
// Function parameter with type parameters arguments.
13+
result := collections.KeysAndValues(m)
14+
keys := result.Keys
15+
values := result.Values
16+
17+
sorts.Pair(keys, values)
18+
19+
parts := zipper(keys, values, stringer)
20+
return `{` + strings.Join(parts, `, `) + `}`
21+
}
22+
23+
func zipper[TIn1, TIn2, TOut any, SIn1 ~[]TIn1, SIn2 ~[]TIn2, F ~func(TIn1, TIn2) TOut](s1 SIn1, s2 SIn2, merge F) []TOut {
24+
// Overly complex type parameters including a generic function type.
25+
min := len(s1)
26+
if len(s2) < min {
27+
min = len(s2)
28+
}
29+
result := make([]any, min)
30+
for i := 0; i < min; i++ {
31+
result[i] = merge(s1[i], s2[i])
32+
}
33+
return castSlice[any, TOut](result)
34+
}
35+
36+
func castSlice[TIn, TOut any, SIn ~[]TIn, SOut []TOut](s SIn) SOut {
37+
result := make(SOut, len(s))
38+
for i, v := range s {
39+
// Using a type parameter to cast the type.
40+
result[i] = any(v).(TOut)
41+
}
42+
return result
43+
}

0 commit comments

Comments
 (0)