wip: migrate to mono-repo. SPN has already been moved to spn/

This commit is contained in:
Patrick Pacher
2024-03-15 11:55:13 +01:00
parent b30fd00ccf
commit 8579430db9
577 changed files with 35981 additions and 818 deletions

3
cmds/testsuite/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
# Compiled binaries
testsuite
testsuite.exe

33
cmds/testsuite/db.go Normal file
View File

@@ -0,0 +1,33 @@
package main
import (
"github.com/safing/portbase/database"
_ "github.com/safing/portbase/database/storage/hashmap"
)
func setupDatabases(path string) error {
err := database.InitializeWithPath(path)
if err != nil {
return err
}
_, err = database.Register(&database.Database{
Name: "core",
Description: "Holds core data, such as settings and profiles",
StorageType: "hashmap",
})
if err != nil {
return err
}
_, err = database.Register(&database.Database{
Name: "cache",
Description: "Cached data, such as Intelligence and DNS Records",
StorageType: "hashmap",
})
if err != nil {
return err
}
return nil
}

125
cmds/testsuite/login.go Normal file
View File

@@ -0,0 +1,125 @@
package main
import (
"errors"
"fmt"
"log"
"github.com/spf13/cobra"
"github.com/safing/portmaster/spn/access"
"github.com/safing/portmaster/spn/access/account"
)
var (
loginCmd = &cobra.Command{
Use: "login",
Short: "Test login and token issuing",
RunE: runTestCommand(testLogin),
}
loginUsername string
loginPassword string
loginDeviceID string
)
func init() {
rootCmd.AddCommand(loginCmd)
// Add flags for login options.
flags := loginCmd.Flags()
flags.StringVar(&loginUsername, "username", "", "set username to use for the login test")
flags.StringVar(&loginPassword, "password", "", "set password to use for the login test")
flags.StringVar(&loginDeviceID, "device-id", "", "set device ID to use for the login test")
// Mark all as required.
_ = loginCmd.MarkFlagRequired("username")
_ = loginCmd.MarkFlagRequired("password")
_ = loginCmd.MarkFlagRequired("device-id")
}
func testLogin(cmd *cobra.Command, args []string) (err error) {
// Init token zones.
err = access.InitializeZones()
if err != nil {
return fmt.Errorf("failed to initialize token zones: %w", err)
}
// Set initial user object in order to set the device ID that should be used for login.
initialUser := &access.UserRecord{
User: &account.User{
Username: loginUsername,
Device: &account.Device{
ID: loginDeviceID,
},
},
}
err = initialUser.Save()
if err != nil {
return fmt.Errorf("failed to save initial user with device ID: %w", err)
}
// Login.
_, _, err = access.Login(loginUsername, loginPassword)
if err != nil {
return fmt.Errorf("login failed: %w", err)
}
// Check user.
user, err := access.GetUser()
if err != nil {
return fmt.Errorf("failed to get user after login: %w", err)
}
if verbose {
log.Printf("user (from login): %+v", user.User)
log.Printf("device (from login): %+v", user.User.Device)
}
// Check if the device ID is unchanged.
if user.Device.ID != loginDeviceID {
return errors.New("device ID changed")
}
// Check Auth Token.
authToken, err := access.GetAuthToken()
if err != nil {
return fmt.Errorf("failed to get auth token after login: %w", err)
}
if verbose {
log.Printf("auth token (from login): %+v", authToken.Token)
}
firstAuthToken := authToken.Token.Token
// Update User.
_, _, err = access.UpdateUser()
if err != nil {
return fmt.Errorf("failed to update user: %w", err)
}
// Check if we received a new Auth Token.
authToken, err = access.GetAuthToken()
if err != nil {
return fmt.Errorf("failed to get auth token after user update: %w", err)
}
if verbose {
log.Printf("auth token (from update): %+v", authToken.Token)
}
if authToken.Token.Token == firstAuthToken {
return errors.New("auth token did not change after update")
}
// Get Tokens.
err = access.UpdateTokens()
if err != nil {
return fmt.Errorf("failed to update tokens: %w", err)
}
regular, fallback := access.GetTokenAmount(access.ExpandAndConnectZones)
if verbose {
log.Printf("received tokens: %d regular, %d fallback", regular, fallback)
}
if regular == 0 || fallback == 0 {
return fmt.Errorf("not enough tokens after fetching: %d regular, %d fallback", regular, fallback)
}
return nil
}

69
cmds/testsuite/main.go Normal file
View File

@@ -0,0 +1,69 @@
package main
import (
"fmt"
"log"
"os"
"github.com/spf13/cobra"
)
var (
rootCmd = &cobra.Command{
Use: "testsuite",
Short: "An integration and end-to-end test tool for the SPN",
}
verbose bool
)
func runTestCommand(cmdFunc func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
// Setup
dbDir, err := os.MkdirTemp("", "spn-testsuite-")
if err != nil {
makeReports(cmd, fmt.Errorf("internal test error: failed to setup datbases: %w", err))
return err
}
if err = setupDatabases(dbDir); err != nil {
makeReports(cmd, fmt.Errorf("internal test error: failed to setup datbases: %w", err))
return err
}
// Run Test
err = cmdFunc(cmd, args)
if err != nil {
log.Printf("test failed: %s", err)
}
// Report
makeReports(cmd, err)
// Cleanup and return more important error.
cleanUpErr := os.RemoveAll(dbDir)
if cleanUpErr != nil {
// Only log if the test failed, so we can return the more important error
if err == nil {
return cleanUpErr
}
log.Printf("cleanup failed: %s", err)
}
return err
}
}
func makeReports(cmd *cobra.Command, err error) {
reportToHealthCheckIfEnabled(cmd, err)
}
func init() {
flags := rootCmd.PersistentFlags()
flags.BoolVarP(&verbose, "verbose", "v", false, "enable verbose logging")
}
func main() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}

View File

@@ -0,0 +1,51 @@
package main
import (
"log"
"net/http"
"strings"
"github.com/spf13/cobra"
)
var healthCheckReportURL string
func init() {
flags := rootCmd.PersistentFlags()
flags.StringVar(&healthCheckReportURL, "report-to-healthcheck", "", "report to the given healthchecks URL")
}
func reportToHealthCheckIfEnabled(_ *cobra.Command, failureErr error) {
if healthCheckReportURL == "" {
return
}
if failureErr != nil {
// Report failure.
resp, err := http.Post(
healthCheckReportURL+"/fail",
"text/plain; utf-8",
strings.NewReader(failureErr.Error()),
)
if err != nil {
log.Printf("failed to report failure to healthcheck at %q: %s", healthCheckReportURL, err)
return
}
_ = resp.Body.Close()
// Always log that we've report the error.
log.Printf("reported failure to healthcheck at %q", healthCheckReportURL)
} else {
// Report success.
resp, err := http.Get(healthCheckReportURL) //nolint:gosec
if err != nil {
log.Printf("failed to report success to healthcheck at %q: %s", healthCheckReportURL, err)
return
}
_ = resp.Body.Close()
if verbose {
log.Printf("reported success to healthcheck at %q", healthCheckReportURL)
}
}
}