// Copyright 2020 Justine Alexandra Roberts Tunney // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package sip_test import ( "bytes" "reflect" "testing" "github.com/jart/gosip/sip" ) type addrTest struct { name string s string s_canonical string addr sip.Addr err error } var addrTests = []addrTest{ { name: "Basic address", s: "", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "pokemon.net", }, }, }, { name: "Address parameter", s: ";tag=deadbeef", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "pokemon.net", }, Param: &sip.Param{Name: "tag", Value: "deadbeef"}, }, }, { name: "Address parameter spacing", s: "\t ;\t tag\t = \tdeadbeef", s_canonical: ";tag=deadbeef", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "pokemon.net", }, Param: &sip.Param{Name: "tag", Value: "deadbeef"}, }, }, { name: "Address parameter quoted", s: ";tag=\"deadbeef\"", s_canonical: ";tag=deadbeef", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "pokemon.net", }, Param: &sip.Param{Name: "tag", Value: "deadbeef"}, }, }, { name: "Address parameter quoted spacing", s: "\t ;\t tag\t = \t\"deadbeef\"", s_canonical: ";tag=deadbeef", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "pokemon.net", }, Param: &sip.Param{Name: "tag", Value: "deadbeef"}, }, }, { name: "Address parameter quoted escaped", s: ";tag=\"\\\"deadbeef\\\"\"", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "pokemon.net", }, Param: &sip.Param{Name: "tag", Value: "\"deadbeef\""}, }, }, { name: "URI parameter", s: "", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", User: "brave", Host: "toaster.net", Param: &sip.URIParam{Name: "isup-oli", Value: "29"}, }, }, }, { name: "Address + URI parameter", s: ";tag=deadbeef", addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", User: "brave", Host: "toaster.net", Param: &sip.URIParam{Name: "isup-oli", Value: "29"}, }, Param: &sip.Param{Name: "tag", Value: "deadbeef"}, }, }, { s: `, Ditto `, addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "pokemon.com", }, Next: &sip.Addr{ Display: "Ditto", Uri: &sip.URI{ Scheme: "sip", User: "ditto", Host: "pokemon.com", }, }, }, }, { s: `, , `, addr: sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "1.2.3.4", }, Next: &sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "1.2.3.5", }, Next: &sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "666::dead:beef", }, }, }, }, }, { s: "\"\\\"\\\"Justine \\\\Tunney \" " + ";tag=deadbeef", addr: sip.Addr{ Display: "\"\"Justine \\Tunney ", Uri: &sip.URI{ Scheme: "sip", User: "jart", Host: "google.com", Param: &sip.URIParam{Name: "isup-oli", Value: "29"}, }, Param: &sip.Param{Name: "tag", Value: "deadbeef"}, }, }, } func ParseAddrBytes(s []byte) (addr *sip.Addr, err error) { var b bytes.Buffer b.WriteString("SIP/2.0 900 ParseAddrBytes()\r\nContact:") b.Write(s) b.WriteString("\r\n\r\n") msg, err := sip.ParseMsg(b.Bytes()) if err != nil { return nil, err } return msg.Contact, nil } func TestParseAddrBytes(t *testing.T) { for _, test := range addrTests { addr, err := ParseAddrBytes([]byte(test.s)) if err != nil { if test.err == nil { t.Error(err) continue } else { // Test was supposed to fail. t.Fatal("TODO(jart): Implement failing support.") } } if !reflect.DeepEqual(&test.addr, addr) { t.Errorf("%s:\n%#v !=\n%#v\n%#v !=\n%#v", test.name, &test.addr, addr, test.addr.Uri, addr.Uri) } } } func TestAddrString(t *testing.T) { for _, test := range addrTests { addr := test.addr.String() if test.s_canonical != "" { if test.s_canonical != addr { t.Errorf("%s (Canonicalization)\nWant: %s\nGot: %s", test.name, test.s_canonical, addr) } } else { if test.s != addr { t.Errorf("%s\nWant: %s\nGot: %s", test.name, test.s, addr) } } } } func TestReversed(t *testing.T) { a := &sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "1.2.3.4", Port: 5060, }, Next: &sip.Addr{ Uri: &sip.URI{ Scheme: "sip", Host: "2.3.4.5", Port: 5060, }, }, } b := a.Reversed() if b.Uri.Host != "2.3.4.5" { t.Error("first bad", b.Uri.Host) } if b.Next.Uri.Host != "1.2.3.4" { t.Error("second bad", b.Next.Uri.Host) } if b.Next.Next != nil { t.Error("wtf", b.Next.Next) } } func addrError(t *testing.T, name string, want, got *sip.Addr) { if want != nil && got != nil { t.Errorf("%s:\n%#v\n%#v\n!=\n%#v\n%#v", name, want, want.Uri, got, got.Uri) } else { t.Errorf("%s:\n%#v\n!=\n%#v", name, want, got) } }