<commit_before>package peer

import (
	"strconv"

	log "github.com/Sirupsen/logrus"
	upnp "github.com/huin/goupnp"
	ig1 "github.com/huin/goupnp/dcps/internetgateway1"
	ig2 "github.com/huin/goupnp/dcps/internetgateway2"
)

var (
	// DiscoveredDevices is a list of devices that responded to our UPnP discovery
	// broadcast. Note that most of them will only support some UPnP services.
	DiscoveredDevices []upnp.MaybeRootDevice
	// ServiceClients is a list of clients we can use to communicate with UPnP
	// devices on the local network
	ServiceClients []upnp.ServiceClient
	// Forwarding1Clients is a list of clients we can use to access the UPnP services
	// offered by the devices on this network
	Forwarding1Clients []ig1.Layer3Forwarding1
)

// DiscoverDevices will search for devices available for UPnP communication.
func DiscoverDevices() {
	log.Debug("Starting uPnP device discovery...")

	// Get a list of devices that may or may not support UPnP services
	mrd, err := upnp.DiscoverDevices(ig2.URN_WANIPConnection_2)
	if err != nil {
		log.WithError(err).Fatal("An error occurred during device discovery")
	}
	log.Debug("Discovered ", len(mrd), " devices")
	for _, maybeRootDevice := range mrd {
		DiscoveredDevices = append(DiscoveredDevices, maybeRootDevice)
		log.Debug(maybeRootDevice.Location.String())
	}

	// Get a list of services clients that we can use to communicate with the
	// devices on our network using SOAP
	ServiceClients, errors, err := upnp.NewServiceClients(ig2.URN_WANIPConnection_1)
	if err != nil {
		log.WithError(err).Fatal("An error occurred while getting service clients")
	} else if len(errors) > 0 && log.GetLevel() == log.DebugLevel {
		logFields := log.Fields{}
		for i, err := range errors {
			logFields[strconv.Itoa(i+1)] = err
		}
		log.WithFields(logFields).Warning(len(errors), " error(s) occurred while getting service clients")
	}

	if len(ServiceClients) > 0 {
		log.Debug("Service clients:")
		for _, serviceClient := range ServiceClients {
			log.Debug(serviceClient.Location.String())
		}
	}

	log.Debug("Retreiving layer 3 forwarding clients...")
	Forwarding1Clients, err := layer3Forwarding1Clients()
	if err != nil {
		log.WithError(err).Error("An error occurred while retreiving layer 2 forwarding client(s)")
	} else if log.GetLevel() == log.DebugLevel {
		log.Debug("Found ", len(Forwarding1Clients), " layer 3 forwarding client(s)")
	}
}

func layer3Forwarding1Clients() ([]*ig1.Layer3Forwarding1, error) {
	clients, errors, err := ig1.NewLayer3Forwarding1Clients()
	if err != nil {
		return nil, err
	} else if len(errors) > 0 && log.GetLevel() == log.DebugLevel {
		logFields := log.Fields{}
		for i, err := range errors {
			logFields[strconv.Itoa(i+1)] = err
		}
		log.WithFields(logFields).Warn(len(errors), " error(s) occurred retreiving layer 3 service clients")
	}

	return clients, nil
}

func ActionMap() map[*ig1.Layer3Forwarding1]string {
	actionMap := make(map[*ig1.Layer3Forwarding1]string)

	for _, client := range Forwarding1Clients {
		actionMap[&client] = client.Service.String()
	}

	return actionMap
}
<commit_msg>Remove upnp hacks<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/arn"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/mbndr/logo"
	"github.com/mmmorris1975/aws-runas/lib"
	"os"
	"runtime"
	"testing"
	"time"
)

func init() {
	os.Unsetenv("AWS_PROFILE")
	os.Unsetenv("AWS_DEFAULT_PROFILE")
	os.Unsetenv("AWS_REGION")
}

func TestAwsProfile(t *testing.T) {
	os.Setenv("AWS_CONFIG_FILE", "lib/config/test/aws.cfg")
	defer os.Unsetenv("AWS_CONFIG_FILE")

	cm, err := lib.NewAwsConfigManager(new(lib.ConfigManagerOptions))
	if err != nil {
		t.Errorf("Error from NewAwsConfigManager(): %v", err)
	}

	u := &iam.User{UserName: aws.String("mock-user"), UserId: aws.String("mock-user")}

	t.Run("basic", func(t *testing.T) {
		_, err = awsProfile(cm, "basic", u)
		if err != nil {
			t.Errorf("Unexpected error from awsProfile(): %v", err)
		}
	})
	t.Run("arnValid", func(t *testing.T) {
		_, err = awsProfile(cm, "arn:aws:iam::1234:role/mock", u)
		if err != nil {
			t.Errorf("Unexpected error from awsProfile() with ARN: %v", err)
		}
	})
	t.Run("arnBad", func(t *testing.T) {
		// Anything that fails arn.Parse() gets treated like a profile name
		p, err := awsProfile(cm, "x", u)
		if err == nil {
			t.Errorf("Did not get expected error from awsProfile() with bad profile, got %+v", p)
		}
	})
	t.Run("ArnNotIam", func(t *testing.T) {
		_, err = awsProfile(cm, "arn:aws:s3:::a", u)
		if err == nil {
			t.Errorf("Did not get expected error from awsProfile() with bad ARN")
		}
	})
	t.Run("NameEmpty", func(t *testing.T) {
		os.Setenv("AWS_DEFAULT_PROFILE", "alt_default")
		defer os.Unsetenv("AWS_DEFAULT_PROFILE")
		p, err := awsProfile(cm, "", u)
		if err != nil {
			t.Errorf("Unexpected error from awsProfile() with empty profile: %v", err)
		}
		if p.Name != "alt_default" || p.Region != "us-west-1" || p.MfaSerial != "12345678" {
			t.Errorf("Unexpected result from awsProfile() with empty profile: %+v", err)
		}
	})
}

func TestAssumeRoleInput(t *testing.T) {
	t.Run("Default", func(t *testing.T) {
		i := assumeRoleInput(new(lib.AWSProfile))
		if *i.DurationSeconds != 3600 {
			t.Errorf("Expected default DurationSeconds to be 3600, got %d", *i.DurationSeconds)
		}
	})
	t.Run("NilProfile", func(t *testing.T) {
		defer func() {
			if x := recover(); x == nil {
				t.Errorf("Did not receive expected panic when using nil AWSProfile")
			}
		}()
		assumeRoleInput(nil)
	})
}

func ExampleAssumeRoleInput() {
	a, err := arn.Parse("arn:aws:iam::666:role/mock")
	if err != nil {
		panic(err)
	}
	p := lib.AWSProfile{
		RoleArn:         a,
		RoleSessionName: "mock-session",
		ExternalId:      "mock-ext-id",
		CredDuration:    1 * time.Hour,
	}

	i := assumeRoleInput(&p)
	fmt.Println(*i.RoleArn)
	fmt.Println(*i.RoleSessionName)
	fmt.Println(*i.ExternalId)
	fmt.Println(*i.DurationSeconds)
	// Output:
	// arn:aws:iam::666:role/mock
	// mock-session
	// mock-ext-id
	// 3600
}

func ExamplePrintCredentials() {
	switch runtime.GOOS {
	case "windows":
		return
	}

	p := lib.AWSProfile{Region: "us-east-1", Name: "mock"}
	c := credentials.Value{
		AccessKeyID:     "MockKey",
		SecretAccessKey: "MockSecret",
		SessionToken:    "MockSession",
	}
	updateEnv(c, p.Region)
	printCredentials()
	// Output:
	// export AWS_REGION='us-east-1'
	// export AWS_DEFAULT_REGION='us-east-1'
	// export AWS_ACCESS_KEY_ID='MockKey'
	// export AWS_SECRET_ACCESS_KEY='MockSecret'
	// export AWS_SESSION_TOKEN='MockSession'
	// export AWS_SECURITY_TOKEN='MockSession'
}

func ExamplePrintCredentialsNoSession() {
	os.Setenv("AWS_SESSION_TOKEN", "bogus")
	defer os.Unsetenv("AWS_SESSION_TOKEN")

	p := lib.AWSProfile{Region: "us-east-1", Name: "mock"}
	c := credentials.Value{
		AccessKeyID:     "MockKey",
		SecretAccessKey: "MockSecret",
	}
	updateEnv(c, p.Region)
	printCredentials()
	// Output:
	// export AWS_REGION='us-east-1'
	// export AWS_DEFAULT_REGION='us-east-1'
	// export AWS_ACCESS_KEY_ID='MockKey'
	// export AWS_SECRET_ACCESS_KEY='MockSecret'
}

func ExamplePrintExpire() {
	p := lib.NewSessionTokenProvider(new(lib.AWSProfile), new(lib.CachedCredentialsProviderOptions))

	// Prints to stderr, so output will be empty
	printExpire(p)
	// Output:
	//
}

func TestCredProvider(t *testing.T) {
	log = logo.NewSimpleLogger(os.Stderr, logo.DEBUG, "TestCredProvider", true)
	t.Run("SessionToken", func(t *testing.T) {
		p := credProvider(new(lib.AWSProfile))
		o := fmt.Sprintf("%T", p)
		if o != "*lib.sessionTokenProvider" {
			t.Errorf("Unexpected type, got %s", o)
		}
	})
	t.Run("AssumeRole", func(t *testing.T) {
		a, _ := arn.Parse("arn:aws:iam::666:role/mock")
		p := credProvider(&lib.AWSProfile{RoleArn: a})
		o := fmt.Sprintf("%T", p)
		if o != "*lib.assumeRoleProvider" {
			t.Errorf("Unexpected type, got %s", o)
		}
	})
}
<commit_msg>Add more test coverage for main<commit_after>package main

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/arn"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/mbndr/logo"
	"github.com/mmmorris1975/aws-runas/lib"
	"os"
	"runtime"
	"testing"
	"time"
)

func init() {
	os.Unsetenv("AWS_PROFILE")
	os.Unsetenv("AWS_DEFAULT_PROFILE")
	os.Unsetenv("AWS_REGION")
}

func TestAwsProfile(t *testing.T) {
	os.Setenv("AWS_CONFIG_FILE", "lib/config/test/aws.cfg")
	defer os.Unsetenv("AWS_CONFIG_FILE")

	cm, err := lib.NewAwsConfigManager(new(lib.ConfigManagerOptions))
	if err != nil {
		t.Errorf("Error from NewAwsConfigManager(): %v", err)
	}

	u := &iam.User{UserName: aws.String("mock-user"), UserId: aws.String("mock-user")}

	t.Run("basic", func(t *testing.T) {
		_, err = awsProfile(cm, "basic", u)
		if err != nil {
			t.Errorf("Unexpected error from awsProfile(): %v", err)
		}
	})
	t.Run("arnValid", func(t *testing.T) {
		_, err = awsProfile(cm, "arn:aws:iam::1234:role/mock", u)
		if err != nil {
			t.Errorf("Unexpected error from awsProfile() with ARN: %v", err)
		}
	})
	t.Run("arnBad", func(t *testing.T) {
		// Anything that fails arn.Parse() gets treated like a profile name
		p, err := awsProfile(cm, "x", u)
		if err == nil {
			t.Errorf("Did not get expected error from awsProfile() with bad profile, got %+v", p)
		}
	})
	t.Run("ArnNotIam", func(t *testing.T) {
		_, err = awsProfile(cm, "arn:aws:s3:::a", u)
		if err == nil {
			t.Errorf("Did not get expected error from awsProfile() with bad ARN")
		}
	})
	t.Run("NameEmpty", func(t *testing.T) {
		os.Setenv("AWS_DEFAULT_PROFILE", "alt_default")
		defer os.Unsetenv("AWS_DEFAULT_PROFILE")
		p, err := awsProfile(cm, "", u)
		if err != nil {
			t.Errorf("Unexpected error from awsProfile() with empty profile: %v", err)
		}
		if p.Name != "alt_default" || p.Region != "us-west-1" || p.MfaSerial != "12345678" {
			t.Errorf("Unexpected result from awsProfile() with empty profile: %+v", err)
		}
	})
}

func TestAssumeRoleInput(t *testing.T) {
	t.Run("Default", func(t *testing.T) {
		i := assumeRoleInput(new(lib.AWSProfile))
		if *i.DurationSeconds != 3600 {
			t.Errorf("Expected default DurationSeconds to be 3600, got %d", *i.DurationSeconds)
		}
	})
	t.Run("NilProfile", func(t *testing.T) {
		defer func() {
			if x := recover(); x == nil {
				t.Errorf("Did not receive expected panic when using nil AWSProfile")
			}
		}()
		assumeRoleInput(nil)
	})
}

func ExampleAssumeRoleInput() {
	a, err := arn.Parse("arn:aws:iam::666:role/mock")
	if err != nil {
		panic(err)
	}
	p := lib.AWSProfile{
		RoleArn:         a,
		RoleSessionName: "mock-session",
		ExternalId:      "mock-ext-id",
		CredDuration:    1 * time.Hour,
	}

	i := assumeRoleInput(&p)
	fmt.Println(*i.RoleArn)
	fmt.Println(*i.RoleSessionName)
	fmt.Println(*i.ExternalId)
	fmt.Println(*i.DurationSeconds)
	// Output:
	// arn:aws:iam::666:role/mock
	// mock-session
	// mock-ext-id
	// 3600
}

func ExamplePrintCredentials() {
	switch runtime.GOOS {
	case "windows":
		return
	}

	p := lib.AWSProfile{Region: "us-east-1", Name: "mock"}
	c := credentials.Value{
		AccessKeyID:     "MockKey",
		SecretAccessKey: "MockSecret",
		SessionToken:    "MockSession",
	}
	updateEnv(c, p.Region)
	printCredentials()
	// Output:
	// export AWS_REGION='us-east-1'
	// export AWS_DEFAULT_REGION='us-east-1'
	// export AWS_ACCESS_KEY_ID='MockKey'
	// export AWS_SECRET_ACCESS_KEY='MockSecret'
	// export AWS_SESSION_TOKEN='MockSession'
	// export AWS_SECURITY_TOKEN='MockSession'
}

func ExamplePrintCredentialsNoSession() {
	os.Setenv("AWS_SESSION_TOKEN", "bogus")
	defer os.Unsetenv("AWS_SESSION_TOKEN")

	p := lib.AWSProfile{Region: "us-east-1", Name: "mock"}
	c := credentials.Value{
		AccessKeyID:     "MockKey",
		SecretAccessKey: "MockSecret",
	}
	updateEnv(c, p.Region)
	printCredentials()
	// Output:
	// export AWS_REGION='us-east-1'
	// export AWS_DEFAULT_REGION='us-east-1'
	// export AWS_ACCESS_KEY_ID='MockKey'
	// export AWS_SECRET_ACCESS_KEY='MockSecret'
}

func ExamplePrintExpire() {
	p := lib.NewSessionTokenProvider(new(lib.AWSProfile), new(lib.CachedCredentialsProviderOptions))

	// Prints to stderr, so output will be empty
	printExpire(p)
	// Output:
	//
}

func TestCredProvider(t *testing.T) {
	log = logo.NewSimpleLogger(os.Stderr, logo.DEBUG, "TestCredProvider", true)
	t.Run("SessionToken", func(t *testing.T) {
		p := credProvider(new(lib.AWSProfile))
		o := fmt.Sprintf("%T", p)
		if o != "*lib.sessionTokenProvider" {
			t.Errorf("Unexpected type, got %s", o)
		}
	})
	t.Run("AssumeRole", func(t *testing.T) {
		a, _ := arn.Parse("arn:aws:iam::666:role/mock")
		p := credProvider(&lib.AWSProfile{RoleArn: a})
		o := fmt.Sprintf("%T", p)
		if o != "*lib.assumeRoleProvider" {
			t.Errorf("Unexpected type, got %s", o)
		}
	})
}

func TestLookupMfa(t *testing.T) {
	t.Run("StaticSerial", func(t *testing.T) {
		serial := "arn:aws:iam::012345678910:mfa/DEADBEEF"
		mfaArn = aws.String(serial)
		m := lookupMfa(nil)
		if *m != serial {
			t.Errorf("Mismatched static MFA serial: expected %s, got %s", serial, *m)
		}
	})
}

func TestWrapCmd(t *testing.T) {
	t.Run("ExistingBinary", func(t *testing.T) {
		cmd := []string{"true"}
		wrap := wrapCmd(&cmd)
		if (*wrap)[0] != cmd[0] {
			t.Errorf("Unexpected result when wrapping existing binary command")
		}
	})
	t.Run("BogusBinary", func(t *testing.T) {
		cmd := []string{"not_a_command.123"}
		wrap := wrapCmd(&cmd)
		if (*wrap)[0] == cmd[0] {
			t.Errorf("Expected invalid command to be wrapped, but it wasn't")
		}
	})
}
<|endoftext|>


<commit_before>package main

import (
	"testing"

	"github.com/kyokomi/gomajan/mjp"
	"reflect"
	"fmt"
)

type TestCase struct {
	in  []mjp.Tehai
	out []mjp.Yaku
}

func TestYakuCheck(t *testing.T) {
	testCases := []TestCase{
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1:  2,
				mjp.S9:  1,
				mjp.P1:  1,
				mjp.P9:  1,
				mjp.M1:  1,
				mjp.M9:  1,
				mjp.TON: 1,
				mjp.NAN: 1,
				mjp.SHA: 1,
				mjp.PEI: 1,
				mjp.HAK: 1,
				mjp.HAT: 1,
				mjp.CHN: 1,
			}),
			out: []mjp.Yaku{mjp.M_国士無双},
		},
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1:  2,
				mjp.S2:  2,
				mjp.M3:  2,
				mjp.M4:  2,
				mjp.P5:  2,
				mjp.P6:  2,
				mjp.TON: 2,
			}),
			out: []mjp.Yaku{mjp.M_七対子},
		},
		// ソーズ清一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1: 2,
				mjp.S2: 2,
				mjp.S3: 2,
				mjp.S4: 1,
				mjp.S5: 1,
				mjp.S6: 1,
				mjp.S7: 3,
				mjp.S9: 2,
			}),
			out: []mjp.Yaku{mjp.M_清一色},
		},
		// マンズ清一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.M1: 2,
				mjp.M2: 2,
				mjp.M3: 2,
				mjp.M4: 1,
				mjp.M5: 1,
				mjp.M6: 1,
				mjp.M7: 3,
				mjp.M9: 2,
			}),
			out: []mjp.Yaku{mjp.M_清一色},
		},
		// ピンズ清一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.P1: 2,
				mjp.P2: 2,
				mjp.P3: 2,
				mjp.P4: 1,
				mjp.P5: 1,
				mjp.P6: 1,
				mjp.P7: 3,
				mjp.P9: 2,
			}),
			out: []mjp.Yaku{mjp.M_清一色},
		},
		// ソーズ混一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1: 2,
				mjp.S2: 2,
				mjp.S3: 2,
				mjp.S4: 1,
				mjp.S5: 1,
				mjp.S6: 1,
				mjp.S7: 3,
				mjp.HAK: 2,
			}),
			out: []mjp.Yaku{mjp.M_混一色},
		},
		// マンズ混一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.M1: 2,
				mjp.M2: 2,
				mjp.M3: 2,
				mjp.M4: 1,
				mjp.M5: 1,
				mjp.M6: 1,
				mjp.M7: 3,
				mjp.TON: 2,
			}),
			out: []mjp.Yaku{mjp.M_混一色},
		},
		// ピンズ混一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.P1: 2,
				mjp.P2: 2,
				mjp.P3: 2,
				mjp.P4: 1,
				mjp.P5: 1,
				mjp.P6: 1,
				mjp.P7: 3,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_混一色},
		},
		// 断么九
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.P2: 1,
				mjp.P3: 1,
				mjp.P4: 1,
				mjp.S4: 1,
				mjp.S5: 1,
				mjp.S6: 1,
				mjp.M7: 3,
				mjp.P8: 2,
			}),
			out: []mjp.Yaku{mjp.M_断么九},
		},
		// 緑一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S2: 2,
				mjp.S3: 2,
				mjp.S4: 2,
				mjp.S6: 3,
				mjp.HAT: 3,
				mjp.S8: 2,
			}),
			out: []mjp.Yaku{mjp.M_緑一色},
		},
		// 大三元
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S2: 1,
				mjp.S3: 1,
				mjp.S4: 1,
				mjp.P5: 2,
				mjp.HAK: 3,
				mjp.HAT: 3,
				mjp.CHN: 3,
			}),
			out: []mjp.Yaku{mjp.M_大三元},
		},
		// 字一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 2,
				mjp.NAN: 2,
				mjp.SHA: 2,
				mjp.PEI: 2,
				mjp.HAK: 2,
				mjp.HAT: 2,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_字一色},
		},
		// TODO: 副露考慮したら、あとで四暗刻なくす
		// 大四喜
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.NAN: 3,
				mjp.SHA: 3,
				mjp.PEI: 3,
				mjp.P1: 2,
			}),
			out: []mjp.Yaku{mjp.M_大四喜, mjp.M_四暗刻},
		},
		// 小四喜
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.NAN: 3,
				mjp.SHA: 3,
				mjp.PEI: 2,
				mjp.P1: 1,
				mjp.P2: 1,
				mjp.P3: 1,
			}),
			out: []mjp.Yaku{mjp.M_小四喜},
		},
		// 四暗刻
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.S1: 3,
				mjp.S5: 3,
				mjp.P9: 3,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_四暗刻},
		},
		// 三暗刻
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.S1: 3,
				mjp.S5: 3,
				mjp.P7: 1,
				mjp.P8: 1,
				mjp.P9: 1,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_三暗刻},
		},
		// TODO: 副露考慮したら、あとで四暗刻なくす
		// 清老頭
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1: 2,
				mjp.P1: 3,
				mjp.P9: 3,
				mjp.M1: 3,
				mjp.M9: 3,
			}),
			out: []mjp.Yaku{mjp.M_四暗刻, mjp.M_清老頭},
		},
		// 小三元
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S2: 1,
				mjp.S3: 1,
				mjp.S4: 1,
				mjp.P5: 1,
				mjp.P6: 1,
				mjp.P7: 1,
				mjp.HAK: 3,
				mjp.HAT: 3,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_小三元},
		},
	}

	for _, testCase := range testCases {
		p := mjp.NewPlayer(testCase.in)

		y := p.NewYakuCheck()

		if reflect.DeepEqual(y.Yakus(), testCase.out) {
			fmt.Println(" => ", y.String())
		} else {
			t.Error(testCase.out, "!= ", y.Yakus(), " error 手牌 => ", p)
		}
	}
}
<commit_msg>test: テストデータ不備を修正<commit_after>package main

import (
	"testing"

	"github.com/kyokomi/gomajan/mjp"
	"reflect"
	"fmt"
)

type TestCase struct {
	in  []mjp.Tehai
	out []mjp.Yaku
}

func TestYakuCheck(t *testing.T) {
	testCases := []TestCase{
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1:  2,
				mjp.S9:  1,
				mjp.P1:  1,
				mjp.P9:  1,
				mjp.M1:  1,
				mjp.M9:  1,
				mjp.TON: 1,
				mjp.NAN: 1,
				mjp.SHA: 1,
				mjp.PEI: 1,
				mjp.HAK: 1,
				mjp.HAT: 1,
				mjp.CHN: 1,
			}),
			out: []mjp.Yaku{mjp.M_国士無双},
		},
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1:  2,
				mjp.S2:  2,
				mjp.M3:  2,
				mjp.M4:  2,
				mjp.P5:  2,
				mjp.P6:  2,
				mjp.TON: 2,
			}),
			out: []mjp.Yaku{mjp.M_七対子},
		},
		// ソーズ清一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1: 2,
				mjp.S2: 2,
				mjp.S3: 2,
				mjp.S4: 1,
				mjp.S5: 1,
				mjp.S6: 1,
				mjp.S7: 3,
				mjp.S9: 2,
			}),
			out: []mjp.Yaku{mjp.M_清一色},
		},
		// マンズ清一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.M1: 2,
				mjp.M2: 2,
				mjp.M3: 2,
				mjp.M4: 1,
				mjp.M5: 1,
				mjp.M6: 1,
				mjp.M7: 3,
				mjp.M9: 2,
			}),
			out: []mjp.Yaku{mjp.M_清一色},
		},
		// ピンズ清一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.P1: 2,
				mjp.P2: 2,
				mjp.P3: 2,
				mjp.P4: 1,
				mjp.P5: 1,
				mjp.P6: 1,
				mjp.P7: 3,
				mjp.P9: 2,
			}),
			out: []mjp.Yaku{mjp.M_清一色},
		},
		// ソーズ混一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1: 2,
				mjp.S2: 2,
				mjp.S3: 2,
				mjp.S4: 1,
				mjp.S5: 1,
				mjp.S6: 1,
				mjp.S7: 3,
				mjp.HAK: 2,
			}),
			out: []mjp.Yaku{mjp.M_混一色},
		},
		// マンズ混一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.M1: 2,
				mjp.M2: 2,
				mjp.M3: 2,
				mjp.M4: 1,
				mjp.M5: 1,
				mjp.M6: 1,
				mjp.M7: 3,
				mjp.TON: 2,
			}),
			out: []mjp.Yaku{mjp.M_混一色},
		},
		// ピンズ混一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.P1: 2,
				mjp.P2: 2,
				mjp.P3: 2,
				mjp.P4: 1,
				mjp.P5: 1,
				mjp.P6: 1,
				mjp.P7: 3,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_混一色},
		},
		// 断么九
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.P2: 1,
				mjp.P3: 1,
				mjp.P4: 1,
				mjp.S4: 1,
				mjp.S5: 1,
				mjp.S6: 1,
				mjp.M7: 3,
				mjp.S7: 3,
				mjp.P8: 2,
			}),
			out: []mjp.Yaku{mjp.M_断么九},
		},
		// 緑一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S2: 2,
				mjp.S3: 2,
				mjp.S4: 2,
				mjp.S6: 3,
				mjp.HAT: 3,
				mjp.S8: 2,
			}),
			out: []mjp.Yaku{mjp.M_緑一色},
		},
		// 大三元
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S2: 1,
				mjp.S3: 1,
				mjp.S4: 1,
				mjp.P5: 2,
				mjp.HAK: 3,
				mjp.HAT: 3,
				mjp.CHN: 3,
			}),
			out: []mjp.Yaku{mjp.M_大三元},
		},
		// 字一色
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 2,
				mjp.NAN: 2,
				mjp.SHA: 2,
				mjp.PEI: 2,
				mjp.HAK: 2,
				mjp.HAT: 2,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_字一色},
		},
		// TODO: 副露考慮したら、あとで四暗刻なくす
		// 大四喜
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.NAN: 3,
				mjp.SHA: 3,
				mjp.PEI: 3,
				mjp.P1: 2,
			}),
			out: []mjp.Yaku{mjp.M_大四喜, mjp.M_四暗刻},
		},
		// 小四喜
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.NAN: 3,
				mjp.SHA: 3,
				mjp.PEI: 2,
				mjp.P1: 1,
				mjp.P2: 1,
				mjp.P3: 1,
			}),
			out: []mjp.Yaku{mjp.M_小四喜},
		},
		// 四暗刻
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.S1: 3,
				mjp.S5: 3,
				mjp.P9: 3,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_四暗刻},
		},
		// 三暗刻
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.TON: 3,
				mjp.S1: 3,
				mjp.S5: 3,
				mjp.P7: 1,
				mjp.P8: 1,
				mjp.P9: 1,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_三暗刻},
		},
		// TODO: 副露考慮したら、あとで四暗刻なくす
		// 清老頭
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S1: 2,
				mjp.P1: 3,
				mjp.P9: 3,
				mjp.M1: 3,
				mjp.M9: 3,
			}),
			out: []mjp.Yaku{mjp.M_四暗刻, mjp.M_清老頭},
		},
		// 小三元
		TestCase{
			in: mjp.NewTehai(map[mjp.MJP]int{
				mjp.S2: 1,
				mjp.S3: 1,
				mjp.S4: 1,
				mjp.P5: 1,
				mjp.P6: 1,
				mjp.P7: 1,
				mjp.HAK: 3,
				mjp.HAT: 3,
				mjp.CHN: 2,
			}),
			out: []mjp.Yaku{mjp.M_小三元},
		},
	}

	for _, testCase := range testCases {
		p := mjp.NewPlayer(testCase.in)

		y := p.NewYakuCheck()

		if reflect.DeepEqual(y.Yakus(), testCase.out) {
			fmt.Println(" => ", y.String())
		} else {
			t.Error(testCase.out, "!= ", y.Yakus(), " error 手牌 => ", p)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"testing"
	"time"
)

type MockInput struct {
	data  [][]byte
	index int
}

func NewMockInput(data [][]byte) *MockInput {
	return &MockInput{data: data, index: 0}
}

func (in *MockInput) ReadLine() (error, []byte) {
	if in.index >= len(in.data) {
		fmt.Println("EOF")
		return io.EOF, nil
	}
	result := in.data[in.index]
	in.index++
	return nil, result
}

func (in *MockInput) Close() {}

type MockDB struct {
	data bytes.Buffer
}

func (d *MockDB) Query(query string) (error, *InfluxQueryResult) {
	fmt.Printf("Would GET %v\n", query)
	var r InfluxQueryResult
	return nil, &r
}

func (d *MockDB) AddValue(stationId int, key string, value float64) {
	fmt.Fprintf(&d.data, "%s,station=%d value=%f\n", key, stationId, value)
}

func (d *MockDB) AddText(key, value string, timestamp time.Time) {
	fmt.Fprintf(&d.data, "%s text=\"%s\" %d", key, value, timestamp.UnixNano())
}

func (d *MockDB) Save() error {
	fmt.Printf("Would POST %v\n", d.data.String())
	d.data.Reset()
	return nil
}

func TestMain(m *testing.M) {
	s := "{ \"weather\": { \"station-id\": 1, \"temp_m\": 727, " +
		"\"rh-true_m\": 7223, \"pressure-nn_c\": 10078, \"rain-cupfills\": 133 } }"

	in := NewMockInput([][]byte{[]byte(s)})
	db := &MockDB{}
	logger := log.New(os.Stdout, "", log.LstdFlags)

	Consume(in, db, logger)
}
<commit_msg>Fix broken main tests.<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"testing"
	"time"
)

type MockInput struct {
	data  [][]byte
	index int
}

func NewMockInput(data [][]byte) *MockInput {
	return &MockInput{data: data, index: 0}
}

func (in *MockInput) ReadLine() (error, []byte) {
	if in.index >= len(in.data) {
		fmt.Println("EOF")
		return io.EOF, nil
	}
	result := in.data[in.index]
	in.index++
	return nil, result
}

func (in *MockInput) Close() {}

type MockDB struct {
	data bytes.Buffer
}

func (d *MockDB) Query(query string) (error, *InfluxQueryResult) {
	fmt.Printf("Would GET %v\n", query)
	var r InfluxQueryResult
	return nil, &r
}

func (d *MockDB) AddValue(stationId int, key string, value float64) {
	fmt.Fprintf(&d.data, "%s,station=%d value=%f\n", key, stationId, value)
}

func (ic *MockDB) AddText(key, value string, tags []TSDBTuple, timestamp time.Time) {
	var b bytes.Buffer
	for _, el := range tags {
		fmt.Fprintf(&b, ",%s=%s", el.key, el.val) // First colon separates measurement from tags
	}
	fmt.Fprintf(&ic.data, "%s%s text=\"%s\" %d", key, b.String(), value, timestamp.UnixNano())
}

func (d *MockDB) Save() error {
	fmt.Printf("Would POST %v\n", d.data.String())
	d.data.Reset()
	return nil
}

func TestMain(m *testing.M) {
	s := "{ \"weather\": { \"station-id\": 1, \"temp_m\": 727, " +
		"\"rh-true_m\": 7223, \"pressure-nn_c\": 10078, \"rain-cupfills\": 133 } }"

	in := NewMockInput([][]byte{[]byte(s)})
	db := &MockDB{}
	logger := log.New(os.Stdout, "", log.LstdFlags)

	Consume(in, db, logger)
}
<|endoftext|>


<commit_before>package main

import "testing"

func TestNothing(t *testing.T) {

}
<commit_msg>Basic benchmarking<commit_after>package main

import (
	"github.com/minotar/minecraft"
	"testing"
)

func TestNothing(t *testing.T) {

}

func BenchmarkGetHead(b *testing.B) {
	skin := fetchSkin("clone1018")
	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		GetHead(skin)
	}
}

func BenchmarkGetHelm(b *testing.B) {
	skin := fetchSkin("clone1018")
	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		GetHelm(skin)
	}
}

func BenchmarkGetBody(b *testing.B) {
	skin := fetchSkin("clone1018")
	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		GetBody(skin)
	}
}
<|endoftext|>


<commit_before>package main
<commit_msg>Add sample manifest, test ValidateManifests<commit_after>package main

import (
	"os"
	"testing"
)

const ManifestFilename = "test-manifest.yml"
const Manifest string = `---
name: The Project
meta:
  team: Project Devs
  email: devs@project.com
  slack: devs
vars:
  - version
  - assets_version
  - owner
tasks:
  - name: Deploy Postgres
    manifests:
      - postgres-rc
      - postgres-service
  - name: Deploy Redis
    manifests:
      - redis-rc
      - redis-service
  - name: Database Setup
    pod_manifest:
      - createdb-pod
    wait_for:
      - success
    when: new_deployment
  - name: Database Migration
    pod_manifest:
      - migration-pod
    wait_for:
      - success
  - name: Deploy Project
    manifests:
      - web-rc
      - web-service
      - sidekiq-rc
`

func TestPass(t *testing.T) {
	//t.Succeed()
}
func TestFail(t *testing.T) {
	//t.Fail()
}

func TestMain(m *testing.M) {
	f, _ := os.Create(ManifestFilename)
	f.Write([]byte(Manifest))
	f.Close()
	tres := m.Run()
	teardown()
	os.Exit(tres)
}
func teardown() {
	os.Remove(ManifestFilename)
}

func TestValidateManifestCorrect(t *testing.T) {

	TestTask := Task{
		Name: ManifestFilename,
	}
	err := TestTask.ValidateManifests()
	if err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"
	"testing"
)
import (
	garray "github.com/hraberg/cljs.go/goog/array"
	gobject "github.com/hraberg/cljs.go/goog/object"
	gstring "github.com/hraberg/cljs.go/goog/string"
	"github.com/hraberg/cljs.go/js"
	"github.com/hraberg/cljs.go/js/Math"
	"github.com/stretchr/testify/assert"
)
import . "github.com/hraberg/cljs.go/cljs/core"

/*
;; IFn

;; Used in core.cljs apply, which uses apply-to built by core.clj gen-apply-to.
;; It falls back to JS .apply it applyTo doesn't exist on the passed in fn.
.-cljs$lang$maxFixedArity ;; a field on the fn
.-cljs$lang$applyTo ;; accessed as field to see if it's there
.cljs$lang$applyTo  ;; then called as fn if it exists.

;; Used by the dispatch fn to actually invoke the various overloaded fns, uses JS arguments in a switch.
;; See emit* :fn and emit* :invoke
;; emit* :fn will emit a single fn or a dispatch fn around the real overlaoded fns.
;; At times these are called directly, like cljs.core.str.cljs$core$IFn$_invoke$arity$1(~{}) in cljs.core/str
.cljs$core$IFn$_invoke$arity$variadic
.cljs$core$IFn$_invoke$arity$N

;; defprotocol

.-cljs$lang$protocol_mask$partitionN$

;; deftype

.-cljs$lang$type
.-cljs$lang$ctorStr
.-cljs$lang$ctorPrWriter

*/

func Main(args ...interface{}) interface{} {
	return nil
}

func MainPreamble() {
	Enable_console_print_BANG_()
	var args = make([]interface{}, len(os.Args[1:]))
	for i, a := range os.Args[1:] {
		args[i] = a
	}
	Main(args...)
}

func Test_JS(t *testing.T) {
	js.Console.Log("Javascript", "Rules", Math.Random(), js.Infinity, js.Number.MAX_VALUE,
		Math.Ceil(2.6), Math.Imul(2.3, 6.7), js.String.FromCharCode(65, 66, 67))
	js.Console.Log(js.RegExp{"hello", "i"}.Exec("World Hello Hello"), js.RegExp{"Hello", ""}.Exec("World") == nil)
	js.Console.Log(js.JSString("Hello World").Replace(js.RegExp{"hello", "i"},
		func(match string) string {
			return strings.ToUpper(match)
		},
	))
	js.Console.Log(js.JSString("Hello World").Search(js.RegExp{"world", "i"}))
	js.Console.Log(js.RegExp{"Hello", "i"})

	var date = js.Date{1407962432671}
	js.Console.Log(date.GetUTCFullYear())
	js.Console.Log(date.GetUTCMonth())
	js.Console.Log(date.GetUTCDate())
	js.Console.Log(date.GetUTCHours())
	js.Console.Log(date.GetUTCMinutes())
	js.Console.Log(date.GetUTCSeconds())
	js.Console.Log(date.GetUTCMilliseconds())
	js.Console.Log(date)

	js.Console.Log(js.ParseFloat("3.14"))
	js.Console.Log(js.ParseFloat(""))
	js.Console.Log(js.ParseInt("314", 10))
	js.Console.Log(js.ParseInt("x", 10))

	var is = []interface{}{1.0, 2.0, 3.0, 4.0, 5.0}
	garray.Shuffle(is)
	js.Console.Log(is)
	garray.StableSort(is, func(a, b interface{}) interface{} { return a.(float64) - b.(float64) })
	js.Console.Log(is)
	garray.Shuffle(is)
	js.Console.Log(is)
	garray.StableSort(is, garray.DefaultCompare)
	js.Console.Log(is)

	var ss = []interface{}{"foo", "bar"}
	garray.StableSort(ss, garray.DefaultCompare)
	js.Console.Log(ss)

	var obj = gobject.Create("foo", 2, "bar", 3)
	js.Console.Log(obj)
	gobject.ForEach(obj, func(k, v, obj interface{}) interface{} {
		js.Console.Log("k:", k, "v:", v, "in", obj)
		return nil
	})

	var sb = gstring.StringBuffer{}
	js.Console.Log(sb.Append("Hello Java").Append("Script World").ToString())
	js.Console.Log(sb.String())

	js.Console.Log(js.JSString("Hello").CharAt(2))
	js.Console.Log(js.JSString("Hello").CharCodeAt(2))

	js.Console.Log(gstring.HashCode("Hello World"))
}

func init() {
	MainPreamble()
}

var Foo_cljs__lang__maxFixedArity = 1

func init() {
	Foo_cljs__core__IFn___invoke__arity__1 = func(x interface{}) interface{} {
		return fmt.Sprint("Hello ", x)
	}
	Foo_cljs__core__IFn___invoke__arity__variadic = func(x interface{}, xs ...interface{}) interface{} {
		return fmt.Sprint("Hello ", x, xs)
	}

	Foo = func(arguments ...interface{}) interface{} {
		var l = len(arguments)
		switch {
		case l > 1:
			return Foo_cljs__core__IFn___invoke__arity__variadic(arguments[0], arguments[1:]...)
		case l == 1:
			return Foo_cljs__core__IFn___invoke__arity__1(arguments[0])
		}
		panic(js.Error{fmt.Sprint("Invalid arity: ", len(arguments))})
	}
}

var Foo_cljs__core__IFn___invoke__arity__1 func(interface{}) interface{}
var Foo_cljs__core__IFn___invoke__arity__variadic func(interface{}, ...interface{}) interface{}
var Foo func(...interface{}) interface{}

func Foo_cljs__lang__applyTo(xs []interface{}) interface{} {
	return Foo(xs...)
}

func Test_Dispatch(t *testing.T) {
	assert.Equal(t, "Hello Space", Foo("Space"))
	assert.Equal(t, "Hello Space", Foo_cljs__core__IFn___invoke__arity__1("Space"))
	assert.Equal(t, "Hello Space[Hyper]", Foo("Space", "Hyper"))
	assert.Equal(t, "Hello Space[Hyper]", Foo_cljs__core__IFn___invoke__arity__variadic("Space", "Hyper"))
	assert.Equal(t, "Hello foo[bar]", Foo_cljs__lang__applyTo([]interface{}{"foo", "bar"}))
	assert.Panics(t, func() { Foo() })
}

func double(x interface{}) float64 {
	switch x.(type) {
	case int:
		return float64(x.(int))
	case int64:
		return float64(x.(int64))
	default:
		return x.(float64)
	}
}

func long(x interface{}) int64 {
	switch x.(type) {
	case int:
		return int64(x.(int))
	case float64:
		return int64(x.(float64))
	default:
		return x.(int64)
	}
}
<commit_msg>Not pretty, but will do<commit_after>package main

import (
	"fmt"
	"math"
	"os"
	"strings"
	"testing"
)
import (
	garray "github.com/hraberg/cljs.go/goog/array"
	gobject "github.com/hraberg/cljs.go/goog/object"
	gstring "github.com/hraberg/cljs.go/goog/string"
	"github.com/hraberg/cljs.go/js"
	"github.com/hraberg/cljs.go/js/Math"
	"github.com/stretchr/testify/assert"
)
import . "github.com/hraberg/cljs.go/cljs/core"

/*
;; IFn

;; Used in core.cljs apply, which uses apply-to built by core.clj gen-apply-to.
;; It falls back to JS .apply it applyTo doesn't exist on the passed in fn.
.-cljs$lang$maxFixedArity ;; a field on the fn
.-cljs$lang$applyTo ;; accessed as field to see if it's there
.cljs$lang$applyTo  ;; then called as fn if it exists.

;; Used by the dispatch fn to actually invoke the various overloaded fns, uses JS arguments in a switch.
;; See emit* :fn and emit* :invoke
;; emit* :fn will emit a single fn or a dispatch fn around the real overlaoded fns.
;; At times these are called directly, like cljs.core.str.cljs$core$IFn$_invoke$arity$1(~{}) in cljs.core/str
.cljs$core$IFn$_invoke$arity$variadic
.cljs$core$IFn$_invoke$arity$N

;; defprotocol

.-cljs$lang$protocol_mask$partitionN$

;; deftype

.-cljs$lang$type
.-cljs$lang$ctorStr
.-cljs$lang$ctorPrWriter

*/

func Main(args ...interface{}) interface{} {
	return nil
}

func MainPreamble() {
	Enable_console_print_BANG_()
	var args = make([]interface{}, len(os.Args[1:]))
	for i, a := range os.Args[1:] {
		args[i] = a
	}
	Main(args...)
}

func Test_JS(t *testing.T) {
	assert.Equal(t, math.Inf(1), js.Infinity)
	assert.Equal(t, math.MaxFloat64, js.Number.MAX_VALUE)
	assert.Equal(t, 0.6046602879796196, Math.Random())
	assert.Equal(t, 3, Math.Ceil(2.6))
	assert.Equal(t, 2, Math.Floor(2.6))
	assert.Equal(t, 12, Math.Imul(2.3, 6.7))
	assert.Equal(t, "ABC", js.String.FromCharCode(65, 66, 67))
	assert.Nil(t, js.RegExp{"Hello", ""}.Exec("World"))
	assert.Equal(t, []string{"Hello", "Hello"}, js.RegExp{"hello", "i"}.Exec("World Hello Hello"))
	assert.Equal(t, "HELLO World", (js.JSString("Hello World").Replace(js.RegExp{"hello", "i"},
		func(match string) string {
			return strings.ToUpper(match)
		},
	)))
	assert.Equal(t, 6, (js.JSString("Hello World").Search(js.RegExp{"world", "i"})))
	assert.Equal(t, "(?i)Hello", (js.RegExp{"Hello", "i"}).String())

	var date = js.Date{1407962432671}
	assert.Equal(t, 2014, date.GetUTCFullYear())
	assert.Equal(t, 7, date.GetUTCMonth())
	assert.Equal(t, 13, date.GetUTCDate())
	assert.Equal(t, 20, date.GetUTCHours())
	assert.Equal(t, 40, date.GetUTCMinutes())
	assert.Equal(t, 32, date.GetUTCSeconds())
	assert.Equal(t, 671, date.GetUTCMilliseconds())
	assert.Equal(t, "2014-08-13 21:40:32.000671 +0100 BST", date.String())

	assert.Equal(t, 3.14, js.ParseFloat("3.14"))
	assert.Equal(t, math.NaN(), js.ParseFloat(""))
	assert.Equal(t, 3, js.ParseInt("3", 10))
	assert.Equal(t, 10, js.ParseInt("a", 16))
	assert.Equal(t, math.NaN(), js.ParseInt("3.14", 10))
	assert.Equal(t, math.NaN(), js.ParseInt("x", 10))

	var is = []interface{}{1.0, 2.0, 3.0, 4.0, 5.0}
	garray.Shuffle(is)
	garray.StableSort(is, func(a, b interface{}) interface{} { return a.(float64) - b.(float64) })
	assert.Equal(t, []interface{}{5.0, 4.0, 3.0, 2.0, 1.0}, is)
	garray.Shuffle(is)
	garray.StableSort(is, garray.DefaultCompare)
	assert.Equal(t, []interface{}{1.0, 2.0, 3.0, 4.0, 5.0}, is)

	var ss = []interface{}{"foo", "bar"}
	garray.StableSort(ss, garray.DefaultCompare)
	assert.Equal(t, []interface{}{"bar", "foo"}, ss)

	var obj = gobject.Create("foo", 2, "bar", 3)
	var sb = gstring.StringBuffer{}
	gobject.ForEach(obj, func(k, v, obj interface{}) interface{} {
		sb.Append(fmt.Sprintf("k: %s v: %v in: %v ", k, v, obj))
		return nil
	})
	assert.True(t, "k: foo v: 2 in: map[foo:2 bar:3] k: bar v: 3 in: map[foo:2 bar:3] " == sb.String() ||
		"k: bar v: 3 in: map[foo:2 bar:3] k: foo v: 2 in: map[foo:2 bar:3] " == sb.String())

	sb = gstring.StringBuffer{}
	assert.Equal(t, "Hello JavaScript World", sb.Append("Hello Java").Append("Script World").ToString())
	assert.Equal(t, "Hello JavaScript World", sb.String())

	assert.Equal(t, "l", (js.JSString("Hello").CharAt(2)))
	assert.Equal(t, 108, (js.JSString("Hello").CharCodeAt(2)))
	assert.Equal(t, 3.012568359e+09, (gstring.HashCode("Hello World")))
}

func init() {
	MainPreamble()
}

var Foo_cljs__lang__maxFixedArity = 1

func init() {
	Foo_cljs__core__IFn___invoke__arity__1 = func(x interface{}) interface{} {
		return fmt.Sprint("Hello ", x)
	}
	Foo_cljs__core__IFn___invoke__arity__variadic = func(x interface{}, xs ...interface{}) interface{} {
		return fmt.Sprint("Hello ", x, xs)
	}

	Foo = func(arguments ...interface{}) interface{} {
		var l = len(arguments)
		switch {
		case l > 1:
			return Foo_cljs__core__IFn___invoke__arity__variadic(arguments[0], arguments[1:]...)
		case l == 1:
			return Foo_cljs__core__IFn___invoke__arity__1(arguments[0])
		}
		panic(js.Error{fmt.Sprint("Invalid arity: ", len(arguments))})
	}
}

var Foo_cljs__core__IFn___invoke__arity__1 func(interface{}) interface{}
var Foo_cljs__core__IFn___invoke__arity__variadic func(interface{}, ...interface{}) interface{}
var Foo func(...interface{}) interface{}

func Foo_cljs__lang__applyTo(xs []interface{}) interface{} {
	return Foo(xs...)
}

func Test_Dispatch(t *testing.T) {
	assert.Equal(t, "Hello Space", Foo("Space"))
	assert.Equal(t, "Hello Space", Foo_cljs__core__IFn___invoke__arity__1("Space"))
	assert.Equal(t, "Hello Space[Hyper]", Foo("Space", "Hyper"))
	assert.Equal(t, "Hello Space[Hyper]", Foo_cljs__core__IFn___invoke__arity__variadic("Space", "Hyper"))
	assert.Equal(t, "Hello foo[bar]", Foo_cljs__lang__applyTo([]interface{}{"foo", "bar"}))
	assert.Panics(t, func() { Foo() })
}

func double(x interface{}) float64 {
	switch x.(type) {
	case int:
		return float64(x.(int))
	case int64:
		return float64(x.(int64))
	default:
		return x.(float64)
	}
}

func long(x interface{}) int64 {
	switch x.(type) {
	case int:
		return int64(x.(int))
	case float64:
		return int64(x.(float64))
	default:
		return x.(int64)
	}
}
<|endoftext|>


<commit_before>package srcgraph

import (
	"bytes"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"sourcegraph.com/sourcegraph/srcgraph/buildstore"

	"testing"

	"github.com/aybabtme/color/brush"
)

var mode = flag.String("test.mode", "test", "[test|keep|gen] 'test' runs test as normal; keep keeps around generated test files for inspection after tests complete; 'gen' generates new expected test data")
var repoMatch = flag.String("test.repo", "", "only test `srcgraph make` for repos that contain this string")

func TestMakeCmd(t *testing.T) {
	// Since we exec `srcgraph`, make sure it's up-to-date.
	if out, err := exec.Command("make", "-C", "..", "srcgraph").CombinedOutput(); err != nil {
		t.Errorf("Failed to build srcgraph for `srcgraph make` tests: %s.\n\nOutput was:\n%s", err, out)
		return
	}

	const testReposDir = "testdata/repos"
	fis, err := ioutil.ReadDir("testdata/repos")
	if err != nil {
		t.Fatal(err)
	}
	n := 0
	for _, fi := range fis {
		if repoDir := fi.Name(); strings.Contains(repoDir, *repoMatch) {
			testMakeCmd(t, filepath.Join(testReposDir, repoDir))
			n++
		}
	}
	if n == 0 {
		t.Errorf("No TestMakeCmd cases were run. Did none match your constraint -test.match=%q?", *repoMatch)
	}
}

func testMakeCmd(t *testing.T, repoDir string) {
	// Update the git submodule automatically.
	cmd := exec.Command("git", "submodule", "update", filepath.Join("srcgraph", repoDir))
	cmd.Dir = ".."
	if out, err := cmd.CombinedOutput(); err != nil {
		t.Errorf("Failed to update git submodule for %s: %s.\n\nOutput was:\n%s", repoDir, err, out)
		return
	}

	repoName := filepath.Base(repoDir)

	// Directories for the actual ("got") and expected ("want") outputs.
	gotOutputDir := filepath.Join(repoDir, "../../repos-output/got", repoName)
	wantOutputDir := filepath.Join(repoDir, "../../repos-output/want", repoName)

	// Determine and wipe the desired output dir.
	var outputDir string
	if *mode == "gen" {
		outputDir = wantOutputDir
	} else {
		outputDir = gotOutputDir
	}
	outputDir, _ = filepath.Abs(outputDir)
	if err := os.RemoveAll(outputDir); err != nil {
		t.Fatal(err)
	}
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		t.Fatal(err)
	}

	// Symlink ${repoDir}/.sourcegraph-data/${commitID} to the desired output dir.
	origOutputDestDir := filepath.Join(repoDir, buildstore.BuildDataDirName, getHEADOrTipCommitID(t, repoDir))
	if err := os.Remove(origOutputDestDir); err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}
	if err := os.Symlink(outputDir, origOutputDestDir); err != nil {
		t.Error(err)
		return
	}
	defer func() {
		// Remove the symlink when we're done so the repo doesn't have
		// uncommitted changes.
		if err := os.Remove(origOutputDestDir); err != nil {
			t.Fatal(err)
		}
	}()

	// Run `srcgraph make`.
	var buf bytes.Buffer
	w := io.MultiWriter(&buf, os.Stderr)
	cmd = exec.Command("srcgraph", "-v", "make")
	cmd.Stderr, cmd.Stdout = w, w
	cmd.Dir = repoDir

	err := cmd.Run()
	if err != nil {
		t.Errorf("Command %v in %s failed: %s.\n\nOutput was:\n%s", cmd.Args, repoDir, err, buf.String())
		return
	}

	if *mode == "gen" {
		t.Errorf("Successfully generated expected output for %s in %s. (Triggering test error so you won't mistakenly interpret a 0 return code as a test success. Run without -test.mode=gen to run the test.)", repoName, wantOutputDir)
	} else {
		checkResults(t, repoName, gotOutputDir, wantOutputDir)
	}
}

func checkResults(t *testing.T, repoName, gotOutputDir, wantOutputDir string) {
	out, err := exec.Command("diff", "-ur", wantOutputDir, gotOutputDir).CombinedOutput()
	if err != nil || len(out) > 0 {
		t.Errorf("Diff failed for %s: %s.", repoName, err)
		if len(out) > 0 {
			t.Log(string(colorizeDiff(out)))
			t.Errorf("Output for %s differed from expected.", repoName)
		}
	} else {
		t.Logf(brush.Green(repoName + " PASS").String())
	}
}

func getHEADOrTipCommitID(t *testing.T, repoDir string) string {
	// TODO(sqs): assumes git
	cmd := exec.Command("git", "rev-parse", "HEAD")
	cmd.Dir = repoDir
	out, err := cmd.Output()
	if err != nil {
		t.Fatal(err)
	}
	return string(bytes.TrimSpace(out))
}

func colorizeDiff(diff []byte) []byte {
	lines := bytes.Split(diff, []byte{'\n'})
	for i, line := range lines {
		log.Printf("XXXXXX %q", line)
		if bytes.HasPrefix(line, []byte{'-'}) {
			lines[i] = []byte(brush.Red(string(line)).String())
		}
		if bytes.HasPrefix(line, []byte{'+'}) {
			lines[i] = []byte(brush.Green(string(line)).String())
		}
	}
	return bytes.Join(lines, []byte{'\n'})
}
<commit_msg>print errors immediately and parallelize<commit_after>package srcgraph

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	"sourcegraph.com/sourcegraph/srcgraph/buildstore"

	"testing"

	"github.com/aybabtme/color/brush"
)

var mode = flag.String("test.mode", "test", "[test|keep|gen] 'test' runs test as normal; keep keeps around generated test files for inspection after tests complete; 'gen' generates new expected test data")
var repoMatch = flag.String("test.repo", "", "only test `srcgraph make` for repos that contain this string")

func TestMakeCmd(t *testing.T) {
	// Since we exec `srcgraph`, make sure it's up-to-date.
	if out, err := exec.Command("make", "-C", "..", "srcgraph").CombinedOutput(); err != nil {
		t.Errorf("Failed to build srcgraph for `srcgraph make` tests: %s.\n\nOutput was:\n%s", err, out)
		return
	}

	const testReposDir = "testdata/repos"
	fis, err := ioutil.ReadDir("testdata/repos")
	if err != nil {
		t.Fatal(err)
	}
	n := 0
	var wg sync.WaitGroup
	for _, fi := range fis {
		if repoDir := fi.Name(); strings.Contains(repoDir, *repoMatch) {
			fullRepoDir := filepath.Join(testReposDir, repoDir)
			wg.Add(1)
			go func() {
				defer wg.Done()
				testMakeCmd(t, fullRepoDir)
			}()
			n++
		}
	}
	wg.Wait()
	if n == 0 {
		t.Errorf("No TestMakeCmd cases were run. Did none match your constraint -test.match=%q?", *repoMatch)
	}
}

func testMakeCmd(t *testing.T, repoDir string) {
	// Update the git submodule automatically.
	cmd := exec.Command("git", "submodule", "update", filepath.Join("srcgraph", repoDir))
	cmd.Dir = ".."
	if out, err := cmd.CombinedOutput(); err != nil {
		t.Errorf("Failed to update git submodule for %s: %s.\n\nOutput was:\n%s", repoDir, err, out)
		return
	}

	repoName := filepath.Base(repoDir)

	// Directories for the actual ("got") and expected ("want") outputs.
	gotOutputDir := filepath.Join(repoDir, "../../repos-output/got", repoName)
	wantOutputDir := filepath.Join(repoDir, "../../repos-output/want", repoName)

	// Determine and wipe the desired output dir.
	var outputDir string
	if *mode == "gen" {
		outputDir = wantOutputDir
	} else {
		outputDir = gotOutputDir
	}
	outputDir, _ = filepath.Abs(outputDir)
	if err := os.RemoveAll(outputDir); err != nil {
		t.Fatal(err)
	}
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		t.Fatal(err)
	}

	// Symlink ${repoDir}/.sourcegraph-data/${commitID} to the desired output dir.
	origOutputDestDir := filepath.Join(repoDir, buildstore.BuildDataDirName, getHEADOrTipCommitID(t, repoDir))
	if err := os.Mkdir(filepath.Dir(origOutputDestDir), 0755); err != nil && !os.IsExist(err) {
		t.Fatal(err)
	}
	if err := os.Remove(origOutputDestDir); err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}
	if err := os.Symlink(outputDir, origOutputDestDir); err != nil {
		t.Error(err)
		return
	}
	defer func() {
		// Remove the symlink when we're done so the repo doesn't have
		// uncommitted changes.
		if err := os.Remove(origOutputDestDir); err != nil {
			t.Fatal(err)
		}
	}()

	// Run `srcgraph make`.
	var w io.Writer
	var buf bytes.Buffer
	if testing.Verbose() {
		w = io.MultiWriter(&buf, os.Stderr)
	} else {
		w = &buf
	}
	cmd = exec.Command("srcgraph", "-v", "make")
	cmd.Stderr, cmd.Stdout = w, w
	cmd.Dir = repoDir

	err := cmd.Run()
	if err != nil {
		t.Errorf("Command %v in %s failed: %s.\n\nOutput was:\n%s", cmd.Args, repoDir, err, buf.String())
		return
	}

	if *mode == "gen" {
		t.Errorf("Successfully generated expected output for %s in %s. (Triggering test error so you won't mistakenly interpret a 0 return code as a test success. Run without -test.mode=gen to run the test.)", repoName, wantOutputDir)
	} else {
		checkResults(t, buf, repoName, gotOutputDir, wantOutputDir)
	}
}

func checkResults(t *testing.T, output bytes.Buffer, repoName, gotOutputDir, wantOutputDir string) {
	out, err := exec.Command("diff", "-ur", wantOutputDir, gotOutputDir).CombinedOutput()
	if err != nil || len(out) > 0 {
		t.Logf(brush.Red(repoName + " FAIL").String())
		t.Errorf("Diff failed for %s: %s.", repoName, err)
		if len(out) > 0 {
			fmt.Println(brush.Red(repoName + "FAIL"))
			fmt.Println(output.String())
			fmt.Println(string(colorizeDiff(out)))
			t.Errorf("Output for %s differed from expected.", repoName)
		}
	} else {
		t.Logf(brush.Green(repoName + " PASS").String())
	}
}

func getHEADOrTipCommitID(t *testing.T, repoDir string) string {
	// TODO(sqs): assumes git
	cmd := exec.Command("git", "rev-parse", "HEAD")
	cmd.Dir = repoDir
	out, err := cmd.Output()
	if err != nil {
		t.Fatal(err)
	}
	return string(bytes.TrimSpace(out))
}

func colorizeDiff(diff []byte) []byte {
	lines := bytes.Split(diff, []byte{'\n'})
	for i, line := range lines {
		if bytes.HasPrefix(line, []byte{'-'}) {
			lines[i] = []byte(brush.Red(string(line)).String())
		}
		if bytes.HasPrefix(line, []byte{'+'}) {
			lines[i] = []byte(brush.Green(string(line)).String())
		}
	}
	return bytes.Join(lines, []byte{'\n'})
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package client

import (
	"fmt"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol"
	"github.com/keybase/client/go/updater/sources"
	"github.com/keybase/go-framed-msgpack-rpc"
	"golang.org/x/net/context"
)

func NewCmdUpdate(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name:         "update",
		Usage:        "The updater",
		ArgumentHelp: "[arguments...]",
		Subcommands: []cli.Command{
			NewCmdUpdateCheck(cl, g),
			NewCmdUpdateCustom(cl, g),
		},
	}
}

func NewCmdUpdateCheck(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name: "check",
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:  "f, force",
				Usage: "Force update.",
			},
		},
		ArgumentHelp: "",
		Usage:        "Perform an update check",
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewCmdUpdateCheckRunner(g), "check", c)
		},
	}
}

type CmdUpdateCheck struct {
	libkb.Contextified
	force bool
}

func NewCmdUpdateCheckRunner(g *libkb.GlobalContext) *CmdUpdateCheck {
	return &CmdUpdateCheck{
		Contextified: libkb.NewContextified(g),
	}
}

func (v *CmdUpdateCheck) GetUsage() libkb.Usage {
	return libkb.Usage{
		API:    true,
		Config: true,
	}
}

func (v *CmdUpdateCheck) ParseArgv(ctx *cli.Context) error {
	v.force = ctx.Bool("force")
	return nil
}

func (v *CmdUpdateCheck) Run() error {
	protocols := []rpc.Protocol{
		NewUpdateUIProtocol(v.G()),
	}
	if err := RegisterProtocolsWithContext(protocols, v.G()); err != nil {
		return err
	}

	client, err := GetUpdateClient(v.G())
	if err != nil {
		return err
	}

	return client.UpdateCheck(context.TODO(), v.force)
}

func NewCmdUpdateCustom(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	defaultOptions := engine.DefaultUpdaterOptions(g)
	return cli.Command{
		Name: "custom",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "e, current-version",
				Usage: fmt.Sprintf("Current version. Default is %q.", defaultOptions.Version),
			},
			cli.StringFlag{
				Name:  "d, destination-path",
				Usage: fmt.Sprintf("Destination of where to apply update. Default is %q.", defaultOptions.DestinationPath),
			},
			cli.StringFlag{
				Name: "s, source",
				Usage: fmt.Sprintf("Update source (%s). Default is %q.",
					sources.UpdateSourcesDescription(", "),
					defaultOptions.Source),
			},
			cli.StringFlag{
				Name:  "u, url",
				Usage: "Custom URL.",
			},
			cli.BoolFlag{
				Name:  "f, force",
				Usage: "Force update.",
			},
		},
		ArgumentHelp: "",
		Usage:        "Run the updater with custom options",
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewCmdUpdateCustomRunner(g, defaultOptions), "run", c)
		},
	}
}

type CmdUpdateCustom struct {
	libkb.Contextified
	checkOnly bool
	source    string
	options   *keybase1.UpdateOptions
}

func NewCmdUpdateCustomRunner(g *libkb.GlobalContext, options *keybase1.UpdateOptions) *CmdUpdateCustom {
	return &CmdUpdateCustom{
		Contextified: libkb.NewContextified(g),
		options:      options,
	}
}

func (v *CmdUpdateCustom) GetUsage() libkb.Usage {
	return libkb.Usage{
		API:    true,
		Config: true,
	}
}

func (v *CmdUpdateCustom) ParseArgv(ctx *cli.Context) error {
	currentVersion := ctx.String("current-version")
	if currentVersion != "" {
		v.options.Version = currentVersion
	}

	destinationPath := ctx.String("destination-path")
	if destinationPath != "" {
		v.options.DestinationPath = destinationPath
	}

	source := ctx.String("source")
	if source != "" {
		v.options.Source = source
	}

	v.options.URL = ctx.String("url")
	v.options.Force = ctx.Bool("force")

	if v.options.DestinationPath == "" {
		return fmt.Errorf("No default destination path for this environment")
	}

	return nil
}

func (v *CmdUpdateCustom) Run() error {
	if libkb.IsBrewBuild {
		return fmt.Errorf("Update is not supported for brew install. Use \"brew update && brew upgrade keybase\" instead.")
	}

	protocols := []rpc.Protocol{
		NewUpdateUIProtocol(v.G()),
	}
	if err := RegisterProtocolsWithContext(protocols, v.G()); err != nil {
		return err
	}

	client, err := GetUpdateClient(v.G())
	if err != nil {
		return err
	}

	v.G().Log.Debug("Options: %#v", *v.options)

	_, err = client.Update(context.TODO(), *v.options)
	return err
}
<commit_msg>Updater run command (instead of custom)<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package client

import (
	"fmt"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol"
	"github.com/keybase/client/go/updater/sources"
	"github.com/keybase/go-framed-msgpack-rpc"
	"golang.org/x/net/context"
)

func NewCmdUpdate(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name:         "update",
		Usage:        "The updater",
		ArgumentHelp: "[arguments...]",
		Subcommands: []cli.Command{
			NewCmdUpdateRun(cl, g),
			NewCmdUpdateCheck(cl, g),
		},
	}
}

func NewCmdUpdateCheck(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name: "check",
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:  "f, force",
				Usage: "Force update.",
			},
		},
		ArgumentHelp: "",
		Usage:        "Trigger an update check (in the service)",
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewCmdUpdateCheckRunner(g), "check", c)
		},
	}
}

type CmdUpdateCheck struct {
	libkb.Contextified
	force bool
}

func NewCmdUpdateCheckRunner(g *libkb.GlobalContext) *CmdUpdateCheck {
	return &CmdUpdateCheck{
		Contextified: libkb.NewContextified(g),
	}
}

func (v *CmdUpdateCheck) GetUsage() libkb.Usage {
	return libkb.Usage{
		API:    true,
		Config: true,
	}
}

func (v *CmdUpdateCheck) ParseArgv(ctx *cli.Context) error {
	v.force = ctx.Bool("force")
	return nil
}

func (v *CmdUpdateCheck) Run() error {
	protocols := []rpc.Protocol{
		NewUpdateUIProtocol(v.G()),
	}
	if err := RegisterProtocolsWithContext(protocols, v.G()); err != nil {
		return err
	}

	client, err := GetUpdateClient(v.G())
	if err != nil {
		return err
	}

	return client.UpdateCheck(context.TODO(), v.force)
}

func NewCmdUpdateRun(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	defaultOptions := engine.DefaultUpdaterOptions(g)
	return cli.Command{
		Name: "run",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "e, current-version",
				Usage: fmt.Sprintf("Current version. Default is %q.", defaultOptions.Version),
			},
			cli.StringFlag{
				Name:  "d, destination-path",
				Usage: fmt.Sprintf("Destination of where to apply update. Default is %q.", defaultOptions.DestinationPath),
			},
			cli.StringFlag{
				Name: "s, source",
				Usage: fmt.Sprintf("Update source (%s). Default is %q.",
					sources.UpdateSourcesDescription(", "),
					defaultOptions.Source),
			},
			cli.StringFlag{
				Name:  "u, url",
				Usage: "Custom URL.",
			},
			cli.BoolFlag{
				Name:  "f, force",
				Usage: "Force update.",
			},
		},
		ArgumentHelp: "",
		Usage:        "Run the updater",
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewCmdUpdateRunRunner(g, defaultOptions), "run", c)
		},
	}
}

type CmdUpdateRun struct {
	libkb.Contextified
	checkOnly bool
	source    string
	options   *keybase1.UpdateOptions
}

func NewCmdUpdateRunRunner(g *libkb.GlobalContext, options *keybase1.UpdateOptions) *CmdUpdateRun {
	return &CmdUpdateRun{
		Contextified: libkb.NewContextified(g),
		options:      options,
	}
}

func (v *CmdUpdateRun) GetUsage() libkb.Usage {
	return libkb.Usage{
		API:    true,
		Config: true,
	}
}

func (v *CmdUpdateRun) ParseArgv(ctx *cli.Context) error {
	currentVersion := ctx.String("current-version")
	if currentVersion != "" {
		v.options.Version = currentVersion
	}

	destinationPath := ctx.String("destination-path")
	if destinationPath != "" {
		v.options.DestinationPath = destinationPath
	}

	source := ctx.String("source")
	if source != "" {
		v.options.Source = source
	}

	v.options.URL = ctx.String("url")
	v.options.Force = ctx.Bool("force")

	if v.options.DestinationPath == "" {
		return fmt.Errorf("No default destination path for this environment")
	}

	return nil
}

func (v *CmdUpdateRun) Run() error {
	if libkb.IsBrewBuild {
		return fmt.Errorf("Update is not supported for brew install. Use \"brew update && brew upgrade keybase\" instead.")
	}

	protocols := []rpc.Protocol{
		NewUpdateUIProtocol(v.G()),
	}
	if err := RegisterProtocolsWithContext(protocols, v.G()); err != nil {
		return err
	}

	client, err := GetUpdateClient(v.G())
	if err != nil {
		return err
	}

	v.G().Log.Debug("Options: %#v", *v.options)

	_, err = client.Update(context.TODO(), *v.options)
	return err
}
<|endoftext|>


<commit_before>package mach

func (k *MachKernel) TaskSelfTrap() uint64 {
	return 1
}

func (k *MachKernel) MachReplyPort() uint64 {
	return 1
}

func (k *MachKernel) HostSelfTrap() uint64 {
	return 2
}

func (k *MachKernel) MachMsgTrap() {}
<commit_msg>stub thread_self_trap<commit_after>package mach

func (k *MachKernel) TaskSelfTrap() uint64 {
	return 1
}

func (k *MachKernel) ThreadSelfTrap() uint64 {
	return 1
}

func (k *MachKernel) MachReplyPort() uint64 {
	return 1
}

func (k *MachKernel) HostSelfTrap() uint64 {
	return 2
}

func (k *MachKernel) MachMsgTrap() {}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package pinentry

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"

	"github.com/keybase/client/go/logger"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

//
// some borrowed from here:
//
//  https://github.com/bradfitz/camlistore/blob/master/pkg/misc/pinentry/pinentry.go
//
// Under the Apache 2.0 license
//

type Pinentry struct {
	initRes *error
	path    string
	term    string
	tty     string
	prog    string
	log     logger.Logger
}

func New(envprog string, log logger.Logger, tty string) *Pinentry {
	return &Pinentry{
		prog: envprog,
		log:  log,
		tty:  tty,
	}
}

func (pe *Pinentry) Init() (error, error) {
	if pe.initRes != nil {
		return *pe.initRes, nil
	}
	err, fatalerr := pe.FindProgram()
	if err == nil {
		pe.GetTerminalName()
	}
	pe.term = os.Getenv("TERM")
	pe.initRes = &err
	return err, fatalerr
}

func (pe *Pinentry) SetInitError(e error) {
	pe.initRes = &e
}

func (pe *Pinentry) FindProgram() (error, error) {
	prog := pe.prog
	var err, fatalerr error
	if len(prog) > 0 {
		if err = canExec(prog); err == nil {
			pe.path = prog
		} else {
			err = fmt.Errorf("Can't execute given pinentry program '%s': %s",
				prog, err)
			fatalerr = err
		}
	} else if prog, err = FindPinentry(pe.log); err == nil {
		pe.path = prog
	}
	return err, fatalerr
}

func (pe *Pinentry) Get(arg keybase1.SecretEntryArg) (res *keybase1.SecretEntryRes, err error) {

	pe.log.Debug("+ Pinentry::Get()")

	// Do a lazy initialization
	if err, _ = pe.Init(); err != nil {
		return
	}

	inst := pinentryInstance{parent: pe}
	defer inst.Close()

	if err = inst.Init(); err != nil {
		// We probably shouldn't try to use this thing again if we failed
		// to set it up.
		pe.SetInitError(err)
		return
	}
	res, err = inst.Run(arg)
	pe.log.Debug("- Pinentry::Get() -> %v", err)
	return
}

func (pi *pinentryInstance) Close() {
	pi.stdin.Close()
	_ = pi.cmd.Wait()
}

type pinentryInstance struct {
	parent *Pinentry
	cmd    *exec.Cmd
	stdout io.ReadCloser
	stdin  io.WriteCloser
	br     *bufio.Reader
}

func (pi *pinentryInstance) Set(cmd, val string, errp *error) {
	if val == "" {
		return
	}
	fmt.Fprintf(pi.stdin, "%s %s\n", cmd, val)
	line, _, err := pi.br.ReadLine()
	if err != nil {
		*errp = err
		return
	}
	if string(line) != "OK" {
		*errp = fmt.Errorf("Response to " + cmd + " was " + string(line))
	}
}

func (pi *pinentryInstance) Init() (err error) {
	parent := pi.parent

	parent.log.Debug("+ pinentryInstance::Init()")

	pi.cmd = exec.Command(parent.path)
	pi.stdin, _ = pi.cmd.StdinPipe()
	pi.stdout, _ = pi.cmd.StdoutPipe()

	if err = pi.cmd.Start(); err != nil {
		parent.log.Warning("unexpected error running pinentry (%s): %s", parent.path, err)
		return
	}

	pi.br = bufio.NewReader(pi.stdout)
	lineb, _, err := pi.br.ReadLine()

	if err != nil {
		err = fmt.Errorf("Failed to get getpin greeting: %s", err)
		return
	}

	line := string(lineb)
	if !strings.HasPrefix(line, "OK") {
		err = fmt.Errorf("getpin greeting didn't say 'OK', said: %q", line)
		return
	}

	if len(parent.tty) > 0 {
		parent.log.Debug("setting ttyname to %s", parent.tty)
		pi.Set("OPTION", "ttyname="+parent.tty, &err)
		if err != nil {
			parent.log.Debug("error setting ttyname: %s", err)
		}
	}
	if len(parent.term) > 0 {
		parent.log.Debug("setting ttytype to %s", parent.term)
		pi.Set("OPTION", "ttytype="+parent.term, &err)
		if err != nil {
			parent.log.Debug("error setting ttytype: %s", err)
		}
	}

	parent.log.Debug("- pinentryInstance::Init() -> %v", err)
	return
}

func descEncode(s string) string {
	s = strings.Replace(s, "%", "%%", -1)
	s = strings.Replace(s, "\n", "%0A", -1)
	return s
}

func resDecode(s string) string {
	s = strings.Replace(s, "%25", "%", -1)
	return s
}

func (pi *pinentryInstance) Run(arg keybase1.SecretEntryArg) (res *keybase1.SecretEntryRes, err error) {

	pi.Set("SETPROMPT", arg.Prompt, &err)
	pi.Set("SETDESC", descEncode(arg.Desc), &err)
	pi.Set("SETOK", arg.Ok, &err)
	pi.Set("SETCANCEL", arg.Cancel, &err)
	pi.Set("SETERROR", arg.Err, &err)

	if err != nil {
		return
	}

	fmt.Fprintf(pi.stdin, "GETPIN\n")
	var lineb []byte
	lineb, _, err = pi.br.ReadLine()
	if err != nil {
		err = fmt.Errorf("Failed to read line after GETPIN: %v", err)
		return
	}
	line := string(lineb)
	switch {
	case strings.HasPrefix(line, "D "):
		res = &keybase1.SecretEntryRes{Text: resDecode(line[2:])}
	case strings.HasPrefix(line, "ERR 83886179 canceled") || strings.HasPrefix(line, "ERR 83886179 Operation cancelled"):
		res = &keybase1.SecretEntryRes{Canceled: true}
	case line == "OK":
		res = &keybase1.SecretEntryRes{}
	default:
		return nil, fmt.Errorf("GETPIN response didn't start with D; got %q", line)
	}

	return
}
<commit_msg>more helpful pinentry error msg (#23813)<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package pinentry

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"

	"github.com/keybase/client/go/logger"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

//
// some borrowed from here:
//
//  https://github.com/bradfitz/camlistore/blob/master/pkg/misc/pinentry/pinentry.go
//
// Under the Apache 2.0 license
//

type Pinentry struct {
	initRes *error
	path    string
	term    string
	tty     string
	prog    string
	log     logger.Logger
}

func New(envprog string, log logger.Logger, tty string) *Pinentry {
	return &Pinentry{
		prog: envprog,
		log:  log,
		tty:  tty,
	}
}

func (pe *Pinentry) Init() (error, error) {
	if pe.initRes != nil {
		return *pe.initRes, nil
	}
	err, fatalerr := pe.FindProgram()
	if err == nil {
		pe.GetTerminalName()
	}
	pe.term = os.Getenv("TERM")
	pe.initRes = &err
	return err, fatalerr
}

func (pe *Pinentry) SetInitError(e error) {
	pe.initRes = &e
}

func (pe *Pinentry) FindProgram() (error, error) {
	prog := pe.prog
	var err, fatalerr error
	if len(prog) > 0 {
		if err = canExec(prog); err == nil {
			pe.path = prog
		} else {
			err = fmt.Errorf("Can't execute given pinentry program '%s': %s",
				prog, err)
			fatalerr = err
		}
	} else if prog, err = FindPinentry(pe.log); err == nil {
		pe.path = prog
	}
	return err, fatalerr
}

func (pe *Pinentry) Get(arg keybase1.SecretEntryArg) (res *keybase1.SecretEntryRes, err error) {

	pe.log.Debug("+ Pinentry::Get()")

	// Do a lazy initialization
	if err, _ = pe.Init(); err != nil {
		return
	}

	inst := pinentryInstance{parent: pe}
	defer inst.Close()

	if err = inst.Init(); err != nil {
		// We probably shouldn't try to use this thing again if we failed
		// to set it up.
		pe.SetInitError(err)
		return
	}
	res, err = inst.Run(arg)
	pe.log.Debug("- Pinentry::Get() -> %v", err)
	return
}

func (pi *pinentryInstance) Close() {
	pi.stdin.Close()
	_ = pi.cmd.Wait()
}

type pinentryInstance struct {
	parent *Pinentry
	cmd    *exec.Cmd
	stdout io.ReadCloser
	stdin  io.WriteCloser
	br     *bufio.Reader
}

func (pi *pinentryInstance) Set(cmd, val string, errp *error) {
	if val == "" {
		return
	}
	fmt.Fprintf(pi.stdin, "%s %s\n", cmd, val)
	line, _, err := pi.br.ReadLine()
	if err != nil {
		*errp = err
		return
	}
	if string(line) != "OK" {
		*errp = fmt.Errorf("Response to " + cmd + " was " + string(line))
	}
}

func (pi *pinentryInstance) Init() (err error) {
	parent := pi.parent

	parent.log.Debug("+ pinentryInstance::Init()")

	pi.cmd = exec.Command(parent.path)
	pi.stdin, _ = pi.cmd.StdinPipe()
	pi.stdout, _ = pi.cmd.StdoutPipe()

	if err = pi.cmd.Start(); err != nil {
		parent.log.Warning("unexpected error running pinentry (%s): %s", parent.path, err)
		return
	}

	pi.br = bufio.NewReader(pi.stdout)
	lineb, _, err := pi.br.ReadLine()

	if err != nil {
		err = fmt.Errorf("Failed to get getpin greeting: %s", err)
		return
	}

	line := string(lineb)
	if !strings.HasPrefix(line, "OK") {
		err = fmt.Errorf("getpin greeting didn't say 'OK', said: %q", line)
		return
	}

	if len(parent.tty) > 0 {
		parent.log.Debug("setting ttyname to %s", parent.tty)
		pi.Set("OPTION", "ttyname="+parent.tty, &err)
		if err != nil {
			parent.log.Debug("error setting ttyname: %s", err)
		}
	}
	if len(parent.term) > 0 {
		parent.log.Debug("setting ttytype to %s", parent.term)
		pi.Set("OPTION", "ttytype="+parent.term, &err)
		if err != nil {
			parent.log.Debug("error setting ttytype: %s", err)
		}
	}

	parent.log.Debug("- pinentryInstance::Init() -> %v", err)
	return
}

func descEncode(s string) string {
	s = strings.Replace(s, "%", "%%", -1)
	s = strings.Replace(s, "\n", "%0A", -1)
	return s
}

func resDecode(s string) string {
	s = strings.Replace(s, "%25", "%", -1)
	return s
}

func (pi *pinentryInstance) Run(arg keybase1.SecretEntryArg) (res *keybase1.SecretEntryRes, err error) {

	pi.Set("SETPROMPT", arg.Prompt, &err)
	pi.Set("SETDESC", descEncode(arg.Desc), &err)
	pi.Set("SETOK", arg.Ok, &err)
	pi.Set("SETCANCEL", arg.Cancel, &err)
	pi.Set("SETERROR", arg.Err, &err)

	if err != nil {
		return
	}

	fmt.Fprintf(pi.stdin, "GETPIN\n")
	var lineb []byte
	lineb, _, err = pi.br.ReadLine()
	if err != nil {
		err = fmt.Errorf("Failed to read line after GETPIN: %v", err)
		return
	}
	line := string(lineb)
	switch {
	case strings.HasPrefix(line, "D "):
		res = &keybase1.SecretEntryRes{Text: resDecode(line[2:])}
	case strings.HasPrefix(line, "ERR 83886179 canceled") || strings.HasPrefix(line, "ERR 83886179 Operation cancelled"):
		res = &keybase1.SecretEntryRes{Canceled: true}
	case line == "OK":
		res = &keybase1.SecretEntryRes{}
	default:
		return nil, fmt.Errorf(
			"failed to run pinentry: GETPIN response didn't start with D; got %q (see %s for troubleshooting help)",
			line,
			"https://github.com/keybase/client/blob/master/go/doc/troubleshooting.md#pinentry-doesnt-work",
		)
	}

	return
}
<|endoftext|>


<commit_before>package stringutil

func (d *StringDeduplicator) clear() {
	if d.lock {
		d.mutex.Lock()
		defer d.mutex.Unlock()
	}
	d.mapping = make(map[string]string)
	d.statistics = StringDuplicationStatistics{}
}

func (d *StringDeduplicator) deDuplicate(str string) string {
	if d.lock {
		d.mutex.Lock()
		defer d.mutex.Unlock()
	}
	if cached, ok := d.mapping[str]; ok {
		d.statistics.DuplicateBytes += uint64(len(str))
		d.statistics.DuplicateStrings++
		return cached
	} else {
		d.mapping[str] = str
		d.statistics.UniqueBytes += uint64(len(str))
		d.statistics.UniqueStrings++
		return str
	}
}

func (d *StringDeduplicator) getStatistics() StringDuplicationStatistics {
	if d.lock {
		d.mutex.Lock()
		defer d.mutex.Unlock()
	}
	return d.statistics
}
<commit_msg>Special case empty string in lib/stringutil.StringDeduplicator.<commit_after>package stringutil

func (d *StringDeduplicator) clear() {
	if d.lock {
		d.mutex.Lock()
		defer d.mutex.Unlock()
	}
	d.mapping = make(map[string]string)
	d.statistics = StringDuplicationStatistics{}
}

func (d *StringDeduplicator) deDuplicate(str string) string {
	if str == "" {
		return ""
	}
	if d.lock {
		d.mutex.Lock()
		defer d.mutex.Unlock()
	}
	if cached, ok := d.mapping[str]; ok {
		d.statistics.DuplicateBytes += uint64(len(str))
		d.statistics.DuplicateStrings++
		return cached
	} else {
		d.mapping[str] = str
		d.statistics.UniqueBytes += uint64(len(str))
		d.statistics.UniqueStrings++
		return str
	}
}

func (d *StringDeduplicator) getStatistics() StringDuplicationStatistics {
	if d.lock {
		d.mutex.Lock()
		defer d.mutex.Unlock()
	}
	return d.statistics
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016, Google 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 tao

import (
	"bytes"
	"fmt"
	"runtime"
	"testing"

	"github.com/jlmucb/cloudproxy/go/tao/auth"
	"github.com/jlmucb/cloudproxy/go/tpm2"
)

// cleanUpTPM2Tao runs the finalizer for TPMTao early then unsets it so it
// doesn't run later. Normal code will only create one instance of TPM2Tao, so
// the finalizer will work correctly. But this test code creates multiple such
// instances, so it needs to call the finalizer early.
func cleanUpTPM2Tao(tt *TPM2Tao) {
	FinalizeTPM2Tao(tt)
	runtime.SetFinalizer(tt, nil)
}

func TestEncode(t *testing.T) {
	b1 := []byte{1, 2, 3}
	b2 := []byte{4, 5, 6}
	cb := EncodeTwoBytes(b1, b2)
	fmt.Printf("combined: %x\n", cb)
	c1, c2 := DecodeTwoBytes(cb)
	fmt.Printf("seperated: %x, %x\n", c1, c2)
}

func TestTPM2Tao(t *testing.T) {
	// Set up a TPM2 Tao that seals and attests against PCRs 17 and 18.
	tt, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tpmtao, ok := tt.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	cleanUpTPM2Tao(tpmtao)
}

func TestTPM2TaoSeal(t *testing.T) {

	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	data := []byte(`test data to seal`)
	sealed, err := tpmtao.Seal(data, SealPolicyDefault)
	if err != nil {
		t.Fatal("Couldn't seal data in the TPM2 Tao:", err)
	}
	fmt.Printf("sealed: %x\n", sealed)

	// Fix this hack
	// tpmtao.(*TPM2Tao).TmpRm()

	unsealed, policy, err := tpmtao.Unseal(sealed)
	if err != nil {
		t.Fatal("Couldn't unseal data sealed by the TPM2 Tao:", err)
	}

	if policy != SealPolicyDefault {
		t.Fatal("Got the wrong policy back from TPM2Tao.Unseal")
	}

	if !bytes.Equal(unsealed, data) {
		t.Fatal("The data returned from TPM2Tao.Unseal didn't match the original data")
	}
}

func TestTPM2TaoLargeSeal(t *testing.T) {

	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2//tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	data := make([]byte, 10000)
	sealed, err := tpmtao.Seal(data, SealPolicyDefault)
	if err != nil {
		t.Fatal("Couldn't seal data in the TPM2 Tao:", err)
	}

	unsealed, policy, err := tpmtao.Unseal(sealed)
	if err != nil {
		t.Fatal("Couldn't unseal data sealed by the TPM2 Tao:", err)
	}

	if policy != SealPolicyDefault {
		t.Fatal("Got the wrong policy back from TPM2Tao.Unseal")
	}

	if !bytes.Equal(unsealed, data) {
		t.Fatal("The data returned from TPM2Tao.Unseal didn't match the original data")
	}
}

func TestTPM2TaoAttest(t *testing.T) {

	// Fix
	hash_alg_id := uint16(tpm2.AlgTPM_ALG_SHA1)

	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	// Set up a fake key delegation.
	taoname, err := tpmtao.GetTaoName()
	if err != nil {
		t.Fatal("Couldn't get the name of the tao:", err)
	}
	stmt := auth.Speaksfor{
		Delegate:  auth.NewKeyPrin([]byte(`FakeKeyBytes`)),
		Delegator: taoname,
	}

	// Let the TPMTao set up the issuer and time and expiration.
	a, err := tpmtao.Attest(nil, nil, nil, stmt)
	if err != nil {
		t.Fatal("Couldn't attest to a key delegation:", err)
	}

	digests, err := ReadTPM2PCRs(tt.rw, []int{17, 18})
	if err != nil {
		t.Fatal("ReadPcrs failed\n")
	}
	var allDigests []byte
	for i := 0; i < len(digests); i++ {
		allDigests = append(allDigests, digests[i]...)
	}
	computedDigest, err := tpm2.ComputeHashValue(hash_alg_id, allDigests)
	if err != nil {
		t.Fatal("Can't compute combined quote digest")
	}
	fmt.Printf("Pcr combined digest: %x\n", computedDigest)

	pms, err := tpm2.UnmarshalCertifyInfo(a.Tpm2QuoteStructure)
	if err != nil {
		fmt.Printf("a.Tpm2QuoteStructure: %x\n", a.Tpm2QuoteStructure)
		t.Fatal("Can't unmarshal quote structure\n")
	}
	tpm2.PrintAttestData(pms)
	quoteHandle, err := tt.loadQuote()
	if err != nil {
	}
	defer tpm2.FlushContext(tt.rw, quoteHandle)
	key, _ := tt.GetRsaTPMKey(quoteHandle)
	ok, err = tpm2.VerifyTpm2Quote(a.SerializedStatement, tt.GetPcrNums(),
		computedDigest, a.Tpm2QuoteStructure, a.Signature, key)
	if err != nil {
		t.Fatal("VerifyQuote error")
	}
	if !ok {
		t.Fatal("VerifyQuote succeeds")
	}
}

func TestTPM2TaoGetCounter(t *testing.T) {
fmt.Printf("TestTPM2TaoGetCounter")
	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	// _ = tpm2.Flushall(tt.rw)
	c, err := tpmtao.GetCounter("TestSealCounterLabel")
	if err != nil {
		t.Fatal("Couldn't GetCounter from TPM2 Tao:", err)
	}
	fmt.Printf("TestTPM2TaoGetCounter: %d\n", c)
}

func TestTPM2TaoRollbackSealUnseal(t *testing.T) {
/*
	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	data := make([]byte, 10000)
	sealed, err := tpmtao.RollbackProtectedSeal("TestSeal", data, SealPolicyDefault)
	if err != nil {
		t.Fatal("Couldn't RollbackProtectedSeal data in the TPM2 Tao:", err)
	}

	unsealed, policy, err := tpmtao.RollbackProtectedUnseal(sealed)
	if err != nil {
		t.Fatal("Couldn't RollbackProtectedUnseal data sealed by the TPM2 Tao:", err)
	}

	if policy != SealPolicyDefault {
		t.Fatal("Got the wrong policy back from TPM2Tao.Unseal")
	}

	if !bytes.Equal(unsealed, data) {
		t.Fatal("The data returned from TPM2Tao.Unseal didn't match the original data")
	}
*/
}
<commit_msg>iRollbackSeal/Unseal test<commit_after>// Copyright (c) 2014-2016, Google 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 tao

import (
	"bytes"
	"fmt"
	"runtime"
	"testing"

	"github.com/jlmucb/cloudproxy/go/tao/auth"
	"github.com/jlmucb/cloudproxy/go/tpm2"
)

// cleanUpTPM2Tao runs the finalizer for TPMTao early then unsets it so it
// doesn't run later. Normal code will only create one instance of TPM2Tao, so
// the finalizer will work correctly. But this test code creates multiple such
// instances, so it needs to call the finalizer early.
func cleanUpTPM2Tao(tt *TPM2Tao) {
	FinalizeTPM2Tao(tt)
	runtime.SetFinalizer(tt, nil)
}

func TestEncode(t *testing.T) {
	b1 := []byte{1, 2, 3}
	b2 := []byte{4, 5, 6}
	cb := EncodeTwoBytes(b1, b2)
	fmt.Printf("combined: %x\n", cb)
	c1, c2 := DecodeTwoBytes(cb)
	fmt.Printf("seperated: %x, %x\n", c1, c2)
}

func TestTPM2Tao(t *testing.T) {
	// Set up a TPM2 Tao that seals and attests against PCRs 17 and 18.
	tt, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tpmtao, ok := tt.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	cleanUpTPM2Tao(tpmtao)
}

func TestTPM2TaoSeal(t *testing.T) {

	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	data := []byte(`test data to seal`)
	sealed, err := tpmtao.Seal(data, SealPolicyDefault)
	if err != nil {
		t.Fatal("Couldn't seal data in the TPM2 Tao:", err)
	}
	fmt.Printf("sealed: %x\n", sealed)

	// Fix this hack
	// tpmtao.(*TPM2Tao).TmpRm()

	unsealed, policy, err := tpmtao.Unseal(sealed)
	if err != nil {
		t.Fatal("Couldn't unseal data sealed by the TPM2 Tao:", err)
	}

	if policy != SealPolicyDefault {
		t.Fatal("Got the wrong policy back from TPM2Tao.Unseal")
	}

	if !bytes.Equal(unsealed, data) {
		t.Fatal("The data returned from TPM2Tao.Unseal didn't match the original data")
	}
}

func TestTPM2TaoLargeSeal(t *testing.T) {

	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2//tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	data := make([]byte, 10000)
	sealed, err := tpmtao.Seal(data, SealPolicyDefault)
	if err != nil {
		t.Fatal("Couldn't seal data in the TPM2 Tao:", err)
	}

	unsealed, policy, err := tpmtao.Unseal(sealed)
	if err != nil {
		t.Fatal("Couldn't unseal data sealed by the TPM2 Tao:", err)
	}

	if policy != SealPolicyDefault {
		t.Fatal("Got the wrong policy back from TPM2Tao.Unseal")
	}

	if !bytes.Equal(unsealed, data) {
		t.Fatal("The data returned from TPM2Tao.Unseal didn't match the original data")
	}
}

func TestTPM2TaoAttest(t *testing.T) {

	// Fix
	hash_alg_id := uint16(tpm2.AlgTPM_ALG_SHA1)

	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	// Set up a fake key delegation.
	taoname, err := tpmtao.GetTaoName()
	if err != nil {
		t.Fatal("Couldn't get the name of the tao:", err)
	}
	stmt := auth.Speaksfor{
		Delegate:  auth.NewKeyPrin([]byte(`FakeKeyBytes`)),
		Delegator: taoname,
	}

	// Let the TPMTao set up the issuer and time and expiration.
	a, err := tpmtao.Attest(nil, nil, nil, stmt)
	if err != nil {
		t.Fatal("Couldn't attest to a key delegation:", err)
	}

	digests, err := ReadTPM2PCRs(tt.rw, []int{17, 18})
	if err != nil {
		t.Fatal("ReadPcrs failed\n")
	}
	var allDigests []byte
	for i := 0; i < len(digests); i++ {
		allDigests = append(allDigests, digests[i]...)
	}
	computedDigest, err := tpm2.ComputeHashValue(hash_alg_id, allDigests)
	if err != nil {
		t.Fatal("Can't compute combined quote digest")
	}
	fmt.Printf("Pcr combined digest: %x\n", computedDigest)

	pms, err := tpm2.UnmarshalCertifyInfo(a.Tpm2QuoteStructure)
	if err != nil {
		fmt.Printf("a.Tpm2QuoteStructure: %x\n", a.Tpm2QuoteStructure)
		t.Fatal("Can't unmarshal quote structure\n")
	}
	tpm2.PrintAttestData(pms)
	quoteHandle, err := tt.loadQuote()
	if err != nil {
	}
	defer tpm2.FlushContext(tt.rw, quoteHandle)
	key, _ := tt.GetRsaTPMKey(quoteHandle)
	ok, err = tpm2.VerifyTpm2Quote(a.SerializedStatement, tt.GetPcrNums(),
		computedDigest, a.Tpm2QuoteStructure, a.Signature, key)
	if err != nil {
		t.Fatal("VerifyQuote error")
	}
	if !ok {
		t.Fatal("VerifyQuote succeeds")
	}
}

func TestTPM2TaoGetCounter(t *testing.T) {
fmt.Printf("TestTPM2TaoGetCounter")
	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	c, err := tpmtao.GetCounter("TestSealCounterLabel")
	if err != nil {
		t.Fatal("Couldn't GetCounter from TPM2 Tao:", err)
	}
	fmt.Printf("TestTPM2TaoGetCounter: %d\n", c)
}

func TestTPM2TaoRollbackSealUnseal(t *testing.T) {
	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM2 Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	data := make([]byte, 10000)
	sealed, err := tpmtao.RollbackProtectedSeal("TestSeal", data, SealPolicyDefault)
	if err != nil {
		t.Fatal("Couldn't RollbackProtectedSeal data in the TPM2 Tao:", err)
	}

	unsealed, policy, err := tpmtao.RollbackProtectedUnseal(sealed)
	if err != nil {
		t.Fatal("Couldn't RollbackProtectedUnseal data sealed by the TPM2 Tao:", err)
	}

	if policy != SealPolicyDefault {
		t.Fatal("Got the wrong policy back from TPM2Tao.Unseal")
	}

	if !bytes.Equal(unsealed, data) {
		t.Fatal("The data returned from TPM2Tao.Unseal didn't match the original data")
	}
}
<|endoftext|>


<commit_before>// Copyright 2013, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// topotools package contains a few utility classes to handle topo.Server
// objects, and transitions.
package topotools

import (
	"fmt"
	"sync"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/vt/concurrency"
	"github.com/youtube/vitess/go/vt/topo"
)

// CopyKeyspaces will create the keyspaces in the destination topo
func CopyKeyspaces(fromTS, toTS topo.Server) {
	keyspaces, err := fromTS.GetKeyspaces()
	if err != nil {
		log.Fatalf("fromTS.GetKeyspaces failed: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, keyspace := range keyspaces {
		wg.Add(1)
		go func(keyspace string) {
			defer wg.Done()
			if err := toTS.CreateKeyspace(keyspace); err != nil {
				if err == topo.ErrNodeExists {
					log.Warningf("keyspace %v already exists", keyspace)
				} else {
					rec.RecordError(fmt.Errorf("Failed to create keyspace %v: %v", keyspace, err))
				}
			}
		}(keyspace)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyKeyspaces failed: %v", rec.Error())
	}
}

// CopyShards will create the shards in the destination topo
func CopyShards(fromTS, toTS topo.Server, deleteKeyspaceShards bool) {
	keyspaces, err := fromTS.GetKeyspaces()
	if err != nil {
		log.Fatalf("fromTS.GetKeyspaces failed: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, keyspace := range keyspaces {
		wg.Add(1)
		go func(keyspace string) {
			defer wg.Done()
			shards, err := fromTS.GetShardNames(keyspace)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetShardNames(%v) failed: %v", keyspace, err))
				return
			}

			if deleteKeyspaceShards {
				if err := toTS.DeleteKeyspaceShards(keyspace); err != nil {
					rec.RecordError(fmt.Errorf("DeleteKeyspaceShards(%v) failed: %v", keyspace, err))
					return
				}
			}

			for _, shard := range shards {
				wg.Add(1)
				go func(keyspace, shard string) {
					defer wg.Done()
					if err := topo.CreateShard(toTS, keyspace, shard); err != nil {
						if err == topo.ErrNodeExists {
							log.Warningf("shard %v/%v already exists", keyspace, shard)
						} else {
							rec.RecordError(fmt.Errorf("CreateShard(%v, %v) failed: %v", keyspace, shard, err))
							return
						}
					}

					si, err := fromTS.GetShard(keyspace, shard)
					if err != nil {
						rec.RecordError(fmt.Errorf("GetShard(%v, %v) failed: %v", keyspace, shard, err))
						return
					}

					if err := toTS.UpdateShard(si); err != nil {
						rec.RecordError(fmt.Errorf("UpdateShard(%v, %v) failed: %v", keyspace, shard, err))
					}
				}(keyspace, shard)
			}
		}(keyspace)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyShards failed: %v", rec.Error())
	}
}

// CopyTablets will create the tablets in the destination topo
func CopyTablets(fromTS, toTS topo.Server) {
	cells, err := fromTS.GetKnownCells()
	if err != nil {
		log.Fatalf("fromTS.GetKnownCells failed: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, cell := range cells {
		wg.Add(1)
		go func(cell string) {
			defer wg.Done()
			tabletAliases, err := fromTS.GetTabletsByCell(cell)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetTabletsByCell(%v) failed: %v", cell, err))
			} else {
				for _, tabletAlias := range tabletAliases {
					wg.Add(1)
					go func(tabletAlias topo.TabletAlias) {
						defer wg.Done()

						// read the source tablet
						ti, err := fromTS.GetTablet(tabletAlias)
						if err != nil {
							rec.RecordError(fmt.Errorf("GetTablet(%v) failed: %v", tabletAlias, err))
							return
						}

						// try to create the destination
						err = toTS.CreateTablet(ti.Tablet)
						if err == topo.ErrNodeExists {
							// update the destination tablet
							log.Warningf("tablet %v already exists, updating it", tabletAlias)
							err = toTS.UpdateTabletFields(ti.GetAlias(), func(t *topo.Tablet) error {
								*t = *ti.Tablet
								return nil
							})
						}
						if err != nil {
							rec.RecordError(fmt.Errorf("CreateTablet(%v) failed: %v", tabletAlias, err))
							return
						}
					}(tabletAlias)
				}
			}
		}(cell)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyTablets failed: %v", rec.Error())
	}
}

// CopyShardReplications will create the ShardReplication objects in
// the destination topo
func CopyShardReplications(fromTS, toTS topo.Server) {
	keyspaces, err := fromTS.GetKeyspaces()
	if err != nil {
		log.Fatalf("fromTS.GetKeyspaces failed: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, keyspace := range keyspaces {
		wg.Add(1)
		go func(keyspace string) {
			defer wg.Done()
			shards, err := fromTS.GetShardNames(keyspace)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetShardNames(%v) failed: %v", keyspace, err))
				return
			}

			for _, shard := range shards {
				wg.Add(1)
				go func(keyspace, shard string) {
					defer wg.Done()

					// read the source shard to get the cells
					si, err := fromTS.GetShard(keyspace, shard)
					if err != nil {
						rec.RecordError(fmt.Errorf("GetShard(%v, %v) failed: %v", keyspace, shard, err))
						return
					}

					for _, cell := range si.Cells {
						sri, err := fromTS.GetShardReplication(cell, keyspace, shard)
						if err != nil {
							rec.RecordError(fmt.Errorf("GetShardReplication(%v, %v, %v) failed: %v", cell, keyspace, shard, err))
							continue
						}

						err = toTS.CreateShardReplication(cell, keyspace, shard, sri.ShardReplication)
						switch err {
						case nil:
							// good
						case topo.ErrNodeExists:
							if err := toTS.UpdateShardReplicationFields(cell, keyspace, shard, func(oldSR *topo.ShardReplication) error {
								*oldSR = *sri.ShardReplication
								return nil
							}); err != nil {
								rec.RecordError(fmt.Errorf("UpdateShardReplicationFields(%v, %v, %v) failed: %v", cell, keyspace, shard, err))
							}
						default:
							rec.RecordError(fmt.Errorf("CreateShardReplication(%v, %v, %v) failed: %v", cell, keyspace, shard, err))
						}
					}
				}(keyspace, shard)
			}
		}(keyspace)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyShards failed: %v", rec.Error())
	}
}
<commit_msg>Fix error messages.<commit_after>// Copyright 2013, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// topotools package contains a few utility classes to handle topo.Server
// objects, and transitions.
package topotools

import (
	"fmt"
	"sync"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/vt/concurrency"
	"github.com/youtube/vitess/go/vt/topo"
)

// CopyKeyspaces will create the keyspaces in the destination topo
func CopyKeyspaces(fromTS, toTS topo.Server) {
	keyspaces, err := fromTS.GetKeyspaces()
	if err != nil {
		log.Fatalf("GetKeyspaces: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, keyspace := range keyspaces {
		wg.Add(1)
		go func(keyspace string) {
			defer wg.Done()
			if err := toTS.CreateKeyspace(keyspace); err != nil {
				if err == topo.ErrNodeExists {
					log.Warningf("keyspace %v already exists", keyspace)
				} else {
					rec.RecordError(fmt.Errorf("CreateKeyspace(%v): %v", keyspace, err))
				}
			}
		}(keyspace)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyKeyspaces failed: %v", rec.Error())
	}
}

// CopyShards will create the shards in the destination topo
func CopyShards(fromTS, toTS topo.Server, deleteKeyspaceShards bool) {
	keyspaces, err := fromTS.GetKeyspaces()
	if err != nil {
		log.Fatalf("fromTS.GetKeyspaces: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, keyspace := range keyspaces {
		wg.Add(1)
		go func(keyspace string) {
			defer wg.Done()
			shards, err := fromTS.GetShardNames(keyspace)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetShardNames(%v): %v", keyspace, err))
				return
			}

			if deleteKeyspaceShards {
				if err := toTS.DeleteKeyspaceShards(keyspace); err != nil {
					rec.RecordError(fmt.Errorf("DeleteKeyspaceShards(%v): %v", keyspace, err))
					return
				}
			}

			for _, shard := range shards {
				wg.Add(1)
				go func(keyspace, shard string) {
					defer wg.Done()
					if err := topo.CreateShard(toTS, keyspace, shard); err != nil {
						if err == topo.ErrNodeExists {
							log.Warningf("shard %v/%v already exists", keyspace, shard)
						} else {
							rec.RecordError(fmt.Errorf("CreateShard(%v, %v): %v", keyspace, shard, err))
							return
						}
					}

					si, err := fromTS.GetShard(keyspace, shard)
					if err != nil {
						rec.RecordError(fmt.Errorf("GetShard(%v, %v): %v", keyspace, shard, err))
						return
					}

					if err := toTS.UpdateShard(si); err != nil {
						rec.RecordError(fmt.Errorf("UpdateShard(%v, %v): %v", keyspace, shard, err))
					}
				}(keyspace, shard)
			}
		}(keyspace)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyShards failed: %v", rec.Error())
	}
}

// CopyTablets will create the tablets in the destination topo
func CopyTablets(fromTS, toTS topo.Server) {
	cells, err := fromTS.GetKnownCells()
	if err != nil {
		log.Fatalf("fromTS.GetKnownCells: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, cell := range cells {
		wg.Add(1)
		go func(cell string) {
			defer wg.Done()
			tabletAliases, err := fromTS.GetTabletsByCell(cell)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetTabletsByCell(%v): %v", cell, err))
			} else {
				for _, tabletAlias := range tabletAliases {
					wg.Add(1)
					go func(tabletAlias topo.TabletAlias) {
						defer wg.Done()

						// read the source tablet
						ti, err := fromTS.GetTablet(tabletAlias)
						if err != nil {
							rec.RecordError(fmt.Errorf("GetTablet(%v): %v", tabletAlias, err))
							return
						}

						// try to create the destination
						err = toTS.CreateTablet(ti.Tablet)
						if err == topo.ErrNodeExists {
							// update the destination tablet
							log.Warningf("tablet %v already exists, updating it", tabletAlias)
							err = toTS.UpdateTabletFields(ti.GetAlias(), func(t *topo.Tablet) error {
								*t = *ti.Tablet
								return nil
							})
						}
						if err != nil {
							rec.RecordError(fmt.Errorf("CreateTablet(%v): %v", tabletAlias, err))
							return
						}
					}(tabletAlias)
				}
			}
		}(cell)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyTablets failed: %v", rec.Error())
	}
}

// CopyShardReplications will create the ShardReplication objects in
// the destination topo
func CopyShardReplications(fromTS, toTS topo.Server) {
	keyspaces, err := fromTS.GetKeyspaces()
	if err != nil {
		log.Fatalf("fromTS.GetKeyspaces: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, keyspace := range keyspaces {
		wg.Add(1)
		go func(keyspace string) {
			defer wg.Done()
			shards, err := fromTS.GetShardNames(keyspace)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetShardNames(%v): %v", keyspace, err))
				return
			}

			for _, shard := range shards {
				wg.Add(1)
				go func(keyspace, shard string) {
					defer wg.Done()

					// read the source shard to get the cells
					si, err := fromTS.GetShard(keyspace, shard)
					if err != nil {
						rec.RecordError(fmt.Errorf("GetShard(%v, %v): %v", keyspace, shard, err))
						return
					}

					for _, cell := range si.Cells {
						sri, err := fromTS.GetShardReplication(cell, keyspace, shard)
						if err != nil {
							rec.RecordError(fmt.Errorf("GetShardReplication(%v, %v, %v): %v", cell, keyspace, shard, err))
							continue
						}

						err = toTS.CreateShardReplication(cell, keyspace, shard, sri.ShardReplication)
						switch err {
						case nil:
							// good
						case topo.ErrNodeExists:
							if err := toTS.UpdateShardReplicationFields(cell, keyspace, shard, func(oldSR *topo.ShardReplication) error {
								*oldSR = *sri.ShardReplication
								return nil
							}); err != nil {
								rec.RecordError(fmt.Errorf("UpdateShardReplicationFields(%v, %v, %v): %v", cell, keyspace, shard, err))
							}
						default:
							rec.RecordError(fmt.Errorf("CreateShardReplication(%v, %v, %v): %v", cell, keyspace, shard, err))
						}
					}
				}(keyspace, shard)
			}
		}(keyspace)
	}
	wg.Wait()
	if rec.HasErrors() {
		log.Fatalf("copyShards failed: %v", rec.Error())
	}
}
<|endoftext|>