blob: 10cbae3df93d611c0569c46b61cd888311772679 [file] [log] [blame]
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package googlegroups
import (
"bytes"
"context"
"fmt"
"net/http"
"regexp"
"strings"
"testing"
"golang.org/x/oscar/internal/httprr"
"golang.org/x/oscar/internal/secret"
"golang.org/x/oscar/internal/storage"
"golang.org/x/oscar/internal/testutil"
)
// aizaRegexp is used to identify AIza Cloud credentials
// in test data.
var aizaRegexp = regexp.MustCompile("AIza[0-9A-Za-z_-]{35}")
// scrub is a response scrubber for use with [rsc.io/httprr].
func scrub(b *bytes.Buffer) error {
body := b.String()
b.Reset()
newBody := aizaRegexp.ReplaceAllString(body, "")
_, err := b.WriteString(newBody)
return err
}
func TestSync(t *testing.T) {
check := testutil.Checker(t)
lg := testutil.Slogger(t)
db := storage.MemDB()
ctx := context.Background()
rr, err := httprr.Open("testdata/sync.httprr", http.DefaultTransport)
check(err)
rr.ScrubResp(scrub)
sdb := secret.Empty()
c := New(lg, db, sdb, rr.Client())
const group = "golang-announce"
check(c.Add(group))
convs := func() []*Conversation {
var convs []*Conversation
for _, cfn := range c.Conversations(group) {
convs = append(convs, cfn())
}
return convs
}
// Only look at changes before a certain date, so that we
// don't get too much data.
testTomorrow = "2011-05-05"
defer func() { testTomorrow = "" }()
check(c.Sync(ctx))
cs := convs()
if len(cs) != 1 {
t.Errorf("got %d conversations; want 1", len(cs))
}
const wantMessage = "just tagged our second stable Go release, release.r57.1."
if html := string(cs[0].HTML); !strings.Contains(html, wantMessage) {
t.Errorf("could not locate '%s' message in the %s conversation", wantMessage, cs[0].URL)
}
// Now go a little bit into the future, but there should
// be no more conversations.
testTomorrow = "2011-05-06"
check(c.Sync(ctx))
if got := len(convs()); got != 1 {
t.Errorf("got %d conversations; want 2", got)
}
}
func TestMatchConversationURL(t *testing.T) {
const group = "golang-dev"
for _, tc := range []struct {
url string
want bool
}{
{"https://groups.google.com/g/golang-dev/c/tXG6Jk_dos8", true},
{"groups.google.com/g/golang-dev/c/tXG6Jk_dos8", false},
{"https://groups.google.com/g/golang-nuts/c/tXG6Jk_dos8/m/my-groups", false}, // wrong group
{"https://groups.google.com/g/golang-dev/c/tXG6Jk_dos8/m/g/golang-dev", false},
} {
if got := matchesConversation(tc.url, group); got != tc.want {
t.Errorf("got match=%t for %s; want %t", got, tc.url, tc.want)
}
}
}
func TestConversationLink(t *testing.T) {
const group = "golang-dev"
for _, tc := range []struct {
url string
want string
}{
{"https://groups.google.com/g/golang-dev/c/tXG6Jk_dos8", // conversation
"https://groups.google.com/g/golang-dev/c/tXG6Jk_dos8"},
{"https://groups.google.com/g/golang-dev/c/tXG6Jk_dos8/m/1234", // conversation message
"https://groups.google.com/g/golang-dev/c/tXG6Jk_dos8"},
{"https://groups.google.com/g/golang-dev/g/golang-dev/c/tXG6Jk_dos8/m/1234", // repeated group
"https://groups.google.com/g/golang-dev/c/tXG6Jk_dos8"},
{"https://groups.google.com/g/golang-dev/about",
"https://groups.google.com/g/golang-dev/about"},
} {
if got := conversationLink(tc.url, group); got != tc.want {
t.Errorf("got %s for %s; want %s", got, tc.url, tc.want)
}
}
}
func TestSyncTesting(t *testing.T) {
check := testutil.Checker(t)
lg := testutil.Slogger(t)
ctx := context.Background()
group := "test"
numConvs := func(c *Client) int {
cnt := 0
for _, _ = range c.Conversations(group) {
cnt++
}
return cnt
}
for _, d := range []struct {
limit int
wantConvs int
wantInterrupt bool
}{
// interrupt is skipped since it should happen at the
// second conversation of the day, but the day limit is 1.
// Due to this limit, we sync only 1 conversation per day.
{1, 4, false},
// With increased limit, we can sync more conversations
// per day.
{2, 6, true},
{3, 7, true},
} {
t.Run(fmt.Sprintf("%d", d.limit), func(t *testing.T) {
db := storage.MemDB()
c := New(lg, db, nil, nil)
check(c.Add(group))
tc := c.Testing()
tc.setLimit(d.limit)
check(tc.LoadTxtar("testdata/convs.txt"))
err := c.Sync(ctx)
if d.wantInterrupt {
if err == nil || !strings.Contains(err.Error(), "test interrupt error") {
t.Fatalf("want test interrupt error; got %v", err)
}
} else if err != nil {
t.Fatal(err)
}
check(c.Sync(ctx)) // repeat without interruption
if gotConvs := numConvs(c); gotConvs != d.wantConvs {
t.Errorf("want %d conversations; got %d", d.wantConvs, gotConvs)
}
})
}
}