[WIP] Fix unit tests

This commit is contained in:
Vladimir Stoilov
2024-10-08 14:13:08 +03:00
parent a8517cd65f
commit a874ec9412
48 changed files with 264 additions and 4088 deletions

View File

@@ -21,7 +21,7 @@ type testInstance struct {
var _ instance = &testInstance{}
func (stub *testInstance) Updates() *updates.Updates {
func (stub *testInstance) IntelUpdates() *updates.Updates {
return stub.updates
}
@@ -54,6 +54,15 @@ func runTest(m *testing.M) error {
return fmt.Errorf("failed to initialize dataroot: %w", err)
}
defer func() { _ = os.RemoveAll(ds) }()
installDir, err := os.MkdirTemp("", "geoip_installdir")
if err != nil {
return fmt.Errorf("failed to create tmp install dir: %w", err)
}
defer func() { _ = os.RemoveAll(installDir) }()
err = updates.GenerateMockFolder(installDir, "Test Intel", "1.0.0")
if err != nil {
return fmt.Errorf("failed to generate mock installation: %w", err)
}
stub := &testInstance{}
stub.db, err = dbmodule.New(stub)
@@ -68,7 +77,10 @@ func runTest(m *testing.M) error {
if err != nil {
return fmt.Errorf("failed to create api: %w", err)
}
stub.updates, err = updates.New(stub)
stub.updates, err = updates.New(stub, "Test Intel", updates.UpdateIndex{
Directory: installDir,
IndexFile: "index.json",
})
if err != nil {
return fmt.Errorf("failed to create updates: %w", err)
}

View File

@@ -21,7 +21,7 @@ type testInstance struct {
var _ instance = &testInstance{}
func (stub *testInstance) Updates() *updates.Updates {
func (stub *testInstance) IntelUpdates() *updates.Updates {
return stub.updates
}
@@ -54,6 +54,15 @@ func runTest(m *testing.M) error {
return fmt.Errorf("failed to initialize dataroot: %w", err)
}
defer func() { _ = os.RemoveAll(ds) }()
installDir, err := os.MkdirTemp("", "netenv_installdir")
if err != nil {
return fmt.Errorf("failed to create tmp install dir: %w", err)
}
defer func() { _ = os.RemoveAll(installDir) }()
err = updates.GenerateMockFolder(installDir, "Test Intel", "1.0.0")
if err != nil {
return fmt.Errorf("failed to generate mock installation: %w", err)
}
stub := &testInstance{}
stub.db, err = dbmodule.New(stub)
@@ -68,7 +77,10 @@ func runTest(m *testing.M) error {
if err != nil {
return fmt.Errorf("failed to create api: %w", err)
}
stub.updates, err = updates.New(stub)
stub.updates, err = updates.New(stub, "Test Intel", updates.UpdateIndex{
Directory: installDir,
IndexFile: "index.json",
})
if err != nil {
return fmt.Errorf("failed to create updates: %w", err)
}

View File

@@ -27,7 +27,7 @@ type testInstance struct {
geoip *geoip.GeoIP
}
func (stub *testInstance) Updates() *updates.Updates {
func (stub *testInstance) IntelUpdates() *updates.Updates {
return stub.updates
}
@@ -61,6 +61,16 @@ func runTest(m *testing.M) error {
}
defer func() { _ = os.RemoveAll(ds) }()
installDir, err := os.MkdirTemp("", "endpoints_installdir")
if err != nil {
return fmt.Errorf("failed to create tmp install dir: %w", err)
}
defer func() { _ = os.RemoveAll(installDir) }()
err = updates.GenerateMockFolder(installDir, "Test Intel", "1.0.0")
if err != nil {
return fmt.Errorf("failed to generate mock installation: %w", err)
}
stub := &testInstance{}
stub.db, err = dbmodule.New(stub)
if err != nil {
@@ -74,7 +84,10 @@ func runTest(m *testing.M) error {
if err != nil {
return fmt.Errorf("failed to create api: %w", err)
}
stub.updates, err = updates.New(stub)
stub.updates, err = updates.New(stub, "Test Intel", updates.UpdateIndex{
Directory: installDir,
IndexFile: "index.json",
})
if err != nil {
return fmt.Errorf("failed to create updates: %w", err)
}

View File

@@ -26,9 +26,7 @@ type testInstance struct {
netenv *netenv.NetEnv
}
// var _ instance = &testInstance{}
func (stub *testInstance) Updates() *updates.Updates {
func (stub *testInstance) IntelUpdates() *updates.Updates {
return stub.updates
}
@@ -70,6 +68,16 @@ func runTest(m *testing.M) error {
}
defer func() { _ = os.RemoveAll(ds) }()
installDir, err := os.MkdirTemp("", "resolver_installdir")
if err != nil {
return fmt.Errorf("failed to create tmp install dir: %w", err)
}
defer func() { _ = os.RemoveAll(installDir) }()
err = updates.GenerateMockFolder(installDir, "Test Intel", "1.0.0")
if err != nil {
return fmt.Errorf("failed to generate mock installation: %w", err)
}
stub := &testInstance{}
stub.db, err = dbmodule.New(stub)
if err != nil {
@@ -91,7 +99,10 @@ func runTest(m *testing.M) error {
if err != nil {
return fmt.Errorf("failed to create netenv: %w", err)
}
stub.updates, err = updates.New(stub)
stub.updates, err = updates.New(stub, "Test Intel", updates.UpdateIndex{
Directory: installDir,
IndexFile: "index.json",
})
if err != nil {
return fmt.Errorf("failed to create updates: %w", err)
}

View File

@@ -1,44 +0,0 @@
[Unit]
Description=Portmaster by Safing
Documentation=https://safing.io
Documentation=https://docs.safing.io
Before=nss-lookup.target network.target shutdown.target
After=systemd-networkd.service
Conflicts=shutdown.target
Conflicts=firewalld.service
Wants=nss-lookup.target
[Service]
Type=simple
Restart=on-failure
RestartSec=10
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
PrivateTmp=yes
PIDFile=/opt/safing/portmaster/core-lock.pid
Environment=LOGLEVEL=info
Environment=PORTMASTER_ARGS=
EnvironmentFile=-/etc/default/portmaster
ProtectSystem=true
#ReadWritePaths=/var/lib/portmaster
#ReadWritePaths=/run/xtables.lock
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
RestrictNamespaces=yes
# In future version portmaster will require access to user home
# directories to verify application permissions.
ProtectHome=read-only
ProtectKernelTunables=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
PrivateDevices=yes
AmbientCapabilities=cap_chown cap_kill cap_net_admin cap_net_bind_service cap_net_broadcast cap_net_raw cap_sys_module cap_sys_ptrace cap_dac_override cap_fowner cap_fsetid cap_sys_resource cap_bpf cap_perfmon
CapabilityBoundingSet=cap_chown cap_kill cap_net_admin cap_net_bind_service cap_net_broadcast cap_net_raw cap_sys_module cap_sys_ptrace cap_dac_override cap_fowner cap_fsetid cap_sys_resource cap_bpf cap_perfmon
# SystemCallArchitectures=native
# SystemCallFilter=@system-service @module
# SystemCallErrorNumber=EPERM
ExecStart=/opt/safing/portmaster/portmaster-start --data /opt/safing/portmaster core -- $PORTMASTER_ARGS
ExecStopPost=-/opt/safing/portmaster/portmaster-start recover-iptables
[Install]
WantedBy=multi-user.target

View File

@@ -3,6 +3,7 @@ package updates
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path"
@@ -179,3 +180,50 @@ func getIdentifierAndVersion(versionedPath string) (identifier, version string,
// `dirPath + filename` is guaranteed by path.Split()
return dirPath + filename, version, true
}
// GenerateMockFolder generates mock bundle folder for testing.
func GenerateMockFolder(dir, name, version string) error {
// Make sure dir exists
_ = os.MkdirAll(dir, defaultDirMode)
// Create empty files
file, err := os.Create(filepath.Join(dir, "portmaster"))
if err != nil {
return err
}
_ = file.Close()
file, err = os.Create(filepath.Join(dir, "portmaster-core"))
if err != nil {
return err
}
_ = file.Close()
file, err = os.Create(filepath.Join(dir, "portmaster.zip"))
if err != nil {
return err
}
_ = file.Close()
file, err = os.Create(filepath.Join(dir, "assets.zip"))
if err != nil {
return err
}
_ = file.Close()
bundle, err := GenerateBundleFromDir(dir, BundleFileSettings{
Name: name,
Version: version,
})
if err != nil {
return err
}
bundleStr, err := json.MarshalIndent(bundle, "", " ")
if err != nil {
fmt.Fprintf(os.Stderr, "failed to marshal bundle: %s\n", err)
}
err = os.WriteFile(filepath.Join(dir, "index.json"), bundleStr, defaultFileMode)
if err != nil {
return err
}
return nil
}

View File

@@ -40,8 +40,10 @@ func CreateDownloader(index UpdateIndex) Downloader {
func (d *Downloader) downloadIndexFile(ctx context.Context) error {
// Make sure dir exists
_ = os.MkdirAll(d.dir, defaultDirMode)
var err error
err := os.MkdirAll(d.dir, defaultDirMode)
if err != nil {
return fmt.Errorf("failed to create directory for updates: %s", d.dir)
}
var content string
for _, url := range d.indexURLs {
content, err = d.downloadIndexFileFromURL(ctx, url)
@@ -50,15 +52,15 @@ func (d *Downloader) downloadIndexFile(ctx context.Context) error {
continue
}
// Downloading was successful.
bundle, err := ParseBundle(content)
var bundle *Bundle
bundle, err = ParseBundle(content)
if err != nil {
log.Warningf("updates: %s", err)
continue
}
// Parsing was successful
version, err := semver.NewVersion(d.bundle.Version)
var version *semver.Version
version, err = semver.NewVersion(d.bundle.Version)
if err != nil {
log.Warningf("updates: failed to parse bundle version: %s", err)
continue
@@ -79,7 +81,7 @@ func (d *Downloader) downloadIndexFile(ctx context.Context) error {
indexFilepath := filepath.Join(d.dir, d.indexFile)
err = os.WriteFile(indexFilepath, []byte(content), defaultFileMode)
if err != nil {
return fmt.Errorf("failed to write index file: %s", err)
return fmt.Errorf("failed to write index file: %w", err)
}
return nil

View File

@@ -6,8 +6,6 @@ import (
"runtime"
"time"
"github.com/safing/portmaster/base/api"
"github.com/safing/portmaster/base/config"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/notifications"
"github.com/safing/portmaster/service/mgr"
@@ -215,8 +213,6 @@ func (u *Updates) Stop() error {
}
type instance interface {
API() *api.API
Config() *config.Config
Restart()
Shutdown()
Notifications() *notifications.Notifications

View File

@@ -0,0 +1,89 @@
package updates
import (
"fmt"
"os"
"path/filepath"
"testing"
"github.com/safing/portmaster/base/notifications"
)
type testInstance struct{}
func (i *testInstance) Restart() {}
func (i *testInstance) Shutdown() {}
func (i *testInstance) Notifications() *notifications.Notifications {
return nil
}
func (i *testInstance) Ready() bool {
return true
}
func (i *testInstance) SetCmdLineOperation(f func() error) {}
func TestPreformUpdate(t *testing.T) {
t.Parallel()
// Initialize mock instance
stub := &testInstance{}
// Make tmp dirs
installedDir, err := os.MkdirTemp("", "updates_current")
if err != nil {
panic(err)
}
defer func() { _ = os.RemoveAll(installedDir) }()
updateDir, err := os.MkdirTemp("", "updates_new")
if err != nil {
panic(err)
}
defer func() { _ = os.RemoveAll(updateDir) }()
purgeDir, err := os.MkdirTemp("", "updates_purge")
if err != nil {
panic(err)
}
defer func() { _ = os.RemoveAll(purgeDir) }()
// Generate mock files
if err := GenerateMockFolder(installedDir, "Test", "1.0.0"); err != nil {
panic(err)
}
if err := GenerateMockFolder(updateDir, "Test", "1.0.1"); err != nil {
panic(err)
}
// Create updater
updates, err := New(stub, "Test", UpdateIndex{
Directory: installedDir,
DownloadDirectory: updateDir,
PurgeDirectory: purgeDir,
IndexFile: "index.json",
AutoApply: false,
NeedsRestart: false,
})
if err != nil {
panic(err)
}
// Read and parse the index file
if err := updates.downloader.Verify(); err != nil {
panic(err)
}
// Try to apply the updates
err = updates.applyUpdates(nil)
if err != nil {
panic(err)
}
// CHeck if the current version is now the new.
bundle, err := LoadBundle(filepath.Join(installedDir, "index.json"))
if err != nil {
panic(err)
}
if bundle.Version != "1.0.1" {
panic(fmt.Errorf("expected version 1.0.1 found %s", bundle.Version))
}
}