summaryrefslogtreecommitdiff
path: root/metautil
diff options
authorMaciej Borzecki <maciej.zenon.borzecki@canonical.com>2019-04-01 16:06:36 +0200
committerMaciej Borzecki <maciej.zenon.borzecki@canonical.com>2019-04-01 16:13:46 +0200
commit4022cc7d32cc4e9fd7cd81c9fd95a8ed843e25f1 (patch)
treebbcd71435d1eaa6c17f9dca99f8241b1ced34915 /metautil
parent360bb174256ff915a9ccc6680519ea88e758e09a (diff)
metautil, snap: extract yaml value normalization to a helper package
The value normalization bits will be reused by the 'gadget' package. Extract the code into a separate helper package. Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Diffstat (limited to 'metautil')
-rw-r--r--metautil/normalize.go79
-rw-r--r--metautil/normalize_test.go71
2 files changed, 150 insertions, 0 deletions
diff --git a/metautil/normalize.go b/metautil/normalize.go
new file mode 100644
index 0000000000..c6f8d0e824
--- /dev/null
+++ b/metautil/normalize.go
@@ -0,0 +1,79 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package metautil
+
+import (
+ "fmt"
+)
+
+// NormalizeValue validates values and returns a normalized version of it
+// (map[interface{}]interface{} is turned into map[string]interface{})
+func NormalizeValue(v interface{}) (interface{}, error) {
+ switch x := v.(type) {
+ case string:
+ return x, nil
+ case bool:
+ return x, nil
+ case int:
+ return int64(x), nil
+ case int64:
+ return x, nil
+ case float64:
+ return x, nil
+ case float32:
+ return float64(x), nil
+ case []interface{}:
+ l := make([]interface{}, len(x))
+ for i, el := range x {
+ el, err := NormalizeValue(el)
+ if err != nil {
+ return nil, err
+ }
+ l[i] = el
+ }
+ return l, nil
+ case map[interface{}]interface{}:
+ m := make(map[string]interface{}, len(x))
+ for k, item := range x {
+ kStr, ok := k.(string)
+ if !ok {
+ return nil, fmt.Errorf("non-string key: %v", k)
+ }
+ item, err := NormalizeValue(item)
+ if err != nil {
+ return nil, err
+ }
+ m[kStr] = item
+ }
+ return m, nil
+ case map[string]interface{}:
+ m := make(map[string]interface{}, len(x))
+ for k, item := range x {
+ item, err := NormalizeValue(item)
+ if err != nil {
+ return nil, err
+ }
+ m[k] = item
+ }
+ return m, nil
+ default:
+ return nil, fmt.Errorf("invalid scalar: %v", v)
+ }
+}
diff --git a/metautil/normalize_test.go b/metautil/normalize_test.go
new file mode 100644
index 0000000000..7e29e1db18
--- /dev/null
+++ b/metautil/normalize_test.go
@@ -0,0 +1,71 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2014-2016 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package metautil_test
+
+import (
+ "testing"
+
+ . "gopkg.in/check.v1"
+
+ "github.com/snapcore/snapd/metautil"
+)
+
+type normalizeTestSuite struct {
+}
+
+var _ = Suite(&normalizeTestSuite{})
+
+func TestMain(t *testing.T) { TestingT(t) }
+
+func (s *normalizeTestSuite) TestNormalize(c *C) {
+ for _, tc := range []struct {
+ v interface{}
+ exp interface{}
+ err string
+ }{
+ {v: "foo", exp: "foo"},
+ {v: 1, exp: int64(1)},
+ {v: int64(1), exp: int64(1)},
+ {v: true, exp: true},
+ {v: 0.5, exp: float64(0.5)},
+ {v: float32(0.5), exp: float64(0.5)},
+ {v: float64(0.5), exp: float64(0.5)},
+ {v: []interface{}{1, 0.5, "foo"}, exp: []interface{}{int64(1), float64(0.5), "foo"}},
+ {v: map[string]interface{}{"foo": 1}, exp: map[string]interface{}{"foo": int64(1)}},
+ {v: map[interface{}]interface{}{"foo": 1}, exp: map[string]interface{}{"foo": int64(1)}},
+ {
+ v: map[interface{}]interface{}{"foo": map[interface{}]interface{}{"bar": 0.5}},
+ exp: map[string]interface{}{"foo": map[string]interface{}{"bar": float64(0.5)}},
+ },
+ {v: uint(1), err: "invalid scalar: 1"},
+ {v: map[interface{}]interface{}{2: 1}, err: "non-string key: 2"},
+ {v: []interface{}{uint(1)}, err: "invalid scalar: 1"},
+ {v: map[string]interface{}{"foo": uint(1)}, err: "invalid scalar: 1"},
+ {v: map[interface{}]interface{}{"foo": uint(1)}, err: "invalid scalar: 1"},
+ } {
+ res, err := metautil.NormalizeValue(tc.v)
+ if tc.err == "" {
+ c.Assert(err, IsNil)
+ c.Assert(res, DeepEquals, tc.exp)
+ } else {
+ c.Assert(err, ErrorMatches, tc.err)
+ }
+ }
+}