7a5f3f8053
libnetwork/etchosts/etchosts_test.go:167:54: empty-lines: extra empty line at the end of a block (revive)
libnetwork/osl/route_linux.go:185:74: empty-lines: extra empty line at the start of a block (revive)
libnetwork/osl/sandbox_linux_test.go:323:36: empty-lines: extra empty line at the start of a block (revive)
libnetwork/bitseq/sequence.go:412:48: empty-lines: extra empty line at the start of a block (revive)
libnetwork/datastore/datastore_test.go:67:46: empty-lines: extra empty line at the end of a block (revive)
libnetwork/datastore/mock_store.go:34:60: empty-lines: extra empty line at the end of a block (revive)
libnetwork/iptables/firewalld.go:202:44: empty-lines: extra empty line at the end of a block (revive)
libnetwork/iptables/firewalld_test.go:76:36: empty-lines: extra empty line at the end of a block (revive)
libnetwork/iptables/iptables.go:256:67: empty-lines: extra empty line at the end of a block (revive)
libnetwork/iptables/iptables.go:303:128: empty-lines: extra empty line at the start of a block (revive)
libnetwork/networkdb/cluster.go:183:72: empty-lines: extra empty line at the end of a block (revive)
libnetwork/ipams/null/null_test.go:44:38: empty-lines: extra empty line at the end of a block (revive)
libnetwork/drivers/macvlan/macvlan_store.go:45:52: empty-lines: extra empty line at the end of a block (revive)
libnetwork/ipam/allocator_test.go:1058:39: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/bridge/port_mapping.go:88:111: empty-lines: extra empty line at the end of a block (revive)
libnetwork/drivers/bridge/link.go:26:90: empty-lines: extra empty line at the end of a block (revive)
libnetwork/drivers/bridge/setup_ipv6_test.go:17:34: empty-lines: extra empty line at the end of a block (revive)
libnetwork/drivers/bridge/setup_ip_tables.go:392:4: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/bridge/bridge.go:804:50: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/overlay/ov_serf.go:183:29: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/overlay/ov_utils.go:81:64: empty-lines: extra empty line at the end of a block (revive)
libnetwork/drivers/overlay/peerdb.go:172:67: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/overlay/peerdb.go:209:67: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/overlay/peerdb.go:344:89: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/overlay/peerdb.go:436:63: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/overlay/overlay.go:183:36: empty-lines: extra empty line at the start of a block (revive)
libnetwork/drivers/overlay/encryption.go:69:28: empty-lines: extra empty line at the end of a block (revive)
libnetwork/drivers/overlay/ov_network.go:563:81: empty-lines: extra empty line at the start of a block (revive)
libnetwork/default_gateway.go:32:43: empty-lines: extra empty line at the start of a block (revive)
libnetwork/errors_test.go:9:40: empty-lines: extra empty line at the start of a block (revive)
libnetwork/service_common.go:184:64: empty-lines: extra empty line at the end of a block (revive)
libnetwork/endpoint.go:161:55: empty-lines: extra empty line at the end of a block (revive)
libnetwork/store.go:320:33: empty-lines: extra empty line at the end of a block (revive)
libnetwork/store_linux_test.go:11:38: empty-lines: extra empty line at the end of a block (revive)
libnetwork/sandbox.go:571:36: empty-lines: extra empty line at the start of a block (revive)
libnetwork/service_common.go:317:246: empty-lines: extra empty line at the start of a block (revive)
libnetwork/endpoint.go:550:17: empty-lines: extra empty line at the end of a block (revive)
libnetwork/sandbox_dns_unix.go:213:106: empty-lines: extra empty line at the start of a block (revive)
libnetwork/controller.go:676:85: empty-lines: extra empty line at the end of a block (revive)
libnetwork/agent.go:876:60: empty-lines: extra empty line at the end of a block (revive)
libnetwork/resolver.go:324:69: empty-lines: extra empty line at the end of a block (revive)
libnetwork/network.go:1153:92: empty-lines: extra empty line at the end of a block (revive)
libnetwork/network.go:1955:67: empty-lines: extra empty line at the start of a block (revive)
libnetwork/network.go:2235:9: empty-lines: extra empty line at the start of a block (revive)
libnetwork/libnetwork_internal_test.go:336:26: empty-lines: extra empty line at the start of a block (revive)
libnetwork/resolver_test.go:76:35: empty-lines: extra empty line at the end of a block (revive)
libnetwork/libnetwork_test.go:303:38: empty-lines: extra empty line at the end of a block (revive)
libnetwork/libnetwork_test.go:985:46: empty-lines: extra empty line at the end of a block (revive)
libnetwork/ipam/allocator_test.go:1263:37: empty-lines: extra empty line at the start of a block (revive)
libnetwork/errors_test.go:9:40: empty-lines: extra empty line at the end of a block (revive)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit cd381aea56
)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
514 lines
11 KiB
Go
514 lines
11 KiB
Go
package etchosts
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
func TestBuildDefault(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
// check that /etc/hosts has consistent ordering
|
|
for i := 0; i <= 5; i++ {
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\nfe00::0\tip6-localnet\nff00::0\tip6-mcastprefix\nff02::1\tip6-allnodes\nff02::2\tip6-allrouters\n"
|
|
|
|
if expected != string(content) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBuildHostnameDomainname(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "10.11.12.13\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func TestBuildHostname(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "10.11.12.13", "testhostname", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "10.11.12.13\ttesthostname\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func TestBuildHostnameFQDN(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "10.11.12.13", "testhostname.testdomainname.com", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "10.11.12.13\ttesthostname.testdomainname.com testhostname\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func TestBuildNoIP(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "", "testhostname", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := ""; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func TestUpdate(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
if err := Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "10.11.12.13\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
|
|
if err := Update(file.Name(), "1.1.1.1", "testhostname"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err = os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "1.1.1.1\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
// This regression test ensures that when a host is given a new IP
|
|
// via the Update function that other hosts which start with the
|
|
// same name as the targeted host are not erroneously updated as well.
|
|
// In the test example, if updating a host called "prefix", unrelated
|
|
// hosts named "prefixAndMore" or "prefix2" or anything else starting
|
|
// with "prefix" should not be changed. For more information see
|
|
// GitHub issue #603.
|
|
func TestUpdateIgnoresPrefixedHostname(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
if err := Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", []Record{
|
|
{
|
|
Hosts: "prefix",
|
|
IP: "2.2.2.2",
|
|
},
|
|
{
|
|
Hosts: "prefixAndMore",
|
|
IP: "3.3.3.3",
|
|
},
|
|
{
|
|
Hosts: "unaffectedHost",
|
|
IP: "4.4.4.4",
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "2.2.2.2\tprefix\n3.3.3.3\tprefixAndMore\n4.4.4.4\tunaffectedHost\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
|
|
if err := Update(file.Name(), "5.5.5.5", "prefix"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err = os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "5.5.5.5\tprefix\n3.3.3.3\tprefixAndMore\n4.4.4.4\tunaffectedHost\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
// This regression test covers the host prefix issue for the
|
|
// Delete function. In the test example, if deleting a host called
|
|
// "prefix", an unrelated host called "prefixAndMore" should not
|
|
// be deleted. For more information see GitHub issue #603.
|
|
func TestDeleteIgnoresPrefixedHostname(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Add(file.Name(), []Record{
|
|
{
|
|
Hosts: "prefix",
|
|
IP: "1.1.1.1",
|
|
},
|
|
{
|
|
Hosts: "prefixAndMore",
|
|
IP: "2.2.2.2",
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Delete(file.Name(), []Record{
|
|
{
|
|
Hosts: "prefix",
|
|
IP: "1.1.1.1",
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "2.2.2.2\tprefixAndMore\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
|
|
if expected := "1.1.1.1\tprefix\n"; bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Did not expect to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func TestAddEmpty(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Add(file.Name(), []Record{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestAdd(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Add(file.Name(), []Record{
|
|
{
|
|
Hosts: "testhostname",
|
|
IP: "2.2.2.2",
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "2.2.2.2\ttesthostname\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func TestDeleteEmpty(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Delete(file.Name(), []Record{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestDeleteNewline(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
b := []byte("\n")
|
|
if _, err := file.Write(b); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rec := []Record{
|
|
{
|
|
Hosts: "prefix",
|
|
IP: "2.2.2.2",
|
|
},
|
|
}
|
|
if err := Delete(file.Name(), rec); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestDelete(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Add(file.Name(), []Record{
|
|
{
|
|
Hosts: "testhostname1",
|
|
IP: "1.1.1.1",
|
|
},
|
|
{
|
|
Hosts: "testhostname2",
|
|
IP: "2.2.2.2",
|
|
},
|
|
{
|
|
Hosts: "testhostname3",
|
|
IP: "3.3.3.3",
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Delete(file.Name(), []Record{
|
|
{
|
|
Hosts: "testhostname1",
|
|
IP: "1.1.1.1",
|
|
},
|
|
{
|
|
Hosts: "testhostname3",
|
|
IP: "3.3.3.3",
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "2.2.2.2\ttesthostname2\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
|
|
if expected := "1.1.1.1\ttesthostname1\n"; bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Did not expect to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func TestConcurrentWrites(t *testing.T) {
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file.Name())
|
|
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := Add(file.Name(), []Record{
|
|
{
|
|
Hosts: "inithostname",
|
|
IP: "172.17.0.1",
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
group := new(errgroup.Group)
|
|
for i := 0; i < 10; i++ {
|
|
i := i
|
|
group.Go(func() error {
|
|
rec := []Record{
|
|
{
|
|
IP: fmt.Sprintf("%d.%d.%d.%d", i, i, i, i),
|
|
Hosts: fmt.Sprintf("testhostname%d", i),
|
|
},
|
|
}
|
|
|
|
for j := 0; j < 25; j++ {
|
|
if err := Add(file.Name(), rec); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := Delete(file.Name(), rec); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
if err := group.Wait(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
content, err := os.ReadFile(file.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "172.17.0.1\tinithostname\n"; !bytes.Contains(content, []byte(expected)) {
|
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
|
}
|
|
}
|
|
|
|
func benchDelete(b *testing.B) {
|
|
b.StopTimer()
|
|
file, err := os.CreateTemp("", "")
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
defer func() {
|
|
b.StopTimer()
|
|
file.Close()
|
|
os.Remove(file.Name())
|
|
b.StartTimer()
|
|
}()
|
|
|
|
err = Build(file.Name(), "", "", "", nil)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
var records []Record
|
|
var toDelete []Record
|
|
for i := 0; i < 255; i++ {
|
|
record := Record{
|
|
Hosts: fmt.Sprintf("testhostname%d", i),
|
|
IP: fmt.Sprintf("%d.%d.%d.%d", i, i, i, i),
|
|
}
|
|
records = append(records, record)
|
|
if i%2 == 0 {
|
|
toDelete = append(records, record)
|
|
}
|
|
}
|
|
|
|
if err := Add(file.Name(), records); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
b.StartTimer()
|
|
if err := Delete(file.Name(), toDelete); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func BenchmarkDelete(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
benchDelete(b)
|
|
}
|
|
}
|