// Copyright (c) 2023 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 ( "encoding/json" "fmt" "testing" F "github.com/IBM/fp-go/function" "github.com/IBM/fp-go/internal/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type ( SampleData struct { Value string OptValue Option[string] } ) func TestJson(t *testing.T) { sample := SampleData{ Value: "value", OptValue: Of("optValue"), } data, err := json.Marshal(&sample) require.NoError(t, err) var deser SampleData err = json.Unmarshal(data, &deser) require.NoError(t, err) assert.Equal(t, sample, deser) sample = SampleData{ Value: "value", OptValue: None[string](), } data, err = json.Marshal(&sample) require.NoError(t, err) err = json.Unmarshal(data, &deser) require.NoError(t, err) assert.Equal(t, sample, deser) } func TestDefault(t *testing.T) { var e Option[string] assert.Equal(t, None[string](), e) } func TestReduce(t *testing.T) { assert.Equal(t, 2, F.Pipe1(None[int](), Reduce(utils.Sum, 2))) assert.Equal(t, 5, F.Pipe1(Some(3), Reduce(utils.Sum, 2))) } func TestIsNone(t *testing.T) { assert.True(t, IsNone(None[int]())) assert.False(t, IsNone(Of(1))) } func TestIsSome(t *testing.T) { assert.True(t, IsSome(Of(1))) assert.False(t, IsSome(None[int]())) } func TestMapOption(t *testing.T) { assert.Equal(t, F.Pipe1(Some(2), Map(utils.Double)), Some(4)) assert.Equal(t, F.Pipe1(None[int](), Map(utils.Double)), None[int]()) } func TestTryCachOption(t *testing.T) { res := TryCatch(utils.Error) assert.Equal(t, None[int](), res) } func TestAp(t *testing.T) { assert.Equal(t, Some(4), F.Pipe1( Some(utils.Double), Ap[int, int](Some(2)), )) assert.Equal(t, None[int](), F.Pipe1( Some(utils.Double), Ap[int, int](None[int]()), )) assert.Equal(t, None[int](), F.Pipe1( None[func(int) int](), Ap[int, int](Some(2)), )) assert.Equal(t, None[int](), F.Pipe1( None[func(int) int](), Ap[int, int](None[int]()), )) } func TestChain(t *testing.T) { f := func(n int) Option[int] { return Some(n * 2) } g := func(_ int) Option[int] { return None[int]() } assert.Equal(t, Some(2), F.Pipe1( Some(1), Chain(f), )) assert.Equal(t, None[int](), F.Pipe1( None[int](), Chain(f), )) assert.Equal(t, None[int](), F.Pipe1( Some(1), Chain(g), )) assert.Equal(t, None[int](), F.Pipe1( None[int](), Chain(g), )) } func TestFlatten(t *testing.T) { assert.Equal(t, Of(1), F.Pipe1(Of(Of(1)), Flatten[int])) } func TestFold(t *testing.T) { f := F.Constant("none") g := func(s string) string { return fmt.Sprintf("some%d", len(s)) } fold := Fold(f, g) assert.Equal(t, "none", fold(None[string]())) assert.Equal(t, "some3", fold(Some("abc"))) } func TestFromPredicate(t *testing.T) { p := func(n int) bool { return n > 2 } f := FromPredicate(p) assert.Equal(t, None[int](), f(1)) assert.Equal(t, Some(3), f(3)) } func TestAlt(t *testing.T) { assert.Equal(t, Some(1), F.Pipe1(Some(1), Alt(F.Constant(Some(2))))) assert.Equal(t, Some(2), F.Pipe1(Some(2), Alt(F.Constant(None[int]())))) assert.Equal(t, Some(1), F.Pipe1(None[int](), Alt(F.Constant(Some(1))))) assert.Equal(t, None[int](), F.Pipe1(None[int](), Alt(F.Constant(None[int]())))) }