github.com/bcampbell/scrapeomat@v0.0.0-20220820232205-23e64141c89e/store/sqlstore/sqlstore_test.go (about)

     1  package sqlstore
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/bcampbell/scrapeomat/store"
    10  )
    11  
    12  // TODO: break all these tests into individual functions.
    13  
    14  func performDBTests(t *testing.T, ss *SQLStore) {
    15  
    16  	testArts := []*store.Article{
    17  		{
    18  			CanonicalURL: "http://example.com/foo-bar-wibble",
    19  			Headline:     "Foo Bar Wibble",
    20  			Content:      "<p>Foo, bar and Wibble.</p>",
    21  			Published:    "2019-04-01",
    22  			Updated:      "2019-04-01",
    23  			Publication:  store.Publication{Code: "example"},
    24  			Authors: []store.Author{
    25  				{Name: "Bob Smith"},
    26  				{Name: "Fred Door"},
    27  			},
    28  		},
    29  		{
    30  			CanonicalURL: "http://example.com/blah-blah",
    31  			Headline:     "Blah Blah",
    32  			Content:      "<p>Blah blah blah. Blah.</p>",
    33  			Published:    "2019-04-02",
    34  			Updated:      "2019-04-02",
    35  			Publication:  store.Publication{Code: "example"},
    36  		},
    37  	}
    38  
    39  	//
    40  	ids, err := ss.Stash(testArts...)
    41  	if err != nil {
    42  		t.Fatalf("stash failed: %s", err)
    43  	}
    44  	if len(ids) != len(testArts) {
    45  		t.Fatalf("wrong article count (got %d, expected %d)",
    46  			len(ids), len(testArts))
    47  	}
    48  	// the test articles now have IDs
    49  	for idx, id := range ids {
    50  		testArts[idx].ID = id
    51  	}
    52  
    53  	checkArticles(t, ss, testArts)
    54  
    55  	// Update an article
    56  	testArts[0].Headline = "A Revised Headline"
    57  	ids, err = ss.Stash(testArts[0])
    58  	if err != nil {
    59  		t.Fatalf("stash failed: %s", err)
    60  	}
    61  
    62  	//
    63  	checkArticles(t, ss, testArts)
    64  
    65  	// Very basic FetchSummary() check
    66  	mustDay := func(s string) time.Time {
    67  		t, err := time.ParseInLocation("2006-01-02", s, time.UTC)
    68  		if err != nil {
    69  			panic("bad time: " + s)
    70  		}
    71  		return t
    72  	}
    73  	expectedCounts := []store.DatePubCount{
    74  		{mustDay("2019-04-01"), "example", 1},
    75  		{mustDay("2019-04-02"), "example", 1},
    76  	}
    77  	counts, err := ss.FetchSummary(&store.Filter{}, "published")
    78  	if !reflect.DeepEqual(expectedCounts, counts) {
    79  		fmt.Printf("BUGGER.\n")
    80  		t.Fatalf("FetchSummary: expected %v, got %v", expectedCounts, counts)
    81  	}
    82  
    83  	// Check FetchCount runs with a non-null filter
    84  	cnt, err := ss.FetchCount(&store.Filter{
    85  		PubFrom: mustDay("1821-01-01"),
    86  		PubTo:   mustDay("2050-01-01"),
    87  	})
    88  	if err != nil {
    89  		t.Fatalf("FetchCount fail: %s", err)
    90  	}
    91  	if cnt != len(testArts) {
    92  		t.Fatalf("FetchCount wrong (got %d, expected %d)",
    93  			cnt, len(testArts))
    94  	}
    95  }
    96  
    97  func checkArticles(t *testing.T, ss *SQLStore, testArts []*store.Article) {
    98  	// check FetchCount()
    99  	cnt, err := ss.FetchCount(&store.Filter{})
   100  	if err != nil {
   101  		t.Fatalf("FetchCount fail: %s", err)
   102  	}
   103  	if cnt != len(testArts) {
   104  		t.Fatalf("FetchCount wrong (got %d, expected %d)",
   105  			cnt, len(testArts))
   106  	}
   107  
   108  	// Now read them back
   109  	lookup := map[string]*store.Article{}
   110  	for _, art := range testArts {
   111  		lookup[art.CanonicalURL] = art
   112  	}
   113  
   114  	it := ss.Fetch(&store.Filter{})
   115  	fetchCnt := 0
   116  	for it.Next() {
   117  		got := it.Article()
   118  		expect, ok := lookup[got.CanonicalURL]
   119  		if !ok {
   120  			t.Fatal("Fetch returned unexpected article")
   121  		}
   122  		if got.CanonicalURL != expect.CanonicalURL {
   123  			t.Fatal("Fetch: mismatch canonical_url")
   124  		}
   125  		if !equalStrings(expect.URLs, got.URLs) {
   126  			t.Fatalf("Fetch: mismatch urls (expect: %v got: %v)", expect.URLs, got.URLs)
   127  		}
   128  		if got.Headline != expect.Headline {
   129  			t.Fatal("Fetch: mismatch headline")
   130  		}
   131  
   132  		//slice might be nil or [] empty...
   133  		if len(expect.Authors) != 0 || len(got.Authors) != 0 {
   134  			if !reflect.DeepEqual(expect.Authors, got.Authors) {
   135  				t.Fatal("Fetch: mismatch authors")
   136  			}
   137  		}
   138  		if got.Content != expect.Content {
   139  			t.Fatal("Fetch: mismatch content")
   140  		}
   141  		if got.Section != expect.Section {
   142  			t.Fatal("Fetch: mismatch section")
   143  		}
   144  		// TODO: check
   145  		//  - Published, Updated fields here (requires parsing)
   146  		//  - keywords
   147  		fetchCnt++
   148  	}
   149  	if it.Err() != nil {
   150  		t.Fatalf("Fetch failed: %s", it.Err())
   151  	}
   152  	if fetchCnt != len(testArts) {
   153  		t.Fatalf("Fetch count wrong (got %d, expected %d)",
   154  			fetchCnt, len(testArts))
   155  	}
   156  }
   157  
   158  func equalStrings(a []string, b []string) bool {
   159  	//slice might be nil or [] empty...
   160  	if len(a) != len(b) {
   161  		return false
   162  	}
   163  	for i := 0; i < len(a); i++ {
   164  		if a[i] != b[i] {
   165  			return false
   166  		}
   167  	}
   168  	return true
   169  }
   170  
   171  func ExampleBuildWhere() {
   172  
   173  	filt := &store.Filter{
   174  		PubFrom:  time.Date(2010, 1, 1, 0, 0, 0, 0, time.UTC),
   175  		PubTo:    time.Date(2010, 2, 1, 0, 0, 0, 0, time.UTC),
   176  		PubCodes: []string{"dailynews", "dailyshoes"},
   177  	}
   178  	s, p := buildWhere(filt)
   179  
   180  	fmt.Println(s)
   181  	fmt.Println(rebind(bindType("sqllite3"), s))
   182  	fmt.Println(rebind(bindType("postgres"), s))
   183  	fmt.Println(p)
   184  	// Output:
   185  	// WHERE a.published>=? AND a.published<? AND p.code IN (?,?)
   186  	// WHERE a.published>=? AND a.published<? AND p.code IN (?,?)
   187  	// WHERE a.published>=$1 AND a.published<$2 AND p.code IN ($3,$4)
   188  	// [2010-01-01 00:00:00 +0000 UTC 2010-02-01 00:00:00 +0000 UTC dailynews dailyshoes]
   189  }