blob: 6ebf75362fa782913894afa68f5b5e0d69e9fdc2 [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 discussion
import (
"encoding/json"
"fmt"
"sync/atomic"
"testing"
"golang.org/x/oscar/internal/storage"
)
// Testing returns a TestingClient, which provides access to Client functionality
// intended for testing.
// Testing only returns a non-nil TestingClient in testing mode,
// which is active if the current program is a test binary (that is, [testing.Testing] returns true)
// or if [Client.EnableTesting] has been called.
// Otherwise, Testing returns nil.
//
// Each Client has only one TestingClient associated with it. Every call to Testing returns the same TestingClient.
func (c *Client) Testing() *TestingClient {
if !testing.Testing() {
return nil
}
c.testMu.Lock()
defer c.testMu.Unlock()
if c.testClient == nil {
c.testClient = &TestingClient{c: c}
}
return c.testClient
}
// A TestingClient provides access to Client functionality intended for testing.
//
// See [Client.Testing] for a description of testing mode.
type TestingClient struct {
c *Client
}
// addEvent adds an event to the Client's underlying database.
func (tc *TestingClient) addEvent(url string, e *Event) {
js := json.RawMessage(storage.JSON(e.Typed))
tc.c.testMu.Lock()
if tc.c.testEvents == nil {
tc.c.testEvents = make(map[string]json.RawMessage)
}
tc.c.testEvents[url] = js
e.JSON = js
tc.c.testMu.Unlock()
b := tc.c.db.Batch()
tc.c.writeEvent(b, e)
b.Apply()
}
var issueID int64 = 1e9
// AddDiscussion adds the given discussion to the identified project,
// assigning it a new issue number starting at 10⁹.
// AddDiscussion creates a new entry in the associated [Client]'s
// underlying database, so other Client's using the same database
// will see the issue too.
//
// NOTE: Only one TestingClient should be adding issues,
// since they do not coordinate in the database about ID assignment.
// Perhaps they should, but normally there is just one Client.
func (tc *TestingClient) AddDiscussion(project string, d *Discussion) int64 {
id := atomic.AddInt64(&issueID, +1)
d.URL = fmt.Sprintf("https://github.com/%s/discussions/%d", project, id)
tc.addEvent(d.URL, &Event{
Project: project,
Discussion: d.Number,
API: DiscussionAPI,
ID: id,
Typed: d,
})
return id
}
var commentID int64 = 1e10
// AddIssueComment adds the given issue comment to the identified project issue,
// assigning it a new comment ID starting at 10¹⁰.
// AddIssueComment creates a new entry in the associated [Client]'s
// underlying database, so other Client's using the same database
// will see the issue comment too.
//
// NOTE: Only one TestingClient should be adding issues,
// since they do not coordinate in the database about ID assignment.
// Perhaps they should, but normally there is just one Client.
func (tc *TestingClient) AddComment(project string, disc int64, comment *Comment) int64 {
id := atomic.AddInt64(&commentID, +1)
comment.URL = fmt.Sprintf("https://github.com/%s/discussions/%d#discussioncomment-%d", project, disc, id)
tc.addEvent(comment.URL, &Event{
Project: project,
Discussion: disc,
API: CommentAPI,
ID: id,
Typed: comment,
})
return id
}