package main import ( "fmt" "testing" ) func TestUpgrade1to2(t *testing.T) { // let's create test config for 1 schema version diskConfig := createTestDiskConfig(1) // update config err := upgradeSchema1to2(&diskConfig) if err != nil { t.Fatalf("Can't upgrade schema version from 1 to 2") } // ensure that schema version was bumped compareSchemaVersion(t, diskConfig["schema_version"], 2) // old coredns entry should be removed _, ok := diskConfig["coredns"] if ok { t.Fatalf("Core DNS config was not removed after upgrade schema version from 1 to 2") } // pull out new dns config dnsMap, ok := diskConfig["dns"] if !ok { t.Fatalf("No DNS config after upgrade schema version from 1 to 2") } // cast dns configurations to maps and compare them oldDNSConfig := castInterfaceToMap(t, createTestDNSConfig(1)) newDNSConfig := castInterfaceToMap(t, dnsMap) compareConfigs(t, &oldDNSConfig, &newDNSConfig) // exclude dns config and schema version from disk config comparison oldExcludedEntries := []string{"coredns", "schema_version"} newExcludedEntries := []string{"dns", "schema_version"} oldDiskConfig := createTestDiskConfig(1) compareConfigsWithoutEntries(t, &oldDiskConfig, &diskConfig, oldExcludedEntries, newExcludedEntries) } func TestUpgrade2to3(t *testing.T) { // let's create test config diskConfig := createTestDiskConfig(2) // upgrade schema from 2 to 3 err := upgradeSchema2to3(&diskConfig) if err != nil { t.Fatalf("Can't update schema version from 2 to 3: %s", err) } // check new schema version compareSchemaVersion(t, diskConfig["schema_version"], 3) // pull out new dns configuration dnsMap, ok := diskConfig["dns"] if !ok { t.Fatalf("No dns config in new configuration") } // cast dns configuration to map newDNSConfig := castInterfaceToMap(t, dnsMap) // check if bootstrap DNS becomes an array bootstrapDNS := newDNSConfig["bootstrap_dns"] switch v := bootstrapDNS.(type) { case []string: if len(v) != 1 { t.Fatalf("Wrong count of bootsrap DNS servers: %d", len(v)) } if v[0] != "8.8.8.8:53" { t.Fatalf("Bootsrap DNS server is not 8.8.8.8:53 : %s", v[0]) } default: t.Fatalf("Wrong type for bootsrap DNS: %T", v) } // exclude bootstrap DNS from DNS configs comparison excludedEntries := []string{"bootstrap_dns"} oldDNSConfig := castInterfaceToMap(t, createTestDNSConfig(2)) compareConfigsWithoutEntries(t, &oldDNSConfig, &newDNSConfig, excludedEntries, excludedEntries) // excluded dns config and schema version from disk config comparison excludedEntries = []string{"dns", "schema_version"} oldDiskConfig := createTestDiskConfig(2) compareConfigsWithoutEntries(t, &oldDiskConfig, &diskConfig, excludedEntries, excludedEntries) } func castInterfaceToMap(t *testing.T, oldConfig interface{}) (newConfig map[string]interface{}) { newConfig = make(map[string]interface{}) switch v := oldConfig.(type) { case map[interface{}]interface{}: for key, value := range v { newConfig[fmt.Sprint(key)] = value } case map[string]interface{}: for key, value := range v { newConfig[key] = value } default: t.Fatalf("DNS configuration is not a map") } return } // compareConfigsWithoutEntry removes entries from configs and returns result of compareConfigs func compareConfigsWithoutEntries(t *testing.T, oldConfig, newConfig *map[string]interface{}, oldKey, newKey []string) { for _, k := range oldKey { delete(*oldConfig, k) } for _, k := range newKey { delete(*newConfig, k) } compareConfigs(t, oldConfig, newConfig) } // compares configs before and after schema upgrade func compareConfigs(t *testing.T, oldConfig, newConfig *map[string]interface{}) { if len(*oldConfig) != len(*newConfig) { t.Fatalf("wrong config entries count! Before upgrade: %d; After upgrade: %d", len(*oldConfig), len(*oldConfig)) } // Check old and new entries for k, v := range *newConfig { switch value := v.(type) { case string: if value != (*oldConfig)[k] { t.Fatalf("wrong value for string %s. Before update: %s; After update: %s", k, (*oldConfig)[k], value) } case int: if value != (*oldConfig)[k] { t.Fatalf("wrong value for int %s. Before update: %d; After update: %d", k, (*oldConfig)[k], value) } case []string: for i, line := range value { if len((*oldConfig)[k].([]string)) != len(value) { t.Fatalf("wrong array length for %s. Before update: %d; After update: %d", k, len((*oldConfig)[k].([]string)), len(value)) } if (*oldConfig)[k].([]string)[i] != line { t.Fatalf("wrong data for string array %s. Before update: %s; After update: %s", k, (*oldConfig)[k].([]string)[i], line) } } case bool: if v != (*oldConfig)[k].(bool) { t.Fatalf("wrong boolean value for %s", k) } case []filter: if len((*oldConfig)[k].([]filter)) != len(value) { t.Fatalf("wrong filters count. Before update: %d; After update: %d", len((*oldConfig)[k].([]filter)), len(value)) } for i, newFilter := range value { oldFilter := (*oldConfig)[k].([]filter)[i] if oldFilter.Enabled != newFilter.Enabled || oldFilter.Name != newFilter.Name || oldFilter.RulesCount != newFilter.RulesCount { t.Fatalf("old filter %s not equals new filter %s", oldFilter.Name, newFilter.Name) } } default: t.Fatalf("uknown data type for %s: %T", k, value) } } } // compareSchemaVersion check if newSchemaVersion equals schemaVersion func compareSchemaVersion(t *testing.T, newSchemaVersion interface{}, schemaVersion int) { switch v := newSchemaVersion.(type) { case int: if v != schemaVersion { t.Fatalf("Wrong schema version in new config file") } default: t.Fatalf("Schema version is not an integer after update") } } func createTestDiskConfig(schemaVersion int) (diskConfig map[string]interface{}) { diskConfig = make(map[string]interface{}) diskConfig["language"] = "en" diskConfig["filters"] = []filter{ { URL: "https://filters.adtidy.org/android/filters/111_optimized.txt", Name: "Latvian filter", RulesCount: 100, }, { URL: "https://easylist.to/easylistgermany/easylistgermany.txt", Name: "Germany filter", RulesCount: 200, }, } diskConfig["user_rules"] = []string{} diskConfig["schema_version"] = schemaVersion diskConfig["bind_host"] = "0.0.0.0" diskConfig["bind_port"] = 80 diskConfig["auth_name"] = "name" diskConfig["auth_pass"] = "pass" dnsConfig := createTestDNSConfig(schemaVersion) if schemaVersion > 1 { diskConfig["dns"] = dnsConfig } else { diskConfig["coredns"] = dnsConfig } return diskConfig } func createTestDNSConfig(schemaVersion int) map[interface{}]interface{} { dnsConfig := make(map[interface{}]interface{}) dnsConfig["port"] = 53 dnsConfig["blocked_response_ttl"] = 10 dnsConfig["querylog_enabled"] = true dnsConfig["ratelimit"] = 20 dnsConfig["bootstrap_dns"] = "8.8.8.8:53" if schemaVersion > 2 { dnsConfig["bootstrap_dns"] = []string{"8.8.8.8:53"} } dnsConfig["parental_sensitivity"] = 13 dnsConfig["ratelimit_whitelist"] = []string{} dnsConfig["upstream_dns"] = []string{"tls://1.1.1.1", "tls://1.0.0.1", "8.8.8.8"} dnsConfig["filtering_enabled"] = true dnsConfig["refuse_any"] = true dnsConfig["parental_enabled"] = true dnsConfig["bind_host"] = "0.0.0.0" dnsConfig["protection_enabled"] = true dnsConfig["safesearch_enabled"] = true dnsConfig["safebrowsing_enabled"] = true return dnsConfig }