func TestPrependHost(t *testing.T) { login := "******" abs := "http://server.com:6103/platinum/search" rel := "/platinum/search" testutils.Equals(t, abs, prependHost(login, abs)) testutils.Equals(t, abs, prependHost(login, rel)) }
func TestSearchXMLComplex(t *testing.T) { type Listing struct { Business string `xml:"Business>RESIOWNS"` Approved bool `xml:"Listing>Approved"` MLS string `xml:"Listing>MLS"` Disclaimer string `xml:"Listing>Disclaimer"` Status string `xml:"Listing>Status"` ListingPrice float64 `xml:"Listing>Price>ListingPrice"` OriginalPrice float64 `xml:"Listing>Price>OriginalPrice"` SellPrice float64 `xml:"Listing>Price>SellingPrice"` } body := ioutil.NopCloser(strings.NewReader(standardXML)) cr, err := NewStandardXMLSearchResult(body) testutils.Ok(t, err) var listings []Listing count, maxRows, err := cr.ForEach(minidom.ByName("PropertyListing"), func(elem io.ReadCloser, err error) error { if err != nil { return err } listing := Listing{} xml.NewDecoder(elem).Decode(&listing) listings = append(listings, listing) return err }) testutils.Ok(t, err) testutils.Equals(t, true, maxRows) testutils.Equals(t, 10, count) testutils.Equals(t, 2, len(listings)) }
func TestSimple(t *testing.T) { doms := ioutil.NopCloser(strings.NewReader(example)) parser := xml.NewDecoder(doms) listings := Listings{} // minidom isnt necessary but its crazy useful for massive streams md := minidom.MiniDom{ StartFunc: func(start xml.StartElement) { switch start.Name.Local { case "Listings": attrs := map[string]string{} for _, v := range start.Attr { attrs[v.Name.Local] = v.Value } listings.ListingsKey = attrs["listingsKey"] listings.Version = attrs["version"] listings.VersionTimestamp = attrs["versionTimestamp"] listings.Language = attrs["lang"] case "Disclaimer": parser.DecodeElement(listings.Disclaimer, &start) } }, // quit on the the xml tag EndFunc: minidom.QuitAt("Listings"), } err := md.Walk(parser, minidom.ByName("Listing"), ToListing(func(l Listing, err error) error { listings.Listings = append(listings.Listings, l) return err })) testutils.Ok(t, err) testutils.Equals(t, 1, len(listings.Listings)) testutils.Equals(t, "http://www.somemls.com/lisings/1234567890", listings.Listings[0].ListingURL) testutils.Equals(t, "New Light Fixtures", *listings.Listings[0].Photos[1].Caption) testutils.Equals(t, "1100.0", listings.Listings[0].Expenses[2].Value.Value) }
func TestCompactRowParsing(t *testing.T) { var col = ` A B C D E F ` var row = ` 1 2 3 4 6 ` var delim = ` ` headers := CompactRow(col).Parse(delim) values := CompactRow(row).Parse(delim) testutils.Equals(t, 6, int(len(headers))) testutils.Equals(t, 6, int(len(values))) }
func TestMetaInfoIDMap(t *testing.T) { test := map[string]string{ "ResourceID": "rid", "LookupName": "ln", "MetadataEntryID": "mid", "ClassName": "cn", "ColumnGroupName": "cgn", } testutils.Equals(t, "rid", MIResource.ID(test)) testutils.Equals(t, "ln", MILookup.ID(test)) testutils.Equals(t, "cn", MIClass.ID(test)) testutils.Equals(t, "cgn", MIColumnGroup.ID(test)) }
func verifyParseResources(t *testing.T, cm CompactMetadata) { resource := cm.Elements["METADATA-RESOURCE"][0] testutils.Equals(t, "1.12.30", resource.Attr["Version"]) testutils.Equals(t, len(resource.CompactRows), 2) indexer := resource.Indexer() var rows []Row resource.Rows(func(i int, r Row) { rows = append(rows, r) }) testutils.Equals(t, "ActiveAgent", indexer("ResourceID", rows[0])) testutils.Equals(t, "Tue, 3 Sep 2013 00:00:00 GMT", indexer("ValidationExternalDate", rows[1])) }
func TestLoad(t *testing.T) { body := ioutil.NopCloser(strings.NewReader(raw)) defer body.Close() parser := xml.NewDecoder(body) xml := RETSResponseWrapper{} err := parser.Decode(&xml) if err != io.EOF { testutils.Ok(t, err) } testutils.Equals(t, "Operation Successful", xml.ReplyText) testutils.Equals(t, "ABBA", xml.Metadata.MSystem.System.ID) testutils.Equals(t, "Property", string(xml.Metadata.MSystem.System.MResource.Resource[0].ResourceID)) }
func TestParseCompactData(t *testing.T) { body := ioutil.NopCloser(strings.NewReader(compact)) decoder := DefaultXMLDecoder(body, false) token, err := decoder.Token() testutils.Ok(t, err) start, ok := token.(xml.StartElement) testutils.Assert(t, ok, "should be a start element") testutils.Equals(t, "METADATA-ELEMENT", start.Name.Local) cm, err := NewCompactData(start, decoder, " ") testutils.Ok(t, err) testutils.Equals(t, "METADATA-ELEMENT", cm.Element) testutils.Equals(t, "Dog", cm.Attr["Cat"]) testutils.Equals(t, 2, len(cm.CompactRows)) testutils.Equals(t, 2, len(cm.Columns())) }
func TestSearchXML(t *testing.T) { body := ioutil.NopCloser(strings.NewReader(standardXML)) cr, err := NewStandardXMLSearchResult(body) testutils.Ok(t, err) var listings []io.ReadCloser count, maxRows, err := cr.ForEach(minidom.ByName("PropertyListing"), func(elem io.ReadCloser, err error) error { listings = append(listings, elem) return err }) testutils.Ok(t, err) testutils.Equals(t, true, maxRows) testutils.Equals(t, 10, count) testutils.Equals(t, 2, len(listings)) }
func verifyParseLookup(t *testing.T, cm CompactMetadata) { mdata := cm.Elements["METADATA-LOOKUP"][0] testutils.Equals(t, "TaxHistoricalDesignation", mdata.Attr["Resource"]) testutils.Equals(t, "1.12.29", mdata.Attr["Version"]) testutils.Equals(t, len(mdata.CompactRows), 4) indexer := mdata.Indexer() var row []Row mdata.Rows(func(i int, r Row) { row = append(row, r) }) testutils.Equals(t, "COUNTIES_OR_REGIONS", indexer("LookupName", row[0])) testutils.Equals(t, "Tue, 3 Sep 2013 00:00:00 GMT", indexer("Date", row[3])) }
func TestSearchCompactNoEof(t *testing.T) { rets := `<RETS ReplyCode="20201" ReplyText="No Records Found." ></RETS>` body := ioutil.NopCloser(strings.NewReader(rets)) cr, err := NewCompactSearchResult(body) testutils.Ok(t, err) testutils.Equals(t, StatusNoRecords, cr.Response.Code) }
func TestCreateHa2(t *testing.T) { method, uri := "GET", "/platinum/login" expected := "1b11c4ebed4a67753078be8020ea9d19" actual := createNoQopDigest().createHa2(method, uri, md5.New()) testutils.Equals(t, expected, actual) }
func TestSystem(t *testing.T) { body := ioutil.NopCloser(strings.NewReader(raw)) defer body.Close() extractor := &Extractor{Body: body} response, err := extractor.Open() testutils.Ok(t, err) testutils.Equals(t, "Operation Successful", response.ReplyText) xml := MSystem{} err = extractor.DecodeNext("METADATA-SYSTEM", &xml) if err != io.EOF { testutils.Ok(t, err) } testutils.Equals(t, "ABBA", xml.System.ID) testutils.Equals(t, "Property", string(xml.System.MResource.Resource[0].ResourceID)) }
func TestCompactEntry(t *testing.T) { body := ioutil.NopCloser(strings.NewReader(compact)) decoder := DefaultXMLDecoder(body, false) token, err := decoder.Token() testutils.Ok(t, err) start, ok := token.(xml.StartElement) testutils.Assert(t, ok, "should be a start element") cm, err := NewCompactData(start, decoder, " ") testutils.Ok(t, err) type Test struct { ResourceID, Standardname string } row1 := Test{} maps := cm.Entries() maps[0].SetFields(&row1) testutils.Equals(t, "ActiveAgent", row1.ResourceID) testutils.Equals(t, "ActiveAgent", row1.Standardname) }
func TestSearchXMLParseSearchQuit(t *testing.T) { noEnd := strings.Split(standardXML, "Commercial")[0] body := ioutil.NopCloser(strings.NewReader(noEnd)) cr, err := NewStandardXMLSearchResult(body) testutils.Ok(t, err) var listings [][]byte count, maxRows, err := cr.ForEach(minidom.ByName("PropertyListing"), func(elem io.ReadCloser, err error) error { tmp, _ := ioutil.ReadAll(elem) listings = append(listings, tmp) return err }) testutils.NotOk(t, err) testutils.Equals(t, false, maxRows) testutils.Equals(t, 10, count) testutils.Equals(t, 1, len(listings)) }
func TestCreateHa1Md5(t *testing.T) { username := "******" password := "******" cnonce := "6ac2c2eee85f5c33" expected := "5c0da895491be93b455ebb56f7ae0a9f" actual := createNoQopDigest().createHa1(username, password, cnonce, md5.New()) testutils.Equals(t, expected, actual) }
func TestSearchCompactParseSearchQuit(t *testing.T) { noEnd := strings.Split(compactDecoded, "<MAXROWS/>")[0] body := ioutil.NopCloser(strings.NewReader(noEnd)) cr, err := NewCompactSearchResult(body) testutils.Ok(t, err) rowsFound := 0 cr.ForEach(func(data Row, err error) error { if err != nil { testutils.Assert(t, strings.Contains(err.Error(), "EOF"), "found something not eof") return err } testutils.Equals(t, "1,2,3,4,,6", strings.Join(data, ",")) rowsFound++ return nil }) testutils.Equals(t, 8, rowsFound) }
func TestSearchCompactEmbeddedRetsStatus(t *testing.T) { rets := `<?xml version="1.0" encoding="UTF-8" ?> <RETS ReplyCode="0" ReplyText="Operation Successful"> <RETS-STATUS ReplyCode="20201" ReplyText="No matching records were found" /> </RETS>` body := ioutil.NopCloser(strings.NewReader(rets)) cr, err := NewCompactSearchResult(body) testutils.Ok(t, err) testutils.Equals(t, StatusNoRecords, cr.Response.Code) }
func TestCreateResponseQopAuth(t *testing.T) { nc := "00000001" cnonce := "6ac2c2eee85f5c33" ha1 := "5c0da895491be93b455ebb56f7ae0a9f" ha2 := "1b11c4ebed4a67753078be8020ea9d19" expected := "28552064c4cde9a3af7610e7ae286d50" actual := createAuthDigest().createResponse(ha1, ha2, nc, cnonce, md5.New()) testutils.Equals(t, expected, actual) }
func TestMetaInfoIDStruct(t *testing.T) { type TestStruct struct { ResourceID string LookupName string MetadataEntryID string ClassName string ColumnGroupName string } test := &TestStruct{ ResourceID: "rid", LookupName: "ln", MetadataEntryID: "mid", ClassName: "cn", ColumnGroupName: "cgn", } testutils.Equals(t, "rid", MIResource.ID(test)) testutils.Equals(t, "ln", MILookup.ID(test)) testutils.Equals(t, "cn", MIClass.ID(test)) testutils.Equals(t, "cgn", MIColumnGroup.ID(test)) }
func TestCreateResponseNoQop(t *testing.T) { nc := "00000001" cnonce := "6ac2c2eee85f5c33" ha1 := "5c0da895491be93b455ebb56f7ae0a9f" ha2 := "1b11c4ebed4a67753078be8020ea9d19" expected := "5f8d366fb430e9b395a84dba52247a35" actual := createNoQopDigest().createResponse(ha1, ha2, nc, cnonce, md5.New()) testutils.Equals(t, expected, actual) }
func TestSystemHierarchyCount(t *testing.T) { count := func(MetaInfo) int { return 0 } count = func(mi MetaInfo) int { counter := 1 for _, c := range mi.Child { counter = counter + count(c) } return counter } testutils.Equals(t, 25, count(MISystem)) }
func TestDigest(t *testing.T) { username, password := "******", "passwd" expected := `Digest username="******", realm="*****@*****.**", nonce="31333739363738363932323632201e00230a639db77779b354d601ee5d2e", uri="/platinum/login", response="5f8d366fb430e9b395a84dba52247a35", algorithm="MD5", opaque="6e6f742075736564"` method, uri := "GET", "/platinum/login" actual := createNoQopDigest().CreateDigestResponse(username, password, method, uri) testutils.Equals(t, expected, actual) }
func TestSearchCompactBadChar(t *testing.T) { rets := `<?xml version="1.0" encoding="UTF-8" ?> <RETS ReplyCode="0" ReplyText="Operation Successful"> <COUNT Records="1" /> <DELIMITER value = "09"/> <COLUMNS> A B C D E F </COLUMNS> <DATA> 1` + "\x0b" + `1 2 3 4 6 </DATA> </RETS>` body := ioutil.NopCloser(strings.NewReader(rets)) cr, err := NewCompactSearchResult(body) testutils.Ok(t, err) testutils.Equals(t, StatusOK, cr.Response.Code) counter := 0 cr.ForEach(func(row Row, err error) error { testutils.Ok(t, err) testutils.Equals(t, "1 1,2,3,4,,6", strings.Join(row, ",")) counter = counter + 1 return nil }) }
func TestParseCapabilitiesRelativeUrls(t *testing.T) { body := `<RETS ReplyCode="0" ReplyText="V2.7.0 2315: Success"> <RETS-RESPONSE> MemberName=Threewide Corporation User=2000343, Association Member Primary:Login:Media Restrictions:Office:RETS:RETS Advanced:RETS Customer:System-MRIS:MDS Access Common:MDS Application Login, 90, TURD1 Broker=TWD,1 MetadataVersion=1.12.30 MinMetadataVersion=1.1.1 OfficeList=TWD;1 TimeoutSeconds=1800 Login=/platinum/login Action=/platinum/get?Command=Message Search=/platinum/search Get=/platinum/get GetObject=/platinum/getobject Logout=/platinum/logout GetMetadata=/platinum/getmetadata ChangePassword=/platinum/changepassword X-SampleLinks=/rets2_2/Links X-SupportSite=http://flexmls.com/rets/ X-NotificationFeed=http://example.com/atom/feed/private/atom.xml </RETS-RESPONSE> </RETS>` urls, err := parseCapability( ioutil.NopCloser(strings.NewReader(body)), "http://server.com:6103/platinum/login", ) testutils.Ok(t, err) testutils.Equals(t, urls.Response.Text, "V2.7.0 2315: Success") testutils.Equals(t, urls.Response.Code, StatusOK) testutils.Equals(t, urls.Login, "http://server.com:6103/platinum/login") testutils.Equals(t, urls.GetMetadata, "http://server.com:6103/platinum/getmetadata") testutils.Equals(t, "http://server.com:6103/rets2_2/Links", urls.AdditionalURLs["X-SampleLinks"]) }
func TestFieldTransfer(t *testing.T) { type Tester struct { Bob string foo string Baz string } test := &Tester{} FieldTransfer(map[string]string{ "Bob": "foo", "Foo": "bar", "baz": "blah", }).To(test) testutils.Equals(t, "foo", test.Bob) testutils.Assert(t, "" == test.foo, "shouldnt be able to set lower case fields") testutils.Assert(t, "blah" == test.Baz, "should be case insensitive") }
func TestDigestQopAuth(t *testing.T) { username, password := "******", "passwd" wwwAuthenticate := `Digest realm="*****@*****.**",nonce="cbbaac704d6762fa2e4c37bb84ffddb8",opaque="77974390-589f-4ec6-b67c-4a9fc096c03f",qop="auth"` expected := `Digest username="******", realm="*****@*****.**", nonce="cbbaac704d6762fa2e4c37bb84ffddb8", uri="/rets/login", response="3b2ce903001cf00a264c69674d691526", qop=auth, nc=00000001, cnonce="6ac2c2eee85f5c33", algorithm="MD5", opaque="77974390-589f-4ec6-b67c-4a9fc096c03f"` method, uri := "GET", "/rets/login" cnonce := "6ac2c2eee85f5c33" dig, err := NewDigest(wwwAuthenticate) if err != nil { t.Fail() } actual := dig.computeAuthorization(username, password, method, uri, cnonce) testutils.Equals(t, expected, actual) }
func TestCreateHa1Md5Sess(t *testing.T) { username := "******" password := "******" cnonce := "6ac2c2eee85f5c33" wwwAuthenticate := `Digest realm="*****@*****.**", nonce="31333739363738363932323632201e00230a639db77779b354d601ee5d2e", opaque="6e6f742075736564, algorithm="MD5-sess"` digest, err := NewDigest(wwwAuthenticate) if err != nil { t.Fail() } expected := "f1843845124dcba66fef064f5aa7a782" actual := digest.createHa1(username, password, cnonce, md5.New()) testutils.Equals(t, expected, actual) }
func TestProcessResponseBodyNoConnectTime(t *testing.T) { actual, err := processResponseBody( ioutil.NopCloser(strings.NewReader( `<RETS ReplyCode="0" ReplyText="Logging out"> <RETS-RESPONSE> Billing=Im Billing You SignOffMessage=Goodbye </RETS-RESPONSE> </RETS>`, ))) if err != nil { t.Fail() } expected := &LogoutResponse{ReplyCode: StatusOK, ReplyText: "Logging out", Billing: "Im Billing You", SignOffMessage: "Goodbye"} testutils.Equals(t, expected, actual) }
func TestParseChallenge(t *testing.T) { wwwAuthenticate := `Digest realm="*****@*****.**", nonce="31333739363738363932323632201e00230a639db77779b354d601ee5d2e", opaque="6e6f742075736564"` digest, err := NewDigest(wwwAuthenticate) if err != nil { t.Fail() } expected := &Digest{ Realm: "*****@*****.**", Nonce: "31333739363738363932323632201e00230a639db77779b354d601ee5d2e", Algorithm: "MD5", Opaque: "6e6f742075736564", Qop: "", NonceCount: 1, } testutils.Equals(t, expected, digest) }