// Copyright 2018-2018 Amazon.com, Inc. or its affiliates. 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. A copy of the License is located at
//
//     http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 cfg

import (
	"errors"

	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
)

var errFile = "error.log"
var tstFileName = "test_config.yaml"
var tstFilePath string
var version2 = 2
var version1 = 1

func setupTestCase() {
	LogFile = errFile
}

func tearTestCase() {
	LogFile = ""
	os.Remove(errFile)
}

func setupTestFile(cnfg string) (string, error) {
	goPath := os.Getenv("PWD")
	if goPath == "" {
		panic("GOPATH not set")
	}
	tstFilePath = goPath + "/" + tstFileName
	f, err := os.Create(tstFilePath)
	if err != nil {
		panic(err)
	}
	f.WriteString(cnfg)
	f.Close()
	return goPath, err
}

func clearTestFile() {
	os.Remove(tstFilePath)
}
func TestLoadConfigFromBytes(t *testing.T) {
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:2000"
  TCPAddress: "127.0.0.1:2000"
TotalBufferSizeMB: 16
Region: "us-east-1"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8
Logging:
  LogRotation: true
  LogPath: ""
  LogLevel: "prod"
NoVerifySSL: false
LocalMode: false
ProxyAddress: ""
Version: 2`

	c := loadConfigFromBytes([]byte(configString))

	assert.EqualValues(t, c.Socket.UDPAddress, "127.0.0.1:2000")
	assert.EqualValues(t, c.Socket.TCPAddress, "127.0.0.1:2000")
	assert.EqualValues(t, c.TotalBufferSizeMB, 16)
	assert.EqualValues(t, c.Region, "us-east-1")
	assert.EqualValues(t, c.Endpoint, "https://xxxx.xxxx.com")
	assert.EqualValues(t, c.ResourceARN, "")
	assert.EqualValues(t, c.RoleARN, "")
	assert.EqualValues(t, c.Concurrency, 8)
	assert.EqualValues(t, c.Logging.LogLevel, "prod")
	assert.EqualValues(t, c.Logging.LogPath, "")
	assert.EqualValues(t, *c.Logging.LogRotation, true)
	assert.EqualValues(t, *c.NoVerifySSL, false)
	assert.EqualValues(t, *c.LocalMode, false)
	assert.EqualValues(t, c.ProxyAddress, "")
	assert.EqualValues(t, c.Version, version2)
}

func TestLoadConfigFromBytesTypeError(t *testing.T) {
	configString :=
		`TotalBufferSizeMB: NotExist`

	// Only run the failing part when a specific env variable is set
	if os.Getenv("Test_Bytes") == "1" {
		loadConfigFromBytes([]byte(configString))
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestLoadConfigFromBytesTypeError")
	cmd.Env = append(os.Environ(), "Test_Bytes=1")
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}

	// Check that the program exited
	err := cmd.Wait()
	if e, ok := err.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}
}

func TestLoadConfigFromFile(t *testing.T) {
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:2000"
  TCPAddress: "127.0.0.1:2000"
TotalBufferSizeMB: 16
Region: "us-east-1"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8
Logging:
  LogRotation: true
  LogPath: ""
  LogLevel: "prod"
NoVerifySSL: false
LocalMode: false
ProxyAddress: ""
Version: 2`
	setupTestFile(configString)

	c := loadConfigFromFile(tstFilePath)

	assert.EqualValues(t, c.Socket.UDPAddress, "127.0.0.1:2000")
	assert.EqualValues(t, c.TotalBufferSizeMB, 16)
	assert.EqualValues(t, c.Region, "us-east-1")
	assert.EqualValues(t, c.Endpoint, "https://xxxx.xxxx.com")
	assert.EqualValues(t, c.ResourceARN, "")
	assert.EqualValues(t, c.RoleARN, "")
	assert.EqualValues(t, c.Concurrency, 8)
	assert.EqualValues(t, c.Logging.LogLevel, "prod")
	assert.EqualValues(t, c.Logging.LogPath, "")
	assert.EqualValues(t, *c.Logging.LogRotation, true)
	assert.EqualValues(t, *c.NoVerifySSL, false)
	assert.EqualValues(t, *c.LocalMode, false)
	assert.EqualValues(t, c.ProxyAddress, "")
	assert.EqualValues(t, c.Version, version2)

	clearTestFile()
}

func TestLoadConfigFromFileDoesNotExist(t *testing.T) {
	setupTestCase()
	testFile := "test_config_does_not_exist_121213.yaml"

	// Only run the failing part when a specific env variable is set
	if os.Getenv("Test_Bytes") == "1" {
		loadConfigFromFile(testFile)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestLoadConfigFromFileDoesNotExist")
	cmd.Env = append(os.Environ(), "Test_Bytes=1")
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}

	// Check that the program exited
	err := cmd.Wait()
	if e, ok := err.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}
	tearTestCase()
}

func TestLoadConfigVersion1(t *testing.T) {
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:2000"
TotalBufferSizeMB: 16
Region: "us-east-1"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8
Logging:
  LogRotation: true
  LogPath: ""
  LogLevel: "prod"
NoVerifySSL: false
LocalMode: false
ProxyAddress: ""
Version: 1`
	setupTestFile(configString)
	configLocations = append([]string{tstFilePath}, configLocations...)

	c := LoadConfig("")

	assert.EqualValues(t, c.Socket.UDPAddress, "127.0.0.1:2000")
	assert.EqualValues(t, c.Socket.TCPAddress, "127.0.0.1:2000") // TCP address for V! cfg.yaml
	assert.EqualValues(t, c.TotalBufferSizeMB, 16)
	assert.EqualValues(t, c.Region, "us-east-1")
	assert.EqualValues(t, c.Endpoint, "https://xxxx.xxxx.com")
	assert.EqualValues(t, c.ResourceARN, "")
	assert.EqualValues(t, c.RoleARN, "")
	assert.EqualValues(t, c.Concurrency, 8)
	assert.EqualValues(t, c.Logging.LogLevel, "prod")
	assert.EqualValues(t, c.Logging.LogPath, "")
	assert.EqualValues(t, *c.Logging.LogRotation, true)
	assert.EqualValues(t, *c.NoVerifySSL, false)
	assert.EqualValues(t, *c.LocalMode, false)
	assert.EqualValues(t, c.ProxyAddress, "")
	assert.EqualValues(t, c.Version, version1)
	clearTestFile()
}

func TestLoadConfigVersion2(t *testing.T) {
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:2000"
  TCPAddress : "127.0.0.2:3000"
TotalBufferSizeMB: 16
Region: "us-east-1"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8
Logging:
  LogRotation: true
  LogPath: ""
  LogLevel: "prod"
NoVerifySSL: false
LocalMode: false
ProxyAddress: ""
Version: 2`
	setupTestFile(configString)
	configLocations = append([]string{tstFilePath}, configLocations...)

	c := LoadConfig("")

	assert.EqualValues(t, c.Socket.UDPAddress, "127.0.0.1:2000")
	assert.EqualValues(t, c.Socket.TCPAddress, "127.0.0.2:3000")
	assert.EqualValues(t, c.TotalBufferSizeMB, 16)
	assert.EqualValues(t, c.Region, "us-east-1")
	assert.EqualValues(t, c.Endpoint, "https://xxxx.xxxx.com")
	assert.EqualValues(t, c.ResourceARN, "")
	assert.EqualValues(t, c.RoleARN, "")
	assert.EqualValues(t, c.Concurrency, 8)
	assert.EqualValues(t, c.Logging.LogLevel, "prod")
	assert.EqualValues(t, c.Logging.LogPath, "")
	assert.EqualValues(t, *c.Logging.LogRotation, true)
	assert.EqualValues(t, *c.NoVerifySSL, false)
	assert.EqualValues(t, *c.LocalMode, false)
	assert.EqualValues(t, c.ProxyAddress, "")
	assert.EqualValues(t, c.Version, version2)
	clearTestFile()
}

func TestLoadConfigFileNotPresent(t *testing.T) {
	configLocations = []string{"test_config_does_not_exist_989078070.yaml"}

	c := LoadConfig("")

	assert.NotNil(t, c)
	// If files config files are not present return default config
	assert.EqualValues(t, DefaultConfig(), c)
}

func TestMergeUserConfigWithDefaultConfig(t *testing.T) {
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:3000"
TotalBufferSizeMB: 8
Region: "us-east-2"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8
Logging:
  LogRotation: false
Version: 2`
	setupTestFile(configString)
	c := merge(tstFilePath)

	assert.EqualValues(t, c.Socket.UDPAddress, "127.0.0.1:3000")
	assert.EqualValues(t, c.Socket.TCPAddress, "127.0.0.1:2000") // set to default value
	assert.EqualValues(t, c.TotalBufferSizeMB, 8)
	assert.EqualValues(t, c.Region, "us-east-2")
	assert.EqualValues(t, c.Endpoint, "https://xxxx.xxxx.com")
	assert.EqualValues(t, c.ResourceARN, "")
	assert.EqualValues(t, c.RoleARN, "")
	assert.EqualValues(t, c.Concurrency, 8)
	assert.EqualValues(t, c.Logging.LogLevel, "prod")
	assert.EqualValues(t, c.Logging.LogPath, "")
	assert.EqualValues(t, *c.Logging.LogRotation, false)
	assert.EqualValues(t, *c.NoVerifySSL, false)
	assert.EqualValues(t, *c.LocalMode, false)
	assert.EqualValues(t, c.ProxyAddress, "")
	assert.EqualValues(t, c.Version, version2)
	clearTestFile()
}

func TestConfigVersionNotSet(t *testing.T) {
	setupTestCase()
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:3000"
TotalBufferSizeMB: 8
Region: "us-east-2"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8`

	goPath, err := setupTestFile(configString)

	// Only run the failing part when a specific env variable is set
	if os.Getenv("TEST_CONFIG_VERSION_NOT_SET") == "1" {
		ConfigValidation(tstFilePath)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestConfigVersionNotSet")
	cmd.Env = append(os.Environ(), "TEST_CONFIG_VERSION_NOT_SET=1")
	if cmdErr := cmd.Start(); cmdErr != nil {
		t.Fatal(cmdErr)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}

	// Check if the log message is what we expected
	if _, logErr := os.Stat(goPath + "/" + errFile); os.IsNotExist(logErr) {
		t.Fatal(logErr)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "Config Version is missing."
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	clearTestFile()
	tearTestCase()
}

func TestConfigUnsupportedVersionSet(t *testing.T) {
	setupTestCase()
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:3000"
TotalBufferSizeMB: 8
Region: "us-east-2"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8
Version: 10000`

	goPath, err := setupTestFile(configString)

	// Only run the failing part when a specific env variable is set
	if os.Getenv("TEST_CONFIG_UNSUPPORTED_VERSION") == "1" {
		merge(tstFilePath)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestConfigUnsupportedVersionSet")
	cmd.Env = append(os.Environ(), "TEST_CONFIG_UNSUPPORTED_VERSION=1")
	if cmdErr := cmd.Start(); cmdErr != nil {
		t.Fatal(cmdErr)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}

	// Check if the log message is what we expected
	if _, logErr := os.Stat(goPath + "/" + errFile); os.IsNotExist(logErr) {
		t.Fatal(logErr)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "Config Version Setting is not correct."
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	clearTestFile()
	tearTestCase()
}

func TestUseMemoryLimitInConfig(t *testing.T) {
	setupTestCase()
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:3000"
MemoryLimit: 8
Region: "us-east-2"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Concurrency: 8
Version: 2`

	goPath, err := setupTestFile(configString)

	// Only run the failing part when a specific env variable is set
	if os.Getenv("TEST_USE_MEMORYLIMIT_FLAG") == "1" {
		ConfigValidation(tstFilePath)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestUseMemoryLimitInConfig")
	cmd.Env = append(os.Environ(), "TEST_USE_MEMORYLIMIT_FLAG=1")
	if cmdErr := cmd.Start(); cmdErr != nil {
		t.Fatal(cmdErr)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}

	// Check if the log message is what we expected
	if _, logErr := os.Stat(goPath + "/" + errFile); os.IsNotExist(logErr) {
		t.Fatal(logErr)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "MemoryLimit flag is not supported."
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	clearTestFile()
	tearTestCase()
}

func TestConfigValidationForNotSupportFlags(t *testing.T) {
	setupTestCase()
	configString :=
		`Socket:
  BufferSizeKB: 128
Version: 2`

	goPath, err := setupTestFile(configString)

	// Only run the failing part when a specific env variable is set
	if os.Getenv("TEST_NOT_SUPPORT_FLAG") == "1" {
		ConfigValidation(tstFilePath)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestConfigValidationForNotSupportFlags")
	cmd.Env = append(os.Environ(), "TEST_NOT_SUPPORT_FLAG=1")
	if cmdErr := cmd.Start(); cmdErr != nil {
		t.Fatal(cmdErr)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}

	// Check if the log message is what we expected
	if _, logErr := os.Stat(goPath + "/" + errFile); os.IsNotExist(logErr) {
		t.Fatal(logErr)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "Socket.BufferSizeKB flag is not supported any more."
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	clearTestFile()
	tearTestCase()
}

func TestConfigValidationForNeedMigrationFlag(t *testing.T) {
	setupTestCase()
	configString :=
		`Processor:
  Region: ""
Version: 2`

	goPath, err := setupTestFile(configString)

	// Only run the failing part when a specific env variable is set
	if os.Getenv("TEST_NEED_MIGRATION_FLAG") == "1" {
		ConfigValidation(tstFilePath)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestConfigValidationForNeedMigrationFlag")
	cmd.Env = append(os.Environ(), "TEST_NEED_MIGRATION_FLAG=1")
	if cmdErr := cmd.Start(); cmdErr != nil {
		t.Fatal(cmdErr)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}

	// Check if the log message is what we expected
	if _, logErr := os.Stat(goPath + "/" + errFile); os.IsNotExist(logErr) {
		t.Fatal(logErr)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "Processor.Region flag is not supported. Use X-Ray Daemon Config Migration Script to update the config file."
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	clearTestFile()
	tearTestCase()
}

func TestConfigValidationForInvalidFlag(t *testing.T) {
	setupTestCase()
	configString := `ABCDE: true
Version: 2`

	goPath := os.Getenv("PWD")
	if goPath == "" {
		panic("GOPATH not set")
	}
	testFile := goPath + "/test_config.yaml"
	f, err := os.Create(testFile)
	if err != nil {
		panic(err)
	}
	f.WriteString(configString)
	f.Close()

	// Only run the failing part when a specific env variable is set
	if os.Getenv("TEST_INVALID_FLAG") == "1" {
		ConfigValidation(testFile)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestConfigValidationForInvalidFlag")
	cmd.Env = append(os.Environ(), "TEST_INVALID_FLAG=1")
	if cmdErr := cmd.Start(); cmdErr != nil {
		t.Fatal(cmdErr)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", err)
	}

	// Check if the log message is what we expected
	if _, logErr := os.Stat(goPath + "/" + errFile); os.IsNotExist(logErr) {
		t.Fatal(logErr)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "ABCDE flag is invalid."
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	os.Remove(testFile)
	tearTestCase()
}

func TestValidConfigArray(t *testing.T) {
	validString := []string{"TotalBufferSizeMB", "Concurrency", "Endpoint", "Region", "Socket.UDPAddress", "Socket.TCPAddress", "ProxyServer.IdleConnTimeout", "ProxyServer.MaxIdleConnsPerHost", "ProxyServer.MaxIdleConns", "Logging.LogRotation", "Logging.LogLevel", "Logging.LogPath", "LocalMode", "ResourceARN", "RoleARN", "NoVerifySSL", "ProxyAddress", "Version"}
	testString := validConfigArray()
	if len(validString) != len(testString) {
		t.Fatalf("Unexpect test array length. Got %v but should be %v", len(testString), len(validString))
	}
	for i, v := range validString {
		if !strings.EqualFold(v, testString[i]) {
			t.Fatalf("Unexpect Flag in test array. Got %v but should be %v", testString[i], v)
		}
	}
}

func TestUserConfigArray(t *testing.T) {
	configString :=
		`Socket:
  UDPAddress: "127.0.0.1:3000"
MemoryLimit: 8
Region: "us-east-2"
Endpoint: "https://xxxx.xxxx.com"
ResourceARN: ""
RoleARN: ""
Version: 2`

	setupTestFile(configString)

	validString := []string{"Socket.UDPAddress", "MemoryLimit", "Region", "Endpoint", "ResourceARN", "RoleARN", "Version"}
	testString := userConfigArray(tstFilePath)
	if len(validString) != len(testString) {
		t.Fatalf("Unexpect test array length. Got %v but should be %v", len(testString), len(validString))
	}
	for i, v := range validString {
		if v != testString[i] {
			t.Fatalf("Unexpect Flag in test array. Got %v but should be %v", testString[i], v)
		}
	}
	clearTestFile()
}

func TestErrorAndExitForGivenString(t *testing.T) {
	setupTestCase()
	// Only run the failing part when a specific env variable is set
	if os.Getenv("TEST_STRING_ERROR") == "1" {
		errorAndExit("error occurred", nil)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestErrorAndExitForGivenString")
	cmd.Env = append(os.Environ(), "TEST_STRING_ERROR=1")
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", e)
	}

	// Check if the log message is what we expected
	goPath := os.Getenv("PWD")
	if goPath == "" {
		panic("GOPATH not set")
	}
	if _, err := os.Stat(goPath + "/" + errFile); os.IsNotExist(err) {
		t.Fatal(err)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "error occurred"
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	tearTestCase()
}

func TestErrorAndExitForGivenError(t *testing.T) {
	setupTestCase()
	if os.Getenv("TEST_ERROR") == "1" {
		err := errors.New("this is an error")
		errorAndExit("", err)
		return
	}

	// Start the actual test in a different subprocess
	cmd := exec.Command(os.Args[0], "-test.run=TestErrorAndExitForGivenError")
	cmd.Env = append(os.Environ(), "TEST_ERROR=1")
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}

	// Check that the program exited
	error := cmd.Wait()
	if e, ok := error.(*exec.ExitError); !ok || e.Success() {
		t.Fatalf("Process ran with err %v, want exit status 1", e)
	}

	// Check if the log message is what we expected
	goPath := os.Getenv("PWD")
	if goPath == "" {
		panic("GOPATH not set")
	}
	if _, err := os.Stat(goPath + "/" + errFile); os.IsNotExist(err) {
		t.Fatal(err)
	}
	gotBytes, err := ioutil.ReadFile(goPath + "/" + errFile)
	if err != nil {
		t.Fatal(err)
	}
	got := string(gotBytes)
	expected := "this is an error"
	if !strings.Contains(got, expected) {
		t.Fatalf("Unexpected log message. Got %s but should contain %s", got, expected)
	}
	tearTestCase()
}
