<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"sample/sampleworld"

	"v.io/v23"

	"v.io/x/ref/lib/flags/consts"
	"v.io/x/ref/lib/modules"
	"v.io/x/ref/lib/modules/core"
	"v.io/x/ref/lib/signals"
	"v.io/x/ref/lib/testutil/expect"
	"v.io/x/ref/profiles"
)

const (
	SampleWorldCommand = "sampleWorld"           // The modules library command.
	stdoutLog          = "tmp/runner.stdout.log" // Used as stdout drain when shutting down.
	stderrLog          = "tmp/runner.stderr.log" // Used as stderr drain when shutting down.
)

var (
	// Flags used as input to this program.
	runSample     bool
	serveHTTP     bool
	portHTTP      string
	rootHTTP      string
	runTests      bool
	runTestsWatch bool
)

func init() {
	modules.RegisterChild(SampleWorldCommand, "desc", sampleWorld)
	flag.BoolVar(&runSample, "runSample", false, "if true, runs sample services")
	flag.BoolVar(&serveHTTP, "serveHTTP", false, "if true, serves HTTP")
	flag.StringVar(&portHTTP, "portHTTP", "9001", "default 9001, the port to serve HTTP on")
	flag.StringVar(&rootHTTP, "rootHTTP", ".", "default '.', the root HTTP folder path")
	flag.BoolVar(&runTests, "runTests", false, "if true, runs the namespace browser tests")
	flag.BoolVar(&runTestsWatch, "runTestsWatch", false, "if true && runTests, runs the tests in watch mode")
}

// Helper function to simply panic on error.
func panicOnError(err error) {
	if err != nil {
		panic(err)
	}
}

// updateVars captures the vars from the given Handle's stdout and adds them to
// the given vars map, overwriting existing entries.
func updateVars(h modules.Handle, vars map[string]string, varNames ...string) error {
	varsToAdd := map[string]bool{}
	for _, v := range varNames {
		varsToAdd[v] = true
	}
	numLeft := len(varsToAdd)

	s := expect.NewSession(nil, h.Stdout(), 30*time.Second)
	for {
		l := s.ReadLine()
		if err := s.OriginalError(); err != nil {
			return err // EOF or otherwise
		}
		parts := strings.Split(l, "=")
		if len(parts) != 2 {
			return fmt.Errorf("Unexpected line: %s", l)
		}
		if _, ok := varsToAdd[parts[0]]; ok {
			numLeft--
			vars[parts[0]] = parts[1]
			if numLeft == 0 {
				break
			}
		}
	}
	return nil
}

// The module command for running the sample world.
func sampleWorld(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	ctx, shutdown := v23.Init()
	defer shutdown()

	sampleworld.RunSampleWorld(ctx)

	modules.WaitForEOF(stdin)
	return nil
}

func main() {
	if modules.IsModulesChildProcess() {
		panicOnError(modules.Dispatch())
		return
	}

	// Try running the program; on failure, exit with error status code.
	if !run() {
		os.Exit(1)
	}
}

// Runs the services and cleans up afterwards.
// Returns true if the run was successful.
func run() bool {
	ctx, shutdown := v23.Init()
	defer shutdown()

	// In order to prevent conflicts, tests and webapp use different mounttable ports.
	port := 5180
	cottagePort := 5181
	housePort := 5182
	if runTests {
		port = 8884
		cottagePort = 8885
		housePort = 8886
	}

	// Start a new shell module.
	vars := map[string]string{}
	sh, err := modules.NewShell(ctx, nil)
	if err != nil {
		panic(fmt.Sprintf("modules.NewShell: %s", err))
	}

	// Collect the output of this shell on termination.
	err = os.MkdirAll("tmp", 0750)
	panicOnError(err)
	outFile, err := os.Create(stdoutLog)
	panicOnError(err)
	defer outFile.Close()
	errFile, err := os.Create(stderrLog)
	panicOnError(err)
	defer errFile.Close()
	defer sh.Cleanup(outFile, errFile)

	// Determine the hostname; this name will be used for mounting.
	hostName, err := exec.Command("hostname", "-s").Output()
	panicOnError(err)

	// Run the host mounttable.
	rootName := fmt.Sprintf("%s-home", strings.TrimSpace(string(hostName))) // Must trim; hostname has \n at the end.
	hRoot, err := sh.Start(core.MTCommand, nil, "--veyron.tcp.protocol=ws", fmt.Sprintf("--veyron.tcp.address=127.0.0.1:%d", port), rootName)
	panicOnError(err)
	panicOnError(updateVars(hRoot, vars, "MT_NAME"))
	defer hRoot.Shutdown(outFile, errFile)

	// Set consts.NamespaceRootPrefix env var, consumed downstream.
	sh.SetVar(consts.NamespaceRootPrefix, vars["MT_NAME"])
	v23.GetNamespace(ctx).SetRoots(vars["MT_NAME"])

	// Run the cottage mounttable at host/cottage.
	hCottage, err := sh.Start(core.MTCommand, nil, "--veyron.tcp.protocol=ws", fmt.Sprintf("--veyron.tcp.address=127.0.0.1:%d", cottagePort), "cottage")
	panicOnError(err)
	expect.NewSession(nil, hCottage.Stdout(), 30*time.Second)
	defer hCottage.Shutdown(outFile, errFile)

	// run the house mounttable at host/house.
	hHouse, err := sh.Start(core.MTCommand, nil, "--veyron.tcp.protocol=ws", fmt.Sprintf("--veyron.tcp.address=127.0.0.1:%d", housePort), "house")
	panicOnError(err)
	expect.NewSession(nil, hHouse.Stdout(), 30*time.Second)
	defer hHouse.Shutdown(outFile, errFile)

	// Possibly run the sample world.
	if runSample {
		fmt.Println("Running Sample World")
		hSample, err := sh.Start(SampleWorldCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0")
		panicOnError(err)
		expect.NewSession(nil, hSample.Stdout(), 30*time.Second)
		defer hSample.Shutdown(outFile, errFile)
	}

	// Possibly serve the public bundle at the portHTTP.
	if serveHTTP {
		fmt.Printf("Also serving HTTP at %s for %s\n", portHTTP, rootHTTP)
		http.ListenAndServe(":"+portHTTP, http.FileServer(http.Dir(rootHTTP)))
	}

	// Just print out the collected variables. This is for debugging purposes.
	bytes, err := json.Marshal(vars)
	panicOnError(err)
	fmt.Println(string(bytes))

	// Possibly run the tests in Prova.
	if runTests {
		// Also set HOUSE_MOUNTTABLE (used in the tests)
		os.Setenv("HOUSE_MOUNTTABLE", fmt.Sprintf("/127.0.0.1:%d", housePort))

		proxyShutdown, proxyEndpoint, err := profiles.NewProxy(ctx, "ws", "127.0.0.1:0", "", "test/proxy")
		panicOnError(err)
		defer proxyShutdown()
		vars["PROXY_NAME"] = proxyEndpoint.Name()

		hIdentityd, err := sh.Start(core.TestIdentitydCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "--veyron.proxy=test/proxy", "--host=localhost", "--httpaddr=localhost:0")
		panicOnError(err)
		panicOnError(updateVars(hIdentityd, vars, "TEST_IDENTITYD_NAME", "TEST_IDENTITYD_HTTP_ADDR"))
		defer hIdentityd.Shutdown(outFile, errFile)

		// Setup a lot of environment variables; these are used for the tests and building the test extension.
		os.Setenv("NAMESPACE_ROOT", vars["MT_NAME"])
		os.Setenv("PROXY_ADDR", vars["PROXY_NAME"])
		os.Setenv("IDENTITYD", fmt.Sprintf("%s/google", vars["TEST_IDENTITYD_NAME"]))
		os.Setenv("IDENTITYD_BLESSING_URL", fmt.Sprintf("%s/blessing-root", vars["TEST_IDENTITYD_HTTP_ADDR"]))
		os.Setenv("DEBUG", "false")

		testsOk := runProva()

		fmt.Println("Cleaning up launched services...")
		return testsOk
	}

	// Not in a test, so run until the program is killed.
	<-signals.ShutdownOnSignals(ctx)
	return true

}

// Run the prova tests and convert its tap output to xunit.
func runProva() bool {
	// This is also useful information for routing the test output.
	VANADIUM_ROOT := os.Getenv("VANADIUM_ROOT")
	VANADIUM_JS := fmt.Sprintf("%s/release/javascript/core", VANADIUM_ROOT)
	VANADIUM_BROWSER := fmt.Sprintf("%s/release/projects/namespace_browser", VANADIUM_ROOT)

	TAP_XUNIT := fmt.Sprintf("%s/node_modules/.bin/tap-xunit", VANADIUM_BROWSER)
	XUNIT_OUTPUT_FILE := os.Getenv("XUNIT_OUTPUT_FILE")
	if XUNIT_OUTPUT_FILE == "" {
		XUNIT_OUTPUT_FILE = fmt.Sprintf("%s/test_output.xml", os.Getenv("TMPDIR"))
	}
	TAP_XUNIT_OPTIONS := " --package=namespace-browser"

	// Make sure we're in the right folder when we run make test-extension.
	vbroot, err := os.Open(VANADIUM_BROWSER)
	panicOnError(err)
	err = vbroot.Chdir()
	panicOnError(err)

	// Make the test-extension, this should also remove the old one.
	fmt.Println("Rebuilding test extension...")
	cmdExtensionClean := exec.Command("rm", "-fr", fmt.Sprintf("%s/extension/build-test", VANADIUM_JS))
	err = cmdExtensionClean.Run()
	panicOnError(err)
	cmdExtensionBuild := exec.Command("make", "-C", fmt.Sprintf("%s/extension", VANADIUM_JS), "build-test")
	err = cmdExtensionBuild.Run()
	panicOnError(err)

	// These are the basic prova options.
	options := []string{
		"test/**/*.js",
		"--browser",
		"--includeFilenameAsPackage",
		"--launch",
		"chrome",
		"--plugin",
		"proxyquireify/plugin",
		"--transform",
		"envify,./main-transform",
		"--log",
		"tmp/chrome.log",
		fmt.Sprintf("--options=--load-extension=%s/extension/build-test/,--ignore-certificate-errors,--enable-logging=stderr", VANADIUM_JS),
	}

	// Normal tests have a few more options and a different port from the watch tests.
	var PROVA_PORT int
	if !runTestsWatch {
		PROVA_PORT = 8893
		options = append(options, "--headless", "--quit", "--progress", "--tap")
		fmt.Printf("\033[34m-Executing tests. See %s for test xunit output.\033[0m\n", XUNIT_OUTPUT_FILE)
	} else {
		PROVA_PORT = 8894
		fmt.Println("\033[34m-Running tests in watch mode.\033[0m")
	}
	options = append(options, "--port", fmt.Sprintf("%d", PROVA_PORT))

	// This is the prova command.
	cmdProva := exec.Command(
		fmt.Sprintf("%s/node_modules/.bin/prova", VANADIUM_BROWSER),
		options...,
	)
	fmt.Printf("\033[34m-Go to \033[32mhttp://0.0.0.0:%d\033[34m to see tests running.\033[0m\n", PROVA_PORT)
	fmt.Println(cmdProva)

	// Collect the prova stdout. This information needs to be sent to xunit.
	provaOut, err := cmdProva.StdoutPipe()
	panicOnError(err)

	// Setup the tap to xunit command. It uses Prova's stdout as input.
	// The output will got the xunit output file.
	cmdTap := exec.Command(TAP_XUNIT, TAP_XUNIT_OPTIONS)
	cmdTap.Stdin = io.TeeReader(provaOut, os.Stdout) // Tee the prova output to see it on the console too.
	outfile, err := os.Create(XUNIT_OUTPUT_FILE)
	panicOnError(err)
	defer outfile.Close()
	bufferedWriter := bufio.NewWriter(outfile)
	cmdTap.Stdout = bufferedWriter
	defer bufferedWriter.Flush() // Ensure that the full xunit output is written.

	// We start the tap command...
	err = cmdTap.Start()
	panicOnError(err)

	// Meanwhile, run Prova to completion. If there was an error, print ERROR, otherwise PASS.
	err = cmdProva.Run()
	testsOk := true
	if err != nil {
		fmt.Println(err)
		fmt.Println("\033[31m\033[1mERROR\033[0m")
		testsOk = false
	} else {
		fmt.Println("\033[32m\033[1mPASS\033[0m")
	}

	// Wait for tap to xunit to finish itself off. This file will be ready for reading by Jenkins.
	fmt.Println("Converting Tap output to XUnit")
	err = cmdTap.Wait()
	panicOnError(err)

	return testsOk
}
<commit_msg>vnb: End runner.go when SIGHUP is received (terminal closed)<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"sample/sampleworld"

	"v.io/v23"

	"v.io/x/ref/lib/flags/consts"
	"v.io/x/ref/lib/modules"
	"v.io/x/ref/lib/modules/core"
	"v.io/x/ref/lib/signals"
	"v.io/x/ref/lib/testutil/expect"
	"v.io/x/ref/profiles"
)

const (
	SampleWorldCommand = "sampleWorld"           // The modules library command.
	stdoutLog          = "tmp/runner.stdout.log" // Used as stdout drain when shutting down.
	stderrLog          = "tmp/runner.stderr.log" // Used as stderr drain when shutting down.
)

var (
	// Flags used as input to this program.
	runSample     bool
	serveHTTP     bool
	portHTTP      string
	rootHTTP      string
	runTests      bool
	runTestsWatch bool
)

func init() {
	modules.RegisterChild(SampleWorldCommand, "desc", sampleWorld)
	flag.BoolVar(&runSample, "runSample", false, "if true, runs sample services")
	flag.BoolVar(&serveHTTP, "serveHTTP", false, "if true, serves HTTP")
	flag.StringVar(&portHTTP, "portHTTP", "9001", "default 9001, the port to serve HTTP on")
	flag.StringVar(&rootHTTP, "rootHTTP", ".", "default '.', the root HTTP folder path")
	flag.BoolVar(&runTests, "runTests", false, "if true, runs the namespace browser tests")
	flag.BoolVar(&runTestsWatch, "runTestsWatch", false, "if true && runTests, runs the tests in watch mode")
}

// Helper function to simply panic on error.
func panicOnError(err error) {
	if err != nil {
		panic(err)
	}
}

// updateVars captures the vars from the given Handle's stdout and adds them to
// the given vars map, overwriting existing entries.
func updateVars(h modules.Handle, vars map[string]string, varNames ...string) error {
	varsToAdd := map[string]bool{}
	for _, v := range varNames {
		varsToAdd[v] = true
	}
	numLeft := len(varsToAdd)

	s := expect.NewSession(nil, h.Stdout(), 30*time.Second)
	for {
		l := s.ReadLine()
		if err := s.OriginalError(); err != nil {
			return err // EOF or otherwise
		}
		parts := strings.Split(l, "=")
		if len(parts) != 2 {
			return fmt.Errorf("Unexpected line: %s", l)
		}
		if _, ok := varsToAdd[parts[0]]; ok {
			numLeft--
			vars[parts[0]] = parts[1]
			if numLeft == 0 {
				break
			}
		}
	}
	return nil
}

// The module command for running the sample world.
func sampleWorld(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	ctx, shutdown := v23.Init()
	defer shutdown()

	sampleworld.RunSampleWorld(ctx)

	modules.WaitForEOF(stdin)
	return nil
}

func main() {
	if modules.IsModulesChildProcess() {
		panicOnError(modules.Dispatch())
		return
	}

	// If we ever get a SIGHUP (terminal closes), then end the program.
	signalChannel := make(chan os.Signal)
	signal.Notify(signalChannel, syscall.SIGHUP)
	go func() {
		sig := <-signalChannel
		switch sig {
		case syscall.SIGHUP:
			os.Exit(1)
		}
	}()

	// Try running the program; on failure, exit with error status code.
	if !run() {
		os.Exit(1)
	}
}

// Runs the services and cleans up afterwards.
// Returns true if the run was successful.
func run() bool {
	ctx, shutdown := v23.Init()
	defer shutdown()

	// In order to prevent conflicts, tests and webapp use different mounttable ports.
	port := 5180
	cottagePort := 5181
	housePort := 5182
	if runTests {
		port = 8884
		cottagePort = 8885
		housePort = 8886
	}

	// Start a new shell module.
	vars := map[string]string{}
	sh, err := modules.NewShell(ctx, nil)
	if err != nil {
		panic(fmt.Sprintf("modules.NewShell: %s", err))
	}

	// Collect the output of this shell on termination.
	err = os.MkdirAll("tmp", 0750)
	panicOnError(err)
	outFile, err := os.Create(stdoutLog)
	panicOnError(err)
	defer outFile.Close()
	errFile, err := os.Create(stderrLog)
	panicOnError(err)
	defer errFile.Close()
	defer sh.Cleanup(outFile, errFile)

	// Determine the hostname; this name will be used for mounting.
	hostName, err := exec.Command("hostname", "-s").Output()
	panicOnError(err)

	// Run the host mounttable.
	rootName := fmt.Sprintf("%s-home", strings.TrimSpace(string(hostName))) // Must trim; hostname has \n at the end.
	hRoot, err := sh.Start(core.MTCommand, nil, "--veyron.tcp.protocol=ws", fmt.Sprintf("--veyron.tcp.address=127.0.0.1:%d", port), rootName)
	panicOnError(err)
	panicOnError(updateVars(hRoot, vars, "MT_NAME"))
	defer hRoot.Shutdown(outFile, errFile)

	// Set consts.NamespaceRootPrefix env var, consumed downstream.
	sh.SetVar(consts.NamespaceRootPrefix, vars["MT_NAME"])
	v23.GetNamespace(ctx).SetRoots(vars["MT_NAME"])

	// Run the cottage mounttable at host/cottage.
	hCottage, err := sh.Start(core.MTCommand, nil, "--veyron.tcp.protocol=ws", fmt.Sprintf("--veyron.tcp.address=127.0.0.1:%d", cottagePort), "cottage")
	panicOnError(err)
	expect.NewSession(nil, hCottage.Stdout(), 30*time.Second)
	defer hCottage.Shutdown(outFile, errFile)

	// run the house mounttable at host/house.
	hHouse, err := sh.Start(core.MTCommand, nil, "--veyron.tcp.protocol=ws", fmt.Sprintf("--veyron.tcp.address=127.0.0.1:%d", housePort), "house")
	panicOnError(err)
	expect.NewSession(nil, hHouse.Stdout(), 30*time.Second)
	defer hHouse.Shutdown(outFile, errFile)

	// Possibly run the sample world.
	if runSample {
		fmt.Println("Running Sample World")
		hSample, err := sh.Start(SampleWorldCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0")
		panicOnError(err)
		expect.NewSession(nil, hSample.Stdout(), 30*time.Second)
		defer hSample.Shutdown(outFile, errFile)
	}

	// Possibly serve the public bundle at the portHTTP.
	if serveHTTP {
		fmt.Printf("Also serving HTTP at %s for %s\n", portHTTP, rootHTTP)
		http.ListenAndServe(":"+portHTTP, http.FileServer(http.Dir(rootHTTP)))
	}

	// Just print out the collected variables. This is for debugging purposes.
	bytes, err := json.Marshal(vars)
	panicOnError(err)
	fmt.Println(string(bytes))

	// Possibly run the tests in Prova.
	if runTests {
		// Also set HOUSE_MOUNTTABLE (used in the tests)
		os.Setenv("HOUSE_MOUNTTABLE", fmt.Sprintf("/127.0.0.1:%d", housePort))

		proxyShutdown, proxyEndpoint, err := profiles.NewProxy(ctx, "ws", "127.0.0.1:0", "", "test/proxy")
		panicOnError(err)
		defer proxyShutdown()
		vars["PROXY_NAME"] = proxyEndpoint.Name()

		hIdentityd, err := sh.Start(core.TestIdentitydCommand, nil, "--veyron.tcp.protocol=ws", "--veyron.tcp.address=127.0.0.1:0", "--veyron.proxy=test/proxy", "--host=localhost", "--httpaddr=localhost:0")
		panicOnError(err)
		panicOnError(updateVars(hIdentityd, vars, "TEST_IDENTITYD_NAME", "TEST_IDENTITYD_HTTP_ADDR"))
		defer hIdentityd.Shutdown(outFile, errFile)

		// Setup a lot of environment variables; these are used for the tests and building the test extension.
		os.Setenv("NAMESPACE_ROOT", vars["MT_NAME"])
		os.Setenv("PROXY_ADDR", vars["PROXY_NAME"])
		os.Setenv("IDENTITYD", fmt.Sprintf("%s/google", vars["TEST_IDENTITYD_NAME"]))
		os.Setenv("IDENTITYD_BLESSING_URL", fmt.Sprintf("%s/blessing-root", vars["TEST_IDENTITYD_HTTP_ADDR"]))
		os.Setenv("DEBUG", "false")

		testsOk := runProva()

		fmt.Println("Cleaning up launched services...")
		return testsOk
	}

	// Not in a test, so run until the program is killed.
	<-signals.ShutdownOnSignals(ctx)
	return true
}

// Run the prova tests and convert its tap output to xunit.
func runProva() bool {
	// This is also useful information for routing the test output.
	VANADIUM_ROOT := os.Getenv("VANADIUM_ROOT")
	VANADIUM_JS := fmt.Sprintf("%s/release/javascript/core", VANADIUM_ROOT)
	VANADIUM_BROWSER := fmt.Sprintf("%s/release/projects/namespace_browser", VANADIUM_ROOT)

	TAP_XUNIT := fmt.Sprintf("%s/node_modules/.bin/tap-xunit", VANADIUM_BROWSER)
	XUNIT_OUTPUT_FILE := os.Getenv("XUNIT_OUTPUT_FILE")
	if XUNIT_OUTPUT_FILE == "" {
		XUNIT_OUTPUT_FILE = fmt.Sprintf("%s/test_output.xml", os.Getenv("TMPDIR"))
	}
	TAP_XUNIT_OPTIONS := " --package=namespace-browser"

	// Make sure we're in the right folder when we run make test-extension.
	vbroot, err := os.Open(VANADIUM_BROWSER)
	panicOnError(err)
	err = vbroot.Chdir()
	panicOnError(err)

	// Make the test-extension, this should also remove the old one.
	fmt.Println("Rebuilding test extension...")
	cmdExtensionClean := exec.Command("rm", "-fr", fmt.Sprintf("%s/extension/build-test", VANADIUM_JS))
	err = cmdExtensionClean.Run()
	panicOnError(err)
	cmdExtensionBuild := exec.Command("make", "-C", fmt.Sprintf("%s/extension", VANADIUM_JS), "build-test")
	err = cmdExtensionBuild.Run()
	panicOnError(err)

	// These are the basic prova options.
	options := []string{
		"test/**/*.js",
		"--browser",
		"--includeFilenameAsPackage",
		"--launch",
		"chrome",
		"--plugin",
		"proxyquireify/plugin",
		"--transform",
		"envify,./main-transform",
		"--log",
		"tmp/chrome.log",
		fmt.Sprintf("--options=--load-extension=%s/extension/build-test/,--ignore-certificate-errors,--enable-logging=stderr", VANADIUM_JS),
	}

	// Normal tests have a few more options and a different port from the watch tests.
	var PROVA_PORT int
	if !runTestsWatch {
		PROVA_PORT = 8893
		options = append(options, "--headless", "--quit", "--progress", "--tap")
		fmt.Printf("\033[34m-Executing tests. See %s for test xunit output.\033[0m\n", XUNIT_OUTPUT_FILE)
	} else {
		PROVA_PORT = 8894
		fmt.Println("\033[34m-Running tests in watch mode.\033[0m")
	}
	options = append(options, "--port", fmt.Sprintf("%d", PROVA_PORT))

	// This is the prova command.
	cmdProva := exec.Command(
		fmt.Sprintf("%s/node_modules/.bin/prova", VANADIUM_BROWSER),
		options...,
	)
	fmt.Printf("\033[34m-Go to \033[32mhttp://0.0.0.0:%d\033[34m to see tests running.\033[0m\n", PROVA_PORT)
	fmt.Println(cmdProva)

	// Collect the prova stdout. This information needs to be sent to xunit.
	provaOut, err := cmdProva.StdoutPipe()
	panicOnError(err)

	// Setup the tap to xunit command. It uses Prova's stdout as input.
	// The output will got the xunit output file.
	cmdTap := exec.Command(TAP_XUNIT, TAP_XUNIT_OPTIONS)
	cmdTap.Stdin = io.TeeReader(provaOut, os.Stdout) // Tee the prova output to see it on the console too.
	outfile, err := os.Create(XUNIT_OUTPUT_FILE)
	panicOnError(err)
	defer outfile.Close()
	bufferedWriter := bufio.NewWriter(outfile)
	cmdTap.Stdout = bufferedWriter
	defer bufferedWriter.Flush() // Ensure that the full xunit output is written.

	// We start the tap command...
	err = cmdTap.Start()
	panicOnError(err)

	// Meanwhile, run Prova to completion. If there was an error, print ERROR, otherwise PASS.
	err = cmdProva.Run()
	testsOk := true
	if err != nil {
		fmt.Println(err)
		fmt.Println("\033[31m\033[1mERROR\033[0m")
		testsOk = false
	} else {
		fmt.Println("\033[32m\033[1mPASS\033[0m")
	}

	// Wait for tap to xunit to finish itself off. This file will be ready for reading by Jenkins.
	fmt.Println("Converting Tap output to XUnit")
	err = cmdTap.Wait()
	panicOnError(err)

	return testsOk
}
<|endoftext|>


<commit_before>package statemachine

type State int

const (
	IDLE State = iota    // beginning of the game (expected input: admin starts game)
	NEW_GAME             // admin started game (expected input: player1 name)
	PLAYER1              // player1 (expected input: player2 name)
	PLAYER2              // player2 (expected input: player3 name)
	START_GAME					 // all names know, broadcast board
	PICK_PLAYER          // server picks player (expected input: question picked by player)
	QUESTION_PICKED      // question is picked, display, start timer (expected input: buzzer 1,2 or 3)
	ANSWER_QUESTION      // first buzzer pressed ansers, start timer (expected input: correct, incorrect, timer_expired)
	CORRECT              // adjust player score -> CHK_GAME_OVER
	WRONG                // addjust player score -> QUESTION_PICKED / CHK_GAME_OVER
	LAST_PLAYER          // have all players (unsuccessfully) tried to anser
	CHK_GAME_OVER        // check if any questions are left on the board -> pick player / GAME_OVER
	GAME_OVER
)

const (
	// events can come from buzzer (high byte 00) or admin (high byte FF)
	START_GAME = 0xFF00
)
type Event struct {
	Id int
	Data string
}

type Player struct {
	Name String
	Score int
}

type Game struct {
	GameState State
	Player1 Player
	Player2 Player
	Player3 Player
	// Buzzer 1
	// Buzzer 2
	// Buzzer 3
	// UI
}

func (g * Game) SwitchState (e Event) {
	switch (g.GameState) {
		case IDLE:
			if e.Id ==  START_GAME {
				g.GameState = NEW_GAME
			}

		case NEW_GAME:
			// alert buzzer
			// alert ui

		case PLAYER1:
		case PLAYER2:
		case START_GAME:
		case PICK_PLAYER:
		case QUESTION_PICKED:
		case ANSWER_QUESTION:
		case CORRECT:
		case WRONG:
		case LAST_PLAYER:
		case CHK_GAME_OVER:
		case GAME_OVER:
	}
}
<commit_msg>statemachine complete<commit_after>package statemachine

type StateId int

const (
	IDLE StateId = iota    // beginning of the game (expected input: admin starts game)
	NEW_GAME             // admin started game (expected input: player1 name)
	PLAYER              // player1 (expected input: player2 name)
//	PLAYER2              // player2 (expected input: player3 name)
	START_GAME					 // all names know, broadcast board
	PICK_PLAYER          // server picks player (expected input: question picked by player)
	QUESTION_PICKED      // question is picked, display, start timer (expected input: buzzer 1,2 or 3)
	ANSWER_QUESTION      // first buzzer pressed ansers, start timer (expected input: correct, incorrect, timer_expired)
	ADJUST_SCORE
	CORRECT              // adjust player score -> CHK_GAME_OVER
	WRONG                // addjust player score -> QUESTION_PICKED / CHK_GAME_OVER
	LAST_PLAYER          // have all players (unsuccessfully) tried to anser
	CHK_GAME_OVER        // check if any questions are left on the board -> pick player / GAME_OVER
	GAME_OVER
	DETERMINE_WINNER
)

const (
	// events can come from buzzer (high byte 00) or admin (high byte FF)
	E_START_GAME = 0xFF00
	E_PLAYER_ONE = 0xFF01
	E_PLAYER_TWO = 0xFF02
	E_PLAYER_THREE = 0xFF03
	E_QUESTION_CHOSEN = 0xFF04
	E_CORRECT = 0xFF05
	E_INCORRECT = 0xFF06

	E_BUZZER_ONE = 0x0000
	E_BUZZER_TWO = 0x0001
	E_BUZZER_THREE = 0x0002

	E_TIMEOUT_NO_ANSWER = 0xF000

)
type Event struct {
	Id int
	Data string
}

type State interface {
	Id() StateId
	Game() *Game
	EnterState(Event)
	HandleEvent(Event) State

}
type Player struct {
	Name string
	Score int
}

type Question struct {
	Answer string
	Question string
	Value int
}

type Game struct {
	GameState State
	Player1 *Player
	Player2 *Player
	Player3 *Player
	CurrentPlayer *Player
	CurrentQuestion * Question
	CurrentAttempts string  // keeps track of who has tried to answer the current Question
	QuestionsRemaining int
	// Buzzer 1
	// Buzzer 2
	// Buzzer 3
	// UI
}

func (g * Game) HandleEvent (e Event) {
	g.GameState = g.GameState.HandleEvent(e)
	g.GameState.EnterState(e)
}

type baseState struct {
	game *Game
}

func (s * baseState) Game()*Game {
	return s.game
}

type S_Idle struct {
	baseState
}

func (s * S_Idle) Id()StateId {return IDLE}
func (s * S_Idle) EnterState(e Event) {return}
func (s * S_Idle) HandleEvent(e Event)State {
	if (e.Id == E_START_GAME) {
		var snew S_NewGame
		snew.game = s.game
		return &snew
	}
	return s;
}

type S_NewGame struct {
	baseState
}
func (s * S_NewGame) Id()StateId {return NEW_GAME}
func (s * S_NewGame) EnterState(e Event) {
	// send board to server
	// send (something) to buzzer
}
func (s * S_NewGame) HandleEvent(e Event)State {
	if (e.Id == E_PLAYER_ONE) {
		// s.sendBoard(e.Data)
		snew := S_Player{}
		snew.game = s.game
		return &snew
	} else {
		return s
	}
}

type S_Player struct {
	baseState
}
func (s * S_Player) Id()StateId {return PLAYER}
func (s * S_Player) EnterState(e Event) {
	switch (e.Id) {
		case E_PLAYER_ONE:
			s.game.Player1 = &Player{e.Data, 0}
		case E_PLAYER_TWO:
			s.game.Player2 = &Player{e.Data, 0}
		case E_PLAYER_THREE:
			s.game.Player3 = &Player{e.Data, 0}

	}
}
func (s * S_Player) HandleEvent(e Event)(state State) {
	switch (e.Id) {
		case E_PLAYER_TWO:
			snew := S_Player{}
			snew.game = s.game
			return &snew
		case E_PLAYER_THREE:
			// new game will start. broadcast board.
			snew := S_StartGame{}
			snew.game = s.game
			return  &snew
		default:
			return s
	}
}

type S_StartGame struct {
	baseState
}

func (s * S_StartGame) Id()StateId{return START_GAME}
func (s * S_StartGame) EnterState(e Event) {
	// set up board. broadcast
	s.game.HandleEvent(e) // advance to next state automatically.
}
func (s * S_StartGame) HandleEvent(e Event)State{
	new_state := new(S_PickPlayer)
	new_state.game = s.game
	return new_state
}

type S_PickPlayer struct {
	baseState
}
func (s * S_PickPlayer) Id()StateId{return PICK_PLAYER}
func (s * S_PickPlayer) EnterState(e Event) {
	// reset some state
	s.game.CurrentAttempts = ""
	// pick player and broadcast
}
func (s * S_PickPlayer) HandleEvent(e Event)State {
	if (e.Id == E_QUESTION_CHOSEN) {
		// tell ui question
		// display question to admin
		nstate := new(S_QuestionChosen)
		nstate.game = s.game
		return nstate
	}
	return s
}

type S_QuestionChosen struct {
	baseState
}

func(s * S_QuestionChosen) Id() StateId {return QUESTION_PICKED}
func(s * S_QuestionChosen) EnterState(e Event) {
		// start_timer
}
func(s * S_QuestionChosen) HandleEvent(e Event) State {
	nstate := new(S_AnswerExpected)
	nstate.game = s.game
	switch (e.Id) {
		case E_BUZZER_ONE:
			return nstate
		case E_BUZZER_TWO:
			return nstate
		case E_BUZZER_THREE:
			return nstate
		case E_TIMEOUT_NO_ANSWER:
			nstate2 := new(S_CheckGameOver)
			nstate2.game = s.game
			return nstate2
		default:
			return s
	}
}

type S_AnswerExpected struct {
	baseState
}

func(s * S_AnswerExpected) Id() StateId {return ANSWER_QUESTION}
func(s * S_AnswerExpected) EnterState(e Event) {
		// start_timer
}
func(s * S_AnswerExpected) HandleEvent(e Event) State {
	var nstate State
	switch (e.Id) {
		case E_CORRECT:
			nstate := new(S_Adjust_Score)
			nstate.game = s.Game()
		case E_INCORRECT:
			nstate := new(S_Adjust_Score)
			nstate.game = s.Game()
		case E_TIMEOUT_NO_ANSWER:
			nstate := new(S_CheckGameOver)
			nstate.game = s.Game()
		default:
			return s
	}
	return nstate
}

type S_Adjust_Score struct {
	baseState
}

func(s * S_Adjust_Score) Id() StateId {return ADJUST_SCORE}
func(s * S_Adjust_Score) EnterState(e Event) {
		switch (e.Id) {
		case E_CORRECT:
			s.game.CurrentPlayer.Score += s.game.CurrentQuestion.Value
		case E_INCORRECT:
			s.game.CurrentPlayer.Score -= s.game.CurrentQuestion.Value
		}
		s.game.HandleEvent(e)

}
func(s * S_Adjust_Score) HandleEvent(e Event) State {
	switch (e.Id) {
		case E_CORRECT:
			nstate := new(S_CheckGameOver)
			nstate.game = s.game
			return nstate
		case E_INCORRECT:
			nstate := new(S_CheckLastPlayer)
			nstate.game = s.game
			if (nstate.game.CurrentPlayer == nstate.game.Player1) {
				nstate.game.CurrentAttempts += "1"
			}else if (nstate.game.CurrentPlayer == nstate.game.Player2) {
				nstate.game.CurrentAttempts += "2"
			} else {
				nstate.game.CurrentAttempts += "3"
			}
			return nstate
		default:
			return s
	}
}

type S_CheckGameOver struct {
	baseState
}

func(s * S_CheckGameOver) Id() StateId {return CHK_GAME_OVER }
func(s * S_CheckGameOver) EnterState(e Event) {
	s.HandleEvent(e)
}
func(s * S_CheckGameOver) HandleEvent(e Event) State {
	if (s.game.QuestionsRemaining == 0) { // TODO!!
		nstate := new(S_DetermineWinner)
		nstate.game = s.game
		return nstate
	} else {
		nstate := new(S_PickPlayer)
		nstate.game = s.game
		return nstate
	}
}

type S_CheckLastPlayer struct {
	baseState
}

func(s * S_CheckLastPlayer) Id() StateId {return LAST_PLAYER }
func(s * S_CheckLastPlayer) EnterState(e Event) {
	s.game.HandleEvent(e)
}
func(s * S_CheckLastPlayer) HandleEvent(e Event) State {
	if (len(s.game.CurrentAttempts) == 3) {
		nstate := new(S_CheckGameOver)
		nstate.game = s.game
		return nstate
	}
	nstate := new(S_QuestionChosen)
	nstate.game = s.game
	return nstate
}

type S_DetermineWinner struct {
	baseState
}

func(s * S_DetermineWinner) Id() StateId {return LAST_PLAYER }
func(s * S_DetermineWinner) EnterState(e Event) {
	// broadcast winner.
}
func(s * S_DetermineWinner) HandleEvent(e Event) State {
	return s
}

<|endoftext|>


<commit_before>package gocbcore

const (
	GoCbVersionStr = "v1.1.1"
)

type CommandMagic uint8

const (
	ReqMagic = CommandMagic(0x80)
	ResMagic = CommandMagic(0x81)
)

// CommandCode for memcached packets.
type CommandCode uint8

const (
	CmdGet                  = CommandCode(0x00)
	CmdSet                  = CommandCode(0x01)
	CmdAdd                  = CommandCode(0x02)
	CmdReplace              = CommandCode(0x03)
	CmdDelete               = CommandCode(0x04)
	CmdIncrement            = CommandCode(0x05)
	CmdDecrement            = CommandCode(0x06)
	CmdAppend               = CommandCode(0x0e)
	CmdPrepend              = CommandCode(0x0f)
	CmdStat                 = CommandCode(0x10)
	CmdTouch                = CommandCode(0x1c)
	CmdGAT                  = CommandCode(0x1d)
	CmdHello                = CommandCode(0x1f)
	CmdSASLListMechs        = CommandCode(0x20)
	CmdSASLAuth             = CommandCode(0x21)
	CmdSASLStep             = CommandCode(0x22)
	CmdGetAllVBSeqnos       = CommandCode(0x48)
	CmdDcpOpenConnection    = CommandCode(0x50)
	CmdDcpAddStream         = CommandCode(0x51)
	CmdDcpCloseStream       = CommandCode(0x52)
	CmdDcpStreamReq         = CommandCode(0x53)
	CmdDcpGetFailoverLog    = CommandCode(0x54)
	CmdDcpStreamEnd         = CommandCode(0x55)
	CmdDcpSnapshotMarker    = CommandCode(0x56)
	CmdDcpMutation          = CommandCode(0x57)
	CmdDcpDeletion          = CommandCode(0x58)
	CmdDcpExpiration        = CommandCode(0x59)
	CmdDcpFlush             = CommandCode(0x5a)
	CmdDcpSetVbucketState   = CommandCode(0x5b)
	CmdDcpNoop              = CommandCode(0x5c)
	CmdDcpBufferAck         = CommandCode(0x5d)
	CmdDcpControl           = CommandCode(0x5e)
	CmdGetReplica           = CommandCode(0x83)
	CmdSelectBucket         = CommandCode(0x89)
	CmdObserveSeqNo         = CommandCode(0x91)
	CmdObserve              = CommandCode(0x92)
	CmdGetLocked            = CommandCode(0x94)
	CmdUnlockKey            = CommandCode(0x95)
	CmdSetMeta              = CommandCode(0xa2)
	CmdDetMeta              = CommandCode(0xa8)
	CmdGetClusterConfig     = CommandCode(0xb5)
	CmdGetRandom            = CommandCode(0xb6)
	CmdSubDocGet            = CommandCode(0xc5)
	CmdSubDocExists         = CommandCode(0xc6)
	CmdSubDocDictAdd        = CommandCode(0xc7)
	CmdSubDocDictSet        = CommandCode(0xc8)
	CmdSubDocDelete         = CommandCode(0xc9)
	CmdSubDocReplace        = CommandCode(0xca)
	CmdSubDocArrayPushLast  = CommandCode(0xcb)
	CmdSubDocArrayPushFirst = CommandCode(0xcc)
	CmdSubDocArrayInsert    = CommandCode(0xcd)
	CmdSubDocArrayAddUnique = CommandCode(0xce)
	CmdSubDocCounter        = CommandCode(0xcf)
	CmdSubDocMultiLookup    = CommandCode(0xd0)
	CmdSubDocMultiMutation  = CommandCode(0xd1)
)

type SubDocFlag uint16

const (
	SubDocFlagMkDirP = SubDocFlag(0x01)
)

type SubDocOpType uint8

const (
	SubDocOpGet            = SubDocOpType(CmdSubDocGet)
	SubDocOpExists         = SubDocOpType(CmdSubDocExists)
	SubDocOpDictAdd        = SubDocOpType(CmdSubDocDictAdd)
	SubDocOpDictSet        = SubDocOpType(CmdSubDocDictSet)
	SubDocOpDelete         = SubDocOpType(CmdSubDocDelete)
	SubDocOpReplace        = SubDocOpType(CmdSubDocReplace)
	SubDocOpArrayPushLast  = SubDocOpType(CmdSubDocArrayPushLast)
	SubDocOpArrayPushFirst = SubDocOpType(CmdSubDocArrayPushFirst)
	SubDocOpArrayInsert    = SubDocOpType(CmdSubDocArrayInsert)
	SubDocOpArrayAddUnique = SubDocOpType(CmdSubDocArrayAddUnique)
	SubDocOpCounter        = SubDocOpType(CmdSubDocCounter)
)

type HelloFeature uint16

const (
	FeatureDatatype = HelloFeature(0x01)
	FeatureSeqNo    = HelloFeature(0x04)
)

// Status field for memcached response.
type StatusCode uint16

const (
	StatusSuccess            = StatusCode(0x00)
	StatusKeyNotFound        = StatusCode(0x01)
	StatusKeyExists          = StatusCode(0x02)
	StatusTooBig             = StatusCode(0x03)
	StatusInvalidArgs        = StatusCode(0x04)
	StatusNotStored          = StatusCode(0x05)
	StatusBadDelta           = StatusCode(0x06)
	StatusNotMyVBucket       = StatusCode(0x07)
	StatusNoBucket           = StatusCode(0x08)
	StatusAuthStale          = StatusCode(0x1f)
	StatusAuthError          = StatusCode(0x20)
	StatusAuthContinue       = StatusCode(0x21)
	StatusRangeError         = StatusCode(0x22)
	StatusRollback           = StatusCode(0x23)
	StatusAccessError        = StatusCode(0x24)
	StatusNotInitialized     = StatusCode(0x25)
	StatusUnknownCommand     = StatusCode(0x81)
	StatusOutOfMemory        = StatusCode(0x82)
	StatusNotSupported       = StatusCode(0x83)
	StatusInternalError      = StatusCode(0x84)
	StatusBusy               = StatusCode(0x85)
	StatusTmpFail            = StatusCode(0x86)
	StatusSubDocPathNotFound = StatusCode(0xc0)
	StatusSubDocPathMismatch = StatusCode(0xc1)
	StatusSubDocPathInvalid  = StatusCode(0xc2)
	StatusSubDocPathTooBig   = StatusCode(0xc3)
	StatusSubDocDocTooDeep   = StatusCode(0xc4)
	StatusSubDocCantInsert   = StatusCode(0xc5)
	StatusSubDocNotJson      = StatusCode(0xc6)
	StatusSubDocBadRange     = StatusCode(0xc7)
	StatusSubDocBadDelta     = StatusCode(0xc8)
	StatusSubDocPathExists   = StatusCode(0xc9)
	StatusSubDocValueTooDeep = StatusCode(0xca)
	StatusSubDocBadCombo     = StatusCode(0xcb)
	StatusSubDocBadMulti     = StatusCode(0xcc)
)

type KeyState uint8

const (
	KeyStateNotPersisted = KeyState(0x00)
	KeyStatePersisted    = KeyState(0x01)
	KeyStateNotFound     = KeyState(0x80)
	KeyStateDeleted      = KeyState(0x81)
)

type StreamEndStatus uint32

const (
	StreamEndOK           = StreamEndStatus(0x00)
	StreamEndClosed       = StreamEndStatus(0x01)
	StreamEndStateChanged = StreamEndStatus(0x02)
	StreamEndDisconnected = StreamEndStatus(0x03)
	StreamEndTooSlow      = StreamEndStatus(0x04)
)

type BucketType int

const (
	BktTypeInvalid   BucketType = 0
	BktTypeCouchbase            = iota
	BktTypeMemcached            = iota
)

type VBucketState uint32

const (
	VBucketStateActive  = VBucketState(0x01)
	VBucketStateReplica = VBucketState(0x02)
	VBucketStatePending = VBucketState(0x03)
	VBucketStateDead    = VBucketState(0x04)
)
<commit_msg>Release v1.1.2<commit_after>package gocbcore

const (
	GoCbVersionStr = "v1.1.2"
)

type CommandMagic uint8

const (
	ReqMagic = CommandMagic(0x80)
	ResMagic = CommandMagic(0x81)
)

// CommandCode for memcached packets.
type CommandCode uint8

const (
	CmdGet                  = CommandCode(0x00)
	CmdSet                  = CommandCode(0x01)
	CmdAdd                  = CommandCode(0x02)
	CmdReplace              = CommandCode(0x03)
	CmdDelete               = CommandCode(0x04)
	CmdIncrement            = CommandCode(0x05)
	CmdDecrement            = CommandCode(0x06)
	CmdAppend               = CommandCode(0x0e)
	CmdPrepend              = CommandCode(0x0f)
	CmdStat                 = CommandCode(0x10)
	CmdTouch                = CommandCode(0x1c)
	CmdGAT                  = CommandCode(0x1d)
	CmdHello                = CommandCode(0x1f)
	CmdSASLListMechs        = CommandCode(0x20)
	CmdSASLAuth             = CommandCode(0x21)
	CmdSASLStep             = CommandCode(0x22)
	CmdGetAllVBSeqnos       = CommandCode(0x48)
	CmdDcpOpenConnection    = CommandCode(0x50)
	CmdDcpAddStream         = CommandCode(0x51)
	CmdDcpCloseStream       = CommandCode(0x52)
	CmdDcpStreamReq         = CommandCode(0x53)
	CmdDcpGetFailoverLog    = CommandCode(0x54)
	CmdDcpStreamEnd         = CommandCode(0x55)
	CmdDcpSnapshotMarker    = CommandCode(0x56)
	CmdDcpMutation          = CommandCode(0x57)
	CmdDcpDeletion          = CommandCode(0x58)
	CmdDcpExpiration        = CommandCode(0x59)
	CmdDcpFlush             = CommandCode(0x5a)
	CmdDcpSetVbucketState   = CommandCode(0x5b)
	CmdDcpNoop              = CommandCode(0x5c)
	CmdDcpBufferAck         = CommandCode(0x5d)
	CmdDcpControl           = CommandCode(0x5e)
	CmdGetReplica           = CommandCode(0x83)
	CmdSelectBucket         = CommandCode(0x89)
	CmdObserveSeqNo         = CommandCode(0x91)
	CmdObserve              = CommandCode(0x92)
	CmdGetLocked            = CommandCode(0x94)
	CmdUnlockKey            = CommandCode(0x95)
	CmdSetMeta              = CommandCode(0xa2)
	CmdDetMeta              = CommandCode(0xa8)
	CmdGetClusterConfig     = CommandCode(0xb5)
	CmdGetRandom            = CommandCode(0xb6)
	CmdSubDocGet            = CommandCode(0xc5)
	CmdSubDocExists         = CommandCode(0xc6)
	CmdSubDocDictAdd        = CommandCode(0xc7)
	CmdSubDocDictSet        = CommandCode(0xc8)
	CmdSubDocDelete         = CommandCode(0xc9)
	CmdSubDocReplace        = CommandCode(0xca)
	CmdSubDocArrayPushLast  = CommandCode(0xcb)
	CmdSubDocArrayPushFirst = CommandCode(0xcc)
	CmdSubDocArrayInsert    = CommandCode(0xcd)
	CmdSubDocArrayAddUnique = CommandCode(0xce)
	CmdSubDocCounter        = CommandCode(0xcf)
	CmdSubDocMultiLookup    = CommandCode(0xd0)
	CmdSubDocMultiMutation  = CommandCode(0xd1)
)

type SubDocFlag uint16

const (
	SubDocFlagMkDirP = SubDocFlag(0x01)
)

type SubDocOpType uint8

const (
	SubDocOpGet            = SubDocOpType(CmdSubDocGet)
	SubDocOpExists         = SubDocOpType(CmdSubDocExists)
	SubDocOpDictAdd        = SubDocOpType(CmdSubDocDictAdd)
	SubDocOpDictSet        = SubDocOpType(CmdSubDocDictSet)
	SubDocOpDelete         = SubDocOpType(CmdSubDocDelete)
	SubDocOpReplace        = SubDocOpType(CmdSubDocReplace)
	SubDocOpArrayPushLast  = SubDocOpType(CmdSubDocArrayPushLast)
	SubDocOpArrayPushFirst = SubDocOpType(CmdSubDocArrayPushFirst)
	SubDocOpArrayInsert    = SubDocOpType(CmdSubDocArrayInsert)
	SubDocOpArrayAddUnique = SubDocOpType(CmdSubDocArrayAddUnique)
	SubDocOpCounter        = SubDocOpType(CmdSubDocCounter)
)

type HelloFeature uint16

const (
	FeatureDatatype = HelloFeature(0x01)
	FeatureSeqNo    = HelloFeature(0x04)
)

// Status field for memcached response.
type StatusCode uint16

const (
	StatusSuccess            = StatusCode(0x00)
	StatusKeyNotFound        = StatusCode(0x01)
	StatusKeyExists          = StatusCode(0x02)
	StatusTooBig             = StatusCode(0x03)
	StatusInvalidArgs        = StatusCode(0x04)
	StatusNotStored          = StatusCode(0x05)
	StatusBadDelta           = StatusCode(0x06)
	StatusNotMyVBucket       = StatusCode(0x07)
	StatusNoBucket           = StatusCode(0x08)
	StatusAuthStale          = StatusCode(0x1f)
	StatusAuthError          = StatusCode(0x20)
	StatusAuthContinue       = StatusCode(0x21)
	StatusRangeError         = StatusCode(0x22)
	StatusRollback           = StatusCode(0x23)
	StatusAccessError        = StatusCode(0x24)
	StatusNotInitialized     = StatusCode(0x25)
	StatusUnknownCommand     = StatusCode(0x81)
	StatusOutOfMemory        = StatusCode(0x82)
	StatusNotSupported       = StatusCode(0x83)
	StatusInternalError      = StatusCode(0x84)
	StatusBusy               = StatusCode(0x85)
	StatusTmpFail            = StatusCode(0x86)
	StatusSubDocPathNotFound = StatusCode(0xc0)
	StatusSubDocPathMismatch = StatusCode(0xc1)
	StatusSubDocPathInvalid  = StatusCode(0xc2)
	StatusSubDocPathTooBig   = StatusCode(0xc3)
	StatusSubDocDocTooDeep   = StatusCode(0xc4)
	StatusSubDocCantInsert   = StatusCode(0xc5)
	StatusSubDocNotJson      = StatusCode(0xc6)
	StatusSubDocBadRange     = StatusCode(0xc7)
	StatusSubDocBadDelta     = StatusCode(0xc8)
	StatusSubDocPathExists   = StatusCode(0xc9)
	StatusSubDocValueTooDeep = StatusCode(0xca)
	StatusSubDocBadCombo     = StatusCode(0xcb)
	StatusSubDocBadMulti     = StatusCode(0xcc)
)

type KeyState uint8

const (
	KeyStateNotPersisted = KeyState(0x00)
	KeyStatePersisted    = KeyState(0x01)
	KeyStateNotFound     = KeyState(0x80)
	KeyStateDeleted      = KeyState(0x81)
)

type StreamEndStatus uint32

const (
	StreamEndOK           = StreamEndStatus(0x00)
	StreamEndClosed       = StreamEndStatus(0x01)
	StreamEndStateChanged = StreamEndStatus(0x02)
	StreamEndDisconnected = StreamEndStatus(0x03)
	StreamEndTooSlow      = StreamEndStatus(0x04)
)

type BucketType int

const (
	BktTypeInvalid   BucketType = 0
	BktTypeCouchbase            = iota
	BktTypeMemcached            = iota
)

type VBucketState uint32

const (
	VBucketStateActive  = VBucketState(0x01)
	VBucketStateReplica = VBucketState(0x02)
	VBucketStatePending = VBucketState(0x03)
	VBucketStateDead    = VBucketState(0x04)
)
<|endoftext|>


<commit_before>/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package rdm

import (
	"context"
	"flag"
	"fmt"
	"strings"

	"github.com/vmware/govmomi/govc/cli"
	"github.com/vmware/govmomi/govc/flags"
	"github.com/vmware/govmomi/vim25/types"
)

type attach struct {
	*flags.VirtualMachineFlag

	device string
}

func init() {
	cli.Register("vm.rdm.attach", &attach{})
}

func (cmd *attach) Register(ctx context.Context, f *flag.FlagSet) {

	cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
	cmd.VirtualMachineFlag.Register(ctx, f)

	f.StringVar(&cmd.device, "device", "", "Device Name")
}

func (cmd *attach) Description() string {
	return `Attach DEVICE to VM with RDM.

Examples:
  govc vm.rdm.attach -vm VM -device /vmfs/devices/disks/naa.000000000000000000000000000000000`
}

func (cmd *attach) Process(ctx context.Context) error {
	if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
		return err
	}
	return nil
}

//This piece of code was developed mainly thanks to the project govmax on github.com
//This file in particular https://github.com/codedellemc/govmax/blob/master/api/v1/vmomi.go
func (cmd *attach) Run(ctx context.Context, f *flag.FlagSet) error {
	vm, err := cmd.VirtualMachine()
	if err != nil {
		return err
	}

	if vm == nil {
		return flag.ErrHelp
	}

	devices, err := vm.Device(ctx)
	if err != nil {
		return err
	}

	controller, err := devices.FindSCSIController("")
	if err != nil {
		return err
	}

	vmConfigOptions, err := vm.QueryConfigTarget(ctx)
	if err != nil {
		return err
	}

	for _, scsiDisk := range vmConfigOptions.ScsiDisk {
		if !strings.Contains(scsiDisk.Disk.CanonicalName, cmd.device) {
			continue
		}
		var backing types.VirtualDiskRawDiskMappingVer1BackingInfo
		backing.CompatibilityMode = string(types.VirtualDiskCompatibilityModePhysicalMode)
		backing.DeviceName = scsiDisk.Disk.DeviceName
		for _, descriptor := range scsiDisk.Disk.Descriptor {
			if strings.HasPrefix(descriptor.Id, "vml.") {
				backing.LunUuid = descriptor.Id
				break
			}
		}
		var device types.VirtualDisk
		device.Backing = &backing
		device.ControllerKey = controller.VirtualController.Key

		var unitNumber *int32
		scsiCtrlUnitNumber := controller.VirtualController.UnitNumber
		var u int32
		for u = 0; u < 16; u++ {
			free := true
			for _, d := range devices {
				if d.GetVirtualDevice().ControllerKey == device.GetVirtualDevice().ControllerKey {
					if u == *(d.GetVirtualDevice().UnitNumber) || u == *scsiCtrlUnitNumber {
						free = false
					}
				}
			}
			if free {
				unitNumber = &u
				break
			}
		}
		device.UnitNumber = unitNumber

		spec := types.VirtualMachineConfigSpec{}

		config := &types.VirtualDeviceConfigSpec{
			Device:    &device,
			Operation: types.VirtualDeviceConfigSpecOperationAdd,
		}

		config.FileOperation = types.VirtualDeviceConfigSpecFileOperationCreate

		spec.DeviceChange = append(spec.DeviceChange, config)

		task, err := vm.Reconfigure(ctx, spec)
		if err != nil {
			return err
		}

		err = task.Wait(ctx)
		if err != nil {
			return fmt.Errorf("error adding device %+v \n with backing %+v \nLogged Item:  %s", device, backing, err)
		}
		return nil

	}
	return fmt.Errorf("error: No LUN with device name containing %s found", cmd.device)
}
<commit_msg>testing for lab<commit_after>/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package rdm

import (
	"context"
	"flag"
	"fmt"
	"strings"

	"github.com/vmware/govmomi/govc/cli"
	"github.com/vmware/govmomi/govc/flags"
	"github.com/vmware/govmomi/vim25/types"
)

type attach struct {
	*flags.VirtualMachineFlag

	device string
}

func init() {
	cli.Register("vm.rdm.attach", &attach{})
}

func (cmd *attach) Register(ctx context.Context, f *flag.FlagSet) {

	cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
	cmd.VirtualMachineFlag.Register(ctx, f)

	f.StringVar(&cmd.device, "device", "", "Device Name")
}

func (cmd *attach) Description() string {
	return `Attach DEVICE to VM with RDM.

Examples:
  govc vm.rdm.attach -vm VM -device /vmfs/devices/disks/naa.000000000000000000000000000000000`
}

func (cmd *attach) Process(ctx context.Context) error {
	if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
		return err
	}
	return nil
}

//This piece of code was developed mainly thanks to the project govmax on github.com
//This file in particular https://github.com/codedellemc/govmax/blob/master/api/v1/vmomi.go
func (cmd *attach) Run(ctx context.Context, f *flag.FlagSet) error {
	vm, err := cmd.VirtualMachine()
	if err != nil {
		return err
	}

	if vm == nil {
		return flag.ErrHelp
	}

	devices, err := vm.Device(ctx)
	if err != nil {
		return err
	}

	controller, err := devices.FindSCSIController("")
	if err != nil {
		return err
	}

	vmConfigOptions, err := vm.QueryConfigTarget(ctx)
	if err != nil {
		return err
	}

	for _, scsiDisk := range vmConfigOptions.ScsiDisk {
		if !strings.Contains(scsiDisk.Disk.CanonicalName, cmd.device) {
			continue
		}
		var backing types.VirtualDiskRawDiskMappingVer1BackingInfo
		backing.CompatibilityMode = string(types.VirtualDiskCompatibilityModePhysicalMode)
		backing.DeviceName = scsiDisk.Disk.DeviceName
		for _, descriptor := range scsiDisk.Disk.Descriptor {
			if strings.HasPrefix(descriptor.Id, "vml.") {
				backing.LunUuid = descriptor.Id
				break
			}
		}
		var device types.VirtualDisk
		device.Backing = &backing
		device.ControllerKey = controller.VirtualController.Key

		var unitNumber *int32
		scsiCtrlUnitNumber := controller.VirtualController.UnitNumber
		var u int32
		for u = 0; u < 16; u++ {
			free := true
			for _, d := range devices {
				if d.GetVirtualDevice().ControllerKey == device.GetVirtualDevice().ControllerKey {
					if u == *(d.GetVirtualDevice().UnitNumber) || u == *scsiCtrlUnitNumber {
						free = false
					}
				}
			}
			if free && u != 7 {
				unitNumber = &u
				break
			}
		}
		device.UnitNumber = unitNumber

		spec := types.VirtualMachineConfigSpec{}

		config := &types.VirtualDeviceConfigSpec{
			Device:    &device,
			Operation: types.VirtualDeviceConfigSpecOperationAdd,
		}

		config.FileOperation = types.VirtualDeviceConfigSpecFileOperationCreate

		spec.DeviceChange = append(spec.DeviceChange, config)

		task, err := vm.Reconfigure(ctx, spec)
		if err != nil {
			return err
		}

		err = task.Wait(ctx)
		if err != nil {
			return fmt.Errorf("error adding device %+v \n with backing %+v \nLogged Item:  %s", device, backing, err)
		}
		return nil

	}
	return fmt.Errorf("error: No LUN with device name containing %s found", cmd.device)
}
<|endoftext|>


<commit_before>package instr

// Jump instruction names.
var (
	Jmp       = []byte("goto")
	JmpNil    = []byte("goto-if-nil")
	JmpNotNil = []byte("goto-if-not-nil")
	Label     = []byte("label")
)

// Binary ops.
var (
	NumEq    = binOp("num=")
	NumGt    = binOp("num>")
	NumLt    = binOp("num<")
	NumSub   = binOp("sub")
	NumAdd   = binOp("add")
	NumMul   = binOp("mul")
	NumQuo   = binOp("quo")
	ArrayRef = binOp("array-ref")

	SetCar = binOp("setcar")
	SetCdr = binOp("setcdr")
)

// Unary ops.
var (
	Add1 = unaryOp("add1")
	Sub1 = unaryOp("sub1")

	Not = unaryOp("not")
	Neg = unaryOp("neg")

	Car = unaryOp("car")
	Cdr = unaryOp("cdr")
)

// Other ops without explicit parameter.
var (
	ArraySet = Instr{
		Name:     []byte("array-set"),
		Encoding: AttrEnc0,
		Input:    AttrTake3,
		Output:   AttrPushAndDiscard,
	}

	Return = Instr{
		Name:     []byte("return"),
		Encoding: AttrEnc0,
		Input:    AttrTake1,
	}
)

func Concat(argc int) Instr {
	return Instr{
		Name:     []byte("concat"),
		Encoding: AttrEnc1,
		Input:    AttrTakeN,
		Output:   AttrPushTmp,
		Data:     uint16(argc),
	}
}

func StackSet(stIndex int) Instr {
	return Instr{
		Name:     []byte("stack-set"),
		Encoding: AttrEnc1,
		Input:    AttrReplaceNth,
		Data:     uint16(stIndex),
	}
}

func VarSet(cvIndex int) Instr {
	return Instr{
		Name:     []byte("var-set"),
		Encoding: AttrEnc1,
		Input:    AttrTake1,
		Data:     uint16(cvIndex),
	}
}

func Discard(n int) Instr {
	return Instr{
		Name:     []byte("discard"),
		Encoding: AttrEnc1,
		Input:    AttrTakeN,
		Data:     uint16(n),
	}
}

func ConstRef(cvIndex int) Instr {
	return Instr{
		Name:     []byte("constant"),
		Encoding: AttrEnc1,
		Output:   AttrPushConst,
		Data:     uint16(cvIndex),
	}
}

func StackRef(stIndex int) Instr {
	return Instr{
		Name:     []byte("stack-ref"),
		Encoding: AttrEnc1,
		Output:   AttrDupNth,
		Data:     uint16(stIndex),
	}
}

func VarRef(cvIndex int) Instr {
	return Instr{
		Name:     []byte("var-ref"),
		Encoding: AttrEnc1,
		Output:   AttrPushTmp,
		Data:     uint16(cvIndex),
	}
}

func Call(argc int) Instr {
	return Instr{
		Name:     []byte("call"),
		Encoding: AttrEnc1,
		Input:    AttrTakeNplus1,
		Output:   AttrPushTmp,
		Data:     uint16(argc),
	}
}
<commit_msg>substr instr<commit_after>package instr

// Jump instruction names.
var (
	Jmp       = []byte("goto")
	JmpNil    = []byte("goto-if-nil")
	JmpNotNil = []byte("goto-if-not-nil")
	Label     = []byte("label")
)

// Binary ops.
var (
	NumEq    = binOp("num=")
	NumGt    = binOp("num>")
	NumLt    = binOp("num<")
	NumSub   = binOp("sub")
	NumAdd   = binOp("add")
	NumMul   = binOp("mul")
	NumQuo   = binOp("quo")
	ArrayRef = binOp("array-ref")

	SetCar = binOp("setcar")
	SetCdr = binOp("setcdr")
)

// Unary ops.
var (
	Add1 = unaryOp("add1")
	Sub1 = unaryOp("sub1")

	Not = unaryOp("not")
	Neg = unaryOp("neg")

	Car = unaryOp("car")
	Cdr = unaryOp("cdr")
)

// Other ops without explicit parameter.
var (
	ArraySet = Instr{
		Name:     []byte("array-set"),
		Encoding: AttrEnc0,
		Input:    AttrTake3,
		Output:   AttrPushAndDiscard,
	}

	Return = Instr{
		Name:     []byte("return"),
		Encoding: AttrEnc0,
		Input:    AttrTake1,
	}

	Substr = Instr{
		Name:     []byte("substr"),
		Encoding: AttrEnc0,
		Input:    AttrTake3,
		Output:   AttrPushTmp,
	}
)

func Concat(argc int) Instr {
	return Instr{
		Name:     []byte("concat"),
		Encoding: AttrEnc1,
		Input:    AttrTakeN,
		Output:   AttrPushTmp,
		Data:     uint16(argc),
	}
}

func StackSet(stIndex int) Instr {
	return Instr{
		Name:     []byte("stack-set"),
		Encoding: AttrEnc1,
		Input:    AttrReplaceNth,
		Data:     uint16(stIndex),
	}
}

func VarSet(cvIndex int) Instr {
	return Instr{
		Name:     []byte("var-set"),
		Encoding: AttrEnc1,
		Input:    AttrTake1,
		Data:     uint16(cvIndex),
	}
}

func Discard(n int) Instr {
	return Instr{
		Name:     []byte("discard"),
		Encoding: AttrEnc1,
		Input:    AttrTakeN,
		Data:     uint16(n),
	}
}

func ConstRef(cvIndex int) Instr {
	return Instr{
		Name:     []byte("constant"),
		Encoding: AttrEnc1,
		Output:   AttrPushConst,
		Data:     uint16(cvIndex),
	}
}

func StackRef(stIndex int) Instr {
	return Instr{
		Name:     []byte("stack-ref"),
		Encoding: AttrEnc1,
		Output:   AttrDupNth,
		Data:     uint16(stIndex),
	}
}

func VarRef(cvIndex int) Instr {
	return Instr{
		Name:     []byte("var-ref"),
		Encoding: AttrEnc1,
		Output:   AttrPushTmp,
		Data:     uint16(cvIndex),
	}
}

func Call(argc int) Instr {
	return Instr{
		Name:     []byte("call"),
		Encoding: AttrEnc1,
		Input:    AttrTakeNplus1,
		Output:   AttrPushTmp,
		Data:     uint16(argc),
	}
}
<|endoftext|>


<commit_before>// Package mockobject provides a mock object which can be created from a string
package mockobject

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"time"

	"github.com/rclone/rclone/fs"
	"github.com/rclone/rclone/fs/hash"
)

var errNotImpl = errors.New("not implemented")

// Object is a mock fs.Object useful for testing
type Object string

// New returns mock fs.Object useful for testing
func New(name string) Object {
	return Object(name)
}

// String returns a description of the Object
func (o Object) String() string {
	return string(o)
}

// Fs returns read only access to the Fs that this object is part of
func (o Object) Fs() fs.Info {
	return nil
}

// Remote returns the remote path
func (o Object) Remote() string {
	return string(o)
}

// Hash returns the selected checksum of the file
// If no checksum is available it returns ""
func (o Object) Hash(ctx context.Context, t hash.Type) (string, error) {
	return "", errNotImpl
}

// ModTime returns the modification date of the file
// It should return a best guess if one isn't available
func (o Object) ModTime(ctx context.Context) (t time.Time) {
	return t
}

// Size returns the size of the file
func (o Object) Size() int64 { return 0 }

// Storable says whether this object can be stored
func (o Object) Storable() bool {
	return true
}

// SetModTime sets the metadata on the object to set the modification date
func (o Object) SetModTime(ctx context.Context, t time.Time) error {
	return errNotImpl
}

// Open opens the file for read.  Call Close() on the returned io.ReadCloser
func (o Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadCloser, error) {
	return nil, errNotImpl
}

// Update in to the object with the modTime given of the given size
func (o Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) error {
	return errNotImpl
}

// Remove this object
func (o Object) Remove(ctx context.Context) error {
	return errNotImpl
}

// SeekMode specifies the optional Seek interface for the ReadCloser returned by Open
type SeekMode int

const (
	// SeekModeNone specifies no seek interface
	SeekModeNone SeekMode = iota
	// SeekModeRegular specifies the regular io.Seek interface
	SeekModeRegular
	// SeekModeRange specifies the fs.RangeSeek interface
	SeekModeRange
)

// SeekModes contains all valid SeekMode's
var SeekModes = []SeekMode{SeekModeNone, SeekModeRegular, SeekModeRange}

type contentMockObject struct {
	Object
	content  []byte
	seekMode SeekMode
}

// WithContent returns a fs.Object with the given content.
func (o Object) WithContent(content []byte, mode SeekMode) fs.Object {
	return &contentMockObject{
		Object:   o,
		content:  content,
		seekMode: mode,
	}
}

func (o *contentMockObject) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadCloser, error) {
	var offset, limit int64 = 0, -1
	for _, option := range options {
		switch x := option.(type) {
		case *fs.SeekOption:
			offset = x.Offset
		case *fs.RangeOption:
			offset, limit = x.Decode(o.Size())
		default:
			if option.Mandatory() {
				return nil, fmt.Errorf("Unsupported mandatory option: %v", option)
			}
		}
	}
	if limit == -1 || offset+limit > o.Size() {
		limit = o.Size() - offset
	}

	var r *bytes.Reader
	if o.seekMode == SeekModeNone {
		r = bytes.NewReader(o.content[offset : offset+limit])
	} else {
		r = bytes.NewReader(o.content)
		_, err := r.Seek(offset, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	switch o.seekMode {
	case SeekModeNone:
		return &readCloser{r}, nil
	case SeekModeRegular:
		return &readSeekCloser{r}, nil
	case SeekModeRange:
		return &readRangeSeekCloser{r}, nil
	default:
		return nil, errors.New(o.seekMode.String())
	}
}
func (o *contentMockObject) Size() int64 {
	return int64(len(o.content))
}

type readCloser struct{ io.Reader }

func (r *readCloser) Close() error { return nil }

type readSeekCloser struct{ io.ReadSeeker }

func (r *readSeekCloser) Close() error { return nil }

type readRangeSeekCloser struct{ io.ReadSeeker }

func (r *readRangeSeekCloser) RangeSeek(offset int64, whence int, length int64) (int64, error) {
	return r.ReadSeeker.Seek(offset, whence)
}

func (r *readRangeSeekCloser) Close() error { return nil }

func (m SeekMode) String() string {
	switch m {
	case SeekModeNone:
		return "SeekModeNone"
	case SeekModeRegular:
		return "SeekModeRegular"
	case SeekModeRange:
		return "SeekModeRange"
	default:
		return fmt.Sprintf("SeekModeInvalid(%d)", m)
	}
}
<commit_msg>fstest/mockobject: add SetFs method so it can have a valid Fs() #3419<commit_after>// Package mockobject provides a mock object which can be created from a string
package mockobject

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"time"

	"github.com/rclone/rclone/fs"
	"github.com/rclone/rclone/fs/hash"
)

var errNotImpl = errors.New("not implemented")

// Object is a mock fs.Object useful for testing
type Object string

// New returns mock fs.Object useful for testing
func New(name string) Object {
	return Object(name)
}

// String returns a description of the Object
func (o Object) String() string {
	return string(o)
}

// Fs returns read only access to the Fs that this object is part of
func (o Object) Fs() fs.Info {
	return nil
}

// Remote returns the remote path
func (o Object) Remote() string {
	return string(o)
}

// Hash returns the selected checksum of the file
// If no checksum is available it returns ""
func (o Object) Hash(ctx context.Context, t hash.Type) (string, error) {
	return "", errNotImpl
}

// ModTime returns the modification date of the file
// It should return a best guess if one isn't available
func (o Object) ModTime(ctx context.Context) (t time.Time) {
	return t
}

// Size returns the size of the file
func (o Object) Size() int64 { return 0 }

// Storable says whether this object can be stored
func (o Object) Storable() bool {
	return true
}

// SetModTime sets the metadata on the object to set the modification date
func (o Object) SetModTime(ctx context.Context, t time.Time) error {
	return errNotImpl
}

// Open opens the file for read.  Call Close() on the returned io.ReadCloser
func (o Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadCloser, error) {
	return nil, errNotImpl
}

// Update in to the object with the modTime given of the given size
func (o Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) error {
	return errNotImpl
}

// Remove this object
func (o Object) Remove(ctx context.Context) error {
	return errNotImpl
}

// SeekMode specifies the optional Seek interface for the ReadCloser returned by Open
type SeekMode int

const (
	// SeekModeNone specifies no seek interface
	SeekModeNone SeekMode = iota
	// SeekModeRegular specifies the regular io.Seek interface
	SeekModeRegular
	// SeekModeRange specifies the fs.RangeSeek interface
	SeekModeRange
)

// SeekModes contains all valid SeekMode's
var SeekModes = []SeekMode{SeekModeNone, SeekModeRegular, SeekModeRange}

// ContentMockObject mocks an fs.Object and has content
type ContentMockObject struct {
	Object
	content  []byte
	seekMode SeekMode
	f        fs.Fs
}

// WithContent returns a fs.Object with the given content.
func (o Object) WithContent(content []byte, mode SeekMode) *ContentMockObject {
	return &ContentMockObject{
		Object:   o,
		content:  content,
		seekMode: mode,
	}
}

// SetFs sets the return value of the Fs() call
func (o *ContentMockObject) SetFs(f fs.Fs) {
	o.f = f
}

// Fs returns read only access to the Fs that this object is part of
//
// This is nil unless SetFs has been called
func (o *ContentMockObject) Fs() fs.Info {
	return o.f
}

// Open opens the file for read.  Call Close() on the returned io.ReadCloser
func (o *ContentMockObject) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadCloser, error) {
	var offset, limit int64 = 0, -1
	for _, option := range options {
		switch x := option.(type) {
		case *fs.SeekOption:
			offset = x.Offset
		case *fs.RangeOption:
			offset, limit = x.Decode(o.Size())
		default:
			if option.Mandatory() {
				return nil, fmt.Errorf("Unsupported mandatory option: %v", option)
			}
		}
	}
	if limit == -1 || offset+limit > o.Size() {
		limit = o.Size() - offset
	}

	var r *bytes.Reader
	if o.seekMode == SeekModeNone {
		r = bytes.NewReader(o.content[offset : offset+limit])
	} else {
		r = bytes.NewReader(o.content)
		_, err := r.Seek(offset, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	switch o.seekMode {
	case SeekModeNone:
		return &readCloser{r}, nil
	case SeekModeRegular:
		return &readSeekCloser{r}, nil
	case SeekModeRange:
		return &readRangeSeekCloser{r}, nil
	default:
		return nil, errors.New(o.seekMode.String())
	}
}

// Size returns the size of the file
func (o *ContentMockObject) Size() int64 {
	return int64(len(o.content))
}

type readCloser struct{ io.Reader }

func (r *readCloser) Close() error { return nil }

type readSeekCloser struct{ io.ReadSeeker }

func (r *readSeekCloser) Close() error { return nil }

type readRangeSeekCloser struct{ io.ReadSeeker }

func (r *readRangeSeekCloser) RangeSeek(offset int64, whence int, length int64) (int64, error) {
	return r.ReadSeeker.Seek(offset, whence)
}

func (r *readRangeSeekCloser) Close() error { return nil }

func (m SeekMode) String() string {
	switch m {
	case SeekModeNone:
		return "SeekModeNone"
	case SeekModeRegular:
		return "SeekModeRegular"
	case SeekModeRange:
		return "SeekModeRange"
	default:
		return fmt.Sprintf("SeekModeInvalid(%d)", m)
	}
}
<|endoftext|>


<commit_before>package node

import (
	"bytes"
	"github.com/AutoRoute/l2"
)

// The layer two protocol takes a layer two device and returns the hash of the
// Public Key of all neighbors it can find.
type NeighborFinder interface {
	Find(l2.FrameReadWriter) <-chan string
}

type layer2 struct{}

func (nf layer2) Find(frw l2.FrameReadWriter) <-chan string {
	c := make(chan string)
	// Broadcast Hash
	broadcastAddr := l2.MacToBytesOrDie("ff:ff:ff:ff:ff:ff")
	localAddr := l2.MacToBytesOrDie("aa:bb:cc:dd:ee:00") // TODO: pass own mac address
	var protocol uint16 = 31337                          // TODO: add real protocol
	var p PublicKey                                      // TODO: pass public key
	publicKeyHash := []byte(p.Hash())
	initFrame := l2.NewEthFrame(broadcastAddr, localAddr, protocol, publicKeyHash)
	frw.WriteFrame(initFrame)
	// Process Loop
	go func() {
		for {
			newInstanceFrame, _ := frw.ReadFrame()
			src := l2.EthFrame(newInstanceFrame).Source()
			dest := l2.EthFrame(newInstanceFrame).Destination()
			if l2.EthFrame(newInstanceFrame).Type() != protocol {
				continue // Throw away if protocols don't match
			}
			if bytes.Equal(src, localAddr) {
				continue // Throw away if from me
			}
			if !(bytes.Equal(dest, localAddr) || bytes.Equal(dest, broadcastAddr)) {
				continue // Throw away if it wasn't to me or the broadcast address
			}
			c <- string(l2.EthFrame(newInstanceFrame).Data())
			if bytes.Equal(dest, broadcastAddr) { // Respond if to broadcast addr
				var p PublicKey // TODO: pass public key
				publicKeyHash := []byte(p.Hash())
				initFrame := l2.NewEthFrame(src, localAddr, 31337, publicKeyHash) //TODO: add real protocol
				frw.WriteFrame(initFrame)
			}
		}
	}()
	return c
}
<commit_msg>Returning EthFrame instead of byte slice from ReadFrame and passing EthFrame instead of byte slice to WriteFrame.<commit_after>package node

import (
	"bytes"
	"github.com/AutoRoute/l2"
)

// The layer two protocol takes a layer two device and returns the hash of the
// Public Key of all neighbors it can find.
type NeighborFinder interface {
	Find(l2.FrameReadWriter) <-chan string
}

type layer2 struct{}

func (nf layer2) Find(frw l2.FrameReadWriter) <-chan string {
	c := make(chan string)
	// Broadcast Hash
	broadcastAddr := l2.MacToBytesOrDie("ff:ff:ff:ff:ff:ff")
	localAddr := l2.MacToBytesOrDie("aa:bb:cc:dd:ee:00") // TODO: pass own mac address
	var protocol uint16 = 31337                          // TODO: add real protocol
	var p PublicKey                                      // TODO: pass public key
	publicKeyHash := []byte(p.Hash())
	initFrame := l2.NewEthFrame(broadcastAddr, localAddr, protocol, publicKeyHash)
	_ = frw.WriteFrame(initFrame) // TODO: check errors
	// Process Loop
	go func() {
		for {
			newInstanceFrame, _ := frw.ReadFrame()
			src := newInstanceFrame.Source()
			dest := newInstanceFrame.Destination()
			if newInstanceFrame.Type() != protocol {
				continue // Throw away if protocols don't match
			}
			if bytes.Equal(src, localAddr) {
				continue // Throw away if from me
			}
			if !(bytes.Equal(dest, localAddr) || bytes.Equal(dest, broadcastAddr)) {
				continue // Throw away if it wasn't to me or the broadcast address
			}
			c <- string(newInstanceFrame.Data())
			if bytes.Equal(dest, broadcastAddr) { // Respond if to broadcast addr
				var p PublicKey // TODO: pass public key
				publicKeyHash := []byte(p.Hash())
				initFrame := l2.NewEthFrame(src, localAddr, 31337, publicKeyHash) // TODO: add real protocol
				_ = frw.WriteFrame(initFrame)                                     // TODO: check errors
			}
		}
	}()
	return c
}
<|endoftext|>


<commit_before>package stripe

import (
	"encoding/json"
)

// CheckoutSessionDisplayItemType is the list of allowed values for the display item type.
type CheckoutSessionDisplayItemType string

// List of values that CheckoutSessionDisplayItemType can take.
const (
	CheckoutSessionDisplayItemTypeCustom CheckoutSessionDisplayItemType = "custom"
	CheckoutSessionDisplayItemTypePlan   CheckoutSessionDisplayItemType = "plan"
	CheckoutSessionDisplayItemTypeSKU    CheckoutSessionDisplayItemType = "sku"
)

// CheckoutSessionLineItemParams is the set of parameters allowed for a line item
// on a checkout session.
type CheckoutSessionLineItemParams struct {
	Amount      *int64    `form:"amount"`
	Currency    *string   `form:"currency"`
	Description *string   `form:"description"`
	Images      []*string `form:"images"`
	Name        *string   `form:"name"`
	Quantity    *int64    `form:"quantity"`
}

// CheckoutSessionPaymentIntentDataTransferDataParams is the set of parameters allowed for the
// transfer_data hash.
type CheckoutSessionPaymentIntentDataTransferDataParams struct {
	Destination *string `form:"destination"`
}

// CheckoutSessionPaymentIntentDataParams is the set of parameters allowed for the
// payment intent creation on a checkout session.
type CheckoutSessionPaymentIntentDataParams struct {
	Params               `form:"*"`
	ApplicationFeeAmount *int64                                              `form:"application_fee_amount"`
	CaptureMethod        *string                                             `form:"capture_method"`
	Description          *string                                             `form:"description"`
	OnBehalfOf           *string                                             `form:"on_behalf_of"`
	ReceiptEmail         *string                                             `form:"receipt_email"`
	Shipping             *ShippingDetailsParams                              `form:"shipping"`
	StatementDescriptor  *string                                             `form:"statement_descriptor"`
	TransferData         *CheckoutSessionPaymentIntentDataTransferDataParams `form:"transfer_data"`
}

// CheckoutSessionSubscriptionDataItemsParams is the set of parameters allowed for one item on a
// checkout session associated with a subscription.
type CheckoutSessionSubscriptionDataItemsParams struct {
	Plan     *string `form:"plan"`
	Quantity *int64  `form:"quantity"`
}

// CheckoutSessionSubscriptionDataParams is the set of parameters allowed for the subscription
// creation on a checkout session.
type CheckoutSessionSubscriptionDataParams struct {
	Params          `form:"*"`
	Items           []*CheckoutSessionSubscriptionDataItemsParams `form:"items"`
	TrialEnd        *int64                                        `form:"trial_end"`
	TrialPeriodDays *int64                                        `form:"trial_period_days"`
}

// CheckoutSessionParams is the set of parameters that can be used when creating
// a checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/create
type CheckoutSessionParams struct {
	Params                   `form:"*"`
	BillingAddressCollection *string                                 `form:"billing_address_collection"`
	CancelURL                *string                                 `form:"cancel_url"`
	ClientReferenceID        *string                                 `form:"client_reference_id"`
	Customer                 *string                                 `form:"customer"`
	CustomerEmail            *string                                 `form:"customer_email"`
	LineItems                []*CheckoutSessionLineItemParams        `form:"line_items"`
	Locale                   *string                                 `form:"locale"`
	PaymentIntentData        *CheckoutSessionPaymentIntentDataParams `form:"payment_intent_data"`
	PaymentMethodTypes       []*string                               `form:"payment_method_types"`
	SubscriptionData         *CheckoutSessionSubscriptionDataParams  `form:"subscription_data"`
	SuccessURL               *string                                 `form:"success_url"`
}

// CheckoutSessionDisplayItemCustom represents an item of type custom in a checkout session
type CheckoutSessionDisplayItemCustom struct {
	Description string   `json:"description"`
	Images      []string `json:"images"`
	Name        string   `json:"name"`
}

// CheckoutSessionDisplayItem represents one of the items in a checkout session.
type CheckoutSessionDisplayItem struct {
	Amount   int64                             `json:"amount"`
	Currency Currency                          `json:"currency"`
	Custom   *CheckoutSessionDisplayItemCustom `json:"custom"`
	Quantity int64                             `json:"quantity"`
	Plan     *Plan                             `json:"plan"`
	SKU      *SKU                              `json:"sku"`
	Type     CheckoutSessionDisplayItemType    `json:"type"`
}

// CheckoutSession is the resource representing a Stripe checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/object
type CheckoutSession struct {
	CancelURL          string                        `json:"cancel_url"`
	ClientReferenceID  string                        `json:"client_reference_id"`
	Customer           *Customer                     `json:"customer"`
	CustomerEmail      string                        `json:"customer_email"`
	Deleted            bool                          `json:"deleted"`
	DisplayItems       []*CheckoutSessionDisplayItem `json:"display_items"`
	ID                 string                        `json:"id"`
	Livemode           bool                          `json:"livemode"`
	Locale             string                        `json:"locale"`
	Object             string                        `json:"object"`
	PaymentIntent      *PaymentIntent                `json:"payment_intent"`
	PaymentMethodTypes []string                      `json:"payment_method_types"`
	Subscription       *Subscription                 `json:"subscription"`
	SuccessURL         string                        `json:"success_url"`
}

// UnmarshalJSON handles deserialization of a checkout session.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (p *CheckoutSession) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		p.ID = id
		return nil
	}

	type session CheckoutSession
	var v session
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*p = CheckoutSession(v)
	return nil
}
<commit_msg>Add support for submit_type to CheckoutSession<commit_after>package stripe

import (
	"encoding/json"
)

// CheckoutSessionSubmitType is the list of allowed values for the `submit_type`
// of a Session.
type CheckoutSessionSubmitType string

// List of values that CheckoutSessionSubmitType can take.
const (
	CheckoutSessionSubmitTypeAuto   CheckoutSessionSubmitType = "auto"
	CheckoutSessionSubmitTypeBook   CheckoutSessionSubmitType = "book"
	CheckoutSessionSubmitTypeDonate CheckoutSessionSubmitType = "donate"
	CheckoutSessionSubmitTypePay    CheckoutSessionSubmitType = "pay"
)

// CheckoutSessionDisplayItemType is the list of allowed values for the display item type.
type CheckoutSessionDisplayItemType string

// List of values that CheckoutSessionDisplayItemType can take.
const (
	CheckoutSessionDisplayItemTypeCustom CheckoutSessionDisplayItemType = "custom"
	CheckoutSessionDisplayItemTypePlan   CheckoutSessionDisplayItemType = "plan"
	CheckoutSessionDisplayItemTypeSKU    CheckoutSessionDisplayItemType = "sku"
)

// CheckoutSessionLineItemParams is the set of parameters allowed for a line item
// on a checkout session.
type CheckoutSessionLineItemParams struct {
	Amount      *int64    `form:"amount"`
	Currency    *string   `form:"currency"`
	Description *string   `form:"description"`
	Images      []*string `form:"images"`
	Name        *string   `form:"name"`
	Quantity    *int64    `form:"quantity"`
}

// CheckoutSessionPaymentIntentDataTransferDataParams is the set of parameters allowed for the
// transfer_data hash.
type CheckoutSessionPaymentIntentDataTransferDataParams struct {
	Destination *string `form:"destination"`
}

// CheckoutSessionPaymentIntentDataParams is the set of parameters allowed for the
// payment intent creation on a checkout session.
type CheckoutSessionPaymentIntentDataParams struct {
	Params               `form:"*"`
	ApplicationFeeAmount *int64                                              `form:"application_fee_amount"`
	CaptureMethod        *string                                             `form:"capture_method"`
	Description          *string                                             `form:"description"`
	OnBehalfOf           *string                                             `form:"on_behalf_of"`
	ReceiptEmail         *string                                             `form:"receipt_email"`
	Shipping             *ShippingDetailsParams                              `form:"shipping"`
	StatementDescriptor  *string                                             `form:"statement_descriptor"`
	TransferData         *CheckoutSessionPaymentIntentDataTransferDataParams `form:"transfer_data"`
}

// CheckoutSessionSubscriptionDataItemsParams is the set of parameters allowed for one item on a
// checkout session associated with a subscription.
type CheckoutSessionSubscriptionDataItemsParams struct {
	Plan     *string `form:"plan"`
	Quantity *int64  `form:"quantity"`
}

// CheckoutSessionSubscriptionDataParams is the set of parameters allowed for the subscription
// creation on a checkout session.
type CheckoutSessionSubscriptionDataParams struct {
	Params          `form:"*"`
	Items           []*CheckoutSessionSubscriptionDataItemsParams `form:"items"`
	TrialEnd        *int64                                        `form:"trial_end"`
	TrialPeriodDays *int64                                        `form:"trial_period_days"`
}

// CheckoutSessionParams is the set of parameters that can be used when creating
// a checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/create
type CheckoutSessionParams struct {
	Params                   `form:"*"`
	BillingAddressCollection *string                                 `form:"billing_address_collection"`
	CancelURL                *string                                 `form:"cancel_url"`
	ClientReferenceID        *string                                 `form:"client_reference_id"`
	Customer                 *string                                 `form:"customer"`
	CustomerEmail            *string                                 `form:"customer_email"`
	LineItems                []*CheckoutSessionLineItemParams        `form:"line_items"`
	Locale                   *string                                 `form:"locale"`
	PaymentIntentData        *CheckoutSessionPaymentIntentDataParams `form:"payment_intent_data"`
	PaymentMethodTypes       []*string                               `form:"payment_method_types"`
	SubscriptionData         *CheckoutSessionSubscriptionDataParams  `form:"subscription_data"`
	SubmitType               *string                                 `form:"submit_type"`
	SuccessURL               *string                                 `form:"success_url"`
}

// CheckoutSessionDisplayItemCustom represents an item of type custom in a checkout session
type CheckoutSessionDisplayItemCustom struct {
	Description string   `json:"description"`
	Images      []string `json:"images"`
	Name        string   `json:"name"`
}

// CheckoutSessionDisplayItem represents one of the items in a checkout session.
type CheckoutSessionDisplayItem struct {
	Amount   int64                             `json:"amount"`
	Currency Currency                          `json:"currency"`
	Custom   *CheckoutSessionDisplayItemCustom `json:"custom"`
	Quantity int64                             `json:"quantity"`
	Plan     *Plan                             `json:"plan"`
	SKU      *SKU                              `json:"sku"`
	Type     CheckoutSessionDisplayItemType    `json:"type"`
}

// CheckoutSession is the resource representing a Stripe checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/object
type CheckoutSession struct {
	CancelURL          string                        `json:"cancel_url"`
	ClientReferenceID  string                        `json:"client_reference_id"`
	Customer           *Customer                     `json:"customer"`
	CustomerEmail      string                        `json:"customer_email"`
	Deleted            bool                          `json:"deleted"`
	DisplayItems       []*CheckoutSessionDisplayItem `json:"display_items"`
	ID                 string                        `json:"id"`
	Livemode           bool                          `json:"livemode"`
	Locale             string                        `json:"locale"`
	Object             string                        `json:"object"`
	PaymentIntent      *PaymentIntent                `json:"payment_intent"`
	PaymentMethodTypes []string                      `json:"payment_method_types"`
	Subscription       *Subscription                 `json:"subscription"`
	SubmitType         CheckoutSessionSubmitType     `json:"submit_type"`
	SuccessURL         string                        `json:"success_url"`
}

// UnmarshalJSON handles deserialization of a checkout session.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (p *CheckoutSession) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		p.ID = id
		return nil
	}

	type session CheckoutSession
	var v session
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*p = CheckoutSession(v)
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"context"
	"fmt"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/stretchr/testify/require"
	"vitess.io/vitess/go/mysql"
	tabletpb "vitess.io/vitess/go/vt/proto/topodata"
	"vitess.io/vitess/go/vt/vtgate/vtgateconn"
	tmc "vitess.io/vitess/go/vt/vttablet/grpctmclient"
)

var (
	tmClient = tmc.NewClient()
)

// Restart restarts vttablet and mysql.
func (tablet *Vttablet) Restart() error {
	if tablet.MysqlctlProcess.TabletUID|tablet.MysqlctldProcess.TabletUID == 0 {
		return fmt.Errorf("no mysql process is running")
	}

	if tablet.MysqlctlProcess.TabletUID > 0 {
		tablet.MysqlctlProcess.Stop()
		tablet.VttabletProcess.TearDown()
		os.RemoveAll(tablet.VttabletProcess.Directory)

		return tablet.MysqlctlProcess.Start()
	}

	tablet.MysqlctldProcess.Stop()
	tablet.VttabletProcess.TearDown()
	os.RemoveAll(tablet.VttabletProcess.Directory)

	return tablet.MysqlctldProcess.Start()
}

// ValidateTabletRestart restarts the tablet and validate error if there is any.
func (tablet *Vttablet) ValidateTabletRestart(t *testing.T) {
	require.Nilf(t, tablet.Restart(), "tablet restart failed")
}

// GetMasterPosition gets the master position of required vttablet
func GetMasterPosition(t *testing.T, vttablet Vttablet, hostname string) (string, string) {
	ctx := context.Background()
	vtablet := getTablet(vttablet.GrpcPort, hostname)
	pos, err := tmClient.MasterPosition(ctx, vtablet)
	require.Nil(t, err)
	gtID := strings.SplitAfter(pos, "/")[1]
	return pos, gtID
}

// VerifyRowsInTabletForTable Verify total number of rows in a table
// this is used to check replication caught up the changes from master
func VerifyRowsInTabletForTable(t *testing.T, vttablet *Vttablet, ksName string, expectedRows int, tableName string) {
	timeout := time.Now().Add(10 * time.Second)
	for time.Now().Before(timeout) {
		// ignoring the error check, if the newly created table is not replicated, then there might be error and we should ignore it
		// but eventually it will catch up and if not caught up in required time, testcase will fail
		qr, _ := vttablet.VttabletProcess.QueryTablet("select * from "+tableName, ksName, true)
		if len(qr.Rows) == expectedRows {
			return
		}
		time.Sleep(300 * time.Millisecond)
	}
	assert.Fail(t, "expected rows not found.")
}

// VerifyRowsInTablet Verify total number of rows in a tablet
func VerifyRowsInTablet(t *testing.T, vttablet *Vttablet, ksName string, expectedRows int) {
	VerifyRowsInTabletForTable(t, vttablet, ksName, expectedRows, "vt_insert_test")
}

// PanicHandler handles the panic in the testcase.
func PanicHandler(t *testing.T) {
	err := recover()
	if t == nil {
		return
	}
	require.Nilf(t, err, "panic occured in testcase %v", t.Name())
}

// VerifyLocalMetadata Verify Local Metadata of a tablet
func VerifyLocalMetadata(t *testing.T, tablet *Vttablet, ksName string, shardName string, cell string) {
	qr, err := tablet.VttabletProcess.QueryTablet("select * from _vt.local_metadata", ksName, false)
	require.Nil(t, err)
	assert.Equal(t, fmt.Sprintf("%v", qr.Rows[0][1]), fmt.Sprintf(`BLOB("%s")`, tablet.Alias))
	assert.Equal(t, fmt.Sprintf("%v", qr.Rows[1][1]), fmt.Sprintf(`BLOB("%s.%s")`, ksName, shardName))
	assert.Equal(t, fmt.Sprintf("%v", qr.Rows[2][1]), fmt.Sprintf(`BLOB("%s")`, cell))
	if tablet.Type == "replica" {
		assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("neutral")`)
	} else if tablet.Type == "rdonly" {
		assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("must_not")`)
	}
}

// ListBackups Lists back preset in shard
func (cluster LocalProcessCluster) ListBackups(shardKsName string) ([]string, error) {
	output, err := cluster.VtctlclientProcess.ExecuteCommandWithOutput("ListBackups", shardKsName)
	if err != nil {
		return nil, err
	}
	result := strings.Split(output, "\n")
	var returnResult []string
	for _, str := range result {
		if str != "" {
			returnResult = append(returnResult, str)
		}
	}
	return returnResult, nil
}

// VerifyBackupCount compares the backup count with expected count.
func (cluster LocalProcessCluster) VerifyBackupCount(t *testing.T, shardKsName string, expected int) []string {
	backups, err := cluster.ListBackups(shardKsName)
	require.Nil(t, err)
	assert.Equalf(t, expected, len(backups), "invalid number of backups")
	return backups
}

// RemoveAllBackups removes all the backup corresponds to list backup.
func (cluster LocalProcessCluster) RemoveAllBackups(t *testing.T, shardKsName string) {
	backups, err := cluster.ListBackups(shardKsName)
	require.Nil(t, err)
	for _, backup := range backups {
		cluster.VtctlclientProcess.ExecuteCommand("RemoveBackup", shardKsName, backup)
	}
}

// ResetTabletDirectory transitions back to tablet state (i.e. mysql process restarts with cleaned directory and tablet is off)
func ResetTabletDirectory(tablet Vttablet) error {
	tablet.MysqlctlProcess.Stop()
	tablet.VttabletProcess.TearDown()
	os.RemoveAll(tablet.VttabletProcess.Directory)

	return tablet.MysqlctlProcess.Start()
}

func getTablet(tabletGrpcPort int, hostname string) *tabletpb.Tablet {
	portMap := make(map[string]int32)
	portMap["grpc"] = int32(tabletGrpcPort)
	return &tabletpb.Tablet{Hostname: hostname, PortMap: portMap}
}

func filterResultWhenRunsForCoverage(input string) string {
	if !*isCoverage {
		return input
	}
	lines := strings.Split(input, "\n")
	var result string
	for _, line := range lines {
		if strings.Contains(line, "=== RUN") {
			continue
		}
		if strings.Contains(line, "--- PASS:") || strings.Contains(line, "PASS") {
			break
		}
		result = result + line + "\n"
	}
	return result
}

// WaitForReplicationPos will wait for replication position to catch-up
func WaitForReplicationPos(t *testing.T, tabletA *Vttablet, tabletB *Vttablet, hostname string, timeout float64) {
	replicationPosA, _ := GetMasterPosition(t, *tabletA, hostname)
	for {
		replicationPosB, _ := GetMasterPosition(t, *tabletB, hostname)
		if positionAtLeast(t, tabletA, replicationPosB, replicationPosA) {
			break
		}
		msg := fmt.Sprintf("%s's replication position to catch up to %s's;currently at: %s, waiting to catch up to: %s", tabletB.Alias, tabletA.Alias, replicationPosB, replicationPosA)
		waitStep(t, msg, timeout, 0.01)
	}
}

func waitStep(t *testing.T, msg string, timeout float64, sleepTime float64) float64 {
	timeout = timeout - sleepTime
	if timeout < 0.0 {
		t.Errorf("timeout waiting for condition '%s'", msg)
	}
	time.Sleep(time.Duration(sleepTime) * time.Second)
	return timeout
}

func positionAtLeast(t *testing.T, tablet *Vttablet, a string, b string) bool {
	isAtleast := false
	val, err := tablet.MysqlctlProcess.ExecuteCommandWithOutput("position", "at_least", a, b)
	require.NoError(t, err)
	if strings.Contains(val, "true") {
		isAtleast = true
	}
	return isAtleast
}

// ExecuteQueriesUsingVtgate sends query to vtgate using vtgate session.
func ExecuteQueriesUsingVtgate(t *testing.T, session *vtgateconn.VTGateSession, query string) {
	_, err := session.Execute(context.Background(), query, nil)
	require.Nil(t, err)
}

// NewConnParams creates ConnParams corresponds to given arguments.
func NewConnParams(port int, password, socketPath, keyspace string) mysql.ConnParams {
	if port != 0 {
		socketPath = ""
	}
	cp := mysql.ConnParams{
		Uname:      "vt_dba",
		Port:       port,
		UnixSocket: socketPath,
		Pass:       password,
	}

	if keyspace != "" {
		cp.DbName = "vt_" + keyspace
	}

	return cp

}
<commit_msg>added nil check<commit_after>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"context"
	"fmt"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/stretchr/testify/require"
	"vitess.io/vitess/go/mysql"
	tabletpb "vitess.io/vitess/go/vt/proto/topodata"
	"vitess.io/vitess/go/vt/vtgate/vtgateconn"
	tmc "vitess.io/vitess/go/vt/vttablet/grpctmclient"
)

var (
	tmClient = tmc.NewClient()
)

// Restart restarts vttablet and mysql.
func (tablet *Vttablet) Restart() error {
	if tablet.MysqlctlProcess.TabletUID|tablet.MysqlctldProcess.TabletUID == 0 {
		return fmt.Errorf("no mysql process is running")
	}

	if tablet.MysqlctlProcess.TabletUID > 0 {
		tablet.MysqlctlProcess.Stop()
		tablet.VttabletProcess.TearDown()
		os.RemoveAll(tablet.VttabletProcess.Directory)

		return tablet.MysqlctlProcess.Start()
	}

	tablet.MysqlctldProcess.Stop()
	tablet.VttabletProcess.TearDown()
	os.RemoveAll(tablet.VttabletProcess.Directory)

	return tablet.MysqlctldProcess.Start()
}

// ValidateTabletRestart restarts the tablet and validate error if there is any.
func (tablet *Vttablet) ValidateTabletRestart(t *testing.T) {
	require.Nilf(t, tablet.Restart(), "tablet restart failed")
}

// GetMasterPosition gets the master position of required vttablet
func GetMasterPosition(t *testing.T, vttablet Vttablet, hostname string) (string, string) {
	ctx := context.Background()
	vtablet := getTablet(vttablet.GrpcPort, hostname)
	pos, err := tmClient.MasterPosition(ctx, vtablet)
	require.Nil(t, err)
	gtID := strings.SplitAfter(pos, "/")[1]
	return pos, gtID
}

// VerifyRowsInTabletForTable Verify total number of rows in a table
// this is used to check replication caught up the changes from master
func VerifyRowsInTabletForTable(t *testing.T, vttablet *Vttablet, ksName string, expectedRows int, tableName string) {
	timeout := time.Now().Add(10 * time.Second)
	for time.Now().Before(timeout) {
		// ignoring the error check, if the newly created table is not replicated, then there might be error and we should ignore it
		// but eventually it will catch up and if not caught up in required time, testcase will fail
		qr, _ := vttablet.VttabletProcess.QueryTablet("select * from "+tableName, ksName, true)
		if qr != nil && len(qr.Rows) == expectedRows {
			return
		}
		time.Sleep(300 * time.Millisecond)
	}
	assert.Fail(t, "expected rows not found.")
}

// VerifyRowsInTablet Verify total number of rows in a tablet
func VerifyRowsInTablet(t *testing.T, vttablet *Vttablet, ksName string, expectedRows int) {
	VerifyRowsInTabletForTable(t, vttablet, ksName, expectedRows, "vt_insert_test")
}

// PanicHandler handles the panic in the testcase.
func PanicHandler(t *testing.T) {
	err := recover()
	if t == nil {
		return
	}
	require.Nilf(t, err, "panic occured in testcase %v", t.Name())
}

// VerifyLocalMetadata Verify Local Metadata of a tablet
func VerifyLocalMetadata(t *testing.T, tablet *Vttablet, ksName string, shardName string, cell string) {
	qr, err := tablet.VttabletProcess.QueryTablet("select * from _vt.local_metadata", ksName, false)
	require.Nil(t, err)
	assert.Equal(t, fmt.Sprintf("%v", qr.Rows[0][1]), fmt.Sprintf(`BLOB("%s")`, tablet.Alias))
	assert.Equal(t, fmt.Sprintf("%v", qr.Rows[1][1]), fmt.Sprintf(`BLOB("%s.%s")`, ksName, shardName))
	assert.Equal(t, fmt.Sprintf("%v", qr.Rows[2][1]), fmt.Sprintf(`BLOB("%s")`, cell))
	if tablet.Type == "replica" {
		assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("neutral")`)
	} else if tablet.Type == "rdonly" {
		assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("must_not")`)
	}
}

// ListBackups Lists back preset in shard
func (cluster LocalProcessCluster) ListBackups(shardKsName string) ([]string, error) {
	output, err := cluster.VtctlclientProcess.ExecuteCommandWithOutput("ListBackups", shardKsName)
	if err != nil {
		return nil, err
	}
	result := strings.Split(output, "\n")
	var returnResult []string
	for _, str := range result {
		if str != "" {
			returnResult = append(returnResult, str)
		}
	}
	return returnResult, nil
}

// VerifyBackupCount compares the backup count with expected count.
func (cluster LocalProcessCluster) VerifyBackupCount(t *testing.T, shardKsName string, expected int) []string {
	backups, err := cluster.ListBackups(shardKsName)
	require.Nil(t, err)
	assert.Equalf(t, expected, len(backups), "invalid number of backups")
	return backups
}

// RemoveAllBackups removes all the backup corresponds to list backup.
func (cluster LocalProcessCluster) RemoveAllBackups(t *testing.T, shardKsName string) {
	backups, err := cluster.ListBackups(shardKsName)
	require.Nil(t, err)
	for _, backup := range backups {
		cluster.VtctlclientProcess.ExecuteCommand("RemoveBackup", shardKsName, backup)
	}
}

// ResetTabletDirectory transitions back to tablet state (i.e. mysql process restarts with cleaned directory and tablet is off)
func ResetTabletDirectory(tablet Vttablet) error {
	tablet.MysqlctlProcess.Stop()
	tablet.VttabletProcess.TearDown()
	os.RemoveAll(tablet.VttabletProcess.Directory)

	return tablet.MysqlctlProcess.Start()
}

func getTablet(tabletGrpcPort int, hostname string) *tabletpb.Tablet {
	portMap := make(map[string]int32)
	portMap["grpc"] = int32(tabletGrpcPort)
	return &tabletpb.Tablet{Hostname: hostname, PortMap: portMap}
}

func filterResultWhenRunsForCoverage(input string) string {
	if !*isCoverage {
		return input
	}
	lines := strings.Split(input, "\n")
	var result string
	for _, line := range lines {
		if strings.Contains(line, "=== RUN") {
			continue
		}
		if strings.Contains(line, "--- PASS:") || strings.Contains(line, "PASS") {
			break
		}
		result = result + line + "\n"
	}
	return result
}

// WaitForReplicationPos will wait for replication position to catch-up
func WaitForReplicationPos(t *testing.T, tabletA *Vttablet, tabletB *Vttablet, hostname string, timeout float64) {
	replicationPosA, _ := GetMasterPosition(t, *tabletA, hostname)
	for {
		replicationPosB, _ := GetMasterPosition(t, *tabletB, hostname)
		if positionAtLeast(t, tabletA, replicationPosB, replicationPosA) {
			break
		}
		msg := fmt.Sprintf("%s's replication position to catch up to %s's;currently at: %s, waiting to catch up to: %s", tabletB.Alias, tabletA.Alias, replicationPosB, replicationPosA)
		waitStep(t, msg, timeout, 0.01)
	}
}

func waitStep(t *testing.T, msg string, timeout float64, sleepTime float64) float64 {
	timeout = timeout - sleepTime
	if timeout < 0.0 {
		t.Errorf("timeout waiting for condition '%s'", msg)
	}
	time.Sleep(time.Duration(sleepTime) * time.Second)
	return timeout
}

func positionAtLeast(t *testing.T, tablet *Vttablet, a string, b string) bool {
	isAtleast := false
	val, err := tablet.MysqlctlProcess.ExecuteCommandWithOutput("position", "at_least", a, b)
	require.NoError(t, err)
	if strings.Contains(val, "true") {
		isAtleast = true
	}
	return isAtleast
}

// ExecuteQueriesUsingVtgate sends query to vtgate using vtgate session.
func ExecuteQueriesUsingVtgate(t *testing.T, session *vtgateconn.VTGateSession, query string) {
	_, err := session.Execute(context.Background(), query, nil)
	require.Nil(t, err)
}

// NewConnParams creates ConnParams corresponds to given arguments.
func NewConnParams(port int, password, socketPath, keyspace string) mysql.ConnParams {
	if port != 0 {
		socketPath = ""
	}
	cp := mysql.ConnParams{
		Uname:      "vt_dba",
		Port:       port,
		UnixSocket: socketPath,
		Pass:       password,
	}

	if keyspace != "" {
		cp.DbName = "vt_" + keyspace
	}

	return cp

}
<|endoftext|>