diff --git a/.gitignore b/.gitignore index 84a3a7e..bb86fc3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ cmd/elvispc/elvispc # Test /coverage.txt +/coverage.tmp diff --git a/cjdns/admin_test.go b/cjdns/admin_test.go new file mode 100644 index 0000000..2adaf1d --- /dev/null +++ b/cjdns/admin_test.go @@ -0,0 +1 @@ +package cjdns_test diff --git a/cjdns/iptunnel_test.go b/cjdns/iptunnel_test.go new file mode 100644 index 0000000..2adaf1d --- /dev/null +++ b/cjdns/iptunnel_test.go @@ -0,0 +1 @@ +package cjdns_test diff --git a/cjdns/nodestore_test.go b/cjdns/nodestore_test.go new file mode 100644 index 0000000..2adaf1d --- /dev/null +++ b/cjdns/nodestore_test.go @@ -0,0 +1 @@ +package cjdns_test diff --git a/database/admin_test.go b/database/admin_test.go index 3d903e9..cdc6dee 100644 --- a/database/admin_test.go +++ b/database/admin_test.go @@ -1,4 +1,4 @@ -package database +package database_test import ( "strconv" @@ -7,7 +7,8 @@ import ( // TestSetAdmin_AdminHash_replace checks if adding a hash again replaces the old one, it tests both the SetAdmin and AdminHash methods func TestSetAdmin_AdminHash_replace(t *testing.T) { - setupDatabase() + db := MustOpen() + defer db.MustClose() var currHash string var retrHash string @@ -15,12 +16,12 @@ func TestSetAdmin_AdminHash_replace(t *testing.T) { for i := 0; i < 2; i++ { currHash = "hashNumber" + strconv.Itoa(i) - err = testDB.SetAdmin(currHash) + err = db.SetAdmin(currHash) if err != nil { t.Errorf("SetAdmin returned unexpected error: %v", err) } - retrHash, err = testDB.AdminHash() + retrHash, err = db.AdminHash() if err != nil { t.Errorf("SetAdmin returned unexpected error: %v", err) } diff --git a/database/database_test.go b/database/database_test.go index ab19367..98d509d 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -1,34 +1,49 @@ -package database +package database_test import ( - "log" + "io/ioutil" "os" - "testing" + + "github.com/willeponken/elvisp/database" ) -const dbPath = "/tmp/testing-show.db" +func tempFile() string { + file, err := ioutil.TempFile("", "elvisp-") + if err != nil { + panic(err) + } -var testDB Database + if err := file.Close(); err != nil { + panic(err) + } -func removeDatabase() error { - return os.Remove(dbPath) -} + if err := os.Remove(file.Name()); err != nil { + panic(err) + } -func setupDatabase() { - var err error + return file.Name() +} - removeDatabase() // Make sure there is no already existing database +type TestDB struct { + database.Database +} - testDB, err = Open(dbPath) +func MustOpen() TestDB { + db, err := database.Open(tempFile()) if err != nil { - log.Fatalf("Open database should be successfull, returned error: %v", err) + panic(err) } -} -func TestMain(m *testing.M) { - runResult := m.Run() + return TestDB{db} +} - removeDatabase() // Clean up the database +func (t *TestDB) Close() error { + defer os.Remove(t.Path()) + return t.Database.Close() +} - os.Exit(runResult) +func (t *TestDB) MustClose() { + if err := t.Close(); err != nil { + panic(err) + } } diff --git a/database/numbers.go b/database/numbers.go new file mode 100644 index 0000000..376f68a --- /dev/null +++ b/database/numbers.go @@ -0,0 +1,22 @@ +package database + +import ( + "encoding/binary" + "fmt" +) + +// uint64ToBin returns an 8-byte big endian representation of v. +func uint64ToBin(v uint64) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, v) + return b +} + +// binToUint64 takes an 8-byte big endian and converts it into a uint64. +func binToUint64(v []byte) uint64 { + if len(v) != 8 { + panic(fmt.Sprintf("invalid length of binary: %d", len(v))) + } + + return binary.BigEndian.Uint64(v) +} diff --git a/database/numbers_test.go b/database/numbers_test.go new file mode 100644 index 0000000..80036b0 --- /dev/null +++ b/database/numbers_test.go @@ -0,0 +1,45 @@ +package database + +import ( + "reflect" + "testing" +) + +var binUint64Tests = []struct { + v uint64 + b []byte +}{ + {1, []byte{0, 0, 0, 0, 0, 0, 0, 1}}, + {18446744073709551616 - 1, []byte{255, 255, 255, 255, 255, 255, 255, 255}}, +} + +func TestUint64ToBin(t *testing.T) { + for row, test := range binUint64Tests { + b := uint64ToBin(test.v) + + if !reflect.DeepEqual(b, test.b) { + t.Errorf("Row: %d returned unexpected binary, got: %v, wanted: %v", row, b, test.b) + } + } +} + +func TestBinToUint64(t *testing.T) { + for row, test := range binUint64Tests { + v := binToUint64(test.b) + + if v != test.v { + t.Errorf("Row: %d returned unexpected number, got: %d, wanted: %d", row, v, test.v) + } + } +} + +func TestBinToUint64_invalidLength(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Invalid length not equal to 8 should panic") + } + }() + + binToUint64(make([]byte, 1)) // should panic, must be equal to 8 + binToUint64(make([]byte, 9)) // same as above +} diff --git a/database/user.go b/database/user.go index bf84330..c3d0353 100644 --- a/database/user.go +++ b/database/user.go @@ -1,7 +1,6 @@ package database import ( - "encoding/binary" "errors" "fmt" "log" @@ -12,22 +11,6 @@ import ( // usersBucket defines the namespace for the user bucket. const usersBucket = "Users" -// uint64ToBin returns an 8-byte big endian representation of v. -func uint64ToBin(v uint64) []byte { - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, v) - return b -} - -// binToUint64 takes an 8-byte big endian and converts it into a uint64. -func binToUint64(v []byte) uint64 { - if len(v) != 8 { - log.Fatalf("Invalid length of binary: %d", len(v)) - } - - return binary.BigEndian.Uint64(v) -} - // userExists takes a identifier and tries to type cast it into either a public key or a uint64, and then lookups that identifier in the database. func (db *Database) userExists(identifier interface{}) (pos []byte, exists bool) { err := db.View(func(tx *Tx) error { diff --git a/database/user_test.go b/database/user_test.go index e106068..7e3def3 100644 --- a/database/user_test.go +++ b/database/user_test.go @@ -1,8 +1,7 @@ -package database +package database_test import ( "log" - "reflect" "testing" "github.com/willeponken/go-cjdns/key" @@ -14,14 +13,6 @@ type mockUser struct { invalid bool } -var binUint64Tests = []struct { - v uint64 - b []byte -}{ - {1, []byte{0, 0, 0, 0, 0, 0, 0, 1}}, - {18446744073709551616 - 1, []byte{255, 255, 255, 255, 255, 255, 255, 255}}, -} - func generateDuplicateUsers() (mockUsers []mockUser) { mockKey, err := key.DecodePublic("lpu15wrt3tb6d8vngq9yh3lr4gmnkuv0rgcd2jwl5rp5v0mhlg30.k") @@ -46,33 +37,15 @@ func generateMockUsers(numUsers int) []mockUser { return mockUsers } -func TestUint64ToBin(t *testing.T) { - for row, test := range binUint64Tests { - b := uint64ToBin(test.v) - - if !reflect.DeepEqual(b, test.b) { - t.Errorf("Row: %d returned unexpected binary, got: %v, wanted: %v", row, b, test.b) - } - } -} - -func TestBinToUint64(t *testing.T) { - for row, test := range binUint64Tests { - v := binToUint64(test.b) - - if v != test.v { - t.Errorf("Row: %d returned unexpected number, got: %d, wanted: %d", row, v, test.v) - } - } -} - // TestAddUser_duplicate checks if adding duplicate users returns an error func TestAddUser_duplicate(t *testing.T) { - setupDatabase() + db := MustOpen() + defer db.MustClose() + mockUsers := generateDuplicateUsers() for row, test := range mockUsers { - id, err := testDB.AddUser(test.pubkey) + id, err := db.AddUser(test.pubkey) // Got error, but it should be a valid call if err != nil && !test.invalid { @@ -97,11 +70,13 @@ func TestAddUser_many(t *testing.T) { t.Skip("Skipping test in short mode") } - setupDatabase() + db := MustOpen() + defer db.MustClose() + mockUsers := generateMockUsers(1000) for row, test := range mockUsers { - id, err := testDB.AddUser(test.pubkey) + id, err := db.AddUser(test.pubkey) // Got error, but it should be a valid call if err != nil && !test.invalid { @@ -122,17 +97,19 @@ func TestAddUser_many(t *testing.T) { // TestAddUser_fillGap checks if the gap created by adding 3 users then removing the 2nd will be filled when adding an user again func TestAddDelUser_fillGap(t *testing.T) { - setupDatabase() + db := MustOpen() + defer db.MustClose() + mockUsers := generateMockUsers(3) // Populate the database with the 3 users for _, test := range mockUsers { - testDB.AddUser(test.pubkey) + db.AddUser(test.pubkey) } secondUser := mockUsers[1] - testDB.DelUser(secondUser.pubkey) // Remove the second user - id, _ := testDB.AddUser(secondUser.pubkey) // Add the user again, should get the same as last time (2) + db.DelUser(secondUser.pubkey) // Remove the second user + id, _ := db.AddUser(secondUser.pubkey) // Add the user again, should get the same as last time (2) if id != secondUser.id { t.Errorf("User was not added inside the gap, got id: %d, wanted: %d", id, secondUser.id) @@ -141,10 +118,11 @@ func TestAddDelUser_fillGap(t *testing.T) { // TestGetID_empty tests if GetID returns an error on empty database (ID: 0 and an error) func TestGetID_empty(t *testing.T) { - setupDatabase() + db := MustOpen() + defer db.MustClose() mockUser := generateMockUsers(1)[0] - id, err := testDB.GetID(mockUser.pubkey) + id, err := db.GetID(mockUser.pubkey) if id != 0 && err == nil { t.Errorf("GetID returned unexpected id: %d, or a nil error", id) diff --git a/lease/lease.go b/lease/lease.go index 692eac3..58b1cba 100644 --- a/lease/lease.go +++ b/lease/lease.go @@ -51,9 +51,6 @@ func uint128Add(a, b, i uint64) (uint64, uint64) { } b += i - if i < 0 { - a += math.MaxUint64 - } return a, b } diff --git a/lease/lease_test.go b/lease/lease_test.go index 2a065f7..a60855f 100644 --- a/lease/lease_test.go +++ b/lease/lease_test.go @@ -1,12 +1,13 @@ -package lease +package lease_test import ( "net" "testing" + + "github.com/willeponken/elvisp/lease" ) func TestGenerate(t *testing.T) { - var generateTests = []struct { cidr string id uint64 @@ -19,15 +20,16 @@ func TestGenerate(t *testing.T) { {"1234::1222:0/16", 423411, net.ParseIP("1234::1228:75f3"), false}, {"1234::1222:0/120", 256, net.ParseIP("1234::1222:100"), true}, {"3214:1261:afb2::0/96", 4294967296, net.ParseIP("3214:1261:afb2::1:0:0"), true}, + {"3214:1261:afb2:ffff:ffff:ffff:ffff:ffff/96", 4294967296, net.ParseIP("3214:1261:afb3::ffff:ffff"), true}, } for row, tests := range generateTests { - cidr, err := ParseCIDR(tests.cidr) + cidr, err := lease.ParseCIDR(tests.cidr) if err != nil { t.Errorf("Row: %d returned unexpected error: %v", row, err) } - ip, err := Generate(cidr, tests.id) + ip, err := lease.Generate(cidr, tests.id) if !ip.Equal(tests.ip) { t.Errorf("Row: %d returned unexpected IP, got: %v, wanted: %v", row, ip, tests.ip) @@ -43,6 +45,13 @@ func TestGenerate(t *testing.T) { } } +func TestGenerate_emptyCIDR(t *testing.T) { + _, err := lease.Generate(lease.CIDR{}, 0) + if err == nil { + t.Errorf("Expected error but got %v", err) + } +} + func TestCIDR(t *testing.T) { var cidrTests = []struct { @@ -53,10 +62,11 @@ func TestCIDR(t *testing.T) { {"1234::1222:0/16", false}, {"192.168.1.0/128", true}, {"1234::1222:0/512", true}, + {"wow:such:an:invalid:address::yes/lol", true}, } for row, tests := range cidrTests { - _, err := ParseCIDR(tests.cidr) // No reason to test the net.ParseCIDR() function, therefore ignoring first return + _, err := lease.ParseCIDR(tests.cidr) // No reason to test the net.ParseCIDR() function, therefore ignoring first return if err != nil && !tests.err { t.Errorf("Row: %d returned unexpected error: %v", row, err) diff --git a/server/server_test.go b/server/server_test.go new file mode 100644 index 0000000..5868720 --- /dev/null +++ b/server/server_test.go @@ -0,0 +1 @@ +package server_test diff --git a/tasks/tasks_test.go b/tasks/tasks_test.go new file mode 100644 index 0000000..e591a7f --- /dev/null +++ b/tasks/tasks_test.go @@ -0,0 +1 @@ +package tasks_test