Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions configtype/duration.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package configtype
import (
"encoding/json"
"time"

"github.com/invopop/jsonschema"
)

// Duration is a wrapper around time.Duration that should be used in config
Expand All @@ -19,6 +21,14 @@ func NewDuration(d time.Duration) Duration {
}
}

func (Duration) JSONSchema() *jsonschema.Schema {
return &jsonschema.Schema{
Type: "string",
Pattern: `^[-+]?([0-9]*(\.[0-9]*)?[a-z]+)+$`, // copied from time.ParseDuration
Title: "CloudQuery configtype.Duration",
}
}

func (d *Duration) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
Expand Down
75 changes: 75 additions & 0 deletions configtype/duration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ package configtype_test

import (
"encoding/json"
"math/rand"
"testing"
"time"

"github.com/cloudquery/plugin-sdk/v4/configtype"
"github.com/cloudquery/plugin-sdk/v4/plugin"
"github.com/google/go-cmp/cmp"
"github.com/invopop/jsonschema"
"github.com/stretchr/testify/require"
)

func TestDuration(t *testing.T) {
Expand Down Expand Up @@ -52,3 +56,74 @@ func TestComparability(t *testing.T) {
}
}
}

func TestDuration_JSONSchema(t *testing.T) {
sc := (&jsonschema.Reflector{RequiredFromJSONSchemaTags: true}).Reflect(configtype.Duration{})
schema, err := json.MarshalIndent(sc, "", " ")
require.NoError(t, err)

validator, err := plugin.JSONSchemaValidator(string(schema))
require.NoError(t, err)

type testCase struct {
Name string
Spec string
Err bool
}

for _, tc := range append([]testCase{
{
Name: "empty",
Err: true,
Spec: `""`,
},
{
Name: "null",
Err: true,
Spec: `null`,
},
{
Name: "bad type",
Err: true,
Spec: `false`,
},
{
Name: "bad format",
Err: true,
Spec: `false`,
},
},
func() []testCase {
Copy link
Member

@hermanschaaf hermanschaaf Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this syntax of appending a function that calls itself and appends the results in-line feels unnecessarily complicated, it'd be more readable to introduce a variable first and append that, like:

generatedCases := make([]testcase, 20)
for i := 0; i < 20; i++ {
     generatedCases[i] = generateTestCase()
}

...
cases := append([]testCase{
		{
			Name: "empty",
			Err:  true,
			Spec: `""`,
		},
                ...,
                generatedCases...
})

or have a few manually created test cases, there doesn't seem to be enough complexity here to warrant generating random cases

rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
const (
cases = 20
maxDur = int64(100 * time.Hour)
maxDurHalf = maxDur / 2
)
result := make([]testCase, cases)
for i := 0; i < cases; i++ {
val := rnd.Int63n(maxDur) - maxDurHalf
d := configtype.NewDuration(time.Duration(val))

data, err := d.MarshalJSON()
require.NoError(t, err)
result[i] = testCase{
Name: string(data),
Spec: string(data),
}
}
return result
}()...,
) {
t.Run(tc.Name, func(t *testing.T) {
var val any
err := json.Unmarshal([]byte(tc.Spec), &val)
require.NoError(t, err)
if tc.Err {
require.Error(t, validator.Validate(val))
} else {
require.NoError(t, validator.Validate(val))
}
})
}
}
3 changes: 1 addition & 2 deletions scheduler/strategy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package scheduler_test
import (
_ "embed"
"encoding/json"
"reflect"
"testing"

"github.com/cloudquery/plugin-sdk/v4/plugin"
Expand All @@ -13,7 +12,7 @@ import (
)

func TestStrategy_JSONSchema(t *testing.T) {
sc := (&jsonschema.Reflector{RequiredFromJSONSchemaTags: true}).ReflectFromType(reflect.TypeOf(scheduler.StrategyDFS))
sc := (&jsonschema.Reflector{RequiredFromJSONSchemaTags: true}).Reflect(scheduler.StrategyDFS)
schema, err := json.MarshalIndent(sc, "", " ")
require.NoError(t, err)

Expand Down