Categorygithub.com/ascii8/nktest
modulepackage
0.12.4
Repository: https://github.com/ascii8/nktest.git
Documentation: pkg.go.dev

# README

About

Package nktest provides a Nakama test runner that makes it easy to build and test Nakama module plugins with complex or advanced game logic using nothing but go test.

See also github.com/ascii8/nakama-go package for a web/realtime Nakama Go client.

Tests Go Report Card [![Reference](https://pkg.go.dev/badge/github.com/ascii8/nktest Releases

Overview

This package uses Podman to create "rootless" containers (specifically, docker.io/heroiclabs/nakama-pluginbuilder and docker.io/heroiclabs/nakama) to build Nakama's Go plugins and launch the necessary server components (PostgreSQL and Nakama).

Provides a stable, repeatable, and quick mechanism for launching testable end-to-end Nakama servers for game modules (Go, Lua, or Javascript).

Provides additional transport and logger types for use with Go clients to readily aid in debugging Nakama's API calls.

Quickstart

Add to package/module:

go get github.com/ascii8/nktest

From Go's TestMain, use nktest.Main to build Go modules, and to setup/teardown PostgreSQL and Nakama server containers:

import "github.com/ascii8/nktest"

// TestMain handles setting up and tearing down the postgres and nakama
// containers.
func TestMain(m *testing.M) {
	ctx := context.Background()
	ctx = nktest.WithAlwaysPullFromEnv(ctx, "PULL")
	ctx = nktest.WithHostPortMap(ctx)
	nktest.Main(ctx, m,
		nktest.WithDir("./testdata"),
		nktest.WithBuildConfig("./nksample", nktest.WithDefaultGoEnv(), nktest.WithDefaultGoVolumes()),
	)
}

Then, from within a Test* func, create a cancelable test context, and a proxy:

import "github.com/ascii8/nktest"

func TestNakamaHealthcheck(t *testing.T) {
	ctx, cancel, nk := nktest.WithCancel(context.Background(), t)
	defer cancel()
	urlstr, err := nktest.RunProxy(ctx)
	if err != nil {
		t.Fatalf("expected no error, got: %v", err)
	}
	t.Logf("proxy: %s", urlstr)
	req, err := http.NewRequestWithContext(ctx, "GET", urlstr+"/healthcheck", nil)
	if err != nil {
		t.Fatalf("expected no error, got: %v", err)
	}
	// create a client with compression disabled (makes debugging the API
	// requests/responses easier)
	cl := &http.Client{
		Transport: &http.Transport{
			DisableCompression: true,
		},
	}
	// execute the request
	res, err := cl.Do(req)
	if err != nil {
		t.Fatalf("expected no error, got: %v", err)
	}
	defer res.Body.Close()
	// check response
	if res.StatusCode != http.StatusOK {
		t.Errorf("expected %d, got: %d", http.StatusOK, res.StatusCode)
	}
	t.Logf("healthcheck status: %d", res.StatusCode)
	// display connection information
	t.Logf("grpc: %s", nk.GrpcLocal())
	t.Logf("http: %s", nk.HttpLocal())
	t.Logf("console: %s", nk.ConsoleLocal())
	t.Logf("http_key: %s", nk.HttpKey())
	t.Logf("server_key: %s", nk.ServerKey())
}

Use the WithHostPortMap() option, to publish the Postgres and Nakama server's default ports on the host, and making it easy to write Example* tests.

For more advanced testing scenarios, see the github.com/ascii8/nakama-go package for a full featured Go Nakama client.

Examples

See the Go package documentation for package level examples.

Why

While Nakama provides a number of different languages with which to build out game modules, building large-scale, complex logic for Nakama is best done using Go. For experienced (and even inexperienced!) Go developers, the go test command is simple, efficient and well understood, and works across platforms.

And, for fully automated deployments of Nakama and game modules, a large amount of quick and reliable testing is needed to ensure rapid application development, and continuous integration/deployment (CI/CD).

As such, there was clear motivation to make it easy and repeatable to test entirely from go test,

Why Podman

The first version of nktest used Docker, but builds and tests were slow as it was not possible to mount the user's Go build/mod cache directories without stomping on the local UID/GID and subsequently affecting the read/write permissions. Thus the change to Podman, which is able to run containers without root permissions, and can keep user UID/GID's on files.

Notes

macOS:

# update homebrew formulas and upgrade packages
brew update && brew upgrade

# install podman
brew install podman

# install gpgme (needed for podman's Go binding dependenices)
brew install gpgme

# if unable to do `go test -v` out of the box, re-init the podman machine
podman machine stop podman-machine-default
podman machine rm podman-machine-default
podman machine init -v $HOME:$HOME
podman machine start

# if receiving a "too many open files" error on M1 macs, try:
podman machine stop && ulimit -n unlimited && podman machine start

# Packages

Copyright 2020 The Nakama Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.

# Functions

AlwaysPull returns whether or not to always pull an image.
Backoff executes f until backoff conditions are met or until f returns nil, or the context is closed.
BuildPodmanConnInfo builds a list of potential podman connection info.
BuildTimeout returns the build timeout.
Cancel cancels the current context.
ConfigFilename returns the config filename.
ConfigTemplate returns the config template.
ConsoleWriter returns the consoleWriter from the context.
Debug returns a debug logger from the context.
DockerAuthName returns the docker token auth name.
DockerAuthScope returns the docker token auth scope for a image id.
DockerImageTags gets the docker registry tags for a image id.
DockerRegistryURL returns the docker registry url.
DockerToken generates a docker auth token for the repo id.
DockerTokenURL returns the docker token url.
Err returns a err logger from the context.
GoEnvVar reads the go env variable from `go env <name>`.
HostPortMap returns the host port for the provided container id and service from the context.
HttpClient returns the http client from the context.
Info returns a info logger from the context.
IsSubDir determines if b is subdir of a.
Logger returns the logger from the context.
Main is the main entry point that should be called from TestMain.
NakamaImageId returns the nakama image id.
NakamaVersion loads and caches the nakama version.
New creates a new context.
NewConsoleWriter creates a zerolog console writer.
NewEnvVolume creates a new environment volume.
NewProxy creates a new http and websocket logging proxy.
NewRoundTripper creates a logging transport.
NewRunner creates a new nakama test runner.
NoopWriter creates a no op writer.
ParsePortMapping creates a port mapping from s.
PluginbuilderImageId returns the pluginbuilder image id.
PodmanBuildMounts creates mount specs for a container.
PodmanConn returns the podman connection on the context.
PodmanCreatePod creates a pod network.
PodmanFollowLogs follows the logs for a container.
PodmanGetAddr inspects id and returns the local and remote addresses.
PodmanOpen opens a podman context.
PodmanPodKill kills pod with matching name.
PodmanPullImages grabs image ids when not present on the host or when AlwaysPull returns true.
PodmanRun runs a container image id.
PodmanStopAndRemove stops and removes a container.
PodmanSystemConnectionList executes podman system connection list to retrieve the remote socket list.
PodmanWait waits until a container has stopped.
PodmanWaitService waits for a container service to be available.
PodRemoveTimeout returns the pod remove timeout.
PortMap returns the port map from the context.
PostgresImageId returns the postgres image id.
PostgresVersion returns the postgres version.
PrefixedWriter creates a new prefixed writer.
QualifiedId fully qualifies a container image id.
ReadCachedFile reads a cached file from disk, returns error if the file name on disk is past the ttl.
Run runs the global context runner.
RunProxy creates and runs a http proxy until the context is closed.
SetLevel sets the global log level.
ShortId truncates id to 16 characters.
Stdout returns the stdout from the context.
Trace returns a trace logger from the context.
Transport creates a transport from the context.
UnderCI returns whether or not to always pull an image.
VersionCacheTTL returns the version cache ttl.
WithAddr is a proxy option to set the listen address.
WithAlwaysPull sets the always pull flag on the context.
WithAlwaysPullFromEnv sets the always pull flag from an environment variable on the context.
WithBackoff sets the backoff min, max, timeout, and factor on the context.
WithBackoffConfig sets the backoff config on the context.
WithBuildConfig is a nakama test runner option to add a module path, and extra options to the build config.
WithBuildTimeout sets the pod remove timeout on the context.
WithCancel creates a new context for use within Test* funcs.
WithConfigFilename sets the config filename on the context.
WithConfigTemplate sets the config template on the context.
WithConsoleWriter sets the console writer out on the context.
WithDefaultGoEnv is a nakama module build config option to copy default host environment variables for Go.
WithGoVolumes is a nakama module build config option to mount the host's Go directories (GOCACHE, GOMODCACHE, and GOPATH) to the plugin builder container.
WithDialer is a proxy option to set the websocket dialer.
WithDir is a nakama test runner option to set the project root dir.
WithDockerAuthName sets the docker token auth name on the context.
WithDockerAuthScope sets a docker token auth scope mask on the context.
WithDockerRegistryURL sets the docker registry url on the context.
WithDockerTokenURL sets the docker token url on the context.
WithEnv is a nakama module build config option to set additional env variables used during builds.
WithGoBuildOptions is a nakama module build config option to add additional command-line options to Go build.
WithGoEnv is a nakama module build config option to copy the host Go environment variables.
WithGoVolumes is a nakama module build config option to mount the host's Go directories (ie, the Go environment's GOCACHE, GOMODCACHE, and GOPATH locations) to the plugin builder container.
WithHostPortMap adds host port mappings for the postgres and nakama services (5432/tcp, 7349/tcp, 7350/tcp, 7351/tcp) to the context.
WithHttpClient sets the http client used on the context.
WithMounts is a nakama module build config option to set additional mounts used during builds.
WithNakamaImageId sets the nakama image id on the context.
WithNakamaVersion sets the nakama image tag on the context.
WithOut is a nakama module build config option to set the out name.
WithPluginbuilderImageId sets the pluginbuilder image id on the context.
WithPodmanConn sets the podman conn used on the context.
WithPodRemoveTimeout sets the pod remove timeout on the context.
WithPortMap adds a host port mapping for a service to the context.
WithPostgresImageId sets the postgres image id on the context.
WithPostgresVersion sets the postgres image tag on the context.
WithRunEnv is a nakama test runner option to set run environment variables.
WithStdout sets the stdout on the context.
WithUnderCIFromEnv sets the under CI flag from an environment variable on the context.
WithUpgrader is a proxy option to set the websocket upgrader.
WithVersionCacheTTL sets the version cache TTL on the context.
WithVolumeDir is a nakama test runner option to set the volume dir, where nakama and postgres data/configs are written.
WithWsPath is a proxy option to set the websocket remote path.

# Variables

ContainerEmptyValue is the container empty value.
ContainerIdFieldName is the container field name used for logs.
Defaults.
Defaults.
Defaults.
Defaults.
go:embed config.yml.tpl.
Defaults.
Defaults.
Defaults.
Defaults.
Defaults.
Defaults.
Defaults.
Defaults.
Defaults.
Defaults.
Defaults.
DefaultProxyReadSize is the default websocket proxy read size.
DefaultProxyWriteSize is the default websocket proxy write size.
DefaultTranpsort is the default http transport.
Defaults.
Defaults.
NakamaBuilderContainerShortName is the nakama builder short name.
NakamaContainerShortName is the nakama short name.
NktestRunnerShortName is the nktest short name.
PostgresContainerShortName is the postgres short name.
TimeFormatValue is the time format.

# Structs

BackoffConfig holds the backoff configuration.
BuildConfig is a nakama module build config.
EnvVolumeInfo holds information about an environment variable derived volume.
PodmanConnInfo holds information about a podman connection.
Proxy is a http and websocket logging proxy.
RoundTripper is a logging transport.
Runner is a nakama test runner.

# Interfaces

TestLogger is the test log interface.
TestRunner is the test runner interface.

# Type aliases

BuildConfigOption is nakama module build config option.
Option is a nakama test runner option.
ProxyOption is a proxy option.