From 63fe61e1d42e907935f4556cdcb219c8eb86af9c Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 20 Nov 2025 14:37:58 +0100 Subject: [PATCH] unit tests --- internal/cac/storage/reader.go | 3 ++- internal/cac/storage/writer.go | 2 +- internal/cac/utils/decoder.go | 2 +- internal/cac/utils/model_test.go | 41 ++++++++++++++++++++++++++++++++ internal/cac/utils/yaml.go | 15 ++++++++++++ internal/cac/utils/yaml_test.go | 32 +++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 internal/cac/utils/yaml_test.go diff --git a/internal/cac/storage/reader.go b/internal/cac/storage/reader.go index 168f5f9..a32fd69 100644 --- a/internal/cac/storage/reader.go +++ b/internal/cac/storage/reader.go @@ -5,6 +5,7 @@ import ( "path/filepath" "github.com/cloudentity/cac/internal/cac/templates" + "github.com/cloudentity/cac/internal/cac/utils" ccyaml "github.com/goccy/go-yaml" "github.com/pkg/errors" "golang.org/x/exp/slog" @@ -44,7 +45,7 @@ func readFile(path string, opts ...ReadFileOpt) (map[string]any, error) { slog.Debug("read template", "path", path, "data", bts) - if err = ccyaml.Unmarshal(bts, &out); err != nil { + if out, err = utils.FromYaml(bts); err != nil { return out, errors.Wrapf(err, "failed to unmarshal template %s", path) } diff --git a/internal/cac/storage/writer.go b/internal/cac/storage/writer.go index ffc9082..477bc6c 100644 --- a/internal/cac/storage/writer.go +++ b/internal/cac/storage/writer.go @@ -170,7 +170,7 @@ func createMultilineIncludeTemplate(str string, indent int) string { var multilineTemplateRegexp = regexp.MustCompile(`⌘⌘(\d+) ([^⌘]+)⌘⌘`) -func postProcessMultilineTemplates(bts []byte) []byte { +func postProcessMultilineTemplates(bts []byte) []byte { bts = multilineTemplateRegexp.ReplaceAll(bts, []byte("{{ $2 | nindent $1 }}")) return bts diff --git a/internal/cac/utils/decoder.go b/internal/cac/utils/decoder.go index 88f2bf7..9231993 100644 --- a/internal/cac/utils/decoder.go +++ b/internal/cac/utils/decoder.go @@ -21,7 +21,7 @@ func Decoder(result any) (*mapstructure.Decoder, error) { func ConfigureDecoder(config *mapstructure.DecoderConfig) { config.TagName = "json" - config.WeaklyTypedInput = true + config.WeaklyTypedInput = false config.DecodeHook = mapstructure.ComposeDecodeHookFunc(urlDecoder(), timeDecoder(), stringToSlice()) } diff --git a/internal/cac/utils/model_test.go b/internal/cac/utils/model_test.go index 27d748e..54d6c2b 100644 --- a/internal/cac/utils/model_test.go +++ b/internal/cac/utils/model_test.go @@ -81,3 +81,44 @@ func TestFilterPatch(t *testing.T) { }) } } + +func TestMappingNumbersToModel(t *testing.T) { + patch := models.Rfc7396PatchOperation{ + "policies": map[string]any{ + "p1": map[string]any{ + "validators": []any{ + map[string]any{ + "conf": map[string]any{ + "max_x": 3, + }, + }, + }, + }, + }, + } + + result, err := utils.FromPatchToModel[models.TreeServer](patch) + + require.NoError(t, err) + require.Equal(t, float64(3), result.Policies["p1"].Validators[0].Conf["max_x"]) +} + +func TestMappingNumbersToYaml(t *testing.T) { + model := models.TreeServer{ + Policies: models.TreePolicies{ + "p1": models.TreePolicy{ + Validators: []*models.ValidatorConfig{ + { + Conf: map[string]any{ + "max_x": 3, + }, + }, + }, + }, + }, + } + patch, err := utils.FromModelToPatch(&model) + + require.NoError(t, err) + require.Equal(t, float64(3), patch["policies"].(map[string]any)["p1"].(map[string]any)["validators"].([]any)[0].(map[string]any)["conf"].(map[string]any)["max_x"]) +} diff --git a/internal/cac/utils/yaml.go b/internal/cac/utils/yaml.go index b4eb86b..3a84d18 100644 --- a/internal/cac/utils/yaml.go +++ b/internal/cac/utils/yaml.go @@ -6,6 +6,7 @@ import ( "github.com/go-json-experiment/json" "github.com/go-json-experiment/json/jsontext" ccyaml "github.com/goccy/go-yaml" + "github.com/pkg/errors" ) func ToYaml(it any) ([]byte, error) { @@ -18,6 +19,7 @@ func ToYaml(it any) ([]byte, error) { enc := jsontext.NewEncoder(buffer, json.FormatNilMapAsNull(true), json.FormatNilSliceAsNull(true), + json.StringifyNumbers(true), ) if err = json.MarshalEncode(enc, it); err != nil { @@ -32,3 +34,16 @@ func ToYaml(it any) ([]byte, error) { return bts, nil } + +func FromYaml(bts []byte) (map[string]any, error) { + var ( + out map[string]any + err error + ) + + if err = ccyaml.Unmarshal(bts, &out); err != nil { + return out, errors.Wrapf(err, "failed to unmarshal template %s", string(bts)) + } + + return out, nil +} diff --git a/internal/cac/utils/yaml_test.go b/internal/cac/utils/yaml_test.go new file mode 100644 index 0000000..e46319c --- /dev/null +++ b/internal/cac/utils/yaml_test.go @@ -0,0 +1,32 @@ +package utils_test + +import ( + "testing" + + "github.com/cloudentity/cac/internal/cac/utils" + "github.com/stretchr/testify/require" +) + +func TestDecodingNumbers(t *testing.T) { + patchWithNumbers := []byte(`something: + else: 3`) + + yml, err := utils.FromYaml(patchWithNumbers) + + require.NoError(t, err) + something, ok := yml["something"].(map[string]any) + require.True(t, ok) + require.Equal(t, uint64(3), something["else"]) +} + +func TestEncodingNumbers(t *testing.T) { + yml, err := utils.ToYaml(map[string]any{ + "something": map[string]any{ + "else": 3, + }, + }) + + require.NoError(t, err) + require.YAMLEq(t, `something: + else: 3`, string(yml)) +} \ No newline at end of file