<commit_before>package vaulted

import (
	"crypto/rand"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/miquella/xdg"
	"golang.org/x/crypto/nacl/secretbox"
)

var (
	ErrInvalidPassword         = errors.New("Invalid password")
	ErrInvalidKeyConfig        = errors.New("Invalid key configuration")
	ErrInvalidEncryptionConfig = errors.New("Invalid encryption configuration")
)

func VaultExists(name string) bool {
	existing := xdg.DATA.Find(filepath.Join("vaulted", name))
	if len(existing) == 0 {
		return false
	}

	return true
}

func ListVaults() ([]string, error) {
	vaults, err := xdg.DATA.Glob(filepath.Join("vaulted", "*"))
	if err != nil {
		return nil, err
	}

	var found []string
	emitted := map[string]bool{}
	for _, vault := range vaults {
		info, err := os.Stat(vault)
		if err != nil {
			return nil, err
		}
		if !info.Mode().IsRegular() {
			continue
		}

		if !emitted[info.Name()] {
			emitted[info.Name()] = true
			found = append(found, info.Name())
		}
	}

	return found, nil
}

func SealVault(name, password string, vault *Vault) error {
	vf := &VaultFile{
		Method:  "secretbox",
		Details: make(Details),
	}

	// generate a new key (while trying to keeping the existing key derivation and encryption methods)
	existingVaultFile, err := readVaultFile(name)
	if err == nil {
		vf.Method = existingVaultFile.Method
		vf.Key = existingVaultFile.Key
	}

	vf.Key = newVaultKey(vf.Key)

	// marshal the vault content
	content, err := json.Marshal(vault)
	if err != nil {
		return err
	}

	// encrypt the vault
	if vf.Method == "" {
		vf.Method = "secretbox"
	}

	switch vf.Method {
	case "secretbox":
		nonce := [24]byte{}
		_, err = rand.Read(nonce[:])
		if err != nil {
			return err
		}
		vf.Details.SetBytes("nonce", nonce[:])

		key := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(key))
		if err != nil {
			return err
		}
		copy(key[:], derivedKey[:])

		vf.Ciphertext = secretbox.Seal(nil, content, &nonce, &key)

	default:
		return fmt.Errorf("Invalid encryption method: %s", vf.Method)
	}

	writeVaultFile(name, vf)

	return nil
}

func OpenVault(name, password string) (*Vault, error) {
	vf, err := readVaultFile(name)
	if err != nil {
		return nil, err
	}

	v := Vault{}

	switch vf.Method {
	case "secretbox":
		if vf.Key == nil {
			return nil, ErrInvalidKeyConfig
		}

		nonce := vf.Details.Bytes("nonce")
		if len(nonce) == 0 {
			return nil, ErrInvalidEncryptionConfig
		}
		boxNonce := [24]byte{}
		copy(boxNonce[:], nonce)

		boxKey := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(boxKey))
		if err != nil {
			return nil, err
		}
		copy(boxKey[:], derivedKey[:])

		plaintext, ok := secretbox.Open(nil, vf.Ciphertext, &boxNonce, &boxKey)
		if !ok {
			return nil, ErrInvalidPassword
		}

		err = json.Unmarshal(plaintext, &v)
		if err != nil {
			return nil, err
		}

	default:
		return nil, fmt.Errorf("Invalid encryption method: %s", vf.Method)
	}

	return &v, nil
}

func RemoveVault(name string) error {
	existing := xdg.DATA_HOME.Find(filepath.Join("vaulted", name))
	if existing == "" {
		untouchable := xdg.DATA_DIRS.Find(filepath.Join("vaulted", name))
		if len(untouchable) == 0 {
			return os.ErrNotExist
		}

		return fmt.Errorf("Because %s is outside the vaulted managed directory (%s), it must be removed manually", untouchable[0], xdg.DATA_HOME.Join("vaulted"))
	}

	removeEnvironment(name)

	return os.Remove(existing)
}

func GetEnvironment(name, password string) (*Environment, error) {
	v, err := OpenVault(name, password)
	if err != nil {
		return nil, err
	}

	env, err := getEnvironment(v, name, password)
	if err != nil {
		return nil, err
	}

	if v.AWSKey != nil && v.AWSKey.Role != "" {
		env, err = env.Assume(v.AWSKey.Role)
		if err != nil {
			return nil, err
		}
	}

	return env, nil
}

func getEnvironment(v *Vault, name, password string) (*Environment, error) {
	env, err := openEnvironment(name, password)
	if err == nil {
		expired := time.Now().Add(5 * time.Minute).After(env.Expiration)
		if !expired {
			return env, nil
		}
	}

	// the environment isn't valid (possibly expired), so remove it
	removeEnvironment(name)

	env, err = v.CreateEnvironment(map[string]string{"VAULTED_ENV": name})
	if err != nil {
		return nil, err
	}

	// we have a valid environment, so if saving fails, ignore the failure
	sealEnvironment(name, password, env)
	return env, nil
}

func sealEnvironment(name, password string, env *Environment) error {
	// read the vault file (to get key details)
	vf, err := readVaultFile(name)
	if err != nil {
		return err
	}

	// marshal the environment content
	content, err := json.Marshal(env)
	if err != nil {
		return err
	}

	// encrypt the environment
	ef := &EnvironmentFile{
		Method:  "secretbox",
		Details: make(Details),
	}

	switch ef.Method {
	case "secretbox":
		nonce := [24]byte{}
		_, err = rand.Read(nonce[:])
		if err != nil {
			return err
		}
		ef.Details.SetBytes("nonce", nonce[:])

		key := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(key))
		if err != nil {
			return err
		}
		copy(key[:], derivedKey[:])

		ef.Ciphertext = secretbox.Seal(nil, content, &nonce, &key)

	default:
		return err
	}

	return writeEnvironmentFile(name, ef)
}

func openEnvironment(name, password string) (*Environment, error) {
	vf, err := readVaultFile(name)
	if err != nil {
		return nil, err
	}

	ef, err := readEnvironmentFile(name)
	if err != nil {
		return nil, err
	}

	e := Environment{}

	switch ef.Method {
	case "secretbox":
		if vf.Key == nil {
			return nil, ErrInvalidKeyConfig
		}

		nonce := ef.Details.Bytes("nonce")
		if len(nonce) == 0 {
			return nil, ErrInvalidEncryptionConfig
		}
		boxNonce := [24]byte{}
		copy(boxNonce[:], nonce)

		boxKey := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(boxKey))
		if err != nil {
			return nil, err
		}
		copy(boxKey[:], derivedKey[:])

		plaintext, ok := secretbox.Open(nil, ef.Ciphertext, &boxNonce, &boxKey)
		if !ok {
			return nil, ErrInvalidPassword
		}

		err = json.Unmarshal(plaintext, &e)
		if err != nil {
			return nil, err
		}

	default:
		return nil, fmt.Errorf("Invalid encryption method: %s", ef.Method)
	}

	return &e, nil
}
<commit_msg>Change cache expiration tolerance to 15 minutes<commit_after>package vaulted

import (
	"crypto/rand"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/miquella/xdg"
	"golang.org/x/crypto/nacl/secretbox"
)

var (
	ErrInvalidPassword         = errors.New("Invalid password")
	ErrInvalidKeyConfig        = errors.New("Invalid key configuration")
	ErrInvalidEncryptionConfig = errors.New("Invalid encryption configuration")
)

func VaultExists(name string) bool {
	existing := xdg.DATA.Find(filepath.Join("vaulted", name))
	if len(existing) == 0 {
		return false
	}

	return true
}

func ListVaults() ([]string, error) {
	vaults, err := xdg.DATA.Glob(filepath.Join("vaulted", "*"))
	if err != nil {
		return nil, err
	}

	var found []string
	emitted := map[string]bool{}
	for _, vault := range vaults {
		info, err := os.Stat(vault)
		if err != nil {
			return nil, err
		}
		if !info.Mode().IsRegular() {
			continue
		}

		if !emitted[info.Name()] {
			emitted[info.Name()] = true
			found = append(found, info.Name())
		}
	}

	return found, nil
}

func SealVault(name, password string, vault *Vault) error {
	vf := &VaultFile{
		Method:  "secretbox",
		Details: make(Details),
	}

	// generate a new key (while trying to keeping the existing key derivation and encryption methods)
	existingVaultFile, err := readVaultFile(name)
	if err == nil {
		vf.Method = existingVaultFile.Method
		vf.Key = existingVaultFile.Key
	}

	vf.Key = newVaultKey(vf.Key)

	// marshal the vault content
	content, err := json.Marshal(vault)
	if err != nil {
		return err
	}

	// encrypt the vault
	if vf.Method == "" {
		vf.Method = "secretbox"
	}

	switch vf.Method {
	case "secretbox":
		nonce := [24]byte{}
		_, err = rand.Read(nonce[:])
		if err != nil {
			return err
		}
		vf.Details.SetBytes("nonce", nonce[:])

		key := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(key))
		if err != nil {
			return err
		}
		copy(key[:], derivedKey[:])

		vf.Ciphertext = secretbox.Seal(nil, content, &nonce, &key)

	default:
		return fmt.Errorf("Invalid encryption method: %s", vf.Method)
	}

	writeVaultFile(name, vf)

	return nil
}

func OpenVault(name, password string) (*Vault, error) {
	vf, err := readVaultFile(name)
	if err != nil {
		return nil, err
	}

	v := Vault{}

	switch vf.Method {
	case "secretbox":
		if vf.Key == nil {
			return nil, ErrInvalidKeyConfig
		}

		nonce := vf.Details.Bytes("nonce")
		if len(nonce) == 0 {
			return nil, ErrInvalidEncryptionConfig
		}
		boxNonce := [24]byte{}
		copy(boxNonce[:], nonce)

		boxKey := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(boxKey))
		if err != nil {
			return nil, err
		}
		copy(boxKey[:], derivedKey[:])

		plaintext, ok := secretbox.Open(nil, vf.Ciphertext, &boxNonce, &boxKey)
		if !ok {
			return nil, ErrInvalidPassword
		}

		err = json.Unmarshal(plaintext, &v)
		if err != nil {
			return nil, err
		}

	default:
		return nil, fmt.Errorf("Invalid encryption method: %s", vf.Method)
	}

	return &v, nil
}

func RemoveVault(name string) error {
	existing := xdg.DATA_HOME.Find(filepath.Join("vaulted", name))
	if existing == "" {
		untouchable := xdg.DATA_DIRS.Find(filepath.Join("vaulted", name))
		if len(untouchable) == 0 {
			return os.ErrNotExist
		}

		return fmt.Errorf("Because %s is outside the vaulted managed directory (%s), it must be removed manually", untouchable[0], xdg.DATA_HOME.Join("vaulted"))
	}

	removeEnvironment(name)

	return os.Remove(existing)
}

func GetEnvironment(name, password string) (*Environment, error) {
	v, err := OpenVault(name, password)
	if err != nil {
		return nil, err
	}

	env, err := getEnvironment(v, name, password)
	if err != nil {
		return nil, err
	}

	if v.AWSKey != nil && v.AWSKey.Role != "" {
		env, err = env.Assume(v.AWSKey.Role)
		if err != nil {
			return nil, err
		}
	}

	return env, nil
}

func getEnvironment(v *Vault, name, password string) (*Environment, error) {
	env, err := openEnvironment(name, password)
	if err == nil {
		expired := time.Now().Add(15 * time.Minute).After(env.Expiration)
		if !expired {
			return env, nil
		}
	}

	// the environment isn't valid (possibly expired), so remove it
	removeEnvironment(name)

	env, err = v.CreateEnvironment(map[string]string{"VAULTED_ENV": name})
	if err != nil {
		return nil, err
	}

	// we have a valid environment, so if saving fails, ignore the failure
	sealEnvironment(name, password, env)
	return env, nil
}

func sealEnvironment(name, password string, env *Environment) error {
	// read the vault file (to get key details)
	vf, err := readVaultFile(name)
	if err != nil {
		return err
	}

	// marshal the environment content
	content, err := json.Marshal(env)
	if err != nil {
		return err
	}

	// encrypt the environment
	ef := &EnvironmentFile{
		Method:  "secretbox",
		Details: make(Details),
	}

	switch ef.Method {
	case "secretbox":
		nonce := [24]byte{}
		_, err = rand.Read(nonce[:])
		if err != nil {
			return err
		}
		ef.Details.SetBytes("nonce", nonce[:])

		key := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(key))
		if err != nil {
			return err
		}
		copy(key[:], derivedKey[:])

		ef.Ciphertext = secretbox.Seal(nil, content, &nonce, &key)

	default:
		return err
	}

	return writeEnvironmentFile(name, ef)
}

func openEnvironment(name, password string) (*Environment, error) {
	vf, err := readVaultFile(name)
	if err != nil {
		return nil, err
	}

	ef, err := readEnvironmentFile(name)
	if err != nil {
		return nil, err
	}

	e := Environment{}

	switch ef.Method {
	case "secretbox":
		if vf.Key == nil {
			return nil, ErrInvalidKeyConfig
		}

		nonce := ef.Details.Bytes("nonce")
		if len(nonce) == 0 {
			return nil, ErrInvalidEncryptionConfig
		}
		boxNonce := [24]byte{}
		copy(boxNonce[:], nonce)

		boxKey := [32]byte{}
		derivedKey, err := vf.Key.key(password, len(boxKey))
		if err != nil {
			return nil, err
		}
		copy(boxKey[:], derivedKey[:])

		plaintext, ok := secretbox.Open(nil, ef.Ciphertext, &boxNonce, &boxKey)
		if !ok {
			return nil, ErrInvalidPassword
		}

		err = json.Unmarshal(plaintext, &e)
		if err != nil {
			return nil, err
		}

	default:
		return nil, fmt.Errorf("Invalid encryption method: %s", ef.Method)
	}

	return &e, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.9.3"
var AppcVersion = schema.AppContainerVersion
<commit_msg>version: bump to v0.9.3+git<commit_after>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.9.3+git"
var AppcVersion = schema.AppContainerVersion
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
)

var (
	dataFile = flag.String("file", "store.json", "data store file name")
	status   = flag.String("status", "stopped|pending|terminated", "the status you would like to poll")
	useToml  = flag.Bool("toml", false, "A switch to use creds from tomlfile instead of ENV")
)

var store *StatusStore

type Conn struct {
	aw2  *ec2.EC2
	data map[string]string
	save chan ec2record
}

type ec2record struct {
	key, status string
}

// create a struct to map toml config file
// TODO: add this as an switch in init()
type AwsConfig struct {
	AwsSecretKey string `toml:"AWS_ACCESS_KEY_ID"`
	AwsAccessKey string `toml:"AWS_SECRET_ACCESS_KEY"`
	Region       string `toml:"AWS_REGION"`
}

func (c *Conn) SetEc2Data(resp *ec2.DescribeInstancesOutput) {
	insMap := make(map[string]string)
	for idx, _ := range resp.Reservations {
		for _, inst := range resp.Reservations[idx].Instances {
			// fmt.Printf("   Instance State: %v InstanceID: %v \n", *inst.State.Name, *inst.InstanceID)
			// dereference pointer
			var id, state string
			id = *inst.PrivateDNSName
			state = *inst.State.Name
			insMap[id] = state
		}
	}
	c.data = insMap
}

func (c *Conn) IterateMapToChan() {

	go func() {
		for k, v := range c.data {

			c.save <- ec2record{k, v}
		}
	}()

}

func (c *Conn) GetEc2Data() {

	resp, err := c.aw2.DescribeInstances(nil)
	if err != nil {
		log.Fatal(err)
	}

	c.SetEc2Data(resp)

}

func NewEc2() *Conn {
	c := new(Conn)
	c.aw2 = ec2.New(&aws.Config{Region: "us-west-2"})
	c.save = make(chan ec2record)

	return c
}

func (d *StatusStore) DataToFile(status string, c *Conn) {
	for k, v := range c.data {
		if v == status {
			if _, ok := d.status[k]; ok {
			} else {
				err := d.save(k, v)
				if err != nil {
					log.Printf("something went wrong save %s", k)
				}
			}
		}
	}
}

func (c *Conn) Run(d *StatusStore) {

	// begin channel operations
	for {
		// set timeout for loop
		timeout := time.After(5 * time.Second)
		// set initial dataset
		RefreshData(d, c)
		select {
		case result := <-c.save:
			if result.status == "stopped" {
				fmt.Println(result.status)
			}
		case <-timeout:
			continue

		}
	}

}

func RefreshData(d *StatusStore, c *Conn) {
	c.GetEc2Data()
	d.DataToFile(*status, c)
	c.IterateMapToChan()
}

func Add(value string) {
	key := store.Put(value)
	fmt.Println(key)
}

func main() {
	// Create an EC2 service object in the "us-west-2" region
	// Note that you can also configure your region globally by
	// exporting the AWS_REGION environment variable
	flag.Parse()

	// instantiate new ec2 "object"
	c := NewEc2()

	// Get new Status store
	d := NewStatusStore(*dataFile)

	c.Run(d)

}
<commit_msg>{WIP}<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
)

var (
	dataFile = flag.String("file", "store.json", "data store file name")
	status   = flag.String("status", "stopped|pending|terminated", "the status you would like to poll")
	useToml  = flag.Bool("toml", false, "A switch to use creds from tomlfile instead of ENV")
)

var store *StatusStore

type Conn struct {
	aw2  *ec2.EC2
	data map[string]string
	save chan ec2record
}

type ec2record struct {
	key, status string
}

// create a struct to map toml config file
// TODO: add this as an switch in init()
type AwsConfig struct {
	AwsSecretKey string `toml:"AWS_ACCESS_KEY_ID"`
	AwsAccessKey string `toml:"AWS_SECRET_ACCESS_KEY"`
	Region       string `toml:"AWS_REGION"`
}

func (c *Conn) SetEc2Data(resp *ec2.DescribeInstancesOutput) {
	insMap := make(map[string]string)
	for idx, _ := range resp.Reservations {
		for _, inst := range resp.Reservations[idx].Instances {
			// fmt.Printf("   Instance State: %v InstanceID: %v \n", *inst.State.Name, *inst.InstanceID)
			// dereference pointer
			var id, state string
			id = *inst.PrivateDNSName
			state = *inst.State.Name
			insMap[id] = state
		}
	}
	c.data = insMap
}

func (c *Conn) IterateMapToChan(status string) {

	go func() {
		for k, v := range c.data {

			if v == status {

				c.save <- ec2record{k, v}
			}
		}
	}()

}

func (c *Conn) GetEc2Data() {

	resp, err := c.aw2.DescribeInstances(nil)
	if err != nil {
		log.Fatal(err)
	}

	c.SetEc2Data(resp)

}

func NewEc2() *Conn {
	c := new(Conn)
	c.aw2 = ec2.New(&aws.Config{Region: "us-west-2"})
	c.save = make(chan ec2record)

	return c
}

func (d *StatusStore) DataToFile(status string, c *Conn) {
	for k, v := range c.data {
		if v == status {
			if _, ok := d.status[k]; ok {
			} else {
				err := d.save(k, v)
				if err != nil {
					log.Printf("something went wrong save %s", k)
				}
			}
		}
	}
}

func (c *Conn) Run(d *StatusStore) {

	// begin channel operations
	for {
		// set timeout for loop
		timeout := time.After(5 * time.Second)
		// set initial dataset
		select {
		case result := <-c.save:
			fmt.Println(result.status)
		case <-timeout:
			return

		}
	}

}

func RefreshData(d *StatusStore, c *Conn) {
	c.GetEc2Data()
	d.DataToFile(*status, c)
	c.IterateMapToChan(*status)
}

func Add(value string) {
	key := store.Put(value)
	fmt.Println(key)
}

func main() {
	// Create an EC2 service object in the "us-west-2" region
	// Note that you can also configure your region globally by
	// exporting the AWS_REGION environment variable
	flag.Parse()

	// instantiate new ec2 "object"
	c := NewEc2()

	// Get new Status store
	d := NewStatusStore(*dataFile)

	RefreshData(d, c)
	c.Run(d)

}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

package runtime

import (
	"math"
	"os"
	"regexp"
	"strings"

	"github.com/ta2gch/iris/runtime/env"
	"github.com/ta2gch/iris/runtime/ilos"
	"github.com/ta2gch/iris/runtime/ilos/instance"
)

func TopLevelHander(e env.Environment, c ilos.Instance) (ilos.Instance, ilos.Instance) {
	return nil, c
}

var TopLevel = env.NewEnvironment(
	instance.NewStream(os.Stdin, nil),
	instance.NewStream(nil, os.Stdout),
	instance.NewStream(nil, os.Stderr),
	instance.NewFunction(instance.NewSymbol("TOP-LEVEL-HANDLER"), TopLevelHander))
var Version = "0.1.0"

func defspecial2(name string, function interface{}) {
	name = regexp.MustCompile(`(.)([A-Z])`).ReplaceAllString(name, "$1-$2")
	name = strings.ToUpper(name)
	symbol := instance.NewSymbol(name)
	TopLevel.Special.Define(symbol, instance.NewFunction(func2symbol(function), function))
}

func defun2(name string, function interface{}) {
	name = regexp.MustCompile(`(.)([A-Z])`).ReplaceAllString(name, "$1-$2")
	name = strings.ToUpper(name)
	symbol := instance.NewSymbol(name)
	TopLevel.Function.Define(symbol, instance.NewFunction(symbol, function))
}
func defglobal(name string, value ilos.Instance) {
	name = regexp.MustCompile(`(.)([A-Z])`).ReplaceAllString(name, "$1-$2")
	name = strings.ToUpper(name)
	symbol := instance.NewSymbol(name)
	TopLevel.Variable.Define(symbol, value)
}
func init() {
	defglobal("*pi*", instance.Float(math.Pi))
	defglobal("*MostPositiveFloat*", MostPositiveFloat)
	defglobal("*MostNegativeFloat*", MostNegativeFloat)
	defun2("-", Substruct)
	defun2("+", Add)
	defun2("*", Multiply)
	defun2("<", NumberLessThan)
	defun2("<=", NumberLessThanOrEqual)
	defun2("=", NumberEqual)
	defun2(">", NumberGreaterThan)
	defun2(">=", NumberGreaterThanOrEqual)
	defspecial2("Quasiquote", Quasiquote)
	defun2("Abs", Abs)
	defspecial2("And", And)
	defun2("Append", Append)
	defun2("Apply", Apply)
	defun2("ArrayDimensions", ArrayDimensions)
	defun2("Aref", Aref)
	defun2("Assoc", Assoc)
	// TODO: defspecial2("Assure", Assure)
	defun2("Atan", Atan)
	defun2("Atan2", Atan2)
	defun2("Atanh", Atanh)
	defun2("BasicArray*P", BasicArrayStarP)
	defun2("BasicArrayP", BasicArrayP)
	defun2("BasicVectorP", BasicVectorP)
	defspecial2("Block", Block)
	defun2("Car", Car)
	defspecial2("Case", Case)
	defspecial2("CaseUsing", CaseUsing)
	defspecial2("Catch", Catch)
	defun2("Cdr", Cdr)
	defun2("Ceiling", Ceiling)
	defun2("Cerror", Cerror)
	defun2("CharIndex", CharIndex)
	defun2("char/=", CharNotEqual)
	defun2("Char<", CharLessThan)
	defun2("Char<=", CharLessThanOrEqual)
	defun2("Char=", CharEqual)
	defun2("Char>", CharGreaterThan)
	defun2("Char>=", CharGreaterThanOrEqual)
	defun2("Characterp", Characterp)
	defspecial2("Class", Class)
	defun2("ClassOf", ClassOf)
	defun2("Close", Close)
	// TODO defun2("Coercion", Coercion)
	defspecial2("Cond", Cond)
	defun2("ConditionContinuable", ConditionContinuable)
	defun2("Cons", Cons)
	defun2("Consp", Consp)
	defun2("ContinueCondition", ContinueCondition)
	// TODO defun2("Convert", Convert)
	defun2("Cos", Cos)
	defun2("Cosh", Cosh)
	defun2("Create", Create) //TODO Change to generic function
	defun2("CreateArray", CreateArray)
	defun2("CreateList", CreateList)
	defun2("CreateString", CreateString)
	defun2("CreateStringInputStream", CreateStringInputStream)
	defun2("CreateStringOutputStream", CreateStringOutputStream)
	defun2("CreateVector", CreateVector)
	defspecial2("Defclass", Defclass)
	defspecial2("Defconstant", Defconstant)
	defspecial2("Defdynamic", Defdynamic)
	defspecial2("Defgeneric", Defgeneric)
	defspecial2("Defmethod", Defmethod)
	defspecial2("Defglobal", Defglobal)
	defspecial2("Defmacro", Defmacro)
	defspecial2("Defun", Defun)
	defun2("Div", Div)
	defspecial2("Dynamic", Dynamic)
	defspecial2("DynamicLet", DynamicLet)
	defun2("Elt", Elt)
	defun2("Eq", Eq)
	defun2("Eql", Eql)
	defun2("Equal", Equal)
	defun2("Error", Error)
	defun2("ErrorOutput", ErrorOutput)
	defun2("Exp", Exp)
	defun2("Expt", Expt)
	// TODO defun2("FileLength", FileLength)
	// TODO defun2("FilePosition", FilePosition)
	// TODO defun2("FinishOutput", FinishOutput)
	defspecial2("Flet", Flet)
	defun2("Float", Float)
	defun2("Floatp", Floatp)
	defun2("Floor", Floor)
	defspecial2("For", For)
	defun2("Format", Format) // TODO full syntax
	// TODO other print function
	defun2("Funcall", Funcall)
	defspecial2("Function", Function)
	defun2("Functionp", Functionp)
	defun2("Garef", Garef)
	defun2("Gcd", Gcd)
	defun2("GeneralArray*P", GeneralArrayStarP)
	defun2("GeneralVectorP", GeneralVectorP)
	// TODO defun2("GenericFunctionP", GenericFunctionP)
	defun2("Gensym", Gensym)
	// TODO defun2("GetInternalRealTime", GetInternalRealTime)
	// TODO defun2("GetInternalRunTime", GetInternalRunTime)
	defun2("GetOutputStreamString", GetOutputStreamString)
	// TODO defun2("GetUniversalTime", GetUniversalTime)
	defspecial2("Go", Go)
	// TODO defun2("Identity", Identity)
	defspecial2("If", If)
	// TODO defspecial2("IgnoreErrors", IgnoreErrors)
	defun2("InitializeObject", InitializeObject) // TODO change generic function
	defun2("InputStreamP", InputStreamP)
	defun2("Instancep", Instancep)
	// TODO defun2("Integer", Integer)
	defun2("Integerp", Integerp)
	// TODO defun2("InternalTimeUnitsPerSecond", InternalTimeUnitsPerSecond)
	defun2("Isqrt", Isqrt)
	defspecial2("Labels", Labels)
	defspecial2("Lambda", Lambda)
	defun2("Lcm", Lcm)
	defun2("Length", Length)
	defspecial2("Let", Let)
	defspecial2("Let*", LetStar)
	defun2("List", List)
	defun2("Listp", Listp)
	defun2("Log", Log)
	defun2("MapInto", MapInto)
	defun2("Mapc", Mapc)
	defun2("Mapcan", Mapcan)
	defun2("Mapcar", Mapcar)
	defun2("Mapcon", Mapcon)
	defun2("Mapl", Mapl)
	defun2("Maplist", Maplist)
	defun2("Max", Max)
	defun2("Member", Member)
	defun2("Min", Min)
	defun2("Mod", Mod)
	defglobal("NIL", Nil)
	defun2("Not", Not)
	defun2("Nreverse", Nreverse)
	defun2("Null", Null)
	defun2("Numberp", Numberp)
	defun2("OpenInputFile", OpenInputFile)
	defun2("OpenIoFile", OpenIoFile)
	defun2("OpenOutputFile", OpenOutputFile)
	defun2("OpenStreamP", OpenStreamP)
	defspecial2("Or", Or)
	defun2("OutputStreamP", OutputStreamP)
	defun2("ParseNumber", ParseNumber)
	// TODO defun2("PreviewChar", PreviewChar)
	// TODO defun2("ProveFile", ProveFile)
	defspecial2("Progn", Progn)
	defun2("Property", Property)
	defspecial2("Quasiquote", Quasiquote)
	defspecial2("Quote", Quote)
	defun2("Quotient", Quotient)
	defun2("Read", Read)
	// TODO defun2("ReadByte", ReadByte)
	defun2("ReadChar", ReadChar)
	defun2("ReadLine", ReadLine)
	defun2("RemoveProperty", RemoveProperty)
	defun2("ReportCondition", ReportCondition)
	defspecial2("ReturnFrom", ReturnFrom)
	defun2("Reverse", Reverse)
	defun2("Round", Round)
	defun2("SetAref", SetAref)
	defun2("(setf aref)", SetAref)
	defun2("SetCar", SetCar)
	defun2("(setf car)", SetCar)
	defun2("SetCdr", SetCdr)
	defun2("(setf cdr)", SetCdr)
	defun2("SetDynamic", SetDynamic)
	defun2("(setf dynamic)", SetDynamic)
	defun2("SetElt", SetElt)
	defun2("(setf elt)", SetElt)
	// TODO defun2("SetFilePosition", SetFilePosition)
	defun2("SetGaref", SetGaref)
	defun2("(setf garef)", SetGaref)
	defun2("SetProperty", SetProperty)
	defun2("(setf property)", SetProperty)
	defspecial2("Setf", Setf)
	defspecial2("Setq", Setq)
	defun2("SignalCondition", SignalCondition)
	// TODO defun2("SimpleErrorFormatArguments", SimpleErrorFormatArguments)
	// TODO defun2("SimpleErrorFormatString", SimpleErrorFormatString)
	defun2("Sin", Sin)
	defun2("Sinh", Sinh)
	defun2("Sqrt", Sqrt)
	defun2("StandardInput", StandardInput)
	defun2("StandardOutput", StandardOutput)
	defun2("StreamReadyP", StreamReadyP)
	defun2("Streamp", Streamp)
	defun2("StringAppend", StringAppend)
	defun2("StringIndex", StringIndex)
	defun2("String/=", StringNotEqual)
	defun2("String>", StringGreaterThan)
	defun2("String>=", StringGreaterThanOrEqual)
	defun2("String=", StringEqual)
	defun2("String<", StringLessThan)
	defun2("String<=", StringLessThanOrEqual)
	defun2("Stringp", Stringp)
	defun2("Subclassp", Subclassp)
	defun2("Subseq", Subseq)
	defun2("Symbolp", Symbolp)
	defglobal("T", T)
	defspecial2("Tagbody", Tagbody)
	defspecial2("Tan", Tan)
	defspecial2("Tanh", Tanh)
	// TODO defspecial2("The", The)
	defspecial2("Throw", Throw)
	defun2("Truncate", Truncate)
	// TODO defun1("UndefinedEntityName", UndefinedEntityName)
	// TODO defun2("UndefinedEntityNamespace", UndefinedEntityNamespace)
	defspecial2("UnwindProtect", UnwindProtect)
	defun2("Vector", Vector)
	defspecial2("While", While)
	defspecial2("WithErrorOutput", WithErrorOutput)
	defspecial2("WithHandler", WithHandler)
	defspecial2("WithOpenInputFile", WithOpenInputFile)
	defspecial2("WithOpenOutputFile", WithOpenOutputFile)
	defspecial2("WithStandardInput", WithStandardInput)
	defspecial2("WithStandardOutput", WithStandardOutput)
	// TODO defun2("WriteByte", WriteByte)
}
<commit_msg>Removed runtime.Version<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

package runtime

import (
	"math"
	"os"
	"regexp"
	"strings"

	"github.com/ta2gch/iris/runtime/env"
	"github.com/ta2gch/iris/runtime/ilos"
	"github.com/ta2gch/iris/runtime/ilos/instance"
)

func TopLevelHander(e env.Environment, c ilos.Instance) (ilos.Instance, ilos.Instance) {
	return nil, c
}

var TopLevel = env.NewEnvironment(
	instance.NewStream(os.Stdin, nil),
	instance.NewStream(nil, os.Stdout),
	instance.NewStream(nil, os.Stderr),
	instance.NewFunction(instance.NewSymbol("TOP-LEVEL-HANDLER"), TopLevelHander),
)

func defspecial2(name string, function interface{}) {
	name = regexp.MustCompile(`(.)([A-Z])`).ReplaceAllString(name, "$1-$2")
	name = strings.ToUpper(name)
	symbol := instance.NewSymbol(name)
	TopLevel.Special.Define(symbol, instance.NewFunction(func2symbol(function), function))
}

func defun2(name string, function interface{}) {
	name = regexp.MustCompile(`(.)([A-Z])`).ReplaceAllString(name, "$1-$2")
	name = strings.ToUpper(name)
	symbol := instance.NewSymbol(name)
	TopLevel.Function.Define(symbol, instance.NewFunction(symbol, function))
}
func defglobal(name string, value ilos.Instance) {
	name = regexp.MustCompile(`(.)([A-Z])`).ReplaceAllString(name, "$1-$2")
	name = strings.ToUpper(name)
	symbol := instance.NewSymbol(name)
	TopLevel.Variable.Define(symbol, value)
}
func init() {
	defglobal("*pi*", instance.Float(math.Pi))
	defglobal("*MostPositiveFloat*", MostPositiveFloat)
	defglobal("*MostNegativeFloat*", MostNegativeFloat)
	defun2("-", Substruct)
	defun2("+", Add)
	defun2("*", Multiply)
	defun2("<", NumberLessThan)
	defun2("<=", NumberLessThanOrEqual)
	defun2("=", NumberEqual)
	defun2(">", NumberGreaterThan)
	defun2(">=", NumberGreaterThanOrEqual)
	defspecial2("Quasiquote", Quasiquote)
	defun2("Abs", Abs)
	defspecial2("And", And)
	defun2("Append", Append)
	defun2("Apply", Apply)
	defun2("ArrayDimensions", ArrayDimensions)
	defun2("Aref", Aref)
	defun2("Assoc", Assoc)
	// TODO: defspecial2("Assure", Assure)
	defun2("Atan", Atan)
	defun2("Atan2", Atan2)
	defun2("Atanh", Atanh)
	defun2("BasicArray*P", BasicArrayStarP)
	defun2("BasicArrayP", BasicArrayP)
	defun2("BasicVectorP", BasicVectorP)
	defspecial2("Block", Block)
	defun2("Car", Car)
	defspecial2("Case", Case)
	defspecial2("CaseUsing", CaseUsing)
	defspecial2("Catch", Catch)
	defun2("Cdr", Cdr)
	defun2("Ceiling", Ceiling)
	defun2("Cerror", Cerror)
	defun2("CharIndex", CharIndex)
	defun2("char/=", CharNotEqual)
	defun2("Char<", CharLessThan)
	defun2("Char<=", CharLessThanOrEqual)
	defun2("Char=", CharEqual)
	defun2("Char>", CharGreaterThan)
	defun2("Char>=", CharGreaterThanOrEqual)
	defun2("Characterp", Characterp)
	defspecial2("Class", Class)
	defun2("ClassOf", ClassOf)
	defun2("Close", Close)
	// TODO defun2("Coercion", Coercion)
	defspecial2("Cond", Cond)
	defun2("ConditionContinuable", ConditionContinuable)
	defun2("Cons", Cons)
	defun2("Consp", Consp)
	defun2("ContinueCondition", ContinueCondition)
	// TODO defun2("Convert", Convert)
	defun2("Cos", Cos)
	defun2("Cosh", Cosh)
	defun2("Create", Create) //TODO Change to generic function
	defun2("CreateArray", CreateArray)
	defun2("CreateList", CreateList)
	defun2("CreateString", CreateString)
	defun2("CreateStringInputStream", CreateStringInputStream)
	defun2("CreateStringOutputStream", CreateStringOutputStream)
	defun2("CreateVector", CreateVector)
	defspecial2("Defclass", Defclass)
	defspecial2("Defconstant", Defconstant)
	defspecial2("Defdynamic", Defdynamic)
	defspecial2("Defgeneric", Defgeneric)
	defspecial2("Defmethod", Defmethod)
	defspecial2("Defglobal", Defglobal)
	defspecial2("Defmacro", Defmacro)
	defspecial2("Defun", Defun)
	defun2("Div", Div)
	defspecial2("Dynamic", Dynamic)
	defspecial2("DynamicLet", DynamicLet)
	defun2("Elt", Elt)
	defun2("Eq", Eq)
	defun2("Eql", Eql)
	defun2("Equal", Equal)
	defun2("Error", Error)
	defun2("ErrorOutput", ErrorOutput)
	defun2("Exp", Exp)
	defun2("Expt", Expt)
	// TODO defun2("FileLength", FileLength)
	// TODO defun2("FilePosition", FilePosition)
	// TODO defun2("FinishOutput", FinishOutput)
	defspecial2("Flet", Flet)
	defun2("Float", Float)
	defun2("Floatp", Floatp)
	defun2("Floor", Floor)
	defspecial2("For", For)
	defun2("Format", Format) // TODO full syntax
	// TODO other print function
	defun2("Funcall", Funcall)
	defspecial2("Function", Function)
	defun2("Functionp", Functionp)
	defun2("Garef", Garef)
	defun2("Gcd", Gcd)
	defun2("GeneralArray*P", GeneralArrayStarP)
	defun2("GeneralVectorP", GeneralVectorP)
	// TODO defun2("GenericFunctionP", GenericFunctionP)
	defun2("Gensym", Gensym)
	// TODO defun2("GetInternalRealTime", GetInternalRealTime)
	// TODO defun2("GetInternalRunTime", GetInternalRunTime)
	defun2("GetOutputStreamString", GetOutputStreamString)
	// TODO defun2("GetUniversalTime", GetUniversalTime)
	defspecial2("Go", Go)
	// TODO defun2("Identity", Identity)
	defspecial2("If", If)
	// TODO defspecial2("IgnoreErrors", IgnoreErrors)
	defun2("InitializeObject", InitializeObject) // TODO change generic function
	defun2("InputStreamP", InputStreamP)
	defun2("Instancep", Instancep)
	// TODO defun2("Integer", Integer)
	defun2("Integerp", Integerp)
	// TODO defun2("InternalTimeUnitsPerSecond", InternalTimeUnitsPerSecond)
	defun2("Isqrt", Isqrt)
	defspecial2("Labels", Labels)
	defspecial2("Lambda", Lambda)
	defun2("Lcm", Lcm)
	defun2("Length", Length)
	defspecial2("Let", Let)
	defspecial2("Let*", LetStar)
	defun2("List", List)
	defun2("Listp", Listp)
	defun2("Log", Log)
	defun2("MapInto", MapInto)
	defun2("Mapc", Mapc)
	defun2("Mapcan", Mapcan)
	defun2("Mapcar", Mapcar)
	defun2("Mapcon", Mapcon)
	defun2("Mapl", Mapl)
	defun2("Maplist", Maplist)
	defun2("Max", Max)
	defun2("Member", Member)
	defun2("Min", Min)
	defun2("Mod", Mod)
	defglobal("NIL", Nil)
	defun2("Not", Not)
	defun2("Nreverse", Nreverse)
	defun2("Null", Null)
	defun2("Numberp", Numberp)
	defun2("OpenInputFile", OpenInputFile)
	defun2("OpenIoFile", OpenIoFile)
	defun2("OpenOutputFile", OpenOutputFile)
	defun2("OpenStreamP", OpenStreamP)
	defspecial2("Or", Or)
	defun2("OutputStreamP", OutputStreamP)
	defun2("ParseNumber", ParseNumber)
	// TODO defun2("PreviewChar", PreviewChar)
	// TODO defun2("ProveFile", ProveFile)
	defspecial2("Progn", Progn)
	defun2("Property", Property)
	defspecial2("Quasiquote", Quasiquote)
	defspecial2("Quote", Quote)
	defun2("Quotient", Quotient)
	defun2("Read", Read)
	// TODO defun2("ReadByte", ReadByte)
	defun2("ReadChar", ReadChar)
	defun2("ReadLine", ReadLine)
	defun2("RemoveProperty", RemoveProperty)
	defun2("ReportCondition", ReportCondition)
	defspecial2("ReturnFrom", ReturnFrom)
	defun2("Reverse", Reverse)
	defun2("Round", Round)
	defun2("SetAref", SetAref)
	defun2("(setf aref)", SetAref)
	defun2("SetCar", SetCar)
	defun2("(setf car)", SetCar)
	defun2("SetCdr", SetCdr)
	defun2("(setf cdr)", SetCdr)
	defun2("SetDynamic", SetDynamic)
	defun2("(setf dynamic)", SetDynamic)
	defun2("SetElt", SetElt)
	defun2("(setf elt)", SetElt)
	// TODO defun2("SetFilePosition", SetFilePosition)
	defun2("SetGaref", SetGaref)
	defun2("(setf garef)", SetGaref)
	defun2("SetProperty", SetProperty)
	defun2("(setf property)", SetProperty)
	defspecial2("Setf", Setf)
	defspecial2("Setq", Setq)
	defun2("SignalCondition", SignalCondition)
	// TODO defun2("SimpleErrorFormatArguments", SimpleErrorFormatArguments)
	// TODO defun2("SimpleErrorFormatString", SimpleErrorFormatString)
	defun2("Sin", Sin)
	defun2("Sinh", Sinh)
	defun2("Sqrt", Sqrt)
	defun2("StandardInput", StandardInput)
	defun2("StandardOutput", StandardOutput)
	defun2("StreamReadyP", StreamReadyP)
	defun2("Streamp", Streamp)
	defun2("StringAppend", StringAppend)
	defun2("StringIndex", StringIndex)
	defun2("String/=", StringNotEqual)
	defun2("String>", StringGreaterThan)
	defun2("String>=", StringGreaterThanOrEqual)
	defun2("String=", StringEqual)
	defun2("String<", StringLessThan)
	defun2("String<=", StringLessThanOrEqual)
	defun2("Stringp", Stringp)
	defun2("Subclassp", Subclassp)
	defun2("Subseq", Subseq)
	defun2("Symbolp", Symbolp)
	defglobal("T", T)
	defspecial2("Tagbody", Tagbody)
	defspecial2("Tan", Tan)
	defspecial2("Tanh", Tanh)
	// TODO defspecial2("The", The)
	defspecial2("Throw", Throw)
	defun2("Truncate", Truncate)
	// TODO defun1("UndefinedEntityName", UndefinedEntityName)
	// TODO defun2("UndefinedEntityNamespace", UndefinedEntityNamespace)
	defspecial2("UnwindProtect", UnwindProtect)
	defun2("Vector", Vector)
	defspecial2("While", While)
	defspecial2("WithErrorOutput", WithErrorOutput)
	defspecial2("WithHandler", WithHandler)
	defspecial2("WithOpenInputFile", WithOpenInputFile)
	defspecial2("WithOpenOutputFile", WithOpenOutputFile)
	defspecial2("WithStandardInput", WithStandardInput)
	defspecial2("WithStandardOutput", WithStandardOutput)
	// TODO defun2("WriteByte", WriteByte)
}
<|endoftext|>


<commit_before>/*
   Copyright 2020 Docker Compose CLI authors

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

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

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

package metrics

import (
	"bytes"
	"context"
	"encoding/json"
	"net"
	"net/http"
	"time"
)

type client struct {
	httpClient *http.Client
}

// Command is a command
type Command struct {
	Command string `json:"command"`
	Context string `json:"context"`
	Source  string `json:"source"`
	Status  string `json:"status"`
}

const (
	// CLISource is sent for cli metrics
	CLISource = "cli"
	// APISource is sent for API metrics
	APISource = "api"
	// SuccessStatus is sent for API metrics
	SuccessStatus = "success"
	// FailureStatus is sent for API metrics
	FailureStatus = "failure"
	// CanceledStatus is sent for API metrics
	CanceledStatus = "canceled"
)

// Client sends metrics to Docker Desktopn
type Client interface {
	// Send sends the command to Docker Desktop. Note that the function doesn't
	// return anything, not even an error, this is because we don't really care
	// if the metrics were sent or not. We only fire and forget.
	Send(Command)
}

// NewClient returns a new metrics client
func NewClient() Client {
	return &client{
		httpClient: &http.Client{
			Transport: &http.Transport{
				DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
					return conn()
				},
			},
		},
	}
}

func (c *client) Send(command Command) {
	result := make(chan bool, 1)
	go func() {
		postMetrics(command, c)
		result <- true
	}()

	// wait for the post finished, or timeout in case anything freezes.
	// Posting metrics without Desktop listening returns in less than a ms, and a handful of ms (often <2ms) when Desktop is listening
	select {
	case <-result:
	case <-time.After(50 * time.Millisecond):
	}
}

func postMetrics(command Command, c *client) {
	req, err := json.Marshal(command)
	if err == nil {
		_, _ = c.httpClient.Post("http://localhost/usage", "application/json", bytes.NewBuffer(req))
	}
}
<commit_msg>make metrics' source configuration (see compose-switch)<commit_after>/*
   Copyright 2020 Docker Compose CLI authors

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

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

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

package metrics

import (
	"bytes"
	"context"
	"encoding/json"
	"net"
	"net/http"
	"os"
	"time"
)

type client struct {
	httpClient *http.Client
}

// Command is a command
type Command struct {
	Command string `json:"command"`
	Context string `json:"context"`
	Source  string `json:"source"`
	Status  string `json:"status"`
}

// CLISource is sent for cli metrics
var CLISource = "cli"

func init() {
	if v, ok := os.LookupEnv("DOCKER_METRICS_SOURCE"); ok {
		CLISource = v
	}
}

const (
	// APISource is sent for API metrics
	APISource = "api"
	// SuccessStatus is sent for API metrics
	SuccessStatus = "success"
	// FailureStatus is sent for API metrics
	FailureStatus = "failure"
	// CanceledStatus is sent for API metrics
	CanceledStatus = "canceled"
)

// Client sends metrics to Docker Desktopn
type Client interface {
	// Send sends the command to Docker Desktop. Note that the function doesn't
	// return anything, not even an error, this is because we don't really care
	// if the metrics were sent or not. We only fire and forget.
	Send(Command)
}

// NewClient returns a new metrics client
func NewClient() Client {
	return &client{
		httpClient: &http.Client{
			Transport: &http.Transport{
				DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
					return conn()
				},
			},
		},
	}
}

func (c *client) Send(command Command) {
	result := make(chan bool, 1)
	go func() {
		postMetrics(command, c)
		result <- true
	}()

	// wait for the post finished, or timeout in case anything freezes.
	// Posting metrics without Desktop listening returns in less than a ms, and a handful of ms (often <2ms) when Desktop is listening
	select {
	case <-result:
	case <-time.After(50 * time.Millisecond):
	}
}

func postMetrics(command Command, c *client) {
	req, err := json.Marshal(command)
	if err == nil {
		_, _ = c.httpClient.Post("http://localhost/usage", "application/json", bytes.NewBuffer(req))
	}
}
<|endoftext|>


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

package deploy

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/repository"
	"github.com/globocom/tsuru/testing"
	"launchpad.net/gocheck"
)

func (s *S) TestDeploy(c *gocheck.C) {
	content := `{"ssh_url": "git://tsuruhost.com/cribcaged.git"}`
	h := &testing.TestHandler{Content: content}
	t := &testing.T{}
	gandalfServer := t.StartGandalfTestServer(h)
	defer gandalfServer.Close()
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte("cloned"))
	provisioner.PrepareOutput([]byte("updated"))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	provisioner.Provision(app)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7", w)
	c.Assert(err, gocheck.IsNil)
	c.Assert(app.Commands, gocheck.DeepEquals, []string{"restart"})
	c.Assert(provisioner.InstalledDeps(app), gocheck.Equals, 1)
	cloneCommand := "git clone git://tsuruhost.com/cribcaged.git test/dir --depth 1"
	c.Assert(provisioner.GetCmds(cloneCommand, app), gocheck.HasLen, 1)
	path, _ := repository.GetPath()
	checkoutCommand := fmt.Sprintf("cd %s && git checkout 5734f0042844fdeb5bbc1b72b18f2dc1779cade7", path)
	c.Assert(provisioner.GetCmds(checkoutCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestDeployLogsActions(c *gocheck.C) {
	h := &testing.TestHandler{}
	t := &testing.T{}
	gandalfServer := t.StartGandalfTestServer(h)
	defer gandalfServer.Close()
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte(""))
	provisioner.PrepareOutput([]byte("updated"))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	provisioner.Provision(app)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7", w)
	c.Assert(err, gocheck.IsNil)
	logs := w.String()
	expected := `
 ---> Tsuru receiving push

 ---> Replicating the application repository across units

 ---> Installing dependencies

 ---> Restarting application
Restarting app...
 ---> Deploy done!

`
	c.Assert(logs, gocheck.Equals, expected)
}

func (s *S) TestCloneRepository(c *gocheck.C) {
	h := &testing.TestHandler{}
	t := &testing.T{}
	gandalfServer := t.StartGandalfTestServer(h)
	defer gandalfServer.Close()
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("something"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := clone(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "something")
	url := repository.ReadOnlyURL(app.GetName())
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("git clone %s %s --depth 1", url, path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestCloneRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := clone(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestPullRepository(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("pulled"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := fetch(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "pulled")
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("cd %s && git fetch origin", path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestPullRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := fetch(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestCheckout(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("updated"))
	app := testing.NewFakeApp("moon", "python", 1)
	out, err := checkout(p, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7")
	c.Assert(err, gocheck.IsNil)
	c.Assert(out, gocheck.IsNil)
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("cd %s && git checkout 5734f0042844fdeb5bbc1b72b18f2dc1779cade7", path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestCheckoutUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := checkout(nil, nil, "")
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestCheckoutFailure(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("failed to update"))
	p.PrepareFailure("ExecuteCommand", errors.New("exit status 128"))
	app := testing.NewFakeApp("moon", "python", 1)
	out, err := checkout(p, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7")
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, "exit status 128")
	c.Assert(string(out), gocheck.Equals, "failed to update")
}
<commit_msg>fixed deploy test.<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package deploy

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/repository"
	"github.com/globocom/tsuru/testing"
	"launchpad.net/gocheck"
)

func (s *S) TestDeploy(c *gocheck.C) {
	content := `{"git_url": "git://tsuruhost.com/cribcaged.git"}`
	h := &testing.TestHandler{Content: content}
	t := &testing.T{}
	gandalfServer := t.StartGandalfTestServer(h)
	defer gandalfServer.Close()
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte("cloned"))
	provisioner.PrepareOutput([]byte("updated"))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	provisioner.Provision(app)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7", w)
	c.Assert(err, gocheck.IsNil)
	c.Assert(app.Commands, gocheck.DeepEquals, []string{"restart"})
	c.Assert(provisioner.InstalledDeps(app), gocheck.Equals, 1)
	cloneCommand := "git clone git://tsuruhost.com/cribcaged.git test/dir --depth 1"
	c.Assert(provisioner.GetCmds(cloneCommand, app), gocheck.HasLen, 1)
	path, _ := repository.GetPath()
	checkoutCommand := fmt.Sprintf("cd %s && git checkout 5734f0042844fdeb5bbc1b72b18f2dc1779cade7", path)
	c.Assert(provisioner.GetCmds(checkoutCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestDeployLogsActions(c *gocheck.C) {
	h := &testing.TestHandler{}
	t := &testing.T{}
	gandalfServer := t.StartGandalfTestServer(h)
	defer gandalfServer.Close()
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte(""))
	provisioner.PrepareOutput([]byte("updated"))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	provisioner.Provision(app)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7", w)
	c.Assert(err, gocheck.IsNil)
	logs := w.String()
	expected := `
 ---> Tsuru receiving push

 ---> Replicating the application repository across units

 ---> Installing dependencies

 ---> Restarting application
Restarting app...
 ---> Deploy done!

`
	c.Assert(logs, gocheck.Equals, expected)
}

func (s *S) TestCloneRepository(c *gocheck.C) {
	h := &testing.TestHandler{}
	t := &testing.T{}
	gandalfServer := t.StartGandalfTestServer(h)
	defer gandalfServer.Close()
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("something"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := clone(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "something")
	url := repository.ReadOnlyURL(app.GetName())
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("git clone %s %s --depth 1", url, path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestCloneRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := clone(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestPullRepository(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("pulled"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := fetch(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "pulled")
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("cd %s && git fetch origin", path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestPullRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := fetch(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestCheckout(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("updated"))
	app := testing.NewFakeApp("moon", "python", 1)
	out, err := checkout(p, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7")
	c.Assert(err, gocheck.IsNil)
	c.Assert(out, gocheck.IsNil)
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("cd %s && git checkout 5734f0042844fdeb5bbc1b72b18f2dc1779cade7", path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestCheckoutUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := checkout(nil, nil, "")
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestCheckoutFailure(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("failed to update"))
	p.PrepareFailure("ExecuteCommand", errors.New("exit status 128"))
	app := testing.NewFakeApp("moon", "python", 1)
	out, err := checkout(p, app, "5734f0042844fdeb5bbc1b72b18f2dc1779cade7")
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, "exit status 128")
	c.Assert(string(out), gocheck.Equals, "failed to update")
}
<|endoftext|>


<commit_before>package terraform

import (
	"strings"
	"testing"

	"github.com/hashicorp/terraform/addrs"
)

func TestOrphanResourceCountTransformer(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.2": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountBasicStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_zero(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.2": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    0,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountZeroStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_oneNoIndex(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.2": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountOneNoIndexStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_oneIndex(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.0": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.1": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountOneIndexStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_zeroAndNone(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.0": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    -1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountZeroAndNoneStr)
	if actual != expected {
		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
	}
}

func TestOrphanResourceCountTransformer_zeroAndNoneCount(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.0": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    2,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountZeroAndNoneCountStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

const testTransformOrphanResourceCountBasicStr = `
aws_instance.foo[2] (orphan)
`

const testTransformOrphanResourceCountZeroStr = `
aws_instance.foo (orphan)
aws_instance.foo[2] (orphan)
`

const testTransformOrphanResourceCountOneNoIndexStr = `
aws_instance.foo[2] (orphan)
`

const testTransformOrphanResourceCountOneIndexStr = `
aws_instance.foo[1] (orphan)
`

const testTransformOrphanResourceCountZeroAndNoneStr = `
aws_instance.foo[0] (orphan)
`

const testTransformOrphanResourceCountZeroAndNoneCountStr = `
aws_instance.foo (orphan)
`
<commit_msg>Add test<commit_after>package terraform

import (
	"strings"
	"testing"

	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/states"
	"github.com/zclconf/go-cty/cty"
)

func TestOrphanResourceCountTransformer(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.2": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountBasicStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_zero(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.2": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    0,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountZeroStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_oneNoIndex(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.2": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountOneNoIndexStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_oneIndex(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.0": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.1": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountOneIndexStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

func TestOrphanResourceCountTransformer_zeroAndNone(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.0": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    -1,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountZeroAndNoneStr)
	if actual != expected {
		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
	}
}

func TestOrphanResourceCountTransformer_zeroAndNoneCount(t *testing.T) {
	state := MustShimLegacyState(&State{
		Modules: []*ModuleState{
			&ModuleState{
				Path: []string{"root"},
				Resources: map[string]*ResourceState{
					"aws_instance.web": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},

					"aws_instance.foo.0": &ResourceState{
						Type: "aws_instance",
						Primary: &InstanceState{
							ID: "foo",
						},
					},
				},
			},
		},
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			Count:    2,
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceCountZeroAndNoneCountStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

// When converting from a NoEach mode to an EachMap via a switch to for_each,
// an edge is necessary to ensure that the map-key'd instances
// are evaluated after the NoKey resource, because the final instance evaluated
// sets the whole resource's EachMode.
func TestOrphanResourceCountTransformer_ForEachEdgesAdded(t *testing.T) {
	state := states.BuildState(func(s *states.SyncState) {
		// "bar" key'd resource
		s.SetResourceInstanceCurrent(
			addrs.Resource{
				Mode: addrs.ManagedResourceMode,
				Type: "aws_instance",
				Name: "foo",
			}.Instance(addrs.StringKey("bar")).Absolute(addrs.RootModuleInstance),
			&states.ResourceInstanceObjectSrc{
				AttrsFlat: map[string]string{
					"id": "foo",
				},
				Status: states.ObjectReady,
			},
			addrs.ProviderConfig{
				Type: "aws",
			}.Absolute(addrs.RootModuleInstance),
		)

		// NoKey'd resource
		s.SetResourceInstanceCurrent(
			addrs.Resource{
				Mode: addrs.ManagedResourceMode,
				Type: "aws_instance",
				Name: "foo",
			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
			&states.ResourceInstanceObjectSrc{
				AttrsFlat: map[string]string{
					"id": "foo",
				},
				Status: states.ObjectReady,
			},
			addrs.ProviderConfig{
				Type: "aws",
			}.Absolute(addrs.RootModuleInstance),
		)
	})

	g := Graph{Path: addrs.RootModuleInstance}

	{
		tf := &OrphanResourceCountTransformer{
			Concrete: testOrphanResourceConcreteFunc,
			// No keys in this ForEach ensure both our resources end
			// up orphaned in this test
			ForEach: map[string]cty.Value{},
			Addr: addrs.RootModuleInstance.Resource(
				addrs.ManagedResourceMode, "aws_instance", "foo",
			),
			State: state,
		}
		if err := tf.Transform(&g); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	actual := strings.TrimSpace(g.String())
	expected := strings.TrimSpace(testTransformOrphanResourceForEachStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}

const testTransformOrphanResourceCountBasicStr = `
aws_instance.foo[2] (orphan)
`

const testTransformOrphanResourceCountZeroStr = `
aws_instance.foo (orphan)
aws_instance.foo[2] (orphan)
`

const testTransformOrphanResourceCountOneNoIndexStr = `
aws_instance.foo[2] (orphan)
`

const testTransformOrphanResourceCountOneIndexStr = `
aws_instance.foo[1] (orphan)
`

const testTransformOrphanResourceCountZeroAndNoneStr = `
aws_instance.foo[0] (orphan)
`

const testTransformOrphanResourceCountZeroAndNoneCountStr = `
aws_instance.foo (orphan)
`

const testTransformOrphanResourceForEachStr = `
aws_instance.foo (orphan)
aws_instance.foo["bar"] (orphan)
  aws_instance.foo (orphan)
`
<|endoftext|>


<commit_before>// Copyright 2022 Google LLC
//
// 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 client

import (
	"bytes"
	"crypto/x509"
	"sync"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/google/go-sev-guest/abi"
	labi "github.com/google/go-sev-guest/client/linuxabi"
	spb "github.com/google/go-sev-guest/proto/sevsnp"
	test "github.com/google/go-sev-guest/testing"
	"google.golang.org/protobuf/encoding/prototext"
	"google.golang.org/protobuf/testing/protocmp"
)

var devMu sync.Once
var device *test.Device
var tests []test.TestCase

// Initializing a device with key generation is expensive. Just do it once for the test suite.
func initDevice() {
	now := time.Date(2022, time.May, 3, 9, 0, 0, 0, time.UTC)
	tests := test.TestCases()
	ones32 := make([]byte, 32)
	for i := range ones32 {
		ones32[i] = 1
	}
	keys := map[string][]byte{
		test.DerivedKeyRequestToString(&labi.SnpDerivedKeyReqABI{}):                    make([]byte, 32),
		test.DerivedKeyRequestToString(&labi.SnpDerivedKeyReqABI{GuestFieldSelect: 1}): ones32,
	}
	newDevice, err := test.TcDevice(tests, keys, now)
	if err != nil { // Unexpected
		panic(err)
	}
	device = newDevice
}

func TestOpenGetReportClose(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	for _, tc := range tests {
		reportProto := &spb.Report{}
		if err := prototext.Unmarshal([]byte(tc.OutputProto), reportProto); err != nil {
			t.Fatalf("test failure: %v", err)
		}

		// Does the proto report match expectations?
		got, err := GetReport(d, tc.Input)
		if err != tc.WantErr {
			t.Fatalf("GetReport(d, %v) = %v, %v. Want err: %v", tc.Input, got, err, tc.WantErr)
		}

		if tc.WantErr == nil {
			want := reportProto
			want.Signature = got.Signature // Zeros were placeholders.
			if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
				t.Errorf("%s: GetReport(%v) expectation diff %s", tc.Name, tc.Input, diff)
			}
		}
	}
}

func TestOpenGetRawExtendedReportClose(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	for _, tc := range tests {
		raw, certs, err := GetRawExtendedReport(d, tc.Input)
		if err != tc.WantErr {
			t.Fatalf("%s: GetRawExtendedReport(d, %v) = %v, %v, %v. Want err: %v", tc.Name, tc.Input, raw, certs, err, tc.WantErr)
		}
		if tc.WantErr == nil {
			got := abi.SignedComponent(raw)
			want := abi.SignedComponent(tc.Output[:])
			if !bytes.Equal(got, want) {
				t.Errorf("%s: GetRawExtendedReport(%v) = {data: %v, certs: _} want %v", tc.Name, tc.Input, got, want)
			}
			der, err := abi.ReportToSignatureDER(raw)
			if err != nil {
				t.Errorf("ReportToSignatureDER(%v) errored unexpectely: %v", raw, err)
			}
			if err := d.Signer.Vcek.CheckSignature(x509.ECDSAWithSHA384, got, der); err != nil {
				t.Errorf("signature with test keys did not verify: %v", err)
			}
		}
	}
}

func TestOpenGetExtendedReportClose(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	for _, tc := range tests {
		ereport, err := GetExtendedReport(d, tc.Input)
		if err != tc.WantErr {
			t.Fatalf("%s: GetExtendedReport(d, %v) = %v, %v. Want err: %v", tc.Name, tc.Input, ereport, err, tc.WantErr)
		}
		if tc.WantErr == nil {
			reportProto := &spb.Report{}
			if err := prototext.Unmarshal([]byte(tc.OutputProto), reportProto); err != nil {
				t.Fatalf("test failure: %v", err)
			}

			got := ereport.Report
			want := reportProto
			want.Signature = got.Signature // Zeros were placeholders.
			if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
				t.Errorf("%s: GetExtendedReport(%v) = {data: %v, certs: _} want %v. Diff: %s", tc.Name, tc.Input, got, want, diff)
			}

			if !bytes.Equal(ereport.GetCertificateChain().GetArkCert(), d.Signer.Ark.Raw) {
				t.Errorf("ARK certificate mismatch. Got %v, want %v",
					ereport.GetCertificateChain().GetArkCert(), d.Signer.Ark.Raw)
			}
			if !bytes.Equal(ereport.GetCertificateChain().GetAskCert(), d.Signer.Ask.Raw) {
				t.Errorf("ASK certificate mismatch. Got %v, want %v",
					ereport.GetCertificateChain().GetAskCert(), d.Signer.Ask.Raw)
			}
			if !bytes.Equal(ereport.GetCertificateChain().GetVcekCert(), d.Signer.Vcek.Raw) {
				t.Errorf("VCEK certificate mismatch. Got %v, want %v",
					ereport.GetCertificateChain().GetVcekCert(), d.Signer.Vcek.Raw)
			}
		}
	}
}

func TestGetDerivedKey(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	key1, err := GetDerivedKeyAcknowledgingItsLimitations(device, &SnpDerivedKeyReq{
		UseVCEK: true,
	})
	if err != nil {
		t.Fatal("Could not get key1: %v", err)
	}
	key2, err := GetDerivedKeyAcknowledgingItsLimitations(device, &SnpDerivedKeyReq{
		UseVCEK: true,
		GuestFieldSelect: GuestFieldSelect{
			GuestPolicy: true,
		},
	})
	if err != nil {
		t.Fatalf("Could not get key2: %v", err)
	}
	key3, err := GetDerivedKeyAcknowledgingItsLimitations(device, &SnpDerivedKeyReq{
		UseVCEK: true,
	})
	if err != nil {
		t.Fatalf("Could not get key3: %v", err)
	}
	if bytes.Equal(key1, key2) {
		t.Errorf("GetDerivedKey...(nothing) = %v = GetDerivedKey...(guestPolicy) = %v", key1, key2)
	}
	if !bytes.Equal(key1, key3) {
		t.Errorf("GetDerivedKey...(nothing) = %v and %v. Expected equality", key1, key3)
	}
}
<commit_msg>Fix client_test after PR#6<commit_after>// Copyright 2022 Google LLC
//
// 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 client

import (
	"bytes"
	"crypto/x509"
	"sync"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/google/go-sev-guest/abi"
	labi "github.com/google/go-sev-guest/client/linuxabi"
	spb "github.com/google/go-sev-guest/proto/sevsnp"
	test "github.com/google/go-sev-guest/testing"
	"google.golang.org/protobuf/encoding/prototext"
	"google.golang.org/protobuf/testing/protocmp"
)

var devMu sync.Once
var device *test.Device
var tests []test.TestCase

// Initializing a device with key generation is expensive. Just do it once for the test suite.
func initDevice() {
	now := time.Date(2022, time.May, 3, 9, 0, 0, 0, time.UTC)
	tests := test.TestCases()
	ones32 := make([]byte, 32)
	for i := range ones32 {
		ones32[i] = 1
	}
	keys := map[string][]byte{
		test.DerivedKeyRequestToString(&labi.SnpDerivedKeyReqABI{}):                    make([]byte, 32),
		test.DerivedKeyRequestToString(&labi.SnpDerivedKeyReqABI{GuestFieldSelect: 1}): ones32,
	}
	newDevice, err := test.TcDevice(tests, keys, now)
	if err != nil { // Unexpected
		panic(err)
	}
	device = newDevice
}

func TestOpenGetReportClose(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	for _, tc := range tests {
		reportProto := &spb.Report{}
		if err := prototext.Unmarshal([]byte(tc.OutputProto), reportProto); err != nil {
			t.Fatalf("test failure: %v", err)
		}

		// Does the proto report match expectations?
		got, err := GetReport(d, tc.Input)
		if err != tc.WantErr {
			t.Fatalf("GetReport(d, %v) = %v, %v. Want err: %v", tc.Input, got, err, tc.WantErr)
		}

		if tc.WantErr == nil {
			want := reportProto
			want.Signature = got.Signature // Zeros were placeholders.
			if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
				t.Errorf("%s: GetReport(%v) expectation diff %s", tc.Name, tc.Input, diff)
			}
		}
	}
}

func TestOpenGetRawExtendedReportClose(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	for _, tc := range tests {
		raw, certs, err := GetRawExtendedReport(d, tc.Input)
		if err != tc.WantErr {
			t.Fatalf("%s: GetRawExtendedReport(d, %v) = %v, %v, %v. Want err: %v", tc.Name, tc.Input, raw, certs, err, tc.WantErr)
		}
		if tc.WantErr == nil {
			got := abi.SignedComponent(raw)
			want := abi.SignedComponent(tc.Output[:])
			if !bytes.Equal(got, want) {
				t.Errorf("%s: GetRawExtendedReport(%v) = {data: %v, certs: _} want %v", tc.Name, tc.Input, got, want)
			}
			der, err := abi.ReportToSignatureDER(raw)
			if err != nil {
				t.Errorf("ReportToSignatureDER(%v) errored unexpectely: %v", raw, err)
			}
			if err := d.Signer.Vcek.CheckSignature(x509.ECDSAWithSHA384, got, der); err != nil {
				t.Errorf("signature with test keys did not verify: %v", err)
			}
		}
	}
}

func TestOpenGetExtendedReportClose(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	for _, tc := range tests {
		ereport, err := GetExtendedReport(d, tc.Input)
		if err != tc.WantErr {
			t.Fatalf("%s: GetExtendedReport(d, %v) = %v, %v. Want err: %v", tc.Name, tc.Input, ereport, err, tc.WantErr)
		}
		if tc.WantErr == nil {
			reportProto := &spb.Report{}
			if err := prototext.Unmarshal([]byte(tc.OutputProto), reportProto); err != nil {
				t.Fatalf("test failure: %v", err)
			}

			got := ereport.Report
			want := reportProto
			want.Signature = got.Signature // Zeros were placeholders.
			if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
				t.Errorf("%s: GetExtendedReport(%v) = {data: %v, certs: _} want %v. Diff: %s", tc.Name, tc.Input, got, want, diff)
			}

			if !bytes.Equal(ereport.GetCertificateChain().GetArkCert(), d.Signer.Ark.Raw) {
				t.Errorf("ARK certificate mismatch. Got %v, want %v",
					ereport.GetCertificateChain().GetArkCert(), d.Signer.Ark.Raw)
			}
			if !bytes.Equal(ereport.GetCertificateChain().GetAskCert(), d.Signer.Ask.Raw) {
				t.Errorf("ASK certificate mismatch. Got %v, want %v",
					ereport.GetCertificateChain().GetAskCert(), d.Signer.Ask.Raw)
			}
			if !bytes.Equal(ereport.GetCertificateChain().GetVcekCert(), d.Signer.Vcek.Raw) {
				t.Errorf("VCEK certificate mismatch. Got %v, want %v",
					ereport.GetCertificateChain().GetVcekCert(), d.Signer.Vcek.Raw)
			}
		}
	}
}

func TestGetDerivedKey(t *testing.T) {
	devMu.Do(initDevice)
	d := device
	if err := d.Open("/dev/sev-guest"); err != nil {
		t.Error(err)
	}
	defer d.Close()
	key1, err := GetDerivedKeyAcknowledgingItsLimitations(device, &SnpDerivedKeyReq{
		UseVCEK: true,
	})
	if err != nil {
		t.Fatalf("Could not get key1: %v", err)
	}
	key2, err := GetDerivedKeyAcknowledgingItsLimitations(device, &SnpDerivedKeyReq{
		UseVCEK: true,
		GuestFieldSelect: GuestFieldSelect{
			GuestPolicy: true,
		},
	})
	if err != nil {
		t.Fatalf("Could not get key2: %v", err)
	}
	key3, err := GetDerivedKeyAcknowledgingItsLimitations(device, &SnpDerivedKeyReq{
		UseVCEK: true,
	})
	if err != nil {
		t.Fatalf("Could not get key3: %v", err)
	}
	if bytes.Equal(key1.Data[:], key2.Data[:]) {
		t.Errorf("GetDerivedKey...(nothing) = %v = GetDerivedKey...(guestPolicy) = %v", key1.Data, key2.Data)
	}
	if !bytes.Equal(key1.Data[:], key3.Data[:]) {
		t.Errorf("GetDerivedKey...(nothing) = %v and %v. Expected equality", key1.Data, key3.Data)
	}
}
<|endoftext|>