Skip to content

Commit 391754e

Browse files
committed
fix: more testing
Signed-off-by: Dr. Carsten Leue <[email protected]>
1 parent 598a7b2 commit 391754e

File tree

11 files changed

+367
-1
lines changed

11 files changed

+367
-1
lines changed

coverage.bat

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
@echo off
2-
go tool cover -html=build/cover.out -o build/cover.html
2+
go tool cover -html=build/cover.out -o build/cover.html
3+
cov-report -ex ".*/cli/.*.go|.*/gen.go|.*/binds.go" build\cover.out

either/array_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package either
22

33
import (
4+
"fmt"
45
"testing"
56

7+
TST "github.com/IBM/fp-go/internal/testing"
68
"github.com/stretchr/testify/assert"
79
)
810

@@ -16,3 +18,33 @@ func TestCompactArray(t *testing.T) {
1618
res := CompactArray(ar)
1719
assert.Equal(t, 2, len(res))
1820
}
21+
22+
func TestSequenceArray(t *testing.T) {
23+
24+
s := TST.SequenceArrayTest(
25+
FromStrictEquals[error, bool](),
26+
Pointed[error, string](),
27+
Pointed[error, bool](),
28+
Functor[error, []string, bool](),
29+
SequenceArray[error, string],
30+
)
31+
32+
for i := 0; i < 10; i++ {
33+
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
34+
}
35+
}
36+
37+
func TestSequenceArrayError(t *testing.T) {
38+
39+
s := TST.SequenceArrayErrorTest(
40+
FromStrictEquals[error, bool](),
41+
Left[string, error],
42+
Left[bool, error],
43+
Pointed[error, string](),
44+
Pointed[error, bool](),
45+
Functor[error, []string, bool](),
46+
SequenceArray[error, string],
47+
)
48+
// run across four bits
49+
s(4)(t)
50+
}

either/functor.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) 2024 IBM Corp.
2+
// All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package either
17+
18+
import (
19+
"github.com/IBM/fp-go/internal/functor"
20+
)
21+
22+
type eitherFunctor[E, A, B any] struct{}
23+
24+
func (o *eitherFunctor[E, A, B]) Map(f func(A) B) func(Either[E, A]) Either[E, B] {
25+
return Map[E, A, B](f)
26+
}
27+
28+
// Functor implements the functoric operations for [Either]
29+
func Functor[E, A, B any]() functor.Functor[A, B, Either[E, A], Either[E, B]] {
30+
return &eitherFunctor[E, A, B]{}
31+
}

either/pointed.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) 2024 IBM Corp.
2+
// All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package either
17+
18+
import (
19+
"github.com/IBM/fp-go/internal/pointed"
20+
)
21+
22+
type eitherPointed[E, A any] struct{}
23+
24+
func (o *eitherPointed[E, A]) Of(a A) Either[E, A] {
25+
return Of[E, A](a)
26+
}
27+
28+
// Pointed implements the pointedic operations for [Either]
29+
func Pointed[E, A any]() pointed.Pointed[A, Either[E, A]] {
30+
return &eitherPointed[E, A]{}
31+
}

internal/testing/sequence.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,84 @@ func SequenceArrayTest[
6262
}
6363
}
6464
}
65+
66+
// SequenceArrayErrorTest tests if the sequence operation works in case the operation can error
67+
func SequenceArrayErrorTest[
68+
HKTA,
69+
HKTB,
70+
HKTAA any, // HKT[[]A]
71+
](
72+
eq EQ.Eq[HKTB],
73+
74+
left func(error) HKTA,
75+
leftB func(error) HKTB,
76+
pa pointed.Pointed[string, HKTA],
77+
pb pointed.Pointed[bool, HKTB],
78+
faa functor.Functor[[]string, bool, HKTAA, HKTB],
79+
seq func([]HKTA) HKTAA,
80+
) func(count int) func(t *testing.T) {
81+
82+
return func(count int) func(t *testing.T) {
83+
84+
expGood := make([]string, count)
85+
good := make([]HKTA, count)
86+
expBad := make([]error, count)
87+
bad := make([]HKTA, count)
88+
89+
for i := 0; i < count; i++ {
90+
goodVal := fmt.Sprintf("TestData %d", i)
91+
badVal := fmt.Errorf("ErrorData %d", i)
92+
expGood[i] = goodVal
93+
good[i] = pa.Of(goodVal)
94+
expBad[i] = badVal
95+
bad[i] = left(badVal)
96+
}
97+
98+
total := 1 << count
99+
100+
return func(t *testing.T) {
101+
// test the good case
102+
res := F.Pipe2(
103+
good,
104+
seq,
105+
faa.Map(func(act []string) bool {
106+
return assert.Equal(t, expGood, act)
107+
}),
108+
)
109+
assert.True(t, eq.Equals(res, pb.Of(true)))
110+
// iterate and test the bad cases
111+
for i := 1; i < total; i++ {
112+
// run the test
113+
t.Run(fmt.Sprintf("Bitmask test %d", i), func(t1 *testing.T) {
114+
// the actual
115+
act := make([]HKTA, count)
116+
// the expected error
117+
var exp error
118+
// prepare the values bases on the bit mask
119+
mask := 1
120+
for j := 0; j < count; j++ {
121+
if (i & mask) == 0 {
122+
act[j] = good[j]
123+
} else {
124+
act[j] = bad[j]
125+
if exp == nil {
126+
exp = expBad[j]
127+
}
128+
}
129+
mask <<= 1
130+
}
131+
// test the good case
132+
res := F.Pipe2(
133+
act,
134+
seq,
135+
faa.Map(func(act []string) bool {
136+
return assert.Equal(t, expGood, act)
137+
}),
138+
)
139+
// validate the error
140+
assert.True(t, eq.Equals(res, leftB(exp)))
141+
})
142+
}
143+
}
144+
}
145+
}

ioeither/generic/monad.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package generic
1717

1818
import (
1919
ET "github.com/IBM/fp-go/either"
20+
"github.com/IBM/fp-go/internal/functor"
2021
"github.com/IBM/fp-go/internal/monad"
2122
"github.com/IBM/fp-go/internal/pointed"
2223
)
@@ -25,6 +26,8 @@ type ioEitherPointed[E, A any, GA ~func() ET.Either[E, A]] struct{}
2526

2627
type ioEitherMonad[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B]] struct{}
2728

29+
type ioEitherFunctor[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B]] struct{}
30+
2831
func (o *ioEitherPointed[E, A, GA]) Of(a A) GA {
2932
return Of[GA, E, A](a)
3033
}
@@ -45,11 +48,20 @@ func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB {
4548
return Ap[GB, GAB, GA, E, A, B](fa)
4649
}
4750

51+
func (o *ioEitherFunctor[E, A, B, GA, GB]) Map(f func(A) B) func(GA) GB {
52+
return Map[GA, GB, E, A, B](f)
53+
}
54+
4855
// Pointed implements the pointed operations for [IOEither]
4956
func Pointed[E, A any, GA ~func() ET.Either[E, A]]() pointed.Pointed[A, GA] {
5057
return &ioEitherPointed[E, A, GA]{}
5158
}
5259

60+
// Functor implements the monadic operations for [IOEither]
61+
func Functor[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B]]() functor.Functor[A, B, GA, GB] {
62+
return &ioEitherFunctor[E, A, B, GA, GB]{}
63+
}
64+
5365
// Monad implements the monadic operations for [IOEither]
5466
func Monad[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B]]() monad.Monad[A, B, GA, GB, GAB] {
5567
return &ioEitherMonad[E, A, B, GA, GB, GAB]{}

ioeither/monad.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package ioeither
1717

1818
import (
19+
"github.com/IBM/fp-go/internal/functor"
1920
"github.com/IBM/fp-go/internal/monad"
2021
"github.com/IBM/fp-go/internal/pointed"
2122
G "github.com/IBM/fp-go/ioeither/generic"
@@ -26,6 +27,11 @@ func Pointed[E, A any]() pointed.Pointed[A, IOEither[E, A]] {
2627
return G.Pointed[E, A, IOEither[E, A]]()
2728
}
2829

30+
// Functor returns the functor operations for [IOEither]
31+
func Functor[E, A, B any]() functor.Functor[A, B, IOEither[E, A], IOEither[E, B]] {
32+
return G.Functor[E, A, B, IOEither[E, A], IOEither[E, B]]()
33+
}
34+
2935
// Monad returns the monadic operations for [IOEither]
3036
func Monad[E, A, B any]() monad.Monad[A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]] {
3137
return G.Monad[E, A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]]()

ioeither/sequence_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
1616
package ioeither
1717

1818
import (
19+
"fmt"
20+
1921
A "github.com/IBM/fp-go/array"
2022
E "github.com/IBM/fp-go/either"
2123
F "github.com/IBM/fp-go/function"
2224
"github.com/stretchr/testify/assert"
2325

26+
TST "github.com/IBM/fp-go/internal/testing"
27+
2428
"testing"
2529
)
2630

@@ -46,3 +50,33 @@ func TestMapSeq(t *testing.T) {
4650

4751
assert.Equal(t, E.Of[error](true), res())
4852
}
53+
54+
func TestSequenceArray(t *testing.T) {
55+
56+
s := TST.SequenceArrayTest(
57+
FromStrictEquals[error, bool](),
58+
Pointed[error, string](),
59+
Pointed[error, bool](),
60+
Functor[error, []string, bool](),
61+
SequenceArray[error, string],
62+
)
63+
64+
for i := 0; i < 10; i++ {
65+
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
66+
}
67+
}
68+
69+
func TestSequenceArrayError(t *testing.T) {
70+
71+
s := TST.SequenceArrayErrorTest(
72+
FromStrictEquals[error, bool](),
73+
Left[string, error],
74+
Left[bool, error],
75+
Pointed[error, string](),
76+
Pointed[error, bool](),
77+
Functor[error, []string, bool](),
78+
SequenceArray[error, string],
79+
)
80+
// run across four bits
81+
s(4)(t)
82+
}

readerioeither/array_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ package readerioeither
1717

1818
import (
1919
"context"
20+
"fmt"
2021
"testing"
2122

2223
A "github.com/IBM/fp-go/array"
2324
ET "github.com/IBM/fp-go/either"
2425
F "github.com/IBM/fp-go/function"
26+
TST "github.com/IBM/fp-go/internal/testing"
2527
"github.com/stretchr/testify/assert"
2628
)
2729

@@ -37,3 +39,33 @@ func TestTraverseArray(t *testing.T) {
3739
assert.Equal(t, ET.Right[string]([]string{"aa", "bb"}), F.Pipe1([]string{"a", "b"}, f)(ctx)())
3840
assert.Equal(t, ET.Left[[]string]("e"), F.Pipe1([]string{"a", ""}, f)(ctx)())
3941
}
42+
43+
func TestSequenceArray(t *testing.T) {
44+
45+
s := TST.SequenceArrayTest(
46+
FromStrictEquals[context.Context, error, bool]()(context.Background()),
47+
Pointed[context.Context, error, string](),
48+
Pointed[context.Context, error, bool](),
49+
Functor[context.Context, error, []string, bool](),
50+
SequenceArray[context.Context, error, string],
51+
)
52+
53+
for i := 0; i < 10; i++ {
54+
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
55+
}
56+
}
57+
58+
func TestSequenceArrayError(t *testing.T) {
59+
60+
s := TST.SequenceArrayErrorTest(
61+
FromStrictEquals[context.Context, error, bool]()(context.Background()),
62+
Left[context.Context, string, error],
63+
Left[context.Context, bool, error],
64+
Pointed[context.Context, error, string](),
65+
Pointed[context.Context, error, bool](),
66+
Functor[context.Context, error, []string, bool](),
67+
SequenceArray[context.Context, error, string],
68+
)
69+
// run across four bits
70+
s(4)(t)
71+
}

0 commit comments

Comments
 (0)