Skip to content

Commit

Permalink
fix: more testing
Browse files Browse the repository at this point in the history
Signed-off-by: Dr. Carsten Leue <[email protected]>
  • Loading branch information
CarstenLeue committed May 25, 2024
1 parent 598a7b2 commit 391754e
Show file tree
Hide file tree
Showing 11 changed files with 367 additions and 1 deletion.
3 changes: 2 additions & 1 deletion coverage.bat
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@echo off
go tool cover -html=build/cover.out -o build/cover.html
go tool cover -html=build/cover.out -o build/cover.html
cov-report -ex ".*/cli/.*.go|.*/gen.go|.*/binds.go" build\cover.out
32 changes: 32 additions & 0 deletions either/array_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package either

import (
"fmt"
"testing"

TST "github.com/IBM/fp-go/internal/testing"
"github.com/stretchr/testify/assert"
)

Expand All @@ -16,3 +18,33 @@ func TestCompactArray(t *testing.T) {
res := CompactArray(ar)
assert.Equal(t, 2, len(res))
}

func TestSequenceArray(t *testing.T) {

s := TST.SequenceArrayTest(
FromStrictEquals[error, bool](),
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)

for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}

func TestSequenceArrayError(t *testing.T) {

s := TST.SequenceArrayErrorTest(
FromStrictEquals[error, bool](),
Left[string, error],
Left[bool, error],
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)
// run across four bits
s(4)(t)
}
31 changes: 31 additions & 0 deletions either/functor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package either

import (
"github.com/IBM/fp-go/internal/functor"
)

type eitherFunctor[E, A, B any] struct{}

func (o *eitherFunctor[E, A, B]) Map(f func(A) B) func(Either[E, A]) Either[E, B] {
return Map[E, A, B](f)
}

// Functor implements the functoric operations for [Either]
func Functor[E, A, B any]() functor.Functor[A, B, Either[E, A], Either[E, B]] {
return &eitherFunctor[E, A, B]{}
}
31 changes: 31 additions & 0 deletions either/pointed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package either

import (
"github.com/IBM/fp-go/internal/pointed"
)

type eitherPointed[E, A any] struct{}

func (o *eitherPointed[E, A]) Of(a A) Either[E, A] {
return Of[E, A](a)
}

// Pointed implements the pointedic operations for [Either]
func Pointed[E, A any]() pointed.Pointed[A, Either[E, A]] {
return &eitherPointed[E, A]{}
}
81 changes: 81 additions & 0 deletions internal/testing/sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,84 @@ func SequenceArrayTest[
}
}
}

// SequenceArrayErrorTest tests if the sequence operation works in case the operation can error
func SequenceArrayErrorTest[
HKTA,
HKTB,
HKTAA any, // HKT[[]A]
](
eq EQ.Eq[HKTB],

left func(error) HKTA,
leftB func(error) HKTB,
pa pointed.Pointed[string, HKTA],
pb pointed.Pointed[bool, HKTB],
faa functor.Functor[[]string, bool, HKTAA, HKTB],
seq func([]HKTA) HKTAA,
) func(count int) func(t *testing.T) {

return func(count int) func(t *testing.T) {

expGood := make([]string, count)
good := make([]HKTA, count)
expBad := make([]error, count)
bad := make([]HKTA, count)

for i := 0; i < count; i++ {
goodVal := fmt.Sprintf("TestData %d", i)
badVal := fmt.Errorf("ErrorData %d", i)
expGood[i] = goodVal
good[i] = pa.Of(goodVal)
expBad[i] = badVal
bad[i] = left(badVal)
}

total := 1 << count

return func(t *testing.T) {
// test the good case
res := F.Pipe2(
good,
seq,
faa.Map(func(act []string) bool {
return assert.Equal(t, expGood, act)
}),
)
assert.True(t, eq.Equals(res, pb.Of(true)))
// iterate and test the bad cases
for i := 1; i < total; i++ {
// run the test
t.Run(fmt.Sprintf("Bitmask test %d", i), func(t1 *testing.T) {
// the actual
act := make([]HKTA, count)
// the expected error
var exp error
// prepare the values bases on the bit mask
mask := 1
for j := 0; j < count; j++ {
if (i & mask) == 0 {
act[j] = good[j]
} else {
act[j] = bad[j]
if exp == nil {
exp = expBad[j]
}
}
mask <<= 1
}
// test the good case
res := F.Pipe2(
act,
seq,
faa.Map(func(act []string) bool {
return assert.Equal(t, expGood, act)
}),
)
// validate the error
assert.True(t, eq.Equals(res, leftB(exp)))
})
}
}
}
}
12 changes: 12 additions & 0 deletions ioeither/generic/monad.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package generic

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

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{}

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

func (o *ioEitherPointed[E, A, GA]) Of(a A) GA {
return Of[GA, E, A](a)
}
Expand All @@ -45,11 +48,20 @@ func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB {
return Ap[GB, GAB, GA, E, A, B](fa)
}

func (o *ioEitherFunctor[E, A, B, GA, GB]) Map(f func(A) B) func(GA) GB {
return Map[GA, GB, E, A, B](f)
}

// Pointed implements the pointed operations for [IOEither]
func Pointed[E, A any, GA ~func() ET.Either[E, A]]() pointed.Pointed[A, GA] {
return &ioEitherPointed[E, A, GA]{}
}

// Functor implements the monadic operations for [IOEither]
func Functor[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B]]() functor.Functor[A, B, GA, GB] {
return &ioEitherFunctor[E, A, B, GA, GB]{}
}

// Monad implements the monadic operations for [IOEither]
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] {
return &ioEitherMonad[E, A, B, GA, GB, GAB]{}
Expand Down
6 changes: 6 additions & 0 deletions ioeither/monad.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package ioeither

import (
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
G "github.com/IBM/fp-go/ioeither/generic"
Expand All @@ -26,6 +27,11 @@ func Pointed[E, A any]() pointed.Pointed[A, IOEither[E, A]] {
return G.Pointed[E, A, IOEither[E, A]]()
}

// Functor returns the functor operations for [IOEither]
func Functor[E, A, B any]() functor.Functor[A, B, IOEither[E, A], IOEither[E, B]] {
return G.Functor[E, A, B, IOEither[E, A], IOEither[E, B]]()
}

// Monad returns the monadic operations for [IOEither]
func Monad[E, A, B any]() monad.Monad[A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]] {
return G.Monad[E, A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]]()
Expand Down
34 changes: 34 additions & 0 deletions ioeither/sequence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
package ioeither

import (
"fmt"

A "github.com/IBM/fp-go/array"
E "github.com/IBM/fp-go/either"
F "github.com/IBM/fp-go/function"
"github.com/stretchr/testify/assert"

TST "github.com/IBM/fp-go/internal/testing"

"testing"
)

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

assert.Equal(t, E.Of[error](true), res())
}

func TestSequenceArray(t *testing.T) {

s := TST.SequenceArrayTest(
FromStrictEquals[error, bool](),
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)

for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}

func TestSequenceArrayError(t *testing.T) {

s := TST.SequenceArrayErrorTest(
FromStrictEquals[error, bool](),
Left[string, error],
Left[bool, error],
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)
// run across four bits
s(4)(t)
}
32 changes: 32 additions & 0 deletions readerioeither/array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ package readerioeither

import (
"context"
"fmt"
"testing"

A "github.com/IBM/fp-go/array"
ET "github.com/IBM/fp-go/either"
F "github.com/IBM/fp-go/function"
TST "github.com/IBM/fp-go/internal/testing"
"github.com/stretchr/testify/assert"
)

Expand All @@ -37,3 +39,33 @@ func TestTraverseArray(t *testing.T) {
assert.Equal(t, ET.Right[string]([]string{"aa", "bb"}), F.Pipe1([]string{"a", "b"}, f)(ctx)())
assert.Equal(t, ET.Left[[]string]("e"), F.Pipe1([]string{"a", ""}, f)(ctx)())
}

func TestSequenceArray(t *testing.T) {

s := TST.SequenceArrayTest(
FromStrictEquals[context.Context, error, bool]()(context.Background()),
Pointed[context.Context, error, string](),
Pointed[context.Context, error, bool](),
Functor[context.Context, error, []string, bool](),
SequenceArray[context.Context, error, string],
)

for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}

func TestSequenceArrayError(t *testing.T) {

s := TST.SequenceArrayErrorTest(
FromStrictEquals[context.Context, error, bool]()(context.Background()),
Left[context.Context, string, error],
Left[context.Context, bool, error],
Pointed[context.Context, error, string](),
Pointed[context.Context, error, bool](),
Functor[context.Context, error, []string, bool](),
SequenceArray[context.Context, error, string],
)
// run across four bits
s(4)(t)
}
Loading

0 comments on commit 391754e

Please sign in to comment.