mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-23 22:14:53 +02:00
* 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>
270 lines
7.3 KiB
Go
270 lines
7.3 KiB
Go
// Copyright (c) 2023 - 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 di
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
E "github.com/IBM/fp-go/v2/either"
|
|
F "github.com/IBM/fp-go/v2/function"
|
|
IOE "github.com/IBM/fp-go/v2/ioeither"
|
|
IOO "github.com/IBM/fp-go/v2/iooption"
|
|
O "github.com/IBM/fp-go/v2/option"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestMakeToken(t *testing.T) {
|
|
token := MakeToken[string]("TestToken")
|
|
|
|
assert.NotNil(t, token)
|
|
assert.Equal(t, "TestToken", token.String())
|
|
assert.NotEmpty(t, token.Id())
|
|
}
|
|
|
|
func TestTokenIdentity(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
identity := token.Identity()
|
|
|
|
assert.NotNil(t, identity)
|
|
assert.Equal(t, token.Id(), identity.Id())
|
|
assert.Equal(t, token.String(), identity.String())
|
|
}
|
|
|
|
func TestTokenOption(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
option := token.Option()
|
|
|
|
assert.NotNil(t, option)
|
|
assert.Contains(t, option.String(), "Option")
|
|
assert.Equal(t, token.Id(), option.Id())
|
|
}
|
|
|
|
func TestTokenIOEither(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
ioeither := token.IOEither()
|
|
|
|
assert.NotNil(t, ioeither)
|
|
assert.Contains(t, ioeither.String(), "IOEither")
|
|
assert.Equal(t, token.Id(), ioeither.Id())
|
|
}
|
|
|
|
func TestTokenIOOption(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
iooption := token.IOOption()
|
|
|
|
assert.NotNil(t, iooption)
|
|
assert.Contains(t, iooption.String(), "IOOption")
|
|
assert.Equal(t, token.Id(), iooption.Id())
|
|
}
|
|
|
|
func TestTokenUnerase(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
|
|
// Test successful unerase
|
|
result := token.Unerase(42)
|
|
assert.True(t, E.IsRight(result))
|
|
assert.Equal(t, E.Of[error](42), result)
|
|
|
|
// Test failed unerase (wrong type)
|
|
result2 := token.Unerase("not an int")
|
|
assert.True(t, E.IsLeft(result2))
|
|
}
|
|
|
|
func TestTokenFlag(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
|
|
// Flags should be set for different dependency types
|
|
optionFlag := token.Option().Flag()
|
|
ioeitherFlag := token.IOEither().Flag()
|
|
iooptionFlag := token.IOOption().Flag()
|
|
|
|
// Flags should be different for different types
|
|
assert.NotEqual(t, optionFlag, ioeitherFlag)
|
|
assert.NotEqual(t, optionFlag, iooptionFlag)
|
|
assert.NotEqual(t, ioeitherFlag, iooptionFlag)
|
|
}
|
|
|
|
func TestTokenProviderFactory(t *testing.T) {
|
|
// Token without default
|
|
token1 := MakeToken[int]("Token1")
|
|
assert.True(t, O.IsNone(token1.ProviderFactory()))
|
|
|
|
// Token with default
|
|
token2 := MakeTokenWithDefault0("Token2", IOE.Of[error](42))
|
|
assert.True(t, O.IsSome(token2.ProviderFactory()))
|
|
}
|
|
|
|
func TestMakeMultiToken(t *testing.T) {
|
|
multiToken := MakeMultiToken[string]("MultiToken")
|
|
|
|
assert.NotNil(t, multiToken)
|
|
assert.NotNil(t, multiToken.Container())
|
|
assert.NotNil(t, multiToken.Item())
|
|
|
|
// Container and Item should share the same ID
|
|
assert.Equal(t, multiToken.Container().Id(), multiToken.Item().Id())
|
|
|
|
// But have different names
|
|
assert.Contains(t, multiToken.Container().String(), "Container")
|
|
assert.Contains(t, multiToken.Item().String(), "Item")
|
|
}
|
|
|
|
func TestMultiTokenFlags(t *testing.T) {
|
|
multiToken := MakeMultiToken[string]("MultiToken")
|
|
|
|
// Container should have Multi flag
|
|
containerFlag := multiToken.Container().Flag()
|
|
assert.NotZero(t, containerFlag)
|
|
|
|
// Item should have Item flag
|
|
itemFlag := multiToken.Item().Flag()
|
|
assert.NotZero(t, itemFlag)
|
|
}
|
|
|
|
func TestTokenUniqueness(t *testing.T) {
|
|
token1 := MakeToken[int]("Token")
|
|
token2 := MakeToken[int]("Token")
|
|
|
|
// Even with same name, IDs should be different
|
|
assert.NotEqual(t, token1.Id(), token2.Id())
|
|
}
|
|
|
|
func TestOptionTokenUnerase(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
optionToken := token.Option()
|
|
|
|
// Test successful unerase with Some
|
|
result := optionToken.Unerase(O.Of[any](42))
|
|
assert.True(t, E.IsRight(result))
|
|
|
|
// Test successful unerase with None
|
|
noneResult := optionToken.Unerase(O.None[any]())
|
|
assert.True(t, E.IsRight(noneResult))
|
|
assert.Equal(t, E.Of[error](O.None[int]()), noneResult)
|
|
|
|
// Test failed unerase (wrong type)
|
|
badResult := optionToken.Unerase(42) // Not an Option
|
|
assert.True(t, E.IsLeft(badResult))
|
|
}
|
|
|
|
func TestIOEitherTokenUnerase(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
ioeitherToken := token.IOEither()
|
|
|
|
// Test successful unerase
|
|
ioValue := IOE.Of[error](any(42))
|
|
result := ioeitherToken.Unerase(ioValue)
|
|
assert.True(t, E.IsRight(result))
|
|
|
|
// Execute the IOEither to verify it works
|
|
if E.IsRight(result) {
|
|
ioe := E.ToOption(result)
|
|
if O.IsSome(ioe) {
|
|
executed := O.GetOrElse(F.Constant(IOE.Left[int](errors.New("fail"))))(ioe)()
|
|
assert.True(t, E.IsRight(executed))
|
|
}
|
|
}
|
|
|
|
// Test failed unerase (wrong type)
|
|
badResult := ioeitherToken.Unerase(42)
|
|
assert.True(t, E.IsLeft(badResult))
|
|
}
|
|
|
|
func TestIOOptionTokenUnerase(t *testing.T) {
|
|
token := MakeToken[int]("IntToken")
|
|
iooptionToken := token.IOOption()
|
|
|
|
// Test successful unerase
|
|
ioValue := IOO.Of(any(42))
|
|
result := iooptionToken.Unerase(ioValue)
|
|
assert.True(t, E.IsRight(result))
|
|
|
|
// Test failed unerase (wrong type)
|
|
badResult := iooptionToken.Unerase(42)
|
|
assert.True(t, E.IsLeft(badResult))
|
|
}
|
|
|
|
func TestMultiTokenContainerUnerase(t *testing.T) {
|
|
multiToken := MakeMultiToken[int]("MultiToken")
|
|
container := multiToken.Container()
|
|
|
|
// Test successful unerase with array
|
|
arrayValue := []any{1, 2, 3}
|
|
result := container.Unerase(arrayValue)
|
|
assert.True(t, E.IsRight(result))
|
|
|
|
if E.IsRight(result) {
|
|
arr := E.ToOption(result)
|
|
if O.IsSome(arr) {
|
|
values := O.GetOrElse(F.Constant([]int{}))(arr)
|
|
assert.Equal(t, []int{1, 2, 3}, values)
|
|
}
|
|
}
|
|
|
|
// Test failed unerase (wrong type in array)
|
|
badArray := []any{1, "not an int", 3}
|
|
badResult := container.Unerase(badArray)
|
|
assert.True(t, E.IsLeft(badResult))
|
|
}
|
|
|
|
func TestMakeTokenWithDefault(t *testing.T) {
|
|
factory := MakeProviderFactory0(IOE.Of[error](42))
|
|
token := MakeTokenWithDefault[int]("TokenWithDefault", factory)
|
|
|
|
assert.NotNil(t, token)
|
|
assert.True(t, O.IsSome(token.ProviderFactory()))
|
|
}
|
|
|
|
func TestTokenStringRepresentation(t *testing.T) {
|
|
token := MakeToken[int]("MyToken")
|
|
|
|
assert.Equal(t, "MyToken", token.String())
|
|
assert.Contains(t, token.Option().String(), "Option[MyToken]")
|
|
assert.Contains(t, token.IOEither().String(), "IOEither[MyToken]")
|
|
assert.Contains(t, token.IOOption().String(), "IOOption[MyToken]")
|
|
}
|
|
|
|
func TestMultiTokenStringRepresentation(t *testing.T) {
|
|
multiToken := MakeMultiToken[int]("MyMulti")
|
|
|
|
assert.Contains(t, multiToken.Container().String(), "Container[MyMulti]")
|
|
assert.Contains(t, multiToken.Item().String(), "Item[MyMulti]")
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkMakeToken(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
MakeToken[int]("BenchToken")
|
|
}
|
|
}
|
|
|
|
func BenchmarkTokenUnerase(b *testing.B) {
|
|
token := MakeToken[int]("BenchToken")
|
|
value := any(42)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
token.Unerase(value)
|
|
}
|
|
}
|
|
|
|
func BenchmarkMakeMultiToken(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
MakeMultiToken[int]("BenchMulti")
|
|
}
|
|
}
|