// Copyright 2015 The Mellium Contributors. // Use of this source code is governed by the BSD 2-clause // license that can be found in the LICENSE file. package stream_test import ( "encoding/xml" "errors" "fmt" "net" "testing" "mellium.im/xmlstream" "mellium.im/xmpp/stream" ) var ( _ error = (*stream.Error)(nil) _ error = stream.Error{} _ xml.Marshaler = (*stream.Error)(nil) _ xml.Marshaler = stream.Error{} _ xml.Unmarshaler = (*stream.Error)(nil) _ xmlstream.Marshaler = (*stream.Error)(nil) _ xmlstream.WriterTo = (*stream.Error)(nil) ) func TestCompare(t *testing.T) { hostGoneApp := stream.HostGone.ApplicationError(xmlstream.Wrap(nil, xml.StartElement{})) if !errors.Is(stream.HostGone, hostGoneApp) { t.Errorf("did not expect adding application error to affect comparison") } if errors.Is(stream.HostGone, stream.BadNamespacePrefix) { t.Errorf("did not expect two errors with different names to be equivalent") } if !errors.Is(stream.HostGone, stream.Error{}) { t.Errorf("expected empty stream error to compare to any other stream error") } } var marshalTests = [...]struct { se stream.Error xml string err bool }{ 0: { // see-other-host errors should wrap IPv6 addresses in brackets. se: stream.SeeOtherHostError(&net.IPAddr{IP: net.ParseIP("::1")}), xml: `[::1]`, err: false, }, 1: { // see-other-host should not wrap IPv6 addresses in brackets if they are already wrapped. se: stream.SeeOtherHostError(&net.TCPAddr{IP: net.ParseIP("::1"), Port: 5222}), xml: `[::1]:5222`, err: false, }, 2: { // see-other-host should not mess with IPv4 addresses. se: stream.SeeOtherHostError(&net.IPAddr{IP: net.ParseIP("127.0.0.1")}), xml: `127.0.0.1`, err: false, }, 3: { se: stream.UnsupportedEncoding.InnerXML(xmlstream.Token(xml.CharData("test"))), xml: `test`, }, 4: { se: stream.UnsupportedEncoding.ApplicationError(xmlstream.Token(xml.CharData("test"))), xml: `test`, }, 5: { se: stream.UnsupportedEncoding.ApplicationError(xmlstream.Token(xml.CharData("test"))).InnerXML(xmlstream.Token(xml.CharData("foo"))), xml: `footest`, }, 6: { se: stream.UnsupportedEncoding.ApplicationError(xmlstream.Token(xml.CharData("test"))).InnerXML(xmlstream.Token(xml.CharData("foo"))), xml: `footest`, }, 7: { se: stream.Error{Err: "undefined-condition", Text: []struct { Lang string Value string }{{ Lang: "en", Value: "some value", }, { Value: "some error", }}}, xml: `some valuesome error`, }, } func TestMarshal(t *testing.T) { for i, tc := range marshalTests { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { xb, err := xml.Marshal(tc.se) switch xbs := string(xb); { case tc.err && err == nil: t.Errorf("expected marshaling to fail") return case !tc.err && err != nil: t.Errorf("did not expect error, got=%v", err) return case err != nil: return case xbs != tc.xml: t.Errorf("bad output:\nwant=`%s`,\n got=`%s`", tc.xml, xbs) } }) } } var unmarshalTests = [...]struct { xml string se stream.Error err bool }{ 0: { xml: ``, se: stream.RestrictedXML, err: false, }, 1: { xml: ``, se: stream.RestrictedXML, err: true, }, 2: { xml: `some valuesome error`, se: stream.Error{Err: "undefined-condition", Text: []struct { Lang string Value string }{{ Lang: "en", Value: "some value", }, { Value: "some error", }}}, }, } func TestUnmarshal(t *testing.T) { for i, test := range unmarshalTests { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { s := stream.Error{} err := xml.Unmarshal([]byte(test.xml), &s) switch { case test.err && err == nil: t.Errorf("expected unmarshaling error for `%v` to fail", test.xml) return case !test.err && err != nil: t.Errorf("unexpected error: %v", err) return case err != nil: return case s.Err != test.se.Err: t.Errorf("expected Err `%#v` but got `%#v`", test.se, s) } }) } } func TestErrorReturnsCondition(t *testing.T) { if stream.RestrictedXML.Error() != "restricted-xml" { t.Error("error should return the error condition") } }