func TestSortByAge(t *testing.T) { q := newJobQueue() q.Push("f1", 0, 20) q.Push("f2", 0, 40) q.Push("f3", 0, 30) q.Push("f4", 0, 10) q.SortOldestFirst() _, actual := q.Jobs() if l := len(actual); l != 4 { t.Fatalf("Weird length %d returned from Jobs()", l) } expected := []string{"f4", "f1", "f3", "f2"} if diff, equal := messagediff.PrettyDiff(expected, actual); !equal { t.Errorf("SortOldestFirst() diff:\n%s", diff) } q.SortNewestFirst() _, actual = q.Jobs() if l := len(actual); l != 4 { t.Fatalf("Weird length %d returned from Jobs()", l) } expected = []string{"f2", "f3", "f1", "f4"} if diff, equal := messagediff.PrettyDiff(expected, actual); !equal { t.Errorf("SortNewestFirst() diff:\n%s", diff) } }
func TestSortBySize(t *testing.T) { q := newJobQueue() q.Push("f1", 20, time.Time{}) q.Push("f2", 40, time.Time{}) q.Push("f3", 30, time.Time{}) q.Push("f4", 10, time.Time{}) q.SortSmallestFirst() _, actual := q.Jobs() if l := len(actual); l != 4 { t.Fatalf("Weird length %d returned from Jobs()", l) } expected := []string{"f4", "f1", "f3", "f2"} if diff, equal := messagediff.PrettyDiff(expected, actual); !equal { t.Errorf("SortSmallestFirst() diff:\n%s", diff) } q.SortLargestFirst() _, actual = q.Jobs() if l := len(actual); l != 4 { t.Fatalf("Weird length %d returned from Jobs()", l) } expected = []string{"f2", "f3", "f1", "f4"} if diff, equal := messagediff.PrettyDiff(expected, actual); !equal { t.Errorf("SortLargestFirst() diff:\n%s", diff) } }
func TestListDropFolder(t *testing.T) { ldb := db.OpenMemory() s0 := db.NewFileSet("test0", ldb) local1 := []protocol.FileInfo{ {Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}}, {Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}}, {Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}}, } s0.Replace(protocol.LocalDeviceID, local1) s1 := db.NewFileSet("test1", ldb) local2 := []protocol.FileInfo{ {Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}}, {Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}}, {Name: "f", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}}, } s1.Replace(remoteDevice0, local2) // Check that we have both folders and their data is in the global list expectedFolderList := []string{"test0", "test1"} actualFolderList := ldb.ListFolders() if diff, equal := messagediff.PrettyDiff(expectedFolderList, actualFolderList); !equal { t.Fatalf("FolderList mismatch. Diff:\n%s", diff) } if l := len(globalList(s0)); l != 3 { t.Errorf("Incorrect global length %d != 3 for s0", l) } if l := len(globalList(s1)); l != 3 { t.Errorf("Incorrect global length %d != 3 for s1", l) } // Drop one of them and check that it's gone. db.DropFolder(ldb, "test1") expectedFolderList = []string{"test0"} actualFolderList = ldb.ListFolders() if diff, equal := messagediff.PrettyDiff(expectedFolderList, actualFolderList); !equal { t.Fatalf("FolderList mismatch. Diff:\n%s", diff) } if l := len(globalList(s0)); l != 3 { t.Errorf("Incorrect global length %d != 3 for s0", l) } if l := len(globalList(s1)); l != 0 { t.Errorf("Incorrect global length %d != 0 for s1", l) } }
func TestKeyspaceComplement(t *testing.T) { t.Parallel() testData := []struct { a, want *Keyspace }{ { &Keyspace{1, 10}, &Keyspace{10, 1}, }, { nil, &Keyspace{1, 0}, }, { &Keyspace{1, 0}, nil, }, } for i, td := range testData { out := td.a.Complement() if diff, equal := messagediff.PrettyDiff(td.want, out); !equal { t.Errorf("%d. %+v.Complement() = %+v not %+v\n%s", i, td.a, out, td.want, diff) } } }
func ExampleAtom() { got := data2() want := data1() diff, equal := messagediff.PrettyDiff(want, got) fmt.Printf("%v %s", equal, diff) // Output: false modified: [0].FirstChild.NextSibling.Attr = " baz" }
func TestDeviceAddressesStatic(t *testing.T) { name, _ := os.Hostname() expected := map[protocol.DeviceID]DeviceConfiguration{ device1: { DeviceID: device1, Addresses: []string{"tcp://192.0.2.1", "tcp://192.0.2.2"}, }, device2: { DeviceID: device2, Addresses: []string{"tcp://192.0.2.3:6070", "tcp://[2001:db8::42]:4242"}, }, device3: { DeviceID: device3, Addresses: []string{"tcp://[2001:db8::44]:4444", "tcp://192.0.2.4:6090"}, }, device4: { DeviceID: device4, Name: name, // Set when auto created Addresses: []string{"dynamic"}, Compression: protocol.CompressMetadata, }, } cfg, err := Load("testdata/deviceaddressesstatic.xml", device4) if err != nil { t.Error(err) } actual := cfg.Devices() if diff, equal := messagediff.PrettyDiff(expected, actual); !equal { t.Errorf("Devices differ. Diff:\n%s", diff) } }
func TestParse(t *testing.T) { testData := []struct { in string want []*protocol.Triple }{{ `[{"subj":"foo", "pred":"bar", "obj":"moo"}, {}]`, []*protocol.Triple{ { Subj: "foo", Pred: "bar", Obj: "moo", }, {}, }, }} for i, td := range testData { out, err := Parse(td.in) if err != nil { t.Error(err) } if diff, eq := messagediff.PrettyDiff(td.want, out); !eq { t.Errorf("%d. Parse(%#v) = %#v\ndiff %s", i, td.in, out, diff) } } }
func TestDirNames(t *testing.T) { names := dirNames("testdata") expected := []string{"default", "foo", "testfolder"} if diff, equal := messagediff.PrettyDiff(expected, names); !equal { t.Errorf("Unexpected dirNames return: %#v\n%s", names, diff) } }
func TestWalk(t *testing.T) { ignores := ignore.New(false) err := ignores.Load("testdata/.stignore") if err != nil { t.Fatal(err) } t.Log(ignores) fchan, err := Walk(Config{ Dir: "testdata", BlockSize: 128 * 1024, Matcher: ignores, Hashers: 2, }) if err != nil { t.Fatal(err) } var tmp []protocol.FileInfo for f := range fchan { tmp = append(tmp, f) } sort.Sort(fileList(tmp)) files := fileList(tmp).testfiles() if diff, equal := messagediff.PrettyDiff(testdata, files); !equal { t.Errorf("Walk returned unexpected data. Diff:\n%s", diff) } }
func TestShardQueryByHash(t *testing.T) { t.Parallel() testData := []struct { step *protocol.ArrayOp want map[uint64]*protocol.ArrayOp }{ { nil, nil, }, { &protocol.ArrayOp{ Triples: []*protocol.Triple{ {Subj: "foo"}, {Subj: "bar"}, }, }, map[uint64]*protocol.ArrayOp{ 0xe271865701f54561: { Triples: []*protocol.Triple{ {Subj: "foo"}, {Subj: "bar"}, }, }, 0x923658dbfd3ae604: { Triples: []*protocol.Triple{ {Subj: "foo"}, {Subj: "bar"}, }, }, }, }, { &protocol.ArrayOp{ Triples: []*protocol.Triple{ {Pred: "bar"}, }, }, map[uint64]*protocol.ArrayOp{ 0: { Triples: []*protocol.Triple{ {Pred: "bar"}, }, }, }, }, } for i, td := range testData { out := ShardQueryByHash(td.step) if diff, eq := messagediff.PrettyDiff(td.want, out); !eq { t.Errorf("%d. Parse(%#v) = %#v\ndiff %s", i, td.step, out, diff) } } }
func TestStaggeredVersioningVersionCount(t *testing.T) { /* Default settings: {30, 3600}, // first hour -> 30 sec between versions {3600, 86400}, // next day -> 1 h between versions {86400, 592000}, // next 30 days -> 1 day between versions {604800, maxAge}, // next year -> 1 week between versions */ loc, _ := time.LoadLocation("Local") now, _ := time.ParseInLocation(TimeFormat, "20160415-140000", loc) files := []string{ // 14:00:00 is "now" "test~20160415-140000", // 0 seconds ago "test~20160415-135959", // 1 second ago "test~20160415-135958", // 2 seconds ago "test~20160415-135900", // 1 minute ago "test~20160415-135859", // 1 minute 1 second ago "test~20160415-135830", // 1 minute 30 seconds ago "test~20160415-135829", // 1 minute 31 seconds ago "test~20160415-135700", // 3 minutes ago "test~20160415-135630", // 3 minutes 30 seconds ago "test~20160415-133000", // 30 minutes ago "test~20160415-132900", // 31 minutes ago "test~20160415-132500", // 35 minutes ago "test~20160415-132000", // 40 minutes ago "test~20160415-130000", // 60 minutes ago "test~20160415-124000", // 80 minutes ago "test~20160415-122000", // 100 minutes ago "test~20160415-110000", // 120 minutes ago } sort.Strings(files) delete := []string{ "test~20160415-140000", // 0 seconds ago "test~20160415-135959", // 1 second ago "test~20160415-135900", // 1 minute ago "test~20160415-135830", // 1 minute 30 second ago "test~20160415-130000", // 60 minutes ago "test~20160415-124000", // 80 minutes ago } sort.Strings(delete) os.MkdirAll("testdata/.stversions", 0755) defer os.RemoveAll("testdata") testCleanDone = make(chan struct{}) v := NewStaggered("", "testdata", map[string]string{"maxAge": strconv.Itoa(365 * 86400)}).(Staggered) <-testCleanDone rem := v.toRemove(files, now) if diff, equal := messagediff.PrettyDiff(delete, rem); !equal { t.Errorf("Incorrect deleted files; got %v, expected %v\n%v", rem, delete, diff) } }
func TestNoListenAddresses(t *testing.T) { cfg, err := Load("testdata/nolistenaddress.xml", device1) if err != nil { t.Error(err) } expected := []string{""} actual := cfg.Options().ListenAddresses if diff, equal := messagediff.PrettyDiff(expected, actual); !equal { t.Errorf("Unexpected ListenAddresses. Diff:\n%s", diff) } }
func TestQuery(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } nodes := launchSwarm(5, t) defer killSwarm(nodes) primary := nodes[0] triples := protocol.CloneTriples(testTriples) if err := primary.signAndInsertTriples(triples, primary.crypto); err != nil { t.Fatal(err) } testData := []struct { query *protocol.QueryRequest want []*protocol.Triple }{ { &protocol.QueryRequest{ Type: protocol.BASIC, Steps: []*protocol.ArrayOp{{ Triples: []*protocol.Triple{{ Subj: "/m/02mjmr", }}, }}, }, []*protocol.Triple{ { Subj: "/m/02mjmr", Pred: "/type/object/name", Obj: "Barack Obama", }, { Subj: "/m/02mjmr", Pred: "/type/object/type", Obj: "/people/person", }, }, }, } for i, td := range testData { trips, err := primary.ExecuteQuery(td.query) if err != nil { t.Error(err) } trips = stripCreated(stripSigning(trips)) if diff, equal := messagediff.PrettyDiff(td.want, trips); !equal { t.Errorf("%d. s.ExecuteQuery(%+v) = %+v\n%s", i, td.query, trips, diff) } } }
func TestBringToFront(t *testing.T) { q := newJobQueue() q.Push("f1", 0, 0) q.Push("f2", 0, 0) q.Push("f3", 0, 0) q.Push("f4", 0, 0) _, queued := q.Jobs() if diff, equal := messagediff.PrettyDiff([]string{"f1", "f2", "f3", "f4"}, queued); !equal { t.Errorf("Order does not match. Diff:\n%s", diff) } q.BringToFront("f1") // corner case: does nothing _, queued = q.Jobs() if diff, equal := messagediff.PrettyDiff([]string{"f1", "f2", "f3", "f4"}, queued); !equal { t.Errorf("Order does not match. Diff:\n%s", diff) } q.BringToFront("f3") _, queued = q.Jobs() if diff, equal := messagediff.PrettyDiff([]string{"f3", "f1", "f2", "f4"}, queued); !equal { t.Errorf("Order does not match. Diff:\n%s", diff) } q.BringToFront("f2") _, queued = q.Jobs() if diff, equal := messagediff.PrettyDiff([]string{"f2", "f3", "f1", "f4"}, queued); !equal { t.Errorf("Order does not match. Diff:\n%s", diff) } q.BringToFront("f4") // corner case: last element _, queued = q.Jobs() if diff, equal := messagediff.PrettyDiff([]string{"f4", "f2", "f3", "f1"}, queued); !equal { t.Errorf("Order does not match. Diff:\n%s", diff) } }
func TestSortTriples(t *testing.T) { t.Parallel() testData := []struct { a, want []*Triple }{ { []*Triple{ { Subj: "b", }, { Subj: "c", }, { Subj: "a", Pred: "b", }, { Subj: "a", Pred: "a", }, }, []*Triple{ { Subj: "a", Pred: "a", }, { Subj: "a", Pred: "b", }, { Subj: "b", }, { Subj: "c", }, }, }, } for i, td := range testData { out := CloneTriples(td.a) SortTriples(out) if diff, equal := messagediff.PrettyDiff(td.want, out); !equal { t.Errorf("%d. SortTriples(%+v) = %+v not %+v\n%s", i, td.a, out, td.want, diff) } } }
func TestInsertAndRetreiveTriples(t *testing.T) { t.Parallel() s := testServer(t) go s.network.Listen() time.Sleep(10 * time.Millisecond) base := fmt.Sprintf("http://localhost:%d", s.network.Port) testTriples := testTriplesKeyspace(s.network.LocalKeyspace()) triples, err := json.Marshal(testTriples) if err != nil { t.Error(err) } buf := bytes.NewBuffer(triples) resp, err := http.Post(base+"/api/v1/insert", "application/json", buf) if err != nil { t.Error(err) } out, _ := ioutil.ReadAll(resp.Body) if !bytes.Contains(out, []byte(strconv.Itoa(len(testTriples)))) { t.Errorf("http.Post(/api/v1/insert) = %+v; missing %+v", string(out), len(testTriples)) } // Takes a bit of time to write time.Sleep(100 * time.Millisecond) var signedTriples []*protocol.Triple resp, err = http.Get(base + "/api/v1/triples") if err != nil { t.Error(err) } err = json.NewDecoder(resp.Body).Decode(&signedTriples) if err != nil { t.Error(err) } strippedTriples := stripCreated(stripSigning(signedTriples)) protocol.SortTriples(strippedTriples) if diff, equal := messagediff.PrettyDiff(testTriples, strippedTriples); !equal { t.Errorf("http.Get(/api/v1/insert) = %+v\n;not %+v\n%s", strippedTriples, testTriples, diff) } }
func TestOverriddenValues(t *testing.T) { expected := OptionsConfiguration{ ListenAddresses: []string{"tcp://:23000"}, GlobalAnnServers: []string{"udp4://syncthing.nym.se:22026"}, GlobalAnnEnabled: false, LocalAnnEnabled: false, LocalAnnPort: 42123, LocalAnnMCAddr: "quux:3232", MaxSendKbps: 1234, MaxRecvKbps: 2341, ReconnectIntervalS: 6000, RelaysEnabled: false, RelayReconnectIntervalM: 20, StartBrowser: false, NATEnabled: false, NATLeaseM: 90, NATRenewalM: 15, NATTimeoutS: 15, RestartOnWakeup: false, AutoUpgradeIntervalH: 24, KeepTemporariesH: 48, CacheIgnoredFiles: true, ProgressUpdateIntervalS: 10, SymlinksEnabled: false, LimitBandwidthInLan: true, MinHomeDiskFreePct: 5.2, URURL: "https://localhost/newdata", URInitialDelayS: 800, URPostInsecurely: true, ReleasesURL: "https://localhost/releases", AlwaysLocalNets: []string{}, OverwriteRemoteDevNames: true, TempIndexMinBlocks: 100, UnackedNotificationIDs: []string{}, } cfg, err := Load("testdata/overridenvalues.xml", device1) if err != nil { t.Error(err) } if diff, equal := messagediff.PrettyDiff(expected, cfg.Options()); !equal { t.Errorf("Overridden config differs. Diff:\n%s", diff) } }
func TestDefaultValues(t *testing.T) { expected := OptionsConfiguration{ ListenAddresses: []string{"default"}, GlobalAnnServers: []string{"default"}, GlobalAnnEnabled: true, LocalAnnEnabled: true, LocalAnnPort: 21027, LocalAnnMCAddr: "[ff12::8384]:21027", MaxSendKbps: 0, MaxRecvKbps: 0, ReconnectIntervalS: 60, RelaysEnabled: true, RelayReconnectIntervalM: 10, StartBrowser: true, NATEnabled: true, NATLeaseM: 60, NATRenewalM: 30, NATTimeoutS: 10, RestartOnWakeup: true, AutoUpgradeIntervalH: 12, KeepTemporariesH: 24, CacheIgnoredFiles: false, ProgressUpdateIntervalS: 5, SymlinksEnabled: true, LimitBandwidthInLan: false, MinHomeDiskFreePct: 1, URURL: "https://data.syncthing.net/newdata", URInitialDelayS: 1800, URPostInsecurely: false, ReleasesURL: "https://upgrades.syncthing.net/meta.json", AlwaysLocalNets: []string{}, OverwriteRemoteDevNames: false, TempIndexMinBlocks: 10, UnackedNotificationIDs: []string{}, } cfg := New(device1) if diff, equal := messagediff.PrettyDiff(expected, cfg.Options); !equal { t.Errorf("Default config differs. Diff:\n%s", diff) } }
// Ensures that PartitionedBloomFilter can be serialized and deserialized without errors. func TestPartitionedBloomGob(t *testing.T) { f := NewPartitionedBloomFilter(100, 0.1) for i := 0; i < 1000; i++ { f.Add([]byte(strconv.Itoa(i))) } var buf bytes.Buffer if err := gob.NewEncoder(&buf).Encode(f); err != nil { t.Error(err) } f2 := NewPartitionedBloomFilter(100, 0.1) if err := gob.NewDecoder(&buf).Decode(f2); err != nil { t.Error(err) } if diff, equal := messagediff.PrettyDiff(f, f2); !equal { t.Errorf("PartitionedBoomFilter Gob Encode and Decode = %+v; not %+v\n%s", f2, f, diff) } }
// Ensures that Buckets can be serialized and deserialized without errors. func TestBucketsGob(t *testing.T) { b := NewBuckets(5, 2) for i := 0; i < 5; i++ { b.Increment(uint(i), 1) } var buf bytes.Buffer if err := gob.NewEncoder(&buf).Encode(b); err != nil { t.Error(err) } b2 := NewBuckets(5, 2) if err := gob.NewDecoder(&buf).Decode(b2); err != nil { t.Error(err) } if diff, equal := messagediff.PrettyDiff(b, b2); !equal { t.Errorf("Buckets Gob Encode and Decode = %+v; not %+v\n%s", b2, b, diff) } }
func TestDefaultValues(t *testing.T) { expected := OptionsConfiguration{ ListenAddress: []string{"tcp://0.0.0.0:22000"}, GlobalAnnServers: []string{"default"}, GlobalAnnEnabled: true, LocalAnnEnabled: true, LocalAnnPort: 21027, LocalAnnMCAddr: "[ff12::8384]:21027", RelayServers: []string{"dynamic+https://relays.syncthing.net/endpoint"}, MaxSendKbps: 0, MaxRecvKbps: 0, ReconnectIntervalS: 60, RelaysEnabled: true, RelayReconnectIntervalM: 10, StartBrowser: true, UPnPEnabled: true, UPnPLeaseM: 60, UPnPRenewalM: 30, UPnPTimeoutS: 10, RestartOnWakeup: true, AutoUpgradeIntervalH: 12, KeepTemporariesH: 24, CacheIgnoredFiles: false, ProgressUpdateIntervalS: 5, SymlinksEnabled: true, LimitBandwidthInLan: false, MinHomeDiskFreePct: 1, URURL: "https://data.syncthing.net/newdata", URInitialDelayS: 1800, URPostInsecurely: false, ReleasesURL: "https://api.github.com/repos/syncthing/syncthing/releases?per_page=30", AlwaysLocalNets: []string{}, } cfg := New(device1) if diff, equal := messagediff.PrettyDiff(expected, cfg.Options); !equal { t.Errorf("Default config differs. Diff:\n%s", diff) } }
func TestVersioningConfig(t *testing.T) { cfg, err := Load("testdata/versioningconfig.xml", device4) if err != nil { t.Error(err) } vc := cfg.Folders()["test"].Versioning if vc.Type != "simple" { t.Errorf(`vc.Type %q != "simple"`, vc.Type) } if l := len(vc.Params); l != 2 { t.Errorf("len(vc.Params) %d != 2", l) } expected := map[string]string{ "foo": "bar", "baz": "quux", } if diff, equal := messagediff.PrettyDiff(expected, vc.Params); !equal { t.Errorf("vc.Params differ. Diff:\n%s", diff) } }
func TestNewSaveLoad(t *testing.T) { path := "testdata/temp.xml" os.Remove(path) exists := func(path string) bool { _, err := os.Stat(path) return err == nil } intCfg := New(device1) cfg := Wrap(path, intCfg) // To make the equality pass later cfg.cfg.XMLName.Local = "configuration" if exists(path) { t.Error(path, "exists") } err := cfg.Save() if err != nil { t.Error(err) } if !exists(path) { t.Error(path, "does not exist") } cfg2, err := Load(path, device1) if err != nil { t.Error(err) } if diff, equal := messagediff.PrettyDiff(cfg.RawCopy(), cfg2.RawCopy()); !equal { t.Errorf("Configs are not equal. Diff:\n%s", diff) } os.Remove(path) }
func TestLocalPeer(t *testing.T) { t.Parallel() testData := []struct { ip string port int serving bool want *protocol.Peer }{ { "127.0.0.1", 7946, false, &protocol.Peer{ Id: "127.0.0.1:7946", Serving: false, Keyspace: &protocol.Keyspace{Start: 0x5677ecc49097f350, End: 0xd677ecc49097f34e}, }, }, { "127.0.0.2", 7947, true, &protocol.Peer{ Id: "127.0.0.2:7947", Serving: true, Keyspace: &protocol.Keyspace{Start: 0xfa367fcf18de76bd, End: 0x7a367fcf18de76bb}, }, }, } for i, td := range testData { s := Server{ IP: td.ip, Port: td.port, Serving: td.serving, } out := s.LocalPeer() if diff, ok := messagediff.PrettyDiff(td.want, out); !ok { t.Errorf("%d. %#v.LocalPeer() = %#v; diff %s", i, s, out, diff) } } }
func TestDeviceCompression(t *testing.T) { name, _ := os.Hostname() expected := map[protocol.DeviceID]DeviceConfiguration{ device1: { DeviceID: device1, Addresses: []string{"dynamic"}, Compression: protocol.CompressMetadata, }, device2: { DeviceID: device2, Addresses: []string{"dynamic"}, Compression: protocol.CompressMetadata, }, device3: { DeviceID: device3, Addresses: []string{"dynamic"}, Compression: protocol.CompressNever, }, device4: { DeviceID: device4, Name: name, // Set when auto created Addresses: []string{"dynamic"}, Compression: protocol.CompressMetadata, }, } cfg, err := Load("testdata/devicecompression.xml", device4) if err != nil { t.Error(err) } actual := cfg.Devices() if diff, equal := messagediff.PrettyDiff(expected, actual); !equal { t.Errorf("Devices differ. Diff:\n%s", diff) } }
func TestShuffle(t *testing.T) { q := newJobQueue() q.Push("f1", 0, 0) q.Push("f2", 0, 0) q.Push("f3", 0, 0) q.Push("f4", 0, 0) // This test will fail once in eight million times (1 / (4!)^5) :) for i := 0; i < 5; i++ { q.Shuffle() _, queued := q.Jobs() if l := len(queued); l != 4 { t.Fatalf("Weird length %d returned from Jobs()", l) } t.Logf("%v", queued) if _, equal := messagediff.PrettyDiff([]string{"f1", "f2", "f3", "f4"}, queued); !equal { // The queue was shuffled return } } t.Error("Queue was not shuffled after five attempts.") }
func TestTripleStore(t *testing.T) { file, err := ioutil.TempFile(os.TempDir(), "triplestore.db") if err != nil { t.Fatal(err) } defer os.Remove(file.Name()) db, err := NewTripleStore(file.Name()) if err != nil { t.Fatal(err) } triples := []*protocol.Triple{ { Subj: "/m/02mjmr", Pred: "/type/object/name", Obj: "Barack Obama", }, { Subj: "/m/02mjmr", Pred: "/type/object/type", Obj: "/people/person", }, { Subj: "/m/0hume", Pred: "/type/object/name", Obj: "Hume", }, { Subj: "/m/0hume", Pred: "/type/object/type", Obj: "/organization/team", }, } db.Insert(triples) // Insert twice to ensure no duplicates. db.Insert(triples) testData := []struct { query *protocol.Triple want []*protocol.Triple }{ { &protocol.Triple{ Subj: "/m/02mjmr", }, []*protocol.Triple{ { Subj: "/m/02mjmr", Pred: "/type/object/name", Obj: "Barack Obama", }, { Subj: "/m/02mjmr", Pred: "/type/object/type", Obj: "/people/person", }, }, }, { &protocol.Triple{ Pred: "/type/object/type", }, []*protocol.Triple{ { Subj: "/m/02mjmr", Pred: "/type/object/type", Obj: "/people/person", }, { Subj: "/m/0hume", Pred: "/type/object/type", Obj: "/organization/team", }, }, }, { &protocol.Triple{ Pred: "/type/object/name", Obj: "Barack Obama", }, []*protocol.Triple{ { Subj: "/m/02mjmr", Pred: "/type/object/name", Obj: "Barack Obama", }, }, }, } for i, td := range testData { triples, err := db.Query(td.query, -1) if err != nil { t.Error(err) } if diff, ok := messagediff.PrettyDiff(td.want, triples); !ok { t.Errorf("%d. Query(%#v, -1) = %#v; diff %s", i, td.query, triples, diff) } } info, err := db.Size() if err != nil { t.Fatal(err) } if info.Triples != uint64(len(triples)) { t.Errorf("Size() = %#v; not %d", info, len(triples)) } }
func TestUnifySubs(t *testing.T) { cases := []struct { in []string // input to unifySubs exists []string // paths that exist in the database out []string // expected output }{ { // 0. trailing slashes are cleaned, known paths are just passed on []string{"foo/", "bar//"}, []string{"foo", "bar"}, []string{"bar", "foo"}, // the output is sorted }, { // 1. "foo/bar" gets trimmed as it's covered by foo []string{"foo", "bar/", "foo/bar/"}, []string{"foo", "bar"}, []string{"bar", "foo"}, }, { // 2. "" gets simplified to the empty list; ie scan all []string{"foo", ""}, []string{"foo"}, nil, }, { // 3. "foo/bar" is unknown, but it's kept // because its parent is known []string{"foo/bar"}, []string{"foo"}, []string{"foo/bar"}, }, { // 4. two independent known paths, both are kept // "usr/lib" is not a prefix of "usr/libexec" []string{"usr/lib", "usr/libexec"}, []string{"usr", "usr/lib", "usr/libexec"}, []string{"usr/lib", "usr/libexec"}, }, { // 5. "usr/lib" is a prefix of "usr/lib/exec" []string{"usr/lib", "usr/lib/exec"}, []string{"usr", "usr/lib", "usr/libexec"}, []string{"usr/lib"}, }, { // 6. .stignore and .stfolder are special and are passed on // verbatim even though they are unknown []string{".stfolder", ".stignore"}, []string{}, []string{".stfolder", ".stignore"}, }, { // 7. but the presense of something else unknown forces an actual // scan []string{".stfolder", ".stignore", "foo/bar"}, []string{}, []string{".stfolder", ".stignore", "foo"}, }, { // 8. explicit request to scan all nil, []string{"foo"}, nil, }, { // 9. empty list of subs []string{}, []string{"foo"}, nil, }, } if runtime.GOOS == "windows" { // Fixup path separators for i := range cases { for j, p := range cases[i].in { cases[i].in[j] = filepath.FromSlash(p) } for j, p := range cases[i].exists { cases[i].exists[j] = filepath.FromSlash(p) } for j, p := range cases[i].out { cases[i].out[j] = filepath.FromSlash(p) } } } for i, tc := range cases { exists := func(f string) bool { for _, e := range tc.exists { if f == e { return true } } return false } out := unifySubs(tc.in, exists) if diff, equal := messagediff.PrettyDiff(tc.out, out); !equal { t.Errorf("Case %d failed; got %v, expected %v, diff:\n%s", i, out, tc.out, diff) } } }
func TestDeviceConfig(t *testing.T) { for i := OldestHandledVersion; i <= CurrentVersion; i++ { os.Remove("testdata/.stfolder") wr, err := Load(fmt.Sprintf("testdata/v%d.xml", i), device1) if err != nil { t.Fatal(err) } _, err = os.Stat("testdata/.stfolder") if i < 6 && err != nil { t.Fatal(err) } else if i >= 6 && err == nil { t.Fatal("Unexpected file") } cfg := wr.cfg expectedFolders := []FolderConfiguration{ { ID: "test", RawPath: "testdata", Devices: []FolderDeviceConfiguration{{DeviceID: device1}, {DeviceID: device4}}, Type: FolderTypeReadOnly, RescanIntervalS: 600, Copiers: 0, Pullers: 0, Hashers: 0, AutoNormalize: true, MinDiskFreePct: 1, MaxConflicts: -1, Fsync: true, Versioning: VersioningConfiguration{ Params: map[string]string{}, }, }, } // The cachedPath will have been resolved to an absolute path, // depending on where the tests are running. Zero it out so we don't // fail based on that. for i := range cfg.Folders { cfg.Folders[i].cachedPath = "" } if runtime.GOOS != "windows" { expectedFolders[0].RawPath += string(filepath.Separator) } expectedDevices := []DeviceConfiguration{ { DeviceID: device1, Name: "node one", Addresses: []string{"tcp://a"}, Compression: protocol.CompressMetadata, }, { DeviceID: device4, Name: "node two", Addresses: []string{"tcp://b"}, Compression: protocol.CompressMetadata, }, } expectedDeviceIDs := []protocol.DeviceID{device1, device4} if cfg.Version != CurrentVersion { t.Errorf("%d: Incorrect version %d != %d", i, cfg.Version, CurrentVersion) } if diff, equal := messagediff.PrettyDiff(expectedFolders, cfg.Folders); !equal { t.Errorf("%d: Incorrect Folders. Diff:\n%s", i, diff) } if diff, equal := messagediff.PrettyDiff(expectedDevices, cfg.Devices); !equal { t.Errorf("%d: Incorrect Devices. Diff:\n%s", i, diff) } if diff, equal := messagediff.PrettyDiff(expectedDeviceIDs, cfg.Folders[0].DeviceIDs()); !equal { t.Errorf("%d: Incorrect DeviceIDs. Diff:\n%s", i, diff) } } }
func TestBloom(t *testing.T) { t.Parallel() file, err := ioutil.TempFile(os.TempDir(), "triplestore.db") if err != nil { t.Fatal(err) } defer os.Remove(file.Name()) db, err := NewTripleStore(file.Name(), log.New(os.Stdout, "", log.Flags())) if err != nil { t.Fatal(err) } tripleCount := 5000 additionalTriples := make([]*protocol.Triple, 0, tripleCount+len(testTriples)) for i := 0; i < tripleCount; i++ { additionalTriples = append(additionalTriples, &protocol.Triple{ Subj: "/m/0test", Pred: "/type/object/name", Obj: "Bloom " + strconv.Itoa(i), }) } additionalTriples = append(additionalTriples, testTriples...) protocol.SortTriples(additionalTriples) db.Insert(additionalTriples) filter, err := db.Bloom(nil) if err != nil { t.Fatal(err) } for _, triple := range additionalTriples { data, err := triple.Marshal() if err != nil { t.Error(err) continue } if !filter.Test(data) { t.Errorf("Bloom filter missing triple %+v", triple) } } filter2, err := db.Bloom(&protocol.Keyspace{}) if err != nil { t.Fatal(err) } for _, triple := range additionalTriples { data, err := triple.Marshal() if err != nil { t.Error(err) continue } if filter2.Test(data) { t.Errorf("Bloom filter incorrectly has %+v", triple) } } var resultTriples []*protocol.Triple results, errs := db.TriplesMatchingBloom(filter) for triples := range results { resultTriples = append(resultTriples, triples...) } for err := range errs { t.Error(err) } protocol.SortTriples(resultTriples) if diff, ok := messagediff.PrettyDiff(additionalTriples, resultTriples); !ok { t.Errorf("TriplesMatchingBloom(filter) = %#v; diff %s", resultTriples, diff) } resultTriples = nil results, errs = db.TriplesMatchingBloom(filter2) for triples := range results { resultTriples = append(resultTriples, triples...) } for err := range errs { t.Error(err) } for _, triple := range resultTriples { t.Errorf("TriplesMatchingBLoom(nil) incorrectly has %+v", triple) } }