wip: migrate to mono-repo. SPN has already been moved to spn/
This commit is contained in:
3
cmds/testsuite/.gitignore
vendored
Normal file
3
cmds/testsuite/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Compiled binaries
|
||||
testsuite
|
||||
testsuite.exe
|
||||
33
cmds/testsuite/db.go
Normal file
33
cmds/testsuite/db.go
Normal 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
125
cmds/testsuite/login.go
Normal 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
69
cmds/testsuite/main.go
Normal 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)
|
||||
}
|
||||
}
|
||||
51
cmds/testsuite/report_healthcheck.go
Normal file
51
cmds/testsuite/report_healthcheck.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user