First integrational test!
This commit is contained in:
parent
8afb4b5c1f
commit
aa029ce71b
@ -3,14 +3,59 @@ package commands
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
clientproto "github.com/anytypeio/go-anytype-infrastructure-experiments/client/debug/clientdebugrpc/clientdebugrpcproto"
|
clientproto "github.com/anytypeio/go-anytype-infrastructure-experiments/client/api/apiproto"
|
||||||
|
nodeproto "github.com/anytypeio/go-anytype-infrastructure-experiments/node/api/apiproto"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DebugClient struct {
|
||||||
|
name string
|
||||||
|
address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func keepChecking(fn func() bool, finished chan bool) {
|
||||||
|
ticker := time.NewTicker(time.Second * 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
if fn() {
|
||||||
|
finished <- true
|
||||||
|
ticker.Stop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-finished
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsFunc[E comparable](s []E, f func(E) bool) bool {
|
||||||
|
return slices.IndexFunc(s, f) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func iterate(shouldStop func(iteration int) bool, wg *sync.WaitGroup, iterationCount int) {
|
||||||
|
ticker := time.NewTicker(time.Millisecond * 10)
|
||||||
|
defer wg.Done()
|
||||||
|
defer ticker.Stop()
|
||||||
|
for i := 0; i < iterationCount; i++ {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
if shouldStop(i) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *service) registerScripts() {
|
func (s *service) registerScripts() {
|
||||||
cmdAddTextMany := &cobra.Command{
|
cmdAddTextMany := &cobra.Command{
|
||||||
Use: "add-text-many [text]",
|
Use: "add-text-many [text]",
|
||||||
@ -76,4 +121,233 @@ func (s *service) registerScripts() {
|
|||||||
cmdAddTextMany.MarkFlagRequired("document")
|
cmdAddTextMany.MarkFlagRequired("document")
|
||||||
cmdAddTextMany.MarkFlagRequired("clients")
|
cmdAddTextMany.MarkFlagRequired("clients")
|
||||||
s.scripts = append(s.scripts, cmdAddTextMany)
|
s.scripts = append(s.scripts, cmdAddTextMany)
|
||||||
|
|
||||||
|
integration := &cobra.Command{
|
||||||
|
Use: "integration-tests",
|
||||||
|
Short: "integration-tests",
|
||||||
|
Args: cobra.RangeArgs(0, 0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
documentsCount, _ := cmd.Flags().GetInt("documents")
|
||||||
|
|
||||||
|
node1, node2, node3 :=
|
||||||
|
DebugClient{
|
||||||
|
name: "Node1",
|
||||||
|
address: s.peers["node1"],
|
||||||
|
},
|
||||||
|
DebugClient{
|
||||||
|
name: "Node2",
|
||||||
|
address: s.peers["node2"],
|
||||||
|
},
|
||||||
|
DebugClient{
|
||||||
|
name: "Node3",
|
||||||
|
address: s.peers["node3"],
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes := []DebugClient{node1, node2, node3}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
elapsedFunc := func() time.Duration { return time.Since(start) }
|
||||||
|
|
||||||
|
print := func(output string) {
|
||||||
|
fmt.Printf("%s | %s \n", output, elapsedFunc())
|
||||||
|
}
|
||||||
|
|
||||||
|
createSpace := func(client DebugClient) string {
|
||||||
|
space, err := s.client.CreateSpace(context.Background(), client.address, &clientproto.CreateSpaceRequest{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic("can't create a space")
|
||||||
|
}
|
||||||
|
|
||||||
|
print(fmt.Sprintf("%s: Created a space with id %s", client.name, space.Id))
|
||||||
|
|
||||||
|
return space.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
doesNodesContainDocument := func(docId string, spaceId string) map[string]bool {
|
||||||
|
var dictionary = map[string]bool{}
|
||||||
|
for _, node := range nodes {
|
||||||
|
resp, _ := s.node.TreeParams(context.Background(), node.address, &nodeproto.TreeParamsRequest{
|
||||||
|
SpaceId: spaceId,
|
||||||
|
DocumentId: docId,
|
||||||
|
})
|
||||||
|
|
||||||
|
dictionary[node.name] = resp.GetHeadIds() != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return dictionary
|
||||||
|
}
|
||||||
|
|
||||||
|
waitUntilLoadSpace := func(spaceId string, client DebugClient) bool {
|
||||||
|
print(fmt.Sprintf("%s: Trying to load space with id %s", client.name, spaceId))
|
||||||
|
|
||||||
|
_, err := s.client.LoadSpace(context.Background(), client.address, &clientproto.LoadSpaceRequest{spaceId})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
print(fmt.Sprintf("%s: Did load space with id %s", client.name, spaceId))
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
waitUntilSpaceExists := func(groupId string, client DebugClient) bool {
|
||||||
|
allSpaces, err := s.client.AllSpaces(context.Background(), client.address, &clientproto.AllSpacesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
panic("can't retrieve all spaces")
|
||||||
|
}
|
||||||
|
|
||||||
|
print(fmt.Sprintf("%s: contains %s, %t", client, groupId, slices.Contains(allSpaces.SpaceIds, groupId)))
|
||||||
|
return slices.Contains(allSpaces.SpaceIds, groupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
waitUntilDocumentExists := func(client DebugClient, spaceId string, documentId string) bool {
|
||||||
|
rs, _ := s.client.AllTrees(context.Background(), client.address, &clientproto.AllTreesRequest{SpaceId: spaceId})
|
||||||
|
|
||||||
|
contains := containsFunc(rs.Trees, func(c *clientproto.Tree) bool {
|
||||||
|
return c.Id == documentId
|
||||||
|
})
|
||||||
|
|
||||||
|
if !contains {
|
||||||
|
print(fmt.Sprintf("%s doesn't contain a document %s", client.name, documentId))
|
||||||
|
fmt.Println(doesNodesContainDocument(documentId, spaceId))
|
||||||
|
} else {
|
||||||
|
print(fmt.Sprintf("%s contains a document %s", client.name, documentId))
|
||||||
|
}
|
||||||
|
|
||||||
|
return contains
|
||||||
|
}
|
||||||
|
|
||||||
|
addTextFunc := func(iterationNumber int, client DebugClient, spaceId string, documentId string) bool {
|
||||||
|
randText := func(nonce int) string {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
buf := make([]byte, nonce*3)
|
||||||
|
rand.Read(buf)
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := s.client.AddText(context.Background(), client.address, &clientproto.AddTextRequest{
|
||||||
|
SpaceId: spaceId,
|
||||||
|
DocumentId: documentId,
|
||||||
|
Text: randText(iterationNumber),
|
||||||
|
IsSnapshot: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
print(client.address + err.Error())
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
print(fmt.Sprintf("%s: Did add text to document %s, head: %s, text: %d", client.name, r.DocumentId, r.HeadId, iterationNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
createDocumentFunc := func(client DebugClient, spaceId string) string {
|
||||||
|
docResponse, err := s.client.CreateDocument(context.Background(), client.address, &clientproto.CreateDocumentRequest{SpaceId: spaceId})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic("can't create a document")
|
||||||
|
}
|
||||||
|
|
||||||
|
print(fmt.Sprintf("%s: Created a document in space %s with id %s", client.name, spaceId, docResponse.Id))
|
||||||
|
return docResponse.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = func(wg *sync.WaitGroup, client DebugClient, spaceId string, docId string) {
|
||||||
|
time.Sleep(2)
|
||||||
|
|
||||||
|
documentDeletion := func() bool {
|
||||||
|
print("Will remove document with id" + spaceId + "." + docId)
|
||||||
|
|
||||||
|
_, err := s.client.DeleteDocument(context.Background(), client.address, &clientproto.DeleteDocumentRequest{
|
||||||
|
SpaceId: spaceId,
|
||||||
|
DocumentId: docId,
|
||||||
|
})
|
||||||
|
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var finita = make(chan bool)
|
||||||
|
go keepChecking(func() bool { return documentDeletion() }, finita)
|
||||||
|
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
checkHeadsEqual := func(client1 DebugClient, client2 DebugClient, spaceId string, docId string) bool {
|
||||||
|
rs1, _ := s.client.TreeParams(context.Background(), client1.address, &clientproto.TreeParamsRequest{
|
||||||
|
SpaceId: spaceId,
|
||||||
|
DocumentId: docId,
|
||||||
|
})
|
||||||
|
rs2, _ := s.client.TreeParams(context.Background(), client2.address, &clientproto.TreeParamsRequest{
|
||||||
|
SpaceId: spaceId,
|
||||||
|
DocumentId: docId,
|
||||||
|
})
|
||||||
|
|
||||||
|
print(fmt.Sprintf("%s document %s head is %v", client1.name, docId, rs1.GetHeadIds()))
|
||||||
|
print(fmt.Sprintf("%s document %s head is %v", client2.name, docId, rs2.GetHeadIds()))
|
||||||
|
|
||||||
|
if rs1.GetHeadIds() == nil || rs1.GetHeadIds() == nil {
|
||||||
|
print("Some head is nil")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return slices.Equal(rs1.GetHeadIds(), rs2.GetHeadIds())
|
||||||
|
}
|
||||||
|
|
||||||
|
client1, client2 := DebugClient{
|
||||||
|
name: "Client1",
|
||||||
|
address: s.peers["client1"],
|
||||||
|
}, DebugClient{
|
||||||
|
name: "Client2",
|
||||||
|
address: s.peers["client2"],
|
||||||
|
}
|
||||||
|
|
||||||
|
singleTest := func(testGroup *sync.WaitGroup, spaceId string) {
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
finished := make(chan bool)
|
||||||
|
|
||||||
|
documentId := createDocumentFunc(client2, spaceId)
|
||||||
|
keepChecking(func() bool { return waitUntilDocumentExists(client1, spaceId, documentId) }, finished)
|
||||||
|
|
||||||
|
wg.Add(2)
|
||||||
|
go iterate(func(iteration int) bool {
|
||||||
|
return addTextFunc(iteration, client2, spaceId, documentId)
|
||||||
|
}, &wg, 70)
|
||||||
|
go iterate(func(iteration int) bool {
|
||||||
|
return addTextFunc(iteration, client1, spaceId, documentId)
|
||||||
|
}, &wg, 100)
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
keepChecking(func() bool { return checkHeadsEqual(client1, client2, spaceId, documentId) }, finished)
|
||||||
|
|
||||||
|
print("The End")
|
||||||
|
|
||||||
|
testGroup.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start
|
||||||
|
finished := make(chan bool)
|
||||||
|
spaceId := createSpace(client1)
|
||||||
|
|
||||||
|
keepChecking(func() bool { return waitUntilLoadSpace(spaceId, client2) }, finished)
|
||||||
|
keepChecking(func() bool { return waitUntilSpaceExists(spaceId, client2) }, finished)
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
|
wg.Add(documentsCount)
|
||||||
|
for i := 0; i < documentsCount; i++ {
|
||||||
|
go singleTest(&wg, spaceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
print("Directed by robert b weide")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
integration.Flags().Int("documents", 50, "how many documents would be created")
|
||||||
|
s.scripts = append(s.scripts, integration)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user