Skip to content

Commit

Permalink
added unit tests for helper-functions
Browse files Browse the repository at this point in the history
  • Loading branch information
superstes committed Oct 9, 2023
1 parent 254adb6 commit 2092a4b
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 15 deletions.
32 changes: 23 additions & 9 deletions lib/u/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ func AllStrInList(list []string, check []string) bool {
return true
}

func IsIPv4(address string) bool {
return strings.Contains(address, ".")
}

func IsDomainName(s string) bool {
// source: https://github.com/golang/go/blob/go1.20.5/src/net/dnsclient.go#L72-L75
if s == "." {
Expand Down Expand Up @@ -111,25 +107,30 @@ func dnsResolveWithServer(srv string) *net.Resolver {
}
}

func DnsLookup(dns string) (ips []net.IP) {
func DnsLookup(host string) (ips []net.IP) {
var err error
isIP, ip := IsIP(host)
if isIP {
return append(ips, ip)
}

for _, srv := range cnf.C.Service.DnsNameservers {
ips, err = dnsResolveWithServer(srv).LookupIP(
context.Background(), "ip", dns,
context.Background(), "ip", host,
)
if err != nil {
log.Debug("util", fmt.Sprintf("Failed to lookup DNS '%s' via server %s: %v", dns, srv, err))
log.Debug("util", fmt.Sprintf("Failed to lookup DNS '%s' via server %s: %v", host, srv, err))
continue
}
if len(ips) > 0 {
break
}
}
if len(ips) == 0 {
log.ErrorS("util", fmt.Sprintf("Failed to lookup DNS '%s'", dns))
log.ErrorS("util", fmt.Sprintf("Failed to lookup DNS '%s'", host))
return
}
log.Debug("util", fmt.Sprintf("DNS '%s' resolved to: %v", dns, ips))
log.Debug("util", fmt.Sprintf("DNS '%s' resolved to: %v", host, ips))
return ips
}

Expand All @@ -144,13 +145,26 @@ func DnsLookup46(dns string) (ip4 []net.IP, ip6 []net.IP) {
return
}

// enclose IPv6 addresses in brackets
func FormatIPv6(ip string) string {
// todo: maybe check if is IP first (needed?)
if !IsIPv4(ip) && !strings.Contains(ip, "[") {
return fmt.Sprintf("[%v]", ip)
}
return ip
}

func IsIPv4(address string) bool {
// todo: maybe check if is IP first (needed?)
return strings.Contains(address, ".")
}

func IsIP(host string) (valid bool, ip net.IP) {
ip = net.ParseIP(host)
valid = !(ip == nil)
return
}

func TrustedCAs() *x509.CertPool {
cafile := cnf.C.Service.Certs.CAPublic
caCertPool := x509.NewCertPool()
Expand Down
181 changes: 175 additions & 6 deletions lib/u/helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,184 @@
package u

import (
"fmt"
"net"
"path/filepath"
"runtime"
"testing"
"time"

"github.com/superstes/calamary/cnf"
)

var TestIPv4_1 = "1.1.1.1"
var TestIPv4_2 = "1.0.0.1"
var TestIPv6_1 = "2606:4700:4700::1001"
var TestIPv6_2 = "2606:4700:4700::1111"

func TestAllStrInList(t *testing.T) {
a := []string{"test", "abc"}
b := []string{"test", "xyz", "abc"}
if !AllStrInList(b, a) {
t.Errorf("Failed to compare slices #1")
}
if AllStrInList(a, b) {
t.Errorf("Failed to compare slices #2")
}
}

func TestToStr(t *testing.T) {
e := fmt.Errorf("test")
if ToStr(e) != "test" {
t.Errorf("Failed convert to string #1")
}

if ToStr(11) != "11" {
t.Errorf("Failed convert to string #2")
}
}

func TestIsDomainName(t *testing.T) {
if !IsDomainName("calamary.net") {
t.Errorf("Failed validate domain #1")
}
if !IsDomainName("sub.calamary.net") {
t.Errorf("Failed validate domain #2")
}
if !IsDomainName("othersub.sub.calamary.net") {
t.Errorf("Failed validate domain #3")
}
if !IsDomainName("129a.calamary.net") {
t.Errorf("Failed validate domain #4")
}
if IsDomainName("ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrssssssssssssssssssssssesassssssssub.calamary.net") {
t.Errorf("Failed validate domain #5")
}
if IsDomainName("subddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrr.calamary.net") {
t.Errorf("Failed validate domain #6")
}
if IsDomainName(TestIPv4_1) {
t.Errorf("Failed validate domain #7")
}
if IsDomainName(TestIPv6_1) {
t.Errorf("Failed validate domain #8")
}
}

func TestTimeout(t *testing.T) {
testTime := uint(33)
to := Timeout(testTime)
comp := time.Duration(int(testTime) * int(time.Millisecond))
if to != comp {
t.Errorf("Failed get timeout #1")
}
}

func TestIn(t *testing.T) {
a := []string{"test", "abc"}
if !IsIn("test", a) {
t.Errorf("Failed to find in slice #1")
}
if IsIn("testa", a) {
t.Errorf("Failed to find in slice #2")
}
}

func TestInStr(t *testing.T) {
if !IsInStr("test", "justAtest") {
t.Errorf("Failed to find substring #1")
}
if IsInStr("no", "justAtest") {
t.Errorf("Failed to find substring #2")
}
}

func TestDnsResolveWithServer(t *testing.T) {
dnsResolveWithServer(TestIPv4_1)
dnsResolveWithServer(TestIPv4_1 + ":53")
dnsResolveWithServer(TestIPv4_1 + ":853")
}

func TestIPv4(t *testing.T) {
if !IsIPv4(TestIPv4_1) {
t.Errorf("Failed to validate IPv4 #1")
}
if IsIPv4(TestIPv6_1) {
t.Errorf("Failed to validate IPv4 #2")
}
}

func TestFormatIPv6(t *testing.T) {
ip := FormatIPv6(TestIPv6_1)
if ip != ("[" + TestIPv6_1 + "]") {
t.Errorf("Failed to format IPv6 #1")
}

ip = FormatIPv6(TestIPv4_1)
if ip != TestIPv4_1 {
t.Errorf("Failed to format IPv6 #2")
}
}

func TestIsIP(t *testing.T) {
valid, ip := IsIP(TestIPv4_1)
if !valid || ip.String() != TestIPv4_1 {
t.Errorf("Failed to check for IP #1")
}

valid, ip = IsIP("test.at")
if valid {
t.Errorf("Failed to check for IP #2")
}

valid, ip = IsIP(TestIPv6_1)
if !valid || ip.String() != TestIPv6_1 {
t.Errorf("Failed to check for IP #3")
}
}

func TestDnsLookup(t *testing.T) {
// NOTE: tests will fail if the IPs change.. should not be common
cnf.C = &cnf.Config{
Service: cnf.ServiceConfig{
DnsNameservers: []string{"1.1.1.1"},
DnsNameservers: []string{TestIPv4_1},
},
}
resp := DnsLookup("one.one.one.one")

if !isInIpList("1.1.1.1", resp) || !isInIpList("1.0.0.1", resp) ||
!isInIpList("2606:4700:4700::1001", resp) || !isInIpList("2606:4700:4700::1111", resp) {
if !isInIpList(TestIPv4_1, resp) || !isInIpList(TestIPv4_2, resp) ||
!isInIpList(TestIPv6_1, resp) || !isInIpList(TestIPv6_2, resp) {
t.Errorf("DNS Query #1 has unexpected result: %v", resp)
}

resp4, resp6 := DnsLookup46("one.one.one.one")

if !isInIpList("1.1.1.1", resp4) || !isInIpList("1.0.0.1", resp4) ||
!isInIpList("2606:4700:4700::1001", resp6) || !isInIpList("2606:4700:4700::1111", resp6) ||
isInIpList("1.1.1.1", resp6) || isInIpList("2606:4700:4700::1001", resp4) {
if !isInIpList(TestIPv4_1, resp4) || !isInIpList(TestIPv4_2, resp4) ||
!isInIpList(TestIPv6_1, resp6) || !isInIpList(TestIPv6_2, resp6) ||
isInIpList(TestIPv4_1, resp6) || isInIpList(TestIPv6_1, resp4) {
t.Errorf("DNS Query #2 has unexpected result: ip4 %v, ip6 %v", resp4, resp6)
}

// edge-cases - input is already IP
resp = DnsLookup(TestIPv4_1)
if len(resp) != 1 || !isInIpList(TestIPv4_1, resp) {
t.Errorf("DNS Query #3 has unexpected result: %v", resp)
}

resp = DnsLookup(TestIPv6_1)
if len(resp) != 1 || !isInIpList(TestIPv6_1, resp) {
t.Errorf("DNS Query #4 has unexpected result: %v", resp)
}

resp4, resp6 = DnsLookup46(TestIPv4_1)
if len(resp4) != 1 || len(resp6) != 0 || !isInIpList(TestIPv4_1, resp4) {
t.Errorf("DNS Query #5 has unexpected result: %v", resp4)
}

resp4, resp6 = DnsLookup46(TestIPv6_1)
if len(resp6) != 1 || len(resp4) != 0 || !isInIpList(TestIPv6_1, resp6) {
t.Errorf("DNS Query #6 has unexpected result: %v", resp6)
}
}

func isInIpList(value string, list []net.IP) bool {
Expand All @@ -38,3 +189,21 @@ func isInIpList(value string, list []net.IP) bool {
}
return false
}

func TestDumpToFile(t *testing.T) {
DumpToFile([]byte{'t', 'e', 's', 't'})
}

func TestTrustedCAs(t *testing.T) {
_, pathToTest, _, _ := runtime.Caller(0)
pathToTestCerts := filepath.Dir(pathToTest) + "/testdata/"

cnf.C = &cnf.Config{
Service: cnf.ServiceConfig{
Certs: cnf.ServiceCertificates{
CAPublic: pathToTestCerts + "ca.crt",
},
},
}
TrustedCAs()
}
20 changes: 20 additions & 0 deletions lib/u/testdata/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDPzCCAiegAwIBAgIUIsS0WWDVdapRl0HWlPErE1lSIiUwDQYJKoZIhvcNAQEL
BQAwEjEQMA4GA1UEAwwHVGVzdCBDQTAeFw0yMzEwMDkxNjQ0NDVaFw0zMzEwMDYx
NjQ0NDVaMBIxEDAOBgNVBAMMB1Rlc3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDl59akmsGWUA2SNUJZqvMXqNO+U7S3j1yQmayfXk1AtrGoXIZZ
6H/qQpHe9uBB+aNR9hePJ+u49XayVj+AzNAheJmBf5W71j4BS/hRZfxfF2kUrrQ6
hI4/Qj2l6L0w49BBuRnYRzXib6wR2BrF9qCIiablso++J2i1SJ4RTvRCLYhJYml9
UTy476HeR8tw8llNYrQCoG+TFvn+n61KnLwj24+qN78DllGc6NR7s4FbtXyRplAQ
oPm3i6t+CJ2g2p3hi2+pw+ZwIEf4cI97XIRWvcMTeqxNKMCkDYYEUUjAixRnuxEz
J32ZjPlh1koo7cecCTOfaHXQeC2luYNFHG0nAgMBAAGjgYwwgYkwDAYDVR0TBAUw
AwEB/zAdBgNVHQ4EFgQU98YSF2wCeIpVdN7xOcfrIM+zDWUwTQYDVR0jBEYwRIAU
98YSF2wCeIpVdN7xOcfrIM+zDWWhFqQUMBIxEDAOBgNVBAMMB1Rlc3QgQ0GCFCLE
tFlg1XWqUZdB1pTxKxNZUiIlMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
AQEAauXzrm14ASlQ6Be1Gbu5unclI9l9eLrIUdod6IjBT1Ayxq+CQOHH0kckWBM7
ZYeb155VJ61HvT7jmioB7Pb0UkxznExsiGdo8HTOgvrgSsQ+RkQIOZjHq5hNToCD
FMVHdXvHTUV6l5/LegZvHy9GScSQ3u0MMFofug0D4r2VZzJ+wlPtRkDpPfj3Qf+K
t545tyKHMlwWOnEQRQPuXUwMnv7NfwuEn+gBaTC3MNpVwJDoLq4IT9SQNUgnpTOU
WdgK7TNbJ3Y73pvxpfazd+0eTmGEjmq75N813Vn+c+Ad2vctuJBQp2znGYAZ0wxM
4Q5gHur6g4ng/VYCqcLJ8A85Fg==
-----END CERTIFICATE-----

0 comments on commit 2092a4b

Please sign in to comment.