diff --git a/core/dns/storage.go b/core/dns/storage.go new file mode 100644 index 000000000..0c8e68437 --- /dev/null +++ b/core/dns/storage.go @@ -0,0 +1,28 @@ +package dns + +import ( + "path/filepath" + + "github.com/miekg/coredns/core/assets" +) + +var storage = Storage(assets.Path()) + +// Storage is a root directory and facilitates +// forming file paths derived from it. +type Storage string + +// Zones gets the directory that stores zones data. +func (s Storage) Zones() string { + return filepath.Join(string(s), "zones") +} + +// Zone returns the path to the folder containing assets for domain. +func (s Storage) Zone(domain string) string { + return filepath.Join(s.Zones(), domain) +} + +// SecondaryZoneFile returns the path to domain's secondary zone file (when fetched). +func (s Storage) SecondaryZoneFile(domain string) string { + return filepath.Join(s.Zone(domain), "db."+domain) +} diff --git a/core/dns/storage_test.go b/core/dns/storage_test.go new file mode 100644 index 000000000..859435a15 --- /dev/null +++ b/core/dns/storage_test.go @@ -0,0 +1,20 @@ +package dns + +import ( + "path/filepath" + "testing" +) + +func TestStorage(t *testing.T) { + storage = Storage("./le_test") + + if expected, actual := filepath.Join("le_test", "zones"), storage.Zones(); actual != expected { + t.Errorf("Expected Zones() to return '%s' but got '%s'", expected, actual) + } + if expected, actual := filepath.Join("le_test", "zones", "test.com"), storage.Zone("test.com"); actual != expected { + t.Errorf("Expected Site() to return '%s' but got '%s'", expected, actual) + } + if expected, actual := filepath.Join("le_test", "zones", "test.com", "db.test.com"), storage.SecondaryZoneFile("test.com"); actual != expected { + t.Errorf("Expected SecondaryZoneFile() to return '%s' but got '%s'", expected, actual) + } +} diff --git a/middleware/etcd/msg/service_test.go b/middleware/etcd/msg/service_test.go new file mode 100644 index 000000000..0c19ba95b --- /dev/null +++ b/middleware/etcd/msg/service_test.go @@ -0,0 +1,125 @@ +package msg + +import "testing" + +func TestSplit255(t *testing.T) { + xs := split255("abc") + if len(xs) != 1 && xs[0] != "abc" { + t.Errorf("Failure to split abc") + } + s := "" + for i := 0; i < 255; i++ { + s += "a" + } + xs = split255(s) + if len(xs) != 1 && xs[0] != s { + t.Errorf("failure to split 255 char long string") + } + s += "b" + xs = split255(s) + if len(xs) != 2 || xs[1] != "b" { + t.Errorf("failure to split 256 char long string: %d", len(xs)) + } + for i := 0; i < 255; i++ { + s += "a" + } + xs = split255(s) + if len(xs) != 3 || xs[2] != "a" { + t.Errorf("failure to split 510 char long string: %d", len(xs)) + } +} + +func TestGroup(t *testing.T) { + // Key are in the wrong order, but for this test it does not matter. + sx := Group( + []Service{ + {Host: "127.0.0.1", Group: "g1", Key: "b/sub/dom1/skydns/test"}, + {Host: "127.0.0.2", Group: "g2", Key: "a/dom1/skydns/test"}, + }, + ) + // Expecting to return the shortest key with a Group attribute. + if len(sx) != 1 { + t.Fatalf("failure to group zeroth set: %v", sx) + } + if sx[0].Key != "a/dom1/skydns/test" { + t.Fatalf("failure to group zeroth set: %v, wrong Key", sx) + } + + // Groups disagree, so we will not do anything. + sx = Group( + []Service{ + {Host: "server1", Group: "g1", Key: "region1/skydns/test"}, + {Host: "server2", Group: "g2", Key: "region1/skydns/test"}, + }, + ) + if len(sx) != 2 { + t.Fatalf("failure to group first set: %v", sx) + } + + // Group is g1, include only the top-level one. + sx = Group( + []Service{ + {Host: "server1", Group: "g1", Key: "a/dom/region1/skydns/test"}, + {Host: "server2", Group: "g2", Key: "a/subdom/dom/region1/skydns/test"}, + }, + ) + if len(sx) != 1 { + t.Fatalf("failure to group second set: %v", sx) + } + + // Groupless services must be included. + sx = Group( + []Service{ + {Host: "server1", Group: "g1", Key: "a/dom/region1/skydns/test"}, + {Host: "server2", Group: "g2", Key: "a/subdom/dom/region1/skydns/test"}, + {Host: "server2", Group: "", Key: "b/subdom/dom/region1/skydns/test"}, + }, + ) + if len(sx) != 2 { + t.Fatalf("failure to group third set: %v", sx) + } + + // Empty group on the highest level: include that one also. + sx = Group( + []Service{ + {Host: "server1", Group: "g1", Key: "a/dom/region1/skydns/test"}, + {Host: "server1", Group: "", Key: "b/dom/region1/skydns/test"}, + {Host: "server2", Group: "g2", Key: "a/subdom/dom/region1/skydns/test"}, + }, + ) + if len(sx) != 2 { + t.Fatalf("failure to group fourth set: %v", sx) + } + + // Empty group on the highest level: include that one also, and the rest. + sx = Group( + []Service{ + {Host: "server1", Group: "g5", Key: "a/dom/region1/skydns/test"}, + {Host: "server1", Group: "", Key: "b/dom/region1/skydns/test"}, + {Host: "server2", Group: "g5", Key: "a/subdom/dom/region1/skydns/test"}, + }, + ) + if len(sx) != 3 { + t.Fatalf("failure to group fith set: %v", sx) + } + + // One group. + sx = Group( + []Service{ + {Host: "server1", Group: "g6", Key: "a/dom/region1/skydns/test"}, + }, + ) + if len(sx) != 1 { + t.Fatalf("failure to group sixth set: %v", sx) + } + + // No group, once service + sx = Group( + []Service{ + {Host: "server1", Key: "a/dom/region1/skydns/test"}, + }, + ) + if len(sx) != 1 { + t.Fatalf("failure to group seventh set: %v", sx) + } +} diff --git a/middleware/singleflight/singleflight_test.go b/middleware/singleflight/singleflight_test.go new file mode 100644 index 000000000..47b4d3dc0 --- /dev/null +++ b/middleware/singleflight/singleflight_test.go @@ -0,0 +1,85 @@ +/* +Copyright 2012 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package singleflight + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "testing" + "time" +) + +func TestDo(t *testing.T) { + var g Group + v, err := g.Do("key", func() (interface{}, error) { + return "bar", nil + }) + if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want { + t.Errorf("Do = %v; want %v", got, want) + } + if err != nil { + t.Errorf("Do error = %v", err) + } +} + +func TestDoErr(t *testing.T) { + var g Group + someErr := errors.New("Some error") + v, err := g.Do("key", func() (interface{}, error) { + return nil, someErr + }) + if err != someErr { + t.Errorf("Do error = %v; want someErr", err) + } + if v != nil { + t.Errorf("unexpected non-nil value %#v", v) + } +} + +func TestDoDupSuppress(t *testing.T) { + var g Group + c := make(chan string) + var calls int32 + fn := func() (interface{}, error) { + atomic.AddInt32(&calls, 1) + return <-c, nil + } + + const n = 10 + var wg sync.WaitGroup + for i := 0; i < n; i++ { + wg.Add(1) + go func() { + v, err := g.Do("key", fn) + if err != nil { + t.Errorf("Do error: %v", err) + } + if v.(string) != "bar" { + t.Errorf("got %q; want %q", v, "bar") + } + wg.Done() + }() + } + time.Sleep(100 * time.Millisecond) // let goroutines above block + c <- "bar" + wg.Wait() + if got := atomic.LoadInt32(&calls); got != 1 { + t.Errorf("number of calls = %d; want 1", got) + } +} diff --git a/middleware/test/file_test.go b/middleware/test/file_test.go new file mode 100644 index 000000000..950ea7cff --- /dev/null +++ b/middleware/test/file_test.go @@ -0,0 +1,11 @@ +package test + +import "testing" + +func TestTempFile(t *testing.T) { + _, f, e := TempFile(t, ".", "test") + if e != nil { + t.Fatalf("failed to create temp file: %s", e) + } + defer f() +} diff --git a/middleware/test/helpers_test.go b/middleware/test/helpers_test.go new file mode 100644 index 000000000..1b4d95bbc --- /dev/null +++ b/middleware/test/helpers_test.go @@ -0,0 +1,8 @@ +package test + +import "testing" + +func TestA(t *testing.T) { + // should not crash + A("miek.nl. IN A 127.0.0.1") +}