feat: (api/cli): add custom type for duration

This commit is contained in:
Jim authored and Timothy Messier committed 2023-05-31 12:18:18 +00:00
1 parent 18e59998e9
commit de88a871c6
3 files changed
+98 -1

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package api
import (
"encoding/json"
"fmt"
"time"
)
// Duration represents a time.Duration and supports marshaling/unmarshaling from
// a json string
type Duration struct {
time.Duration
}
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Duration.String())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
const op = "api.(Duration).UnmarshalJSON"
var str string
if err := json.Unmarshal(b, &str); err != nil {
return fmt.Errorf("%s: %w", op, err)
}
val, err := time.ParseDuration(str)
if err != nil {
return fmt.Errorf("%s: %w", op, err)
}
d.Duration = val
return nil
}
+63
View File
@@ -0,0 +1,63 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package api
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestTypes(t *testing.T) {
t.Parallel()
tests := []struct {
name string
json string
want any
wantErrContains string
}{
{
name: "Duration-valid",
json: `"12345s"`,
want: Duration{Duration: 12345000000000},
},
{
name: "Duration-valid",
json: `"1h"`,
want: Duration{Duration: 3600000000000},
},
{
name: "UInt64String-InvalidNumber",
json: `"abcd"`,
want: Duration{Duration: 0},
wantErrContains: "invalid duration \"abcd\"",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
var got any
var err error
switch tc.want.(type) {
case Duration:
var i Duration
err = json.Unmarshal([]byte(tc.json), &i)
got = i
default:
t.Fatalf("invalid type for test: %s", tc.name)
}
if tc.wantErrContains != "" {
require.Error(err)
assert.Equal(tc.want, got)
assert.ErrorContains(err, tc.wantErrContains)
return
}
require.NoError(err)
assert.Equal(tc.want, got)
})
}
}
+1 -1
View File
@@ -126,7 +126,7 @@ func messageKind(fd protoreflect.FieldDescriptor) (ptr, pkg, name string) {
case timestampName:
return "", "time", "Time"
case durationName:
return "", "time", "Duration"
return "", "api", "Duration"
default:
return "*", packageFromFullName(fd.Message().FullName()), string(fd.Message().Name())
}