Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Commit

Permalink
Test creating default db directory (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
jlegrone committed Sep 29, 2022
1 parent 8833863 commit f974733
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 45 deletions.
32 changes: 20 additions & 12 deletions cmd/temporalite/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ import (
// as a dependency when building with the `headless` tag enabled.
const uiServerModule = "github.com/temporalio/ui-server/v2"

var (
defaultCfg *liteconfig.Config
)

const (
ephemeralFlag = "ephemeral"
dbPathFlag = "filename"
Expand All @@ -54,10 +50,6 @@ const (
dynamicConfigValueFlag = "dynamic-config-value"
)

func init() {
defaultCfg, _ = liteconfig.NewDefaultConfig()
}

func main() {
if err := buildCLI().Run(os.Args); err != nil {
goLog.Fatal(err)
Expand All @@ -68,6 +60,8 @@ func main() {
var version string

func buildCLI() *cli.App {
defaultCfg, _ := liteconfig.NewDefaultConfig()

if version == "" {
version = "(devel)"
}
Expand Down Expand Up @@ -177,7 +171,7 @@ func buildCLI() *cli.App {
}

switch c.String(logFormatFlag) {
case "json", "pretty":
case "json", "pretty", "noop":
default:
return cli.Exit(fmt.Sprintf("bad value %q passed for flag %q", c.String(logFormatFlag), logFormatFlag), 1)
}
Expand Down Expand Up @@ -237,6 +231,17 @@ func buildCLI() *cli.App {
}
}

interruptChan := make(chan interface{}, 1)
go func() {
if doneChan := c.Done(); doneChan != nil {
s := <-doneChan
interruptChan <- s
} else {
s := <-temporal.InterruptCh()
interruptChan <- s
}
}()

opts := []temporalite.ServerOption{
temporalite.WithDynamicPorts(),
temporalite.WithFrontendPort(serverPort),
Expand All @@ -246,7 +251,7 @@ func buildCLI() *cli.App {
temporalite.WithNamespaces(c.StringSlice(namespaceFlag)...),
temporalite.WithSQLitePragmas(pragmas),
temporalite.WithUpstreamOptions(
temporal.InterruptOn(temporal.InterruptCh()),
temporal.InterruptOn(interruptChan),
),
temporalite.WithBaseConfig(baseConfig),
}
Expand All @@ -265,7 +270,8 @@ func buildCLI() *cli.App {
}

var logger log.Logger
if c.String(logFormatFlag) == "pretty" {
switch c.String(logFormatFlag) {
case "pretty":
lcfg := zap.NewDevelopmentConfig()
switch c.String(logLevelFlag) {
case "debug":
Expand All @@ -288,7 +294,9 @@ func buildCLI() *cli.App {
return err
}
logger = log.NewZapLogger(l)
} else {
case "noop":
logger = log.NewNoopLogger()
default:
logger = log.NewZapLogger(log.BuildZapLogger(log.Config{
Stdout: true,
Level: c.String(logLevelFlag),
Expand Down
156 changes: 156 additions & 0 deletions cmd/temporalite/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,22 @@
package main

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"testing"
"time"

"github.com/urfave/cli/v2"
"go.temporal.io/api/enums/v1"
"go.temporal.io/sdk/client"

"github.com/temporalio/temporalite/internal/liteconfig"
)

func TestGetDynamicConfigValues(t *testing.T) {
Expand Down Expand Up @@ -63,3 +77,145 @@ func TestGetDynamicConfigValues(t *testing.T) {
"foo=123", `bar="baz"`, "qux=true", `foo=["123", false]`,
)
}

func newServerAndClientOpts(port int, customArgs ...string) ([]string, client.Options) {
args := []string{
"temporalite",
"start",
"--namespace", "default",
// Use noop logger to avoid fatal logs failing tests on shutdown signal.
"--log-format", "noop",
"--headless",
"--port", strconv.Itoa(port),
}

return append(args, customArgs...), client.Options{
HostPort: fmt.Sprintf("localhost:%d", port),
Namespace: "temporal-system",
}
}

func assertServerHealth(t *testing.T, ctx context.Context, opts client.Options) {
var (
c client.Client
clientErr error
)
for i := 0; i < 50; i++ {
if c, clientErr = client.Dial(opts); clientErr == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
if clientErr != nil {
t.Error(clientErr)
}

if _, err := c.CheckHealth(ctx, nil); err != nil {
t.Error(err)
}

// Check for pollers on a system task queue to ensure that the worker service is running.
for {
if ctx.Err() != nil {
t.Error(ctx.Err())
break
}
resp, err := c.DescribeTaskQueue(ctx, "temporal-sys-tq-scanner-taskqueue-0", enums.TASK_QUEUE_TYPE_WORKFLOW)
if err != nil {
t.Error(err)
}
if len(resp.GetPollers()) > 0 {
break
}
time.Sleep(time.Millisecond * 100)
}
}

func TestCreateDataDirectory(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

testUserHome := filepath.Join(os.TempDir(), "temporalite_test", t.Name())
t.Cleanup(func() {
if err := os.RemoveAll(testUserHome); err != nil {
fmt.Println("error cleaning up temp dir:", err)
}
})
// Set user home for all supported operating systems
t.Setenv("AppData", testUserHome) // Windows
t.Setenv("HOME", testUserHome) // macOS
t.Setenv("XDG_CONFIG_HOME", testUserHome) // linux
// Verify that worked
configDir, _ := os.UserConfigDir()
if !strings.HasPrefix(configDir, testUserHome) {
t.Fatalf("expected config dir %q to be inside user home directory %q", configDir, testUserHome)
}

temporaliteCLI := buildCLI()
// Don't call os.Exit
temporaliteCLI.ExitErrHandler = func(_ *cli.Context, _ error) {}

portProvider := liteconfig.NewPortProvider()
var (
port1 = portProvider.MustGetFreePort()
port2 = portProvider.MustGetFreePort()
port3 = portProvider.MustGetFreePort()
)
portProvider.Close()

t.Run("default db path", func(t *testing.T) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()

args, clientOpts := newServerAndClientOpts(port1)

go func() {
if err := temporaliteCLI.RunContext(ctx, args); err != nil {
fmt.Println("Server closed with error:", err)
}
}()

assertServerHealth(t, ctx, clientOpts)

// If the rest of this test case passes but this assertion fails,
// there may have been a breaking change in the liteconfig package
// related to how the default db file path is calculated.
if _, err := os.Stat(filepath.Join(configDir, "temporalite", "db", "default.db")); err != nil {
t.Errorf("error checking for default db file: %s", err)
}
})

t.Run("custom db path -- missing directory", func(t *testing.T) {
customDBPath := filepath.Join(testUserHome, "foo", "bar", "baz.db")
args, _ := newServerAndClientOpts(
port2, "-f", customDBPath,
)
if err := temporaliteCLI.RunContext(ctx, args); err != nil {
if !errors.Is(err, os.ErrNotExist) {
t.Errorf("expected error %q, got %q", os.ErrNotExist, err)
}
if !strings.Contains(err.Error(), filepath.Dir(customDBPath)) {
t.Errorf("expected error %q to contain string %q", err, filepath.Dir(customDBPath))
}
} else {
t.Error("no error when directory missing")
}
})

t.Run("custom db path -- existing directory", func(t *testing.T) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()

args, clientOpts := newServerAndClientOpts(
port3, "-f", filepath.Join(testUserHome, "foo.db"),
)

go func() {
if err := temporaliteCLI.RunContext(ctx, args); err != nil {
fmt.Println("Server closed with error:", err)
}
}()

assertServerHealth(t, ctx, clientOpts)
})
}
34 changes: 23 additions & 11 deletions cmd/temporalite/mtls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"net/http"
"os"
Expand All @@ -40,9 +41,12 @@ import (
"text/template"
"time"

"github.com/urfave/cli/v2"
"go.temporal.io/api/enums/v1"
"go.temporal.io/api/workflowservice/v1"
"go.temporal.io/sdk/client"

"github.com/temporalio/temporalite/internal/liteconfig"
)

func TestMTLSConfig(t *testing.T) {
Expand All @@ -52,11 +56,7 @@ func TestMTLSConfig(t *testing.T) {
mtlsDir := filepath.Join(thisFile, "../../../internal/examples/mtls")

// Create temp config dir
confDir, err := os.MkdirTemp("", "temporalite-conf-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(confDir)
confDir := t.TempDir()

// Run templated config and put in temp dir
var buf bytes.Buffer
Expand All @@ -82,19 +82,31 @@ func TestMTLSConfig(t *testing.T) {
t.Fatal(err)
}

portProvider := liteconfig.NewPortProvider()
var (
frontendPort = portProvider.MustGetFreePort()
webUIPort = portProvider.MustGetFreePort()
)
portProvider.Close()

// Run ephemerally using temp config
args := []string{
"temporalite",
"start",
"--ephemeral",
"--config", confDir,
"--namespace", "default",
"--log-format", "pretty",
"--port", "10233",
"--log-format", "noop",
"--port", strconv.Itoa(frontendPort),
"--ui-port", strconv.Itoa(webUIPort),
}
go func() {
if err := buildCLI().RunContext(ctx, args); err != nil {
t.Logf("CLI failed: %v", err)
temporaliteCLI := buildCLI()
// Don't call os.Exit
temporaliteCLI.ExitErrHandler = func(_ *cli.Context, _ error) {}

if err := temporaliteCLI.RunContext(ctx, args); err != nil {
fmt.Printf("CLI failed: %s\n", err)
}
}()

Expand All @@ -116,7 +128,7 @@ func TestMTLSConfig(t *testing.T) {

// Build client options and try to connect client every 100ms for 5s
options := client.Options{
HostPort: "localhost:10233",
HostPort: fmt.Sprintf("localhost:%d", frontendPort),
ConnectionOptions: client.ConnectionOptions{
TLS: &tls.Config{
Certificates: []tls.Certificate{clientCert},
Expand Down Expand Up @@ -151,7 +163,7 @@ func TestMTLSConfig(t *testing.T) {
}

// Pretend to be a browser to invoke the UI API
res, err := http.Get("http://localhost:11233/api/v1/namespaces?")
res, err := http.Get(fmt.Sprintf("http://localhost:%d/api/v1/namespaces?", webUIPort))
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit f974733

Please sign in to comment.