← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~jtv/gomaasapi/test-json-serialization into lp:gomaasapi

 

Jeroen T. Vermeulen has proposed merging lp:~jtv/gomaasapi/test-json-serialization into lp:gomaasapi.

Commit message:
Move JSON serializers for JSONObject and MAASObject into jsonobject.go and maasobject.go, respectively, and test them properly.

Requested reviews:
  MAAS Maintainers (maas-maintainers)

For more details, see:
https://code.launchpad.net/~jtv/gomaasapi/test-json-serialization/+merge/147860
-- 
https://code.launchpad.net/~jtv/gomaasapi/test-json-serialization/+merge/147860
Your team MAAS Maintainers is requested to review the proposed merge of lp:~jtv/gomaasapi/test-json-serialization into lp:gomaasapi.
=== modified file 'jsonobject.go'
--- jsonobject.go	2013-02-11 12:29:23 +0000
+++ jsonobject.go	2013-02-12 09:14:22 +0000
@@ -81,6 +81,18 @@
 	return errors.New(msg)
 }
 
+// MarshalJSON tells the standard json package how to serialize a JSONObject
+// back to JSON.
+func (obj JSONObject) MarshalJSON() ([]byte, error) {
+	if obj.IsNil() {
+		return json.Marshal(nil)
+	}
+	return json.Marshal(obj.value)
+}
+
+// With MarshalJSON, JSONObject implements json.Marshaler.
+var _ json.Marshaler = (*JSONObject)(nil)
+
 func (obj JSONObject) IsNil() bool {
 	return obj.value == nil
 }

=== modified file 'jsonobject_test.go'
--- jsonobject_test.go	2013-02-12 05:42:32 +0000
+++ jsonobject_test.go	2013-02-12 09:14:22 +0000
@@ -4,6 +4,8 @@
 package gomaasapi
 
 import (
+	"encoding/json"
+	"fmt"
 	. "launchpad.net/gocheck"
 )
 
@@ -258,3 +260,114 @@
 	_, err = obj.GetArray()
 	c.Check(err, NotNil)
 }
+
+func (suite *JSONObjectSuite) TestNilSerializesToJSON(c *C) {
+	output, err := json.Marshal(maasify(Client{}, nil))
+	c.Assert(err, IsNil)
+	c.Check(output, DeepEquals, []byte("null"))
+}
+
+func (suite *JSONObjectSuite) TestStringSerializesToJSON(c *C) {
+	text := "Text wrapped in JSON"
+	output, err := json.Marshal(maasify(Client{}, text))
+	c.Assert(err, IsNil)
+	c.Check(output, DeepEquals, []byte(fmt.Sprintf(`"%s"`, text)))
+}
+
+func (suite *JSONObjectSuite) TestStringIsEscapedInJSON(c *C) {
+	text := `\"Quote,\" \\backslash, and \'apostrophe\'.`
+	output, err := json.Marshal(maasify(Client{}, text))
+	c.Assert(err, IsNil)
+	var deserialized string
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized, Equals, text)
+}
+
+func (suite *JSONObjectSuite) TestFloat64SerializesToJSON(c *C) {
+	number := 3.1415926535
+	output, err := json.Marshal(maasify(Client{}, number))
+	c.Assert(err, IsNil)
+	var deserialized float64
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized, Equals, number)
+}
+
+func (suite *JSONObjectSuite) TestEmptyMapSerializesToJSON(c *C) {
+	mp := map[string]interface{}{}
+	output, err := json.Marshal(maasify(Client{}, mp))
+	c.Assert(err, IsNil)
+	var deserialized interface{}
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized.(map[string]interface{}), DeepEquals, mp)
+}
+
+func (suite *JSONObjectSuite) TestMapSerializesToJSON(c *C) {
+	// Sample data: counting in Japanese.
+	mp := map[string]interface{}{"one": "ichi", "two": "nii", "three": "san"}
+	output, err := json.Marshal(maasify(Client{}, mp))
+	c.Assert(err, IsNil)
+	var deserialized interface{}
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized.(map[string]interface{}), DeepEquals, mp)
+}
+
+func (suite *JSONObjectSuite) TestEmptyArraySerializesToJSON(c *C) {
+	arr := []interface{}{}
+	output, err := json.Marshal(maasify(Client{}, arr))
+	c.Assert(err, IsNil)
+	var deserialized interface{}
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	// The deserialized value is a slice, and it contains no elements.
+	// Can't do a regular comparison here because at least in the current
+	// json implementation, an empty list deserializes as a nil slice,
+	// not as an empty slice!
+	// (It doesn't work that way for maps though, for some reason).
+	c.Check(len(deserialized.([]interface{})), Equals, len(arr))
+}
+
+func (suite *JSONObjectSuite) TestArrayOfStringsSerializesToJSON(c *C) {
+	value := "item"
+	output, err := json.Marshal(maasify(Client{}, []interface{}{value}))
+	c.Assert(err, IsNil)
+	var deserialized []string
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized, DeepEquals, []string{value})
+}
+
+func (suite *JSONObjectSuite) TestArrayOfNumbersSerializesToJSON(c *C) {
+	value := 9.0
+	output, err := json.Marshal(maasify(Client{}, []interface{}{value}))
+	c.Assert(err, IsNil)
+	var deserialized []float64
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized, DeepEquals, []float64{value})
+}
+
+func (suite *JSONObjectSuite) TestArrayPreservesOrderInJSON(c *C) {
+	// Sample data: counting in Korean.
+	arr := []interface{}{"jong", "il", "ee", "sam"}
+	output, err := json.Marshal(maasify(Client{}, arr))
+	c.Assert(err, IsNil)
+
+	var deserialized []interface{}
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized, DeepEquals, arr)
+}
+
+func (suite *JSONObjectSuite) TestBoolSerializesToJSON(c *C) {
+	f, err := json.Marshal(maasify(Client{}, false))
+	c.Assert(err, IsNil)
+	t, err := json.Marshal(maasify(Client{}, true))
+	c.Assert(err, IsNil)
+
+	c.Check(f, DeepEquals, []byte("false"))
+	c.Check(t, DeepEquals, []byte("true"))
+}

=== modified file 'maasobject.go'
--- maasobject.go	2013-02-11 12:15:14 +0000
+++ maasobject.go	2013-02-12 09:14:22 +0000
@@ -4,6 +4,7 @@
 package gomaasapi
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
 	"net/url"
@@ -33,6 +34,20 @@
 	return obj
 }
 
+// MarshalJSON tells the standard json package how to serialize a MAASObject.
+func (obj MAASObject) MarshalJSON() ([]byte, error) {
+	return json.Marshal(obj.GetMap())
+}
+
+// With MarshalJSON, MAASObject implements json.Marshaler.
+var _ json.Marshaler = (*MAASObject)(nil)
+
+func marshalNode(node MAASObject) string {
+	res, _ := json.Marshal(node)
+	return string(res)
+
+}
+
 var noResourceURI = errors.New("not a MAAS object: no 'resource_uri' key")
 
 // extractURI obtains the "resource_uri" string from a JSONObject map.

=== modified file 'maasobject_test.go'
--- maasobject_test.go	2013-02-11 12:15:14 +0000
+++ maasobject_test.go	2013-02-12 09:14:22 +0000
@@ -4,6 +4,7 @@
 package gomaasapi
 
 import (
+	"encoding/json"
 	"fmt"
 	. "launchpad.net/gocheck"
 	"math/rand"
@@ -144,3 +145,20 @@
 	c.Check(err, IsNil)
 	c.Check(value, Equals, fieldValue)
 }
+
+func (suite *MAASObjectSuite) TestSerializesToJSON(c *C) {
+	attrs := map[string]interface{}{
+		resourceURI: "http://maas.example.com/";,
+		"counter":   5.0,
+		"active":    true,
+		"macs":      map[string]interface{}{"eth0": "AA:BB:CC:DD:EE:FF"},
+	}
+	obj := maasify(Client{}, attrs)
+	output, err := json.Marshal(obj)
+	c.Assert(err, IsNil)
+
+	var deserialized map[string]interface{}
+	err = json.Unmarshal(output, &deserialized)
+	c.Assert(err, IsNil)
+	c.Check(deserialized, DeepEquals, attrs)
+}

=== modified file 'testservice.go'
--- testservice.go	2013-02-12 05:47:33 +0000
+++ testservice.go	2013-02-12 09:14:22 +0000
@@ -180,31 +180,6 @@
 	}
 }
 
-// MarshalJSON tells the standard json package how to serialize a JSONObject.
-func (obj JSONObject) MarshalJSON() ([]byte, error) {
-	if obj.IsNil() {
-		return json.Marshal(nil)
-	}
-	return json.Marshal(obj.value)
-}
-
-// With MarshalJSON, JSONObject implements json.Marshaler.
-var _ json.Marshaler = (*JSONObject)(nil)
-
-// MarshalJSON tells the standard json package how to serialize a MAASObject.
-func (obj MAASObject) MarshalJSON() ([]byte, error) {
-	return json.Marshal(obj.GetMap())
-}
-
-// With MarshalJSON, MAASObject implements json.Marshaler.
-var _ json.Marshaler = (*MAASObject)(nil)
-
-func marshalNode(node MAASObject) string {
-	res, _ := json.Marshal(node)
-	return string(res)
-
-}
-
 // nodeHandler handles requests for '/api/<version>/nodes/<system_id>/'.
 func nodeHandler(server *TestServer, w http.ResponseWriter, r *http.Request, systemId string, operation string) {
 	node, ok := server.nodes[systemId]