-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexamples_test.go
118 lines (102 loc) · 3.56 KB
/
examples_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package automergendjsonsync
import (
"context"
"errors"
"fmt"
"log/slog"
"net"
"net/http"
"os"
"sync"
"testing"
"github.com/automerge/automerge-go"
)
// A key integration test that checks that we can synchronise 2 clients and a server together
func Test_sync3(t *testing.T) {
t.Parallel()
// Create a starting server side doc that has some existing content.
sd := NewSharedDoc(automerge.New())
assertEqual(t, sd.Doc().RootMap().Set("a", "b"), nil)
_, _ = sd.Doc().Commit("change")
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if err := sd.ServeChanges(w, r); err != nil {
t.Fatal(err)
}
})
listener, err := net.Listen("tcp", "127.0.0.1:0")
assertEqual(t, err, nil)
server := &http.Server{Handler: mux}
defer server.Close()
goErrors := make(chan error, 3)
go func() {
if err := server.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
panic(err)
}
}()
peerDocs := make([]*SharedDoc, 0)
wg := new(sync.WaitGroup)
for i := 0; i < 2; i++ {
wg.Add(1)
// Each peer also has a starting doc that has some existing content.
peerDoc := NewSharedDoc(automerge.New())
peerDocs = append(peerDocs, peerDoc)
assertEqual(t, peerDoc.Doc().RootMap().Set(fmt.Sprintf("peer-%d", i), int64(i)), nil)
_, _ = peerDoc.Doc().Commit("change")
go func() {
defer wg.Done()
if err := peerDoc.HttpPushPullChanges(context.Background(), "http://"+listener.Addr().String(), WithClientTerminationCheck(func(doc *automerge.Doc, m *automerge.SyncMessage) bool {
return len(doc.Heads()) == 3
})); err != nil {
goErrors <- err
}
}()
}
wg.Wait()
close(goErrors)
for err2 := range goErrors {
t.Error(err2.Error())
}
t.Log(LoggableChangeHashes(sd.Doc().Heads()).LogValue().String())
t.Log(LoggableChangeHashes(peerDocs[0].Doc().Heads()).LogValue().String())
t.Log(LoggableChangeHashes(peerDocs[1].Doc().Heads()).LogValue().String())
assertEqual(t, sd.Doc().Heads(), peerDocs[0].Doc().Heads())
assertEqual(t, sd.Doc().Heads(), peerDocs[1].Doc().Heads())
assertEqual(t, sd.Doc().RootMap().Len(), 3)
values, _ := sd.Doc().RootMap().Values()
assertEqual(t, values["a"].Str(), "b")
assertEqual(t, values["peer-0"].Int64(), 0)
assertEqual(t, values["peer-1"].Int64(), 1)
}
// It's very useful to be able to load balance clients via HTTP redirect semantics.
func TestExample_HttpRedirect(t *testing.T) {
t.Parallel()
ctx := SetContextLogger(context.Background(), slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug})))
// Create a starting server side doc that has some existing content.
sd := NewSharedDoc(automerge.New())
assertEqual(t, sd.Doc().RootMap().Set("a", "b"), nil)
_, _ = sd.Doc().Commit("change")
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "/redirected")
w.WriteHeader(http.StatusTemporaryRedirect)
})
mux.HandleFunc("/redirected", func(w http.ResponseWriter, r *http.Request) {
if err := sd.ServeChanges(w, r); err != nil {
t.Fatal(err)
}
})
listener, err := net.Listen("tcp", "127.0.0.1:0")
assertEqual(t, err, nil)
server := &http.Server{Handler: mux, BaseContext: func(listener net.Listener) context.Context {
return ctx
}}
defer server.Close()
go func() {
if err := server.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
panic(err)
}
}()
peerDoc := NewSharedDoc(automerge.New())
assertEqual(t, peerDoc.HttpPushPullChanges(ctx, "http://"+listener.Addr().String(), WithClientTerminationCheck(HasAllRemoteHeads)), nil)
}