// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file). // All rights reserved. Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. package config import ( "os" "reflect" "testing" "github.com/syncthing/syncthing/protocol" ) var node1, node2, node3, node4 protocol.NodeID func init() { node1, _ = protocol.NodeIDFromString("AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ") node2, _ = protocol.NodeIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY") node3, _ = protocol.NodeIDFromString("LGFPDIT-7SKNNJL-VJZA4FC-7QNCRKA-CE753K7-2BW5QDK-2FOZ7FR-FEP57QJ") node4, _ = protocol.NodeIDFromString("P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2") } func TestDefaultValues(t *testing.T) { expected := OptionsConfiguration{ ListenAddress: []string{"0.0.0.0:22000"}, GlobalAnnServer: "announce.syncthing.net:22026", GlobalAnnEnabled: true, LocalAnnEnabled: true, LocalAnnPort: 21025, LocalAnnMCAddr: "[ff32::5222]:21026", ParallelRequests: 16, MaxSendKbps: 0, MaxRecvKbps: 0, ReconnectIntervalS: 60, StartBrowser: true, UPnPEnabled: true, UPnPLease: 0, UPnPRenewal: 30, RestartOnWakeup: true, } cfg := New("test", node1) if !reflect.DeepEqual(cfg.Options, expected) { t.Errorf("Default config differs;\n E: %#v\n A: %#v", expected, cfg.Options) } } func TestNodeConfig(t *testing.T) { for i, ver := range []string{"v1", "v2", "v3", "v4"} { cfg, err := Load("testdata/"+ver+".xml", node1) if err != nil { t.Error(err) } expectedRepos := []RepositoryConfiguration{ { ID: "test", Directory: "~/Sync", Nodes: []RepositoryNodeConfiguration{{NodeID: node1}, {NodeID: node4}}, ReadOnly: true, RescanIntervalS: 600, }, } expectedNodes := []NodeConfiguration{ { NodeID: node1, Name: "node one", Addresses: []string{"a"}, Compression: true, }, { NodeID: node4, Name: "node two", Addresses: []string{"b"}, Compression: true, }, } expectedNodeIDs := []protocol.NodeID{node1, node4} if cfg.Version != 4 { t.Errorf("%d: Incorrect version %d != 3", i, cfg.Version) } if !reflect.DeepEqual(cfg.Repositories, expectedRepos) { t.Errorf("%d: Incorrect Repositories\n A: %#v\n E: %#v", i, cfg.Repositories, expectedRepos) } if !reflect.DeepEqual(cfg.Nodes, expectedNodes) { t.Errorf("%d: Incorrect Nodes\n A: %#v\n E: %#v", i, cfg.Nodes, expectedNodes) } if !reflect.DeepEqual(cfg.Repositories[0].NodeIDs(), expectedNodeIDs) { t.Errorf("%d: Incorrect NodeIDs\n A: %#v\n E: %#v", i, cfg.Repositories[0].NodeIDs(), expectedNodeIDs) } if len(cfg.NodeMap()) != len(expectedNodes) { t.Errorf("Unexpected number of NodeMap() entries") } if len(cfg.RepoMap()) != len(expectedRepos) { t.Errorf("Unexpected number of RepoMap() entries") } } } func TestNoListenAddress(t *testing.T) { cfg, err := Load("testdata/nolistenaddress.xml", node1) if err != nil { t.Error(err) } expected := []string{""} if !reflect.DeepEqual(cfg.Options.ListenAddress, expected) { t.Errorf("Unexpected ListenAddress %#v", cfg.Options.ListenAddress) } } func TestOverriddenValues(t *testing.T) { expected := OptionsConfiguration{ ListenAddress: []string{":23000"}, GlobalAnnServer: "syncthing.nym.se:22026", GlobalAnnEnabled: false, LocalAnnEnabled: false, LocalAnnPort: 42123, LocalAnnMCAddr: "quux:3232", ParallelRequests: 32, MaxSendKbps: 1234, MaxRecvKbps: 2341, ReconnectIntervalS: 6000, StartBrowser: false, UPnPEnabled: false, UPnPLease: 60, UPnPRenewal: 15, RestartOnWakeup: false, } cfg, err := Load("testdata/overridenvalues.xml", node1) if err != nil { t.Error(err) } if !reflect.DeepEqual(cfg.Options, expected) { t.Errorf("Overridden config differs;\n E: %#v\n A: %#v", expected, cfg.Options) } } func TestNodeAddressesDynamic(t *testing.T) { name, _ := os.Hostname() expected := []NodeConfiguration{ { NodeID: node1, Addresses: []string{"dynamic"}, Compression: true, }, { NodeID: node2, Addresses: []string{"dynamic"}, Compression: true, }, { NodeID: node3, Addresses: []string{"dynamic"}, Compression: true, }, { NodeID: node4, Name: name, // Set when auto created Addresses: []string{"dynamic"}, }, } cfg, err := Load("testdata/nodeaddressesdynamic.xml", node4) if err != nil { t.Error(err) } if !reflect.DeepEqual(cfg.Nodes, expected) { t.Errorf("Nodes differ;\n E: %#v\n A: %#v", expected, cfg.Nodes) } } func TestNodeAddressesStatic(t *testing.T) { name, _ := os.Hostname() expected := []NodeConfiguration{ { NodeID: node1, Addresses: []string{"192.0.2.1", "192.0.2.2"}, }, { NodeID: node2, Addresses: []string{"192.0.2.3:6070", "[2001:db8::42]:4242"}, }, { NodeID: node3, Addresses: []string{"[2001:db8::44]:4444", "192.0.2.4:6090"}, }, { NodeID: node4, Name: name, // Set when auto created Addresses: []string{"dynamic"}, }, } cfg, err := Load("testdata/nodeaddressesstatic.xml", node4) if err != nil { t.Error(err) } if !reflect.DeepEqual(cfg.Nodes, expected) { t.Errorf("Nodes differ;\n E: %#v\n A: %#v", expected, cfg.Nodes) } } func TestVersioningConfig(t *testing.T) { cfg, err := Load("testdata/versioningconfig.xml", node4) if err != nil { t.Error(err) } vc := cfg.Repositories[0].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 !reflect.DeepEqual(vc.Params, expected) { t.Errorf("vc.Params differ;\n E: %#v\n A: %#v", expected, vc.Params) } } func TestNewSaveLoad(t *testing.T) { path := "testdata/temp.xml" os.Remove(path) exists := func(path string) bool { _, err := os.Stat(path) return err == nil } cfg := New(path, node1) // To make the equality pass later 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, node1) if err != nil { t.Error(err) } if !reflect.DeepEqual(cfg, cfg2) { t.Errorf("Configs are not equal;\n E: %#v\n A: %#v", cfg, cfg2) } cfg.GUI.User = "test" cfg.Save() cfg2, err = Load(path, node1) if err != nil { t.Error(err) } if cfg2.GUI.User != "test" || !reflect.DeepEqual(cfg, cfg2) { t.Errorf("Configs are not equal;\n E: %#v\n A: %#v", cfg, cfg2) } os.Remove(path) } func TestPrepare(t *testing.T) { var cfg Configuration if cfg.Repositories != nil || cfg.Nodes != nil || cfg.Options.ListenAddress != nil { t.Error("Expected nil") } cfg.prepare(node1) if cfg.Repositories == nil || cfg.Nodes == nil || cfg.Options.ListenAddress == nil { t.Error("Unexpected nil") } }