diff --git a/float64_test.go b/float64_test.go
index a9ce53c..14e5f9e 100644
--- a/float64_test.go
+++ b/float64_test.go
@@ -6,15 +6,50 @@ import (
"testing"
)
-func float64NullValue() nullTestValue {
+func float64NullValue() interface{} {
return &Float64{}
}
+func newFloat64NullValueXmlWrapper() interface{} {
+ return &nullTestValueXmlWrapper{Namespace: xsiNamespace, Value: float64NullValue()}
+}
+
+func newFloat64ValueXmlWrapper(value *Float64) interface{} {
+ return &nullTestValueXmlWrapper{Namespace: xsiNamespace, Value: value}
+}
+
func TestFloat64(t *testing.T) {
tests := []nullTest{
- {float64NullValue, float64NullValue(), `null`, float64NullValue(), ``, float64NullValue(), ``},
- {float64NullValue, NewFloat64Ptr(0.0), `0`, NewFloat64Ptr(0.0), `0`, NewFloat64Ptr(0.0), `0`},
- {float64NullValue, NewFloat64Ptr(1.12), `1.12`, NewFloat64Ptr(1.12), `1.12`, NewFloat64Ptr(1.12), `1.12`},
+ // null values
+ {testTypeJson, float64NullValue, float64NullValue(), `null`},
+ {testTypeText, float64NullValue, float64NullValue(), ``},
+ {testTypeXml, float64NullValue, float64NullValue(), ``},
+ {
+ testTypeXml,
+ newFloat64NullValueXmlWrapper,
+ newFloat64NullValueXmlWrapper(),
+ ``,
+ },
+ // 0.0 values
+ {testTypeJson, float64NullValue, NewFloat64Ptr(0.0), `0`},
+ {testTypeText, float64NullValue, NewFloat64Ptr(0.0), `0`},
+ {testTypeXml, float64NullValue, NewFloat64Ptr(0.0), `0`},
+ {
+ testTypeXml,
+ newFloat64NullValueXmlWrapper,
+ newFloat64ValueXmlWrapper(NewFloat64Ptr(0.0)),
+ `0`,
+ },
+ // 1.12 values
+ {testTypeJson, float64NullValue, NewFloat64Ptr(1.12), `1.12`},
+ {testTypeText, float64NullValue, NewFloat64Ptr(1.12), `1.12`},
+ {testTypeXml, float64NullValue, NewFloat64Ptr(1.12), `1.12`},
+ {
+ testTypeXml,
+ newFloat64NullValueXmlWrapper,
+ newFloat64ValueXmlWrapper(NewFloat64Ptr(1.12)),
+ `1.12`,
+ },
}
nullTestRun(t, tests)
diff --git a/int64_test.go b/int64_test.go
index 704a9ac..22d2009 100644
--- a/int64_test.go
+++ b/int64_test.go
@@ -2,19 +2,52 @@
package null
-import (
- "testing"
-)
+import "testing"
-func int64NullValue() nullTestValue {
+func int64NullValue() interface{} {
return &Int64{}
}
+func newInt64NullValueXmlWrapper() interface{} {
+ return &nullTestValueXmlWrapper{Namespace: xsiNamespace, Value: int64NullValue()}
+}
+
+func newInt64ValueXmlWrapper(value *Int64) interface{} {
+ return &nullTestValueXmlWrapper{Namespace: xsiNamespace, Value: value}
+}
+
func TestInt64(t *testing.T) {
tests := []nullTest{
- {int64NullValue, int64NullValue(), `null`, int64NullValue(), ``, int64NullValue(), ``},
- {int64NullValue, NewInt64Ptr(0), `0`, NewInt64Ptr(0), `0`, NewInt64Ptr(0), `0`},
- {int64NullValue, NewInt64Ptr(1), `1`, NewInt64Ptr(1), `1`, NewInt64Ptr(1), `1`},
+ // null values
+ {testTypeJson, int64NullValue, int64NullValue(), `null`},
+ {testTypeText, int64NullValue, int64NullValue(), ``},
+ {testTypeXml, int64NullValue, int64NullValue(), ``},
+ {
+ testTypeXml,
+ newInt64NullValueXmlWrapper,
+ newInt64NullValueXmlWrapper(),
+ ``,
+ },
+ // 0 values
+ {testTypeJson, int64NullValue, NewInt64Ptr(0), `0`},
+ {testTypeText, int64NullValue, NewInt64Ptr(0), `0`},
+ {testTypeXml, int64NullValue, NewInt64Ptr(0), `0`},
+ {
+ testTypeXml,
+ newInt64NullValueXmlWrapper,
+ newInt64ValueXmlWrapper(NewInt64Ptr(0)),
+ `0`,
+ },
+ // 1 values
+ {testTypeJson, int64NullValue, NewInt64Ptr(1), `1`},
+ {testTypeText, int64NullValue, NewInt64Ptr(1), `1`},
+ {testTypeXml, int64NullValue, NewInt64Ptr(1), `1`},
+ {
+ testTypeXml,
+ newInt64NullValueXmlWrapper,
+ newInt64ValueXmlWrapper(NewInt64Ptr(1)),
+ `1`,
+ },
}
nullTestRun(t, tests)
diff --git a/null.go b/null.go
index 58ad980..80f3230 100644
--- a/null.go
+++ b/null.go
@@ -4,7 +4,10 @@ package null
import "encoding/xml"
-const jsonNull = "null"
+const (
+ jsonNull = "null"
+ xsiNamespace = "http://www.w3.org/2001/XMLSchema-instance"
+)
var xsiNilAttr = xml.Attr{
Name: xml.Name{Local: "xsi:nil"},
@@ -12,5 +15,6 @@ var xsiNilAttr = xml.Attr{
}
func isXsiNilAttr(attr xml.Attr) bool {
- return attr.Name.Space == "xsi" && attr.Name.Local == "nil" && attr.Value == "true"
+ return (attr.Name.Space == "xsi" || attr.Name.Space == xsiNamespace) &&
+ attr.Name.Local == "nil" && attr.Value == "true"
}
diff --git a/null_test.go b/null_test.go
index faa81fd..4dc509c 100644
--- a/null_test.go
+++ b/null_test.go
@@ -10,6 +10,14 @@ import (
"testing"
)
+const (
+ testTypeJson testType = "json"
+ testTypeText testType = "text"
+ testTypeXml testType = "xml"
+)
+
+type testType string
+
type nullTestValue interface {
json.Marshaler
json.Unmarshaler
@@ -19,86 +27,104 @@ type nullTestValue interface {
xml.Unmarshaler
}
+type nullTestValueXmlWrapper struct {
+ Namespace string `xml:"xmlns:xsi,attr"`
+ Value interface{} `xml:"Value"` // *nullTestValue
+}
+
type nullTest struct {
- new func() nullTestValue
- jsonValue nullTestValue
- json string
- textValue nullTestValue
- text string
- xmlValue nullTestValue
- xml string
+ Type testType
+ New func() interface{} // Generator of *nullTestValue (and their wrappers)
+ Unmarshaled interface{}
+ Marshaled string
}
func nullTestMarshalJSON(t *testing.T, tt nullTest) {
- got, err := json.Marshal(tt.jsonValue)
+ got, err := json.Marshal(tt.Unmarshaled)
if err != nil {
t.Error(err)
}
- if string(got) != tt.json {
- t.Errorf("got %s; expected %s", got, tt.json)
+ if string(got) != tt.Marshaled {
+ t.Errorf("got %s; expected %s", got, tt.Marshaled)
}
}
func nullTestUnmarshalJSON(t *testing.T, tt nullTest) {
- got := tt.new()
- if err := json.Unmarshal([]byte(tt.json), got); err != nil {
+ got := tt.New()
+ if err := json.Unmarshal([]byte(tt.Marshaled), got); err != nil {
t.Error(err)
}
- if !reflect.DeepEqual(got, tt.jsonValue) {
- t.Errorf("got %v; expected %v", got, tt.jsonValue)
+ if !reflect.DeepEqual(got, tt.Unmarshaled) {
+ t.Errorf("got %v; expected %v", got, tt.Unmarshaled)
}
}
func nullTestMarshalText(t *testing.T, tt nullTest) {
- got, err := tt.textValue.MarshalText()
+ got, err := tt.Unmarshaled.(nullTestValue).MarshalText()
if err != nil {
t.Error(err)
}
- if string(got) != tt.text {
- t.Errorf("got %s; expected %s", got, tt.text)
+ if string(got) != tt.Marshaled {
+ t.Errorf("got %s; expected %s", got, tt.Marshaled)
}
}
func nullTestUnmarshalText(t *testing.T, tt nullTest) {
- got := tt.new()
- if err := got.UnmarshalText([]byte(tt.text)); err != nil {
+ got := tt.New().(nullTestValue)
+ if err := got.UnmarshalText([]byte(tt.Marshaled)); err != nil {
t.Error(err)
}
- if !reflect.DeepEqual(got, tt.textValue) {
- t.Errorf("got %v; expected %v", got, tt.textValue)
+ if !reflect.DeepEqual(got, tt.Unmarshaled) {
+ t.Errorf("got %v; expected %v", got, tt.Unmarshaled)
}
}
func nullTestMarshalXML(t *testing.T, tt nullTest) {
- got, err := xml.Marshal(tt.xmlValue)
+ got, err := xml.Marshal(tt.Unmarshaled)
if err != nil {
t.Error(err)
}
- if string(got) != tt.xml {
- t.Errorf("got %s; expected %s", got, tt.xml)
+ if string(got) != tt.Marshaled {
+ t.Errorf("got %s; expected %s", got, tt.Marshaled)
}
}
func nullTestUnmarshalXML(t *testing.T, tt nullTest) {
- got := tt.new()
- if err := xml.Unmarshal([]byte(tt.xml), got); err != nil {
+ got := tt.New()
+ if err := xml.Unmarshal([]byte(tt.Marshaled), got); err != nil {
t.Error(err)
}
- if !reflect.DeepEqual(got, tt.xmlValue) {
- t.Errorf("got %v; expected %v", got, tt.xmlValue)
+ if !reflect.DeepEqual(got, tt.Unmarshaled) {
+ t.Errorf("got %v; expected %v", got, tt.Unmarshaled)
}
}
func nullTestRun(t *testing.T, tests []nullTest) {
for _, tt := range tests {
- tt := tt
- t.Run("", func(t *testing.T) {
- nullTestMarshalJSON(t, tt)
- nullTestUnmarshalJSON(t, tt)
- nullTestMarshalText(t, tt)
- nullTestUnmarshalText(t, tt)
- nullTestMarshalXML(t, tt)
- nullTestUnmarshalXML(t, tt)
- })
+ switch tt.Type {
+ case testTypeJson:
+ t.Run("MarshalJSON", func(t *testing.T) {
+ nullTestMarshalJSON(t, tt)
+ })
+ t.Run("UnmarshalJSON", func(t *testing.T) {
+ nullTestUnmarshalJSON(t, tt)
+ })
+ case testTypeText:
+ t.Run("MarshalText", func(t *testing.T) {
+ nullTestMarshalText(t, tt)
+ })
+ t.Run("UnmarshalText", func(t *testing.T) {
+ nullTestUnmarshalText(t, tt)
+ })
+ case testTypeXml:
+ t.Run("MarshalXML", func(t *testing.T) {
+ nullTestMarshalXML(t, tt)
+ })
+ t.Run("UnmarshalXML", func(t *testing.T) {
+ nullTestUnmarshalXML(t, tt)
+ })
+ default:
+ t.Errorf("Unsupported testType: %#v", tt.Type)
+ }
}
}
diff --git a/string_test.go b/string_test.go
index df1e288..dfc0ce7 100644
--- a/string_test.go
+++ b/string_test.go
@@ -2,19 +2,52 @@
package null
-import (
- "testing"
-)
+import "testing"
-func stringNullValue() nullTestValue {
+func stringNullValue() interface{} {
return &String{}
}
+func newStringNullValueXmlWrapper() interface{} {
+ return &nullTestValueXmlWrapper{Namespace: xsiNamespace, Value: stringNullValue()}
+}
+
+func newStringValueXmlWrapper(value *String) interface{} {
+ return &nullTestValueXmlWrapper{Namespace: xsiNamespace, Value: value}
+}
+
func TestString(t *testing.T) {
tests := []nullTest{
- {stringNullValue, stringNullValue(), `null`, NewStringPtr(``), ``, stringNullValue(), ``},
- {stringNullValue, NewStringPtr(``), `""`, NewStringPtr(``), ``, NewStringPtr(``), ``},
- {stringNullValue, NewStringPtr(`foo`), `"foo"`, NewStringPtr(`foo`), `foo`, NewStringPtr(`foo`), `foo`},
+ // null values
+ {testTypeJson, stringNullValue, stringNullValue(), `null`},
+ {testTypeText, stringNullValue, NewStringPtr(``), ``},
+ {testTypeXml, stringNullValue, stringNullValue(), ``},
+ {
+ testTypeXml,
+ newStringNullValueXmlWrapper,
+ newStringNullValueXmlWrapper(),
+ ``,
+ },
+ // `` values
+ {testTypeJson, stringNullValue, NewStringPtr(``), `""`},
+ {testTypeText, stringNullValue, NewStringPtr(``), ``},
+ {testTypeXml, stringNullValue, NewStringPtr(``), ``},
+ {
+ testTypeXml,
+ newStringNullValueXmlWrapper,
+ newStringValueXmlWrapper(NewStringPtr(``)),
+ ``,
+ },
+ // `foo` values
+ {testTypeJson, stringNullValue, NewStringPtr(`foo`), `"foo"`},
+ {testTypeText, stringNullValue, NewStringPtr(`foo`), `foo`},
+ {testTypeXml, stringNullValue, NewStringPtr(`foo`), `foo`},
+ {
+ testTypeXml,
+ newStringNullValueXmlWrapper,
+ newStringValueXmlWrapper(NewStringPtr(`foo`)),
+ `foo`,
+ },
}
nullTestRun(t, tests)