mirror of https://github.com/matrix-org/go-neb.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.4 KiB
153 lines
4.4 KiB
package clients
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/matrix-org/go-neb/database"
|
|
"github.com/matrix-org/go-neb/types"
|
|
"maunium.net/go/mautrix"
|
|
"maunium.net/go/mautrix/crypto"
|
|
mevt "maunium.net/go/mautrix/event"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
var commandParseTests = []struct {
|
|
body string
|
|
expectArgs []string
|
|
}{
|
|
{"!test word", []string{"word"}},
|
|
{"!test two words", []string{"two", "words"}},
|
|
{`!test "words with double quotes"`, []string{"words with double quotes"}},
|
|
{"!test 'words with single quotes'", []string{"words with single quotes"}},
|
|
{`!test 'single quotes' "double quotes"`, []string{"single quotes", "double quotes"}},
|
|
{`!test ‘smart single quotes’ “smart double quotes”`, []string{"smart single quotes", "smart double quotes"}},
|
|
}
|
|
|
|
type MockService struct {
|
|
types.DefaultService
|
|
commands []types.Command
|
|
}
|
|
|
|
func (s *MockService) Commands(cli types.MatrixClient) []types.Command {
|
|
return s.commands
|
|
}
|
|
|
|
type MockStore struct {
|
|
database.NopStorage
|
|
service types.Service
|
|
}
|
|
|
|
func (d *MockStore) LoadServicesForUser(userID id.UserID) ([]types.Service, error) {
|
|
return []types.Service{d.service}, nil
|
|
}
|
|
|
|
type MockTransport struct {
|
|
roundTrip func(*http.Request) (*http.Response, error)
|
|
}
|
|
|
|
func (t MockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
return t.roundTrip(req)
|
|
}
|
|
|
|
func TestCommandParsing(t *testing.T) {
|
|
var executedCmdArgs []string
|
|
cmds := []types.Command{
|
|
types.Command{
|
|
Path: []string{"test"},
|
|
Command: func(roomID id.RoomID, userID id.UserID, args []string) (interface{}, error) {
|
|
executedCmdArgs = args
|
|
return nil, nil
|
|
},
|
|
},
|
|
}
|
|
s := MockService{commands: cmds}
|
|
store := MockStore{service: &s}
|
|
database.SetServiceDB(&store)
|
|
|
|
trans := struct{ MockTransport }{}
|
|
trans.roundTrip = func(*http.Request) (*http.Response, error) {
|
|
return nil, fmt.Errorf("unhandled test path")
|
|
}
|
|
cli := &http.Client{
|
|
Transport: trans,
|
|
}
|
|
clients := New(&store, cli)
|
|
mxCli, _ := mautrix.NewClient("https://someplace.somewhere", "@service:user", "token")
|
|
mxCli.Client = cli
|
|
botClient := BotClient{Client: mxCli}
|
|
|
|
for _, input := range commandParseTests {
|
|
executedCmdArgs = []string{}
|
|
content := mevt.Content{Raw: map[string]interface{}{
|
|
"body": input.body,
|
|
"msgtype": "m.text",
|
|
}}
|
|
if veryRaw, err := content.MarshalJSON(); err != nil {
|
|
t.Errorf("Error marshalling JSON: %s", err)
|
|
} else {
|
|
content.VeryRaw = veryRaw
|
|
}
|
|
content.ParseRaw(mevt.EventMessage)
|
|
event := mevt.Event{
|
|
Type: mevt.EventMessage,
|
|
Sender: "@someone:somewhere",
|
|
RoomID: "!foo:bar",
|
|
Content: content,
|
|
}
|
|
clients.onMessageEvent(&botClient, &event)
|
|
if !reflect.DeepEqual(executedCmdArgs, input.expectArgs) {
|
|
t.Errorf("TestCommandParsing want %s, got %s", input.expectArgs, executedCmdArgs)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestSASVerificationHandling(t *testing.T) {
|
|
botClient := BotClient{verificationSAS: &sync.Map{}}
|
|
botClient.olmMachine = &crypto.OlmMachine{
|
|
DefaultSASTimeout: time.Minute,
|
|
}
|
|
otherUserID := id.UserID("otherUser")
|
|
otherDeviceID := id.DeviceID("otherDevice")
|
|
otherDevice := &crypto.DeviceIdentity{
|
|
UserID: otherUserID,
|
|
DeviceID: otherDeviceID,
|
|
}
|
|
botClient.SubmitDecimalSAS(otherUserID, otherDeviceID, crypto.DecimalSASData([3]uint{4, 5, 6}))
|
|
matched := botClient.VerifySASMatch(otherDevice, crypto.DecimalSASData([3]uint{1, 2, 3}))
|
|
if matched {
|
|
t.Error("SAS matched when they shouldn't have")
|
|
}
|
|
|
|
botClient.SubmitDecimalSAS(otherUserID, otherDeviceID, crypto.DecimalSASData([3]uint{1, 2, 3}))
|
|
matched = botClient.VerifySASMatch(otherDevice, crypto.DecimalSASData([3]uint{1, 2, 3}))
|
|
if !matched {
|
|
t.Error("Expected SAS to match but they didn't")
|
|
}
|
|
|
|
botClient.SubmitDecimalSAS(otherUserID+"wrong", otherDeviceID, crypto.DecimalSASData([3]uint{4, 5, 6}))
|
|
finished := make(chan bool)
|
|
go func() {
|
|
matched := botClient.VerifySASMatch(otherDevice, crypto.DecimalSASData([3]uint{1, 2, 3}))
|
|
finished <- true
|
|
if !matched {
|
|
t.Error("SAS didn't match when it should have (receiving SAS after calling verification func)")
|
|
}
|
|
}()
|
|
select {
|
|
case <-finished:
|
|
t.Error("Verification finished before receiving the SAS from the correct user")
|
|
default:
|
|
}
|
|
botClient.SubmitDecimalSAS(otherUserID, otherDeviceID, crypto.DecimalSASData([3]uint{1, 2, 3}))
|
|
select {
|
|
case <-finished:
|
|
case <-time.After(10 * time.Second):
|
|
t.Error("Verification did not finish after receiving the SAS from the correct user")
|
|
}
|
|
}
|