diff --git a/pkl/external_reader_test.go b/pkl/external_reader_test.go index f36c1a5e..37507120 100644 --- a/pkl/external_reader_test.go +++ b/pkl/external_reader_test.go @@ -1,5 +1,5 @@ //===----------------------------------------------------------------------===// -// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. +// Copyright © 2024-2026 Apple Inc. and the Pkl project authors. 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. @@ -17,10 +17,12 @@ package pkl import ( + "bytes" "context" "path/filepath" "runtime" "testing" + "testing/fstest" "github.com/apple/pkl-go/pkl/internal" "github.com/stretchr/testify/assert" @@ -38,6 +40,56 @@ fibErrB = test.catch(() -> read("fib:abc")) fibErrC = test.catch(() -> read("fib:-10")) ` +func TestWithExternalClientResourceReader(t *testing.T) { + t.Parallel() + reader := &fsResourceReader{&fsReader{fs: fstest.MapFS{}, scheme: "test"}} + opts := &ExternalReaderClientOptions{} + WithExternalClientResourceReader(reader)(opts) + + assert.NotNil(t, opts.ResourceReaders) + assert.Len(t, opts.ResourceReaders, 1) + assert.Equal(t, "test", opts.ResourceReaders[0].Scheme()) +} + +func TestWithExternalClientModuleReader(t *testing.T) { + t.Parallel() + reader := &fsModuleReader{&fsReader{fs: fstest.MapFS{}, scheme: "test"}} + opts := &ExternalReaderClientOptions{} + WithExternalClientModuleReader(reader)(opts) + + assert.NotNil(t, opts.ModuleReaders) + assert.Len(t, opts.ModuleReaders, 1) + assert.Equal(t, "test", opts.ModuleReaders[0].Scheme()) +} + +func TestWithExternalClientStreams(t *testing.T) { + t.Parallel() + requestReader := &bytes.Buffer{} + responseWriter := &bytes.Buffer{} + opts := &ExternalReaderClientOptions{} + WithExternalClientStreams(requestReader, responseWriter)(opts) + + assert.NotNil(t, opts.RequestReader) + assert.NotNil(t, opts.ResponseWriter) +} + +func TestWithExternalClientFs(t *testing.T) { + t.Parallel() + fsTest := fstest.MapFS{ + "hello.txt": &fstest.MapFile{Data: []byte("hello")}, + } + opts := &ExternalReaderClientOptions{} + WithExternalClientFs(fsTest, "fsTest")(opts) + + assert.NotNil(t, opts.ResourceReaders) + assert.Len(t, opts.ResourceReaders, 1) + assert.Equal(t, "fsTest", opts.ResourceReaders[0].Scheme()) + + assert.NotNil(t, opts.ModuleReaders) + assert.Len(t, opts.ModuleReaders, 1) + assert.Equal(t, "fsTest", opts.ModuleReaders[0].Scheme()) +} + func TestExternalReaderE2E(t *testing.T) { manager := NewEvaluatorManager() defer func() { _ = manager.Close() }() diff --git a/pkl/unmarshal_test.go b/pkl/unmarshal_test.go index 3bee36d5..15471565 100644 --- a/pkl/unmarshal_test.go +++ b/pkl/unmarshal_test.go @@ -1,5 +1,5 @@ //===----------------------------------------------------------------------===// -// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. +// Copyright © 2024-2026 Apple Inc. and the Pkl project authors. 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. @@ -19,6 +19,7 @@ package pkl_test import ( "bytes" _ "embed" + "fmt" "testing" "github.com/apple/pkl-go/pkl" @@ -483,3 +484,18 @@ func TestUnmarshal_Types_Pre_030(t *testing.T) { assert.Equal(t, types.Types{}, res) } + +func TestUnmarshal_NonPointerTypes(t *testing.T) { + var res types.Types + err := pkl.Unmarshal([]byte{}, res) + assert.NotNil(t, err) + assert.EqualError(t, fmt.Errorf("cannot unmarshal non-pointer. Got kind: struct"), err.Error()) +} + +func TestUnmarshal_Nil(t *testing.T) { + var s *string + err := pkl.Unmarshal([]byte{}, s) + assert.NotNil(t, err) + + assert.EqualError(t, fmt.Errorf("cannot unmarshal into nil"), err.Error()) +} diff --git a/pkl/values_test.go b/pkl/values_test.go index 19824521..45020804 100644 --- a/pkl/values_test.go +++ b/pkl/values_test.go @@ -1,5 +1,5 @@ //===----------------------------------------------------------------------===// -// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. +// Copyright © 2024-2026 Apple Inc. and the Pkl project authors. 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. @@ -17,7 +17,9 @@ package pkl import ( + "fmt" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -54,11 +56,39 @@ func TestDataSize_String(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { + t.Parallel() assert.Equal(t, test.expected, test.input.String()) }) } } +func TestDataSizeUnit_String(t *testing.T) { + tests := []struct { + name string + unit DataSizeUnit + want string + }{ + {name: "byte", unit: Bytes, want: "b"}, + {name: "kilobyte", unit: Kilobytes, want: "kb"}, + {name: "kibibyte", unit: Kibibytes, want: "kib"}, + {name: "megabyte", unit: Megabytes, want: "mb"}, + {name: "mebibyte", unit: Mebibytes, want: "mib"}, + {name: "gigabyte", unit: Gigabytes, want: "gb"}, + {name: "gibibyte", unit: Gibibytes, want: "gib"}, + {name: "terabyte", unit: Terabytes, want: "tb"}, + {name: "tebibyte", unit: Tebibytes, want: "tib"}, + {name: "petabyte", unit: Petabytes, want: "pb"}, + {name: "pebibyte", unit: Pebibytes, want: "pib"}, + {name: "invalid", unit: DataSizeUnit(-1), want: ""}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + assert.Equal(t, test.want, test.unit.String()) + }) + } +} + func TestDataSize_ConvertToUnit(t *testing.T) { tests := []struct { name string @@ -95,3 +125,161 @@ func TestDataSize_ConvertToUnit(t *testing.T) { }) } } + +func TestDuration_String(t *testing.T) { + tests := map[string]struct { + d Duration + want string + }{ + "should successfully return valid second string": { + d: Duration{ + Unit: Second, + }, + want: "s", + }, + "should successfully return valid millisecond string": { + d: Duration{ + Unit: Millisecond, + }, + want: "ms", + }, + "should successfully return valid nanosecond string": { + d: Duration{ + Unit: Nanosecond, + }, + want: "ns", + }, + "should successfully return valid microsecond string": { + d: Duration{ + Unit: Microsecond, + }, + want: "us", + }, + "should successfully return valid minute string": { + d: Duration{ + Unit: Minute, + }, + want: "min", + }, + "should successfully return valid hour string": { + d: Duration{ + Unit: Hour, + }, + want: "h", + }, + "should successfully return valid day string": { + d: Duration{ + Unit: Day, + }, + want: "d", + }, + "should return invalid string when provided unknown DurationUnit": { + d: Duration{ + Unit: DurationUnit(-1), + }, + want: "", + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + t.Parallel() + + assert.Equal(t, tc.want, fmt.Sprintf("%s", tc.d.Unit.String())) + }) + } +} + +func TestDuration_GoDuration(t *testing.T) { + t.Run("should successfully convert to GoDuration in second", func(t *testing.T) { + t.Parallel() + d := Duration{ + Value: 1, + Unit: Second, + } + assert.Equal(t, d.GoDuration(), 1*time.Second) + }) +} + +func TestDuration_UnmarshalBinary(t *testing.T) { + tests := map[string]struct { + input []byte + want DurationUnit + expectedErr error + }{ + "should successfully unmarshal binary from nanosecond": { + input: []byte("ns"), + want: Nanosecond, + }, + "should successfully unmarshal binary from microsecond": { + input: []byte("us"), + want: Microsecond, + }, + "should successfully unmarshal binary from millisecond": { + input: []byte("ms"), + want: Millisecond, + }, + "should successfully unmarshal binary from second": { + input: []byte("s"), + want: Second, + }, + "should successfully unmarshal binary from minute": { + input: []byte("min"), + want: Minute, + }, + "should successfully unmarshal binary from hour": { + input: []byte("h"), + want: Hour, + }, + "should successfully unmarshal binary from day": { + input: []byte("d"), + want: Day, + }, + "should fail unmarshal binary from unknown field": { + input: []byte("unknown"), + expectedErr: fmt.Errorf("unrecognized Duration unit: `unknown`"), + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + t.Parallel() + var unit DurationUnit + err := unit.UnmarshalBinary(tc.input) + + assert.Equal(t, tc.want, unit) + assert.Equal(t, tc.expectedErr, err) + }) + } +} + +func TestDataSizeUnit_UnmarshalBinary(t *testing.T) { + tests := []struct { + name string + input []byte + want DataSizeUnit + expectedErr error + }{ + {name: "byte", input: []byte("b"), want: Bytes}, + {name: "kilobyte", input: []byte("kb"), want: Kilobytes}, + {name: "kibibyte", input: []byte("kib"), want: Kibibytes}, + {name: "megabyte", input: []byte("mb"), want: Megabytes}, + {name: "mebibyte", input: []byte("mib"), want: Mebibytes}, + {name: "gigabyte", input: []byte("gb"), want: Gigabytes}, + {name: "gibibyte", input: []byte("gib"), want: Gibibytes}, + {name: "terabyte", input: []byte("tb"), want: Terabytes}, + {name: "tebibyte", input: []byte("tib"), want: Tebibytes}, + {name: "petabyte", input: []byte("pb"), want: Petabytes}, + {name: "pebibyte", input: []byte("pib"), want: Pebibytes}, + {name: "unknown", input: []byte("unknown"), expectedErr: fmt.Errorf("unrecognized DataSize unit: `unknown`")}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + var unit DataSizeUnit + err := unit.UnmarshalBinary(test.input) + + assert.Equal(t, test.want, unit) + assert.Equal(t, test.expectedErr, err) + }) + } +}