Ensure loaded config is free of duplicate devices (fixes #2627)

This commit is contained in:
Jakob Borg 2015-12-31 09:17:17 +01:00
parent 62a81cfdd1
commit 18e70f4e79
3 changed files with 82 additions and 2 deletions

View File

@ -199,6 +199,9 @@ func (cfg *Configuration) prepare(myID protocol.DeviceID) {
existingDevices[myID] = true
}
// Ensure that the device list is free from duplicates
cfg.Devices = ensureNoDuplicateDevices(cfg.Devices)
sort.Sort(DeviceConfigurationList(cfg.Devices))
// Ensure that any loose devices are not present in the wrong places
// Ensure that there are no duplicate devices
@ -206,7 +209,7 @@ func (cfg *Configuration) prepare(myID protocol.DeviceID) {
for i := range cfg.Folders {
cfg.Folders[i].Devices = ensureDevicePresent(cfg.Folders[i].Devices, myID)
cfg.Folders[i].Devices = ensureExistingDevices(cfg.Folders[i].Devices, existingDevices)
cfg.Folders[i].Devices = ensureNoDuplicates(cfg.Folders[i].Devices)
cfg.Folders[i].Devices = ensureNoDuplicateFolderDevices(cfg.Folders[i].Devices)
sort.Sort(FolderDeviceConfigurationList(cfg.Folders[i].Devices))
}
@ -408,7 +411,25 @@ loop:
return devices[0:count]
}
func ensureNoDuplicates(devices []FolderDeviceConfiguration) []FolderDeviceConfiguration {
func ensureNoDuplicateFolderDevices(devices []FolderDeviceConfiguration) []FolderDeviceConfiguration {
count := len(devices)
i := 0
seenDevices := make(map[protocol.DeviceID]bool)
loop:
for i < count {
id := devices[i].DeviceID
if _, ok := seenDevices[id]; ok {
devices[i] = devices[count-1]
count--
continue loop
}
seenDevices[id] = true
i++
}
return devices[0:count]
}
func ensureNoDuplicateDevices(devices []DeviceConfiguration) []DeviceConfiguration {
count := len(devices)
i := 0
seenDevices := make(map[protocol.DeviceID]bool)

View File

@ -592,3 +592,29 @@ func TestGUIConfigURL(t *testing.T) {
}
}
}
func TestRemoveDuplicateDevicesFolders(t *testing.T) {
wrapper, err := Load("testdata/duplicates.xml", device1)
if err != nil {
t.Fatal(err)
}
// All folders are loaded, but the duplicate ones are disabled.
if l := len(wrapper.Raw().Folders); l != 3 {
t.Errorf("Incorrect number of folders, %d != 3", l)
}
for i, f := range wrapper.Raw().Folders {
if f.ID == "f1" && f.Invalid == "" {
t.Errorf("Folder %d (%q) is not set invalid", i, f.ID)
}
}
if l := len(wrapper.Raw().Devices); l != 3 {
t.Errorf("Incorrect number of devices, %d != 3", l)
}
f := wrapper.Folders()["f2"]
if l := len(f.Devices); l != 2 {
t.Errorf("Incorrect number of folder devices, %d != 2", l)
}
}

33
lib/config/testdata/duplicates.xml vendored Normal file
View File

@ -0,0 +1,33 @@
<configuration version="12">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR">
<address>192.0.2.1</address>
<address>192.0.2.2</address>
</device>
<device id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA">
<address>192.0.2.3:6070</address>
<address>[2001:db8::42]:4242</address>
</device>
<device id="LGFPDIT7SKNNJVJZA4FC7QNCRKCE753K72BW5QD2FOZ7FRFEP57Q">
<address>[2001:db8::44]:4444</address>
<address>192.0.2.4:6090</address>
</device>
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR">
<!-- duplicate, will be removed -->
<address>192.0.2.5</address>
</device>
<folder id="f1" directory="testdata/">
<!-- duplicate, will be disabled -->
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA"></device>
</folder>
<folder id="f1" directory="testdata/">
<!-- duplicate, will be disabled -->
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
</folder>
<folder id="f2" directory="testdata/">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA"></device>
<!-- duplicate device, will be removed -->
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
</folder>
</configuration>