package skate import ( "bytes" "encoding/json" "fmt" "reflect" "testing" "github.com/nsf/jsondiff" ) // XXX: Work on JSON directly, as structs can get unwieldy. func TestOpenLibraryToRelease(t *testing.T) { var cases = []struct { work OpenLibrarySolrDoc release Release err error }{ { work: OpenLibrarySolrDoc{}, release: Release{ ExtIDs: struct { Arxiv string `json:"arxiv,omitempty"` Core string `json:"core,omitempty"` DOI string `json:"doi,omitempty"` ISBN []string `json:"isbn,omitempty"` Jstor string `json:"jstor,omitempty"` OLID string `json:"olid,omitempty"` PMCID string `json:"pmcid,omitempty"` PMID string `json:"pmid,omitempty"` WikidataQID string `json:"wikidata_qid,omitempty"` }{}, }, err: nil, }, { work: OpenLibrarySolrDoc{ Title: "Hello World", Isbn: []string{ "2844273386", "9782844273383", }, }, release: Release{ ExtIDs: struct { Arxiv string `json:"arxiv,omitempty"` Core string `json:"core,omitempty"` DOI string `json:"doi,omitempty"` ISBN []string `json:"isbn,omitempty"` Jstor string `json:"jstor,omitempty"` OLID string `json:"olid,omitempty"` PMCID string `json:"pmcid,omitempty"` PMID string `json:"pmid,omitempty"` WikidataQID string `json:"wikidata_qid,omitempty"` }{ ISBN: []string{"9782844273383"}, }, Title: "Hello World", }, err: nil, }, { work: OpenLibrarySolrDoc{ Key: "/works/OL10000003W", Title: "Hello World", Isbn: []string{ "2844273386", "9782844273383", }, HasFulltext: false, }, release: Release{ ExtIDs: struct { Arxiv string `json:"arxiv,omitempty"` Core string `json:"core,omitempty"` DOI string `json:"doi,omitempty"` ISBN []string `json:"isbn,omitempty"` Jstor string `json:"jstor,omitempty"` OLID string `json:"olid,omitempty"` PMCID string `json:"pmcid,omitempty"` PMID string `json:"pmid,omitempty"` WikidataQID string `json:"wikidata_qid,omitempty"` }{ ISBN: []string{"9782844273383"}, OLID: "OL10000003W", }, Title: "Hello World", Extra: struct { ContainerName string `json:"container_name,omitempty"` SubtitleValue interface{} `json:"subtitle,omitempty"` // []str or str Crossref struct { Type string `json:"type,omitempty"` } `json:"crossref,omitempty"` DataCite struct { MetadataVersion int `json:"metadataVersion,omitempty"` Relations []DataCiteRelation `json:"relations,omitempty"` } `json:"datacite,omitempty"` Skate struct { // Mark as converted (e.g. by setting status to "ref") Status string `json:"status,omitempty"` // Carry the ref index and key around. Ref struct { Index int64 `json:"index,omitempty"` Key string `json:"key,omitempty"` Locator string `json:"locator,omitempty"` Source string `json:"source,omitempty"` } `json:"ref,omitempty"` ResearchGate struct { URL string `json:"url,omitempty"` } `json:"rg,omitempty"` ResolvedContainerName string `json:"resolved_container_name"` } `json:"skate,omitempty"` OpenLibrary struct { HasFulltext bool `json:"has_fulltext,omitempty"` WorkID string `json:"work,omitempty"` SourceRecords []string `json:"source_records,omitempty"` } `json:"ol,omitempty"` }{ OpenLibrary: struct { HasFulltext bool `json:"has_fulltext,omitempty"` WorkID string `json:"work,omitempty"` SourceRecords []string `json:"source_records,omitempty"` }{ HasFulltext: false, }, }, }, err: nil, }, } for _, c := range cases { r, err := OpenLibrarySolrDocToRelease(&c.work) if err != nil { t.Fatalf("got %v, want %v", err, c.err) } if !reflect.DeepEqual(r, &c.release) { t.Fatalf(prettyStructDiff(r, &c.release)) } } } func prettyStructDiff(s, t interface{}) string { b, err := json.MarshalIndent(s, "", " ") if err != nil { return fmt.Sprintf("diff failed: %v", err) } c, err := json.MarshalIndent(t, "", " ") if err != nil { return fmt.Sprintf("diff failed: %v", err) } opts := jsondiff.DefaultConsoleOptions() _, d := jsondiff.Compare(b, c, &opts) return d } func TestParseIsbn(t *testing.T) { var cases = []struct { s string result []string }{ {s: "", result: nil}, {s: "0000000000000000000000", result: nil}, {s: "978953510472X", result: nil}, {s: "978-0-262-06197-1", result: []string{"9780262061971"}}, {s: "0-262-06197-X", result: []string{"9780262061971"}}, {s: "9789535104728 9789535104728 9789535104728", result: []string{"9789535104728"}}, { s: "Continuous, .. Dr. Marina Pana (Ed.), ISBN: 978-953-51-0472-8, InTech, Available from", result: []string{"9789535104728"}, }, { s: "(IGN). Madrid. M. de Fomento ISBN 84-498-0665-8", result: []string{"9788449806650"}, }, { s: "House Pvt. Limited., (2006), ISBN 9788183561426. Date accessed: August 2015.", result: []string{"9788183561426"}, }, { s: "Electrolytes. 2003. ISBN 0-9726720-0-1. Pages 341, 357.", result: []string{"9780972672009"}, }, { s: "£25.00. ISBN 0 631 15254 7. First published in Italian in 1985.", result: []string{"9780631152545"}, }, { s: "Kluwer Academic Inc., 1996. ISBN O- 7923-9777-0.", result: []string{"9780792397779"}, }, { s: "Fisheries and Aquaculture, Rome 2012; ISBN: 978-92-5- 107225-7.", result: []string{"9789251072257"}, }, { s: " Praha; iSBn 80-247- 1046-3.", result: []string{"9788024710464"}, }, { s: "Avialable at: http://www.urn.fi/urn:isbn:9514257693 (accessed: 3.07.2017).", result: []string{"9789514257698"}, }, { s: "Colegio de Arquitectos de Málaga, 1987, ISBN: 8439899939, 9788439899938.", result: []string{"9788439899938"}, }, } for _, c := range cases { r := ParseIsbn(c.s) if !reflect.DeepEqual(r, c.result) { t.Fatalf("got %v, want %v", r, c.result) } } } func TestLinkHash(t *testing.T) { var cases = []struct { bref BiblioRef linkHash string }{ { bref: BiblioRef{}, linkHash: "8b8c3f74dd1472aa8869ee3a58295b70c7064aa8", }, { bref: BiblioRef{SourceReleaseIdent: "123"}, linkHash: "23d0f9e279ec533f46a6b220f7a5758ec0c9d9af", }, { bref: BiblioRef{ SourceReleaseIdent: "123", TargetReleaseIdent: "456", }, linkHash: "fc:123--fc:456", }, { bref: BiblioRef{ SourceReleaseIdent: "123", TargetOpenLibraryWork: "/works/OL456M", }, linkHash: "fc:123--ol:/works/OL456M", }, { bref: BiblioRef{ SourceReleaseIdent: "123", TargetURL: "http://fatcat.wiki", }, linkHash: "fc:123--wb:http://fatcat.wiki", }, } for _, c := range cases { result := c.bref.LinkHash() if result != c.linkHash { t.Fatalf("got %v, want %v", result, c.linkHash) } } } func TestSchemaMarshal(t *testing.T) { // CSL when issued is empty, but accepted is not var csl = CSL{ Title: "test-doc", Issued: &CSLDate{ Parts: [][]int{{2012}}, }, } var csl_json = []byte(`{"issued":{"date-parts":[[2012]]},"title":"test-doc"}`) var csl_encoded, _ = json.Marshal(csl) if bytes.Compare(csl_json, csl_encoded) != 0 { t.Fatalf("got:\n%v\nwant:\n%v\n", string(csl_json[:]), string(csl_encoded[:])) } } func TestReleaseToUnstructured(t *testing.T) { var cases = []struct { r *Release s string }{ {r: &Release{}, s: ""}, {r: &Release{Volume: "12"}, s: "vol. 12"}, {r: &Release{Volume: "12", Issue: "X"}, s: "vol. 12, no. X"}, {r: &Release{Volume: "12", Issue: "X", ReleaseYearValue: "1999"}, s: "vol. 12, no. X, 1999"}, {r: &Release{Volume: "12", ContainerName: "Solar", ReleaseYearValue: "1999"}, s: "Solar, vol. 12, 1999"}, {r: &Release{ExtIDs: struct { Arxiv string `json:"arxiv,omitempty"` Core string `json:"core,omitempty"` DOI string `json:"doi,omitempty"` ISBN []string `json:"isbn,omitempty"` // should be isbn13 Jstor string `json:"jstor,omitempty"` OLID string `json:"olid,omitempty"` PMCID string `json:"pmcid,omitempty"` PMID string `json:"pmid,omitempty"` WikidataQID string `json:"wikidata_qid,omitempty"` }{ DOI: "10.1234/1234", }, Volume: "12", ContainerName: "Solar", ReleaseYearValue: "1999"}, s: "Solar, vol. 12, 1999, 10.1234/1234"}, {r: &Release{ Title: "ABC", }, s: "ABC"}, {r: &Release{ Title: "ABC", ReleaseYearValue: "2000", }, s: "ABC, 2000"}, {r: &Release{ ContainerName: "Journal of Letters", }, s: "Journal of Letters"}, {r: &Release{ ContainerName: "Journal of Letters", }, s: "Journal of Letters"}, {r: &Release{ Title: "ABC", ContainerName: "Journal of Letters", }, s: "ABC. Journal of Letters"}, {r: &Release{ Title: "ABC", ContainerName: "Journal of Letters", Volume: "12", Pages: "1-10", }, s: "ABC. Journal of Letters, vol. 12, pp. 1-10"}, {r: &Release{ Title: "ABC", ReleaseYearValue: "2010", ContainerName: "Journal of Letters", }, s: "ABC. Journal of Letters, 2010"}, {r: &Release{ Title: "ABC", ContainerName: "Journal of Letters", Contribs: []struct { Index int `json:"index,omitempty"` RawName string `json:"raw_name,omitempty"` Role string `json:"role,omitempty"` }{ { RawName: "Liam Ling", }, }, }, s: "Liam Ling. ABC. Journal of Letters"}, {r: &Release{ Title: "ABC", ContainerName: "Journal of Letters", Contribs: []struct { Index int `json:"index,omitempty"` RawName string `json:"raw_name,omitempty"` Role string `json:"role,omitempty"` }{ { RawName: "Liam Ling", }, { RawName: "Lin Lee", }, }, }, s: "Liam Ling, Lin Lee. ABC. Journal of Letters"}, } for _, c := range cases { got := ReleaseToUnstructured(c.r) if got != c.s { t.Fatalf("got %v, want %v", got, c.s) } } } func TestCSLDateString(t *testing.T) { var cases = []struct { date CSLDate s string }{ {CSLDate{}, ""}, {CSLDate{Raw: "2012"}, "2012"}, {CSLDate{Raw: "about 2012"}, "about 2012"}, {CSLDate{Raw: "", Parts: nil}, ""}, {CSLDate{Raw: "", Parts: [][]int{}}, ""}, {CSLDate{Raw: "", Parts: [][]int{ []int{2001}, }}, "2001"}, {CSLDate{Raw: "", Parts: [][]int{ []int{2001, 1}, }}, "2001-01"}, {CSLDate{Raw: "", Parts: [][]int{ []int{2001, 1, 1}, }}, "2001-01-01"}, {CSLDate{Raw: "", Parts: [][]int{ []int{2001, 1, 12}, }}, "2001-01-12"}, } for i, c := range cases { result := c.date.String() if result != c.s { t.Fatalf("[%d] got %v, want %v", i, result, c.s) } } } func BenchmarkParseIsbn(b *testing.B) { for n := 0; n < b.N; n++ { ParseIsbn("House Pvt. Limited., (2006), ISBN 9788183561426. Date accessed: August 2015.") } } func BenchmarkRefToRelease(b *testing.B) { var ref Ref _ = json.Unmarshal([]byte(` { "biblio": { "arxiv_id": "123", "container_name": "IEEE Trans. Pattern Anal. Mach. Intell", "contrib_raw_names": [ "M Ben-Ezra", "S K Nayar" ], "doi": "123", "issue": "6", "pages": "689-698", "pmcid": "123", "publisher": "ABC", "title": "Motion-based motion deblurring", "unstructured": "M. Ben-Ezra and S. K. Nayar. Motion-based motion deblurring. IEEE Trans. Pattern Anal. Mach. Intell., 26(6):689-698, 2004. 2", "url": "https://abc.com", "volume": "26", "year": 2004 }, "index": 0, "key": "b0", "ref_source": "grobid", "release_ident": "26qgat7mzrerjacrlsz3gdmcgy", "release_year": 2014, "work_ident": "aaaoe2wcbvdjthnv36dlqgkray" }`), &ref) for n := 0; n < b.N; n++ { _, _ = RefToRelease(&ref) } }