package json import ( "encoding/json" "fmt" "log" "reflect" "testing" "forge.cadoles.com/wpetit/guesstimate/internal/diffsync" "github.com/davecgh/go-spew/spew" ) func TestJSONSync(t *testing.T) { doc1 := diffsync.NewDocument( []byte("{}"), WithJSONSync(), ) doc2 := diffsync.NewDocument( []byte("{}"), WithJSONSync(), ) p1 := doc1.NewPeer() p2 := doc2.NewPeer() log.Printf("p1 shadow: %s", p1.Shadow().Content()) log.Printf("p2 shadow: %s", p2.Shadow().Content()) newContent1 := []byte(`{"hello":"world"}`) log.Printf("updating doc1 with '%s'", newContent1) stack1, err := p1.Update(newContent1) if err != nil { t.Error(err) } log.Printf("applying stack1 to doc2 '%s'", doc2.Content()) if err := p2.Apply(stack1); err != nil { t.Error(err) } log.Printf("new doc2 content: '%s'", doc2.Content()) if g, e := doc2.Content(), doc1.Content(); !jsonEqual(e, g) { t.Errorf("doc2.Content(): expected '%s', got '%s'", e, g) } } type testStep struct { Local *diffsync.Peer Remote *diffsync.Peer Update string MatchLocal bool MatchRemote bool } func TestBidirectionnalUpdate(t *testing.T) { doc1 := diffsync.NewDocument([]byte(`{}`), WithJSONSync()) doc2 := diffsync.NewDocument([]byte(`{}`), WithJSONSync()) p1 := doc1.NewPeer() p2 := doc2.NewPeer() var cases = []testStep{ { Local: p1, Remote: p2, Update: `{"hello":"world"}`, MatchLocal: true, MatchRemote: true, }, { Local: p2, Remote: p1, Update: `{"hello":"world","foo":"bar"}`, MatchLocal: true, MatchRemote: true, }, { Local: p1, Remote: p2, Update: `{"hello":1,"foo":"bar"}`, MatchLocal: true, MatchRemote: true, }, { Local: p1, Remote: nil, Update: `{"hello":1,"foo":"bar", "test":{"bar": "baz"}}`, MatchLocal: true, MatchRemote: false, }, { Local: p2, Remote: p1, Update: `{"hello":2,"foo":"bar", "test":{"bar": "baz","world":"hello"}}`, MatchLocal: true, MatchRemote: true, }, } for i, step := range cases { func(step testStep, i int) { t.Run(fmt.Sprintf("Step %d", i), func(t *testing.T) { log.Printf("local document before update: '%s'", step.Local.Document().Content()) stack, err := step.Local.Update([]byte(step.Update)) if err != nil { t.Error(err) } log.Printf("local document after update: '%s'", step.Local.Document().Content()) log.Printf("resulting stack: '%s'", spew.Sdump(stack)) if step.MatchLocal { if e, g := step.Local.Document().Content(), []byte(step.Update); !jsonEqual(e, g) { t.Errorf("local.Document().Content(): expected '%s', got '%s'", e, g) } } if step.Remote != nil { log.Printf("remote document before apply: '%s'", step.Remote.Document().Content()) if err := step.Remote.Apply(stack); err != nil { t.Error(err) } log.Printf("remote document after apply: '%s'", step.Remote.Document().Content()) } if step.MatchRemote { if e, g := step.Remote.Document().Content(), []byte(step.Update); !jsonEqual(e, g) { t.Errorf("remote.Document().Content(): expected '%s', got '%s'", e, g) } } if step.MatchLocal && step.MatchRemote { if e, g := step.Local.Document().Content(), step.Remote.Document().Content(); !jsonEqual(e, g) { t.Errorf("local.Document().Content() should match remote.Document().Content() ! Got '%s' and '%s'", e, g) } } }) }(step, i) } } func jsonEqual(s1, s2 []byte) bool { var ( o1 interface{} o2 interface{} ) var err error err = json.Unmarshal(s1, &o1) if err != nil { panic(fmt.Errorf("Error mashalling []byte 1 :: %s", err.Error())) } err = json.Unmarshal(s2, &o2) if err != nil { panic(fmt.Errorf("Error mashalling []byte 2 :: %s", err.Error())) } return reflect.DeepEqual(o1, o2) }