1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-11-25 22:21:49 +02:00
Files
fp-go/v2/option/option_coverage_test.go
Carsten Leue 3385c705dc Implement v2 using type aliases (#141)
* fix: initial checkin of v2

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: slowly migrate IO

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate MonadTraverseArray and TraverseArray

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate traversal

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: complete migration of IO

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate ioeither

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: refactorY

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: next step in migration

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: adjust IO generation code

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: get rid of more IO methods

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: get rid of more IO

* fix: convert iooption

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: convert reader

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: convert a bit of reader

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: new build script

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: cleanup

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: reformat

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: simplify

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: some cleanup

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: adjust Pair to Haskell semantic

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: documentation and testcases

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: some performance optimizations

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: remove coverage

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: better doc

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

---------

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 09:27:00 +01:00

568 lines
15 KiB
Go

// Copyright (c) 2025 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 option
import (
"fmt"
"testing"
T "github.com/IBM/fp-go/v2/tuple"
"github.com/stretchr/testify/assert"
)
// Test Logger function
func TestLogger(t *testing.T) {
logger := Logger[int]()
logFunc := logger("test")
// Test with Some
result := logFunc(Some(42))
assert.Equal(t, Some(42), result)
// Test with None
result = logFunc(None[int]())
assert.Equal(t, None[int](), result)
}
// Test TraverseArrayG with custom slice types
func TestTraverseArrayG(t *testing.T) {
type MySlice []int
type MyResultSlice []string
f := func(x int) Option[string] {
if x > 0 {
return Some(fmt.Sprintf("%d", x))
}
return None[string]()
}
result := TraverseArrayG[MySlice, MyResultSlice](f)(MySlice{1, 2, 3})
expected := Some(MyResultSlice{"1", "2", "3"})
assert.Equal(t, expected, result)
// Test with failure
result = TraverseArrayG[MySlice, MyResultSlice](f)(MySlice{1, -1, 3})
assert.Equal(t, None[MyResultSlice](), result)
}
// Test SequenceArrayG with custom slice types
func TestSequenceArrayG(t *testing.T) {
type MySlice []int
input := []Option[int]{Some(1), Some(2), Some(3)}
result := SequenceArrayG[MySlice](input)
expected := Some(MySlice{1, 2, 3})
assert.Equal(t, expected, result)
// Test with None
input = []Option[int]{Some(1), None[int](), Some(3)}
result = SequenceArrayG[MySlice](input)
assert.Equal(t, None[MySlice](), result)
}
// Test CompactArrayG with custom slice types
func TestCompactArrayG(t *testing.T) {
type MySlice []int
input := []Option[int]{Some(1), None[int](), Some(3), Some(5)}
result := CompactArrayG[[]Option[int], MySlice](input)
expected := MySlice{1, 3, 5}
assert.Equal(t, expected, result)
}
// Test TraverseRecordG with custom map types
func TestTraverseRecordG(t *testing.T) {
type MyMap map[string]int
type MyResultMap map[string]string
f := func(x int) Option[string] {
if x > 0 {
return Some(fmt.Sprintf("%d", x))
}
return None[string]()
}
input := MyMap{"a": 1, "b": 2}
result := TraverseRecordG[MyMap, MyResultMap](f)(input)
assert.True(t, IsSome(result))
unwrapped, _ := Unwrap(result)
assert.Equal(t, "1", unwrapped["a"])
assert.Equal(t, "2", unwrapped["b"])
}
// Test SequenceRecordG with custom map types
func TestSequenceRecordG(t *testing.T) {
type MyMap map[string]int
input := map[string]Option[int]{"a": Some(1), "b": Some(2)}
result := SequenceRecordG[MyMap](input)
assert.True(t, IsSome(result))
unwrapped, _ := Unwrap(result)
assert.Equal(t, 1, unwrapped["a"])
assert.Equal(t, 2, unwrapped["b"])
}
// Test CompactRecordG with custom map types
func TestCompactRecordG(t *testing.T) {
type MyMap map[string]int
input := map[string]Option[int]{"a": Some(1), "b": None[int](), "c": Some(3)}
result := CompactRecordG[map[string]Option[int], MyMap](input)
expected := MyMap{"a": 1, "c": 3}
assert.Equal(t, expected, result)
}
// Test Optionize3 through Optionize10
func TestOptionize3(t *testing.T) {
f := func(a, b, c int) (int, bool) {
if a > 0 && b > 0 && c > 0 {
return a + b + c, true
}
return 0, false
}
optF := Optionize3(f)
assert.Equal(t, Some(6), optF(1, 2, 3))
assert.Equal(t, None[int](), optF(-1, 2, 3))
}
func TestOptionize4(t *testing.T) {
f := func(a, b, c, d int) (int, bool) {
sum := a + b + c + d
return sum, sum > 0
}
optF := Optionize4(f)
assert.Equal(t, Some(10), optF(1, 2, 3, 4))
assert.Equal(t, None[int](), optF(-5, 1, 1, 1))
}
func TestOptionize5(t *testing.T) {
f := func(a, b, c, d, e int) (int, bool) {
sum := a + b + c + d + e
return sum, sum > 0
}
optF := Optionize5(f)
assert.Equal(t, Some(15), optF(1, 2, 3, 4, 5))
}
// Test Unoptionize3 through Unoptionize10
func TestUnoptionize3(t *testing.T) {
f := func(a, b, c int) Option[int] {
if a > 0 && b > 0 && c > 0 {
return Some(a + b + c)
}
return None[int]()
}
unoptF := Unoptionize3(f)
val, ok := unoptF(1, 2, 3)
assert.True(t, ok)
assert.Equal(t, 6, val)
_, ok = unoptF(-1, 2, 3)
assert.False(t, ok)
}
func TestUnoptionize4(t *testing.T) {
f := func(a, b, c, d int) Option[int] {
return Some(a + b + c + d)
}
unoptF := Unoptionize4(f)
val, ok := unoptF(1, 2, 3, 4)
assert.True(t, ok)
assert.Equal(t, 10, val)
}
// Test SequenceT5 through SequenceT10
func TestSequenceT5(t *testing.T) {
result := SequenceT5(Some(1), Some(2), Some(3), Some(4), Some(5))
expected := Some(T.MakeTuple5(1, 2, 3, 4, 5))
assert.Equal(t, expected, result)
// Test with None
result = SequenceT5(Some(1), None[int](), Some(3), Some(4), Some(5))
assert.Equal(t, None[T.Tuple5[int, int, int, int, int]](), result)
}
func TestSequenceT6(t *testing.T) {
result := SequenceT6(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6))
expected := Some(T.MakeTuple6(1, 2, 3, 4, 5, 6))
assert.Equal(t, expected, result)
}
func TestSequenceT7(t *testing.T) {
result := SequenceT7(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7))
expected := Some(T.MakeTuple7(1, 2, 3, 4, 5, 6, 7))
assert.Equal(t, expected, result)
}
func TestSequenceT8(t *testing.T) {
result := SequenceT8(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8))
expected := Some(T.MakeTuple8(1, 2, 3, 4, 5, 6, 7, 8))
assert.Equal(t, expected, result)
}
func TestSequenceT9(t *testing.T) {
result := SequenceT9(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9))
expected := Some(T.MakeTuple9(1, 2, 3, 4, 5, 6, 7, 8, 9))
assert.Equal(t, expected, result)
}
func TestSequenceT10(t *testing.T) {
result := SequenceT10(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(10))
expected := Some(T.MakeTuple10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
assert.Equal(t, expected, result)
}
// Test SequenceTuple4 through SequenceTuple10
func TestSequenceTuple4(t *testing.T) {
tuple := T.MakeTuple4(Some(1), Some(2), Some(3), Some(4))
result := SequenceTuple4(tuple)
expected := Some(T.MakeTuple4(1, 2, 3, 4))
assert.Equal(t, expected, result)
}
func TestSequenceTuple5(t *testing.T) {
tuple := T.MakeTuple5(Some(1), Some(2), Some(3), Some(4), Some(5))
result := SequenceTuple5(tuple)
expected := Some(T.MakeTuple5(1, 2, 3, 4, 5))
assert.Equal(t, expected, result)
}
func TestSequenceTuple6(t *testing.T) {
tuple := T.MakeTuple6(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6))
result := SequenceTuple6(tuple)
expected := Some(T.MakeTuple6(1, 2, 3, 4, 5, 6))
assert.Equal(t, expected, result)
}
// Test TraverseTuple3 through TraverseTuple10
func TestTraverseTuple3(t *testing.T) {
f1 := func(x int) Option[int] { return Some(x * 2) }
f2 := func(s string) Option[string] { return Some(s + "!") }
f3 := func(b bool) Option[bool] { return Some(!b) }
traverse := TraverseTuple3(f1, f2, f3)
tuple := T.MakeTuple3(5, "hello", true)
result := traverse(tuple)
expected := Some(T.MakeTuple3(10, "hello!", false))
assert.Equal(t, expected, result)
}
func TestTraverseTuple4(t *testing.T) {
f1 := func(x int) Option[int] { return Some(x * 2) }
f2 := func(x int) Option[int] { return Some(x + 1) }
f3 := func(x int) Option[int] { return Some(x - 1) }
f4 := func(x int) Option[int] { return Some(x * 3) }
traverse := TraverseTuple4(f1, f2, f3, f4)
tuple := T.MakeTuple4(1, 2, 3, 4)
result := traverse(tuple)
expected := Some(T.MakeTuple4(2, 3, 2, 12))
assert.Equal(t, expected, result)
}
// Test JSON marshaling edge cases
func TestJSONMarshalNone(t *testing.T) {
none := None[int]()
data, err := none.MarshalJSON()
assert.NoError(t, err)
assert.Equal(t, []byte("null"), data)
}
func TestJSONMarshalSome(t *testing.T) {
some := Some(42)
data, err := some.MarshalJSON()
assert.NoError(t, err)
assert.Equal(t, []byte("42"), data)
}
// Test Format method
func TestFormat(t *testing.T) {
some := Some(42)
formatted := fmt.Sprintf("%s", some)
assert.Contains(t, formatted, "Some")
assert.Contains(t, formatted, "42")
none := None[int]()
formatted = fmt.Sprintf("%s", none)
assert.Contains(t, formatted, "None")
}
// Test edge cases for MonadFold
func TestMonadFoldEdgeCases(t *testing.T) {
// Test with complex types
type ComplexType struct {
value int
name string
}
some := Some(ComplexType{value: 42, name: "test"})
result := MonadFold(some,
func() string { return "none" },
func(ct ComplexType) string { return ct.name },
)
assert.Equal(t, "test", result)
none := None[ComplexType]()
result = MonadFold(none,
func() string { return "none" },
func(ct ComplexType) string { return ct.name },
)
assert.Equal(t, "none", result)
}
// Test TraverseArrayWithIndexG
func TestTraverseArrayWithIndexG(t *testing.T) {
type MySlice []int
type MyResultSlice []string
f := func(i int, x int) Option[string] {
return Some(fmt.Sprintf("%d:%d", i, x))
}
result := TraverseArrayWithIndexG[MySlice, MyResultSlice](f)(MySlice{10, 20, 30})
expected := Some(MyResultSlice{"0:10", "1:20", "2:30"})
assert.Equal(t, expected, result)
}
// Test TraverseRecordWithIndexG
func TestTraverseRecordWithIndexG(t *testing.T) {
type MyMap map[string]int
type MyResultMap map[string]string
f := func(k string, v int) Option[string] {
return Some(fmt.Sprintf("%s=%d", k, v))
}
input := MyMap{"a": 1, "b": 2}
result := TraverseRecordWithIndexG[MyMap, MyResultMap](f)(input)
assert.True(t, IsSome(result))
}
// Test SequenceTuple1
func TestSequenceTuple1(t *testing.T) {
tuple := T.MakeTuple1(Some(42))
result := SequenceTuple1(tuple)
expected := Some(T.MakeTuple1(42))
assert.Equal(t, expected, result)
// Test with None
tuple = T.MakeTuple1(None[int]())
result = SequenceTuple1(tuple)
assert.Equal(t, None[T.Tuple1[int]](), result)
}
// Test TraverseTuple1
func TestTraverseTuple1(t *testing.T) {
f := func(x int) Option[int] { return Some(x * 2) }
traverse := TraverseTuple1(f)
tuple := T.MakeTuple1(5)
result := traverse(tuple)
expected := Some(T.MakeTuple1(10))
assert.Equal(t, expected, result)
}
// Test Unoptionize2
func TestUnoptionize2(t *testing.T) {
f := func(a, b int) Option[int] {
return Some(a + b)
}
unoptF := Unoptionize2(f)
val, ok := unoptF(2, 3)
assert.True(t, ok)
assert.Equal(t, 5, val)
}
// Test Unoptionize5
func TestUnoptionize5(t *testing.T) {
f := func(a, b, c, d, e int) Option[int] {
return Some(a + b + c + d + e)
}
unoptF := Unoptionize5(f)
val, ok := unoptF(1, 2, 3, 4, 5)
assert.True(t, ok)
assert.Equal(t, 15, val)
}
// Test Unoptionize6
func TestUnoptionize6(t *testing.T) {
f := func(a, b, c, d, e, f int) Option[int] {
return Some(a + b + c + d + e + f)
}
unoptF := Unoptionize6(f)
val, ok := unoptF(1, 2, 3, 4, 5, 6)
assert.True(t, ok)
assert.Equal(t, 21, val)
}
// Test Optionize6
func TestOptionize6(t *testing.T) {
f := func(a, b, c, d, e, f int) (int, bool) {
sum := a + b + c + d + e + f
return sum, sum > 0
}
optF := Optionize6(f)
assert.Equal(t, Some(21), optF(1, 2, 3, 4, 5, 6))
}
// Test Optionize7
func TestOptionize7(t *testing.T) {
f := func(a, b, c, d, e, f, g int) (int, bool) {
sum := a + b + c + d + e + f + g
return sum, sum > 0
}
optF := Optionize7(f)
assert.Equal(t, Some(28), optF(1, 2, 3, 4, 5, 6, 7))
}
// Test Unoptionize7
func TestUnoptionize7(t *testing.T) {
f := func(a, b, c, d, e, f, g int) Option[int] {
return Some(a + b + c + d + e + f + g)
}
unoptF := Unoptionize7(f)
val, ok := unoptF(1, 2, 3, 4, 5, 6, 7)
assert.True(t, ok)
assert.Equal(t, 28, val)
}
// Test Optionize8
func TestOptionize8(t *testing.T) {
f := func(a, b, c, d, e, f, g, h int) (int, bool) {
sum := a + b + c + d + e + f + g + h
return sum, sum > 0
}
optF := Optionize8(f)
assert.Equal(t, Some(36), optF(1, 2, 3, 4, 5, 6, 7, 8))
}
// Test Unoptionize8
func TestUnoptionize8(t *testing.T) {
f := func(a, b, c, d, e, f, g, h int) Option[int] {
return Some(a + b + c + d + e + f + g + h)
}
unoptF := Unoptionize8(f)
val, ok := unoptF(1, 2, 3, 4, 5, 6, 7, 8)
assert.True(t, ok)
assert.Equal(t, 36, val)
}
// Test Optionize9
func TestOptionize9(t *testing.T) {
f := func(a, b, c, d, e, f, g, h, i int) (int, bool) {
sum := a + b + c + d + e + f + g + h + i
return sum, sum > 0
}
optF := Optionize9(f)
assert.Equal(t, Some(45), optF(1, 2, 3, 4, 5, 6, 7, 8, 9))
}
// Test Unoptionize9
func TestUnoptionize9(t *testing.T) {
f := func(a, b, c, d, e, f, g, h, i int) Option[int] {
return Some(a + b + c + d + e + f + g + h + i)
}
unoptF := Unoptionize9(f)
val, ok := unoptF(1, 2, 3, 4, 5, 6, 7, 8, 9)
assert.True(t, ok)
assert.Equal(t, 45, val)
}
// Test Optionize10
func TestOptionize10(t *testing.T) {
f := func(a, b, c, d, e, f, g, h, i, j int) (int, bool) {
sum := a + b + c + d + e + f + g + h + i + j
return sum, sum > 0
}
optF := Optionize10(f)
assert.Equal(t, Some(55), optF(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
}
// Test Unoptionize10
func TestUnoptionize10(t *testing.T) {
f := func(a, b, c, d, e, f, g, h, i, j int) Option[int] {
return Some(a + b + c + d + e + f + g + h + i + j)
}
unoptF := Unoptionize10(f)
val, ok := unoptF(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
assert.True(t, ok)
assert.Equal(t, 55, val)
}
// Test SequenceTuple7
func TestSequenceTuple7(t *testing.T) {
tuple := T.MakeTuple7(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7))
result := SequenceTuple7(tuple)
expected := Some(T.MakeTuple7(1, 2, 3, 4, 5, 6, 7))
assert.Equal(t, expected, result)
}
// Test SequenceTuple8
func TestSequenceTuple8(t *testing.T) {
tuple := T.MakeTuple8(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8))
result := SequenceTuple8(tuple)
expected := Some(T.MakeTuple8(1, 2, 3, 4, 5, 6, 7, 8))
assert.Equal(t, expected, result)
}
// Test SequenceTuple9
func TestSequenceTuple9(t *testing.T) {
tuple := T.MakeTuple9(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9))
result := SequenceTuple9(tuple)
expected := Some(T.MakeTuple9(1, 2, 3, 4, 5, 6, 7, 8, 9))
assert.Equal(t, expected, result)
}
// Test SequenceTuple10
func TestSequenceTuple10(t *testing.T) {
tuple := T.MakeTuple10(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(10))
result := SequenceTuple10(tuple)
expected := Some(T.MakeTuple10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
assert.Equal(t, expected, result)
}
// Test TryCatch with success case
func TestTryCatchSuccess(t *testing.T) {
result := TryCatch(func() (int, error) {
return 42, nil
})
assert.Equal(t, Some(42), result)
}