126 lines
3.2 KiB
Go
126 lines
3.2 KiB
Go
package docker
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestContainerHostPort(t *testing.T) {
|
|
c := Container{Ports: "0.0.0.0:7576->7575/tcp, [::]:7576->7575/tcp"}
|
|
if got := c.HostPort(); got != "7576" {
|
|
t.Fatalf("HostPort() = %q, want 7576", got)
|
|
}
|
|
}
|
|
|
|
func TestIsPortConflict(t *testing.T) {
|
|
for _, message := range []string{
|
|
"Bind for 0.0.0.0:7575 failed: port is already allocated",
|
|
"driver failed programming external connectivity on endpoint",
|
|
} {
|
|
if !IsPortConflict(errors.New(message)) {
|
|
t.Fatalf("expected port conflict for %q", message)
|
|
}
|
|
}
|
|
if IsPortConflict(errors.New("manifest unknown")) {
|
|
t.Fatal("manifest error classified as port conflict")
|
|
}
|
|
}
|
|
|
|
func TestParseUsedDockerPortsPreservesLineBoundaries(t *testing.T) {
|
|
ports := parseUsedDockerPorts([]byte("6379/tcp\n0.0.0.0:7575->7575/tcp, [::]:7575->7575/tcp\n0.0.0.0:8000-8002->8000-8002/tcp\n"))
|
|
for _, port := range []int{7575, 8000, 8001, 8002} {
|
|
if !ports[port] {
|
|
t.Fatalf("port %d was not detected", port)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFindFreePortRejectsOutOfRangeStart(t *testing.T) {
|
|
if port := FindFreePort(65536); port != 0 {
|
|
t.Fatalf("port = %d, want 0", port)
|
|
}
|
|
}
|
|
|
|
func TestDevelopmentEncryptionKeyUsesEnvironmentOverride(t *testing.T) {
|
|
want := strings.Repeat("a", 64)
|
|
t.Setenv(developmentEncryptionKeyEnv, want)
|
|
got, err := developmentEncryptionKey()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != want {
|
|
t.Fatalf("key = %q, want environment value", got)
|
|
}
|
|
}
|
|
|
|
func TestPersistedDevelopmentEncryptionKeyIsReused(t *testing.T) {
|
|
configDir := t.TempDir()
|
|
first, err := persistedDevelopmentEncryptionKey(configDir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
second, err := persistedDevelopmentEncryptionKey(configDir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if first != second {
|
|
t.Fatal("persisted key changed between reads")
|
|
}
|
|
decoded, err := hex.DecodeString(first)
|
|
if err != nil || len(decoded) != 32 {
|
|
t.Fatalf("generated key is not 32 bytes: %q", first)
|
|
}
|
|
info, err := os.Stat(filepath.Join(configDir, "homarr-dev", "secret-encryption-key"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if info.Mode().Perm() != 0o600 {
|
|
t.Fatalf("key permissions = %o, want 600", info.Mode().Perm())
|
|
}
|
|
}
|
|
|
|
func TestPersistedDevelopmentEncryptionKeyRejectsInvalidValue(t *testing.T) {
|
|
configDir := t.TempDir()
|
|
dir := filepath.Join(configDir, "homarr-dev")
|
|
if err := os.Mkdir(dir, 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dir, "secret-encryption-key"), []byte("invalid\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := persistedDevelopmentEncryptionKey(configDir); err == nil {
|
|
t.Fatal("expected invalid persisted key to fail")
|
|
}
|
|
}
|
|
|
|
func TestPersistedDevelopmentEncryptionKeyConcurrentCreation(t *testing.T) {
|
|
configDir := t.TempDir()
|
|
type result struct {
|
|
key string
|
|
err error
|
|
}
|
|
results := make(chan result, 20)
|
|
for range 20 {
|
|
go func() {
|
|
key, err := persistedDevelopmentEncryptionKey(configDir)
|
|
results <- result{key: key, err: err}
|
|
}()
|
|
}
|
|
var first string
|
|
for range 20 {
|
|
result := <-results
|
|
if result.err != nil {
|
|
t.Fatal(result.err)
|
|
}
|
|
if first == "" {
|
|
first = result.key
|
|
} else if result.key != first {
|
|
t.Fatal("concurrent callers received different keys")
|
|
}
|
|
}
|
|
}
|