<commit_before>package aws

import (
	"reflect"
	"testing"

	"github.com/hashicorp/aws-sdk-go/aws"
	"github.com/hashicorp/aws-sdk-go/gen/elb"
	"github.com/hashicorp/aws-sdk-go/gen/rds"
	"github.com/hashicorp/terraform/flatmap"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/goamz/ec2"
)

// Returns test configuration
func testConf() map[string]string {
	return map[string]string{
		"listener.#":                   "1",
		"listener.0.lb_port":           "80",
		"listener.0.lb_protocol":       "http",
		"listener.0.instance_port":     "8000",
		"listener.0.instance_protocol": "http",
		"availability_zones.#":         "2",
		"availability_zones.0":         "us-east-1a",
		"availability_zones.1":         "us-east-1b",
		"ingress.#":                    "1",
		"ingress.0.protocol":           "icmp",
		"ingress.0.from_port":          "1",
		"ingress.0.to_port":            "-1",
		"ingress.0.cidr_blocks.#":      "1",
		"ingress.0.cidr_blocks.0":      "0.0.0.0/0",
		"ingress.0.security_groups.#":  "2",
		"ingress.0.security_groups.0":  "sg-11111",
		"ingress.0.security_groups.1":  "foo/sg-22222",
	}
}

func Test_expandIPPerms(t *testing.T) {
	hash := func(v interface{}) int {
		return hashcode.String(v.(string))
	}

	expanded := []interface{}{
		map[string]interface{}{
			"protocol":    "icmp",
			"from_port":   1,
			"to_port":     -1,
			"cidr_blocks": []interface{}{"0.0.0.0/0"},
			"security_groups": schema.NewSet(hash, []interface{}{
				"sg-11111",
				"foo/sg-22222",
			}),
		},
		map[string]interface{}{
			"protocol":  "icmp",
			"from_port": 1,
			"to_port":   -1,
			"self":      true,
		},
	}
	perms := expandIPPerms("foo", expanded)

	expected := []ec2.IPPerm{
		ec2.IPPerm{
			Protocol:  "icmp",
			FromPort:  1,
			ToPort:    -1,
			SourceIPs: []string{"0.0.0.0/0"},
			SourceGroups: []ec2.UserSecurityGroup{
				ec2.UserSecurityGroup{
					OwnerId: "foo",
					Id:      "sg-22222",
				},
				ec2.UserSecurityGroup{
					Id: "sg-11111",
				},
			},
		},
		ec2.IPPerm{
			Protocol: "icmp",
			FromPort: 1,
			ToPort:   -1,
			SourceGroups: []ec2.UserSecurityGroup{
				ec2.UserSecurityGroup{
					Id: "foo",
				},
			},
		},
	}

	if !reflect.DeepEqual(perms, expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			perms[0],
			expected)
	}

}

func Test_flattenIPPerms(t *testing.T) {
	cases := []struct {
		Input  []ec2.IPPerm
		Output []map[string]interface{}
	}{
		{
			Input: []ec2.IPPerm{
				ec2.IPPerm{
					Protocol:  "icmp",
					FromPort:  1,
					ToPort:    -1,
					SourceIPs: []string{"0.0.0.0/0"},
					SourceGroups: []ec2.UserSecurityGroup{
						ec2.UserSecurityGroup{
							Id: "sg-11111",
						},
					},
				},
			},

			Output: []map[string]interface{}{
				map[string]interface{}{
					"protocol":        "icmp",
					"from_port":       1,
					"to_port":         -1,
					"cidr_blocks":     []string{"0.0.0.0/0"},
					"security_groups": []string{"sg-11111"},
				},
			},
		},

		{
			Input: []ec2.IPPerm{
				ec2.IPPerm{
					Protocol:     "icmp",
					FromPort:     1,
					ToPort:       -1,
					SourceIPs:    []string{"0.0.0.0/0"},
					SourceGroups: nil,
				},
			},

			Output: []map[string]interface{}{
				map[string]interface{}{
					"protocol":    "icmp",
					"from_port":   1,
					"to_port":     -1,
					"cidr_blocks": []string{"0.0.0.0/0"},
				},
			},
		},
		{
			Input: []ec2.IPPerm{
				ec2.IPPerm{
					Protocol:  "icmp",
					FromPort:  1,
					ToPort:    -1,
					SourceIPs: nil,
				},
			},

			Output: []map[string]interface{}{
				map[string]interface{}{
					"protocol":  "icmp",
					"from_port": 1,
					"to_port":   -1,
				},
			},
		},
	}

	for _, tc := range cases {
		output := flattenIPPerms(tc.Input)
		if !reflect.DeepEqual(output, tc.Output) {
			t.Fatalf("Input:\n\n%#v\n\nOutput:\n\n%#v", tc.Input, output)
		}
	}
}

func Test_expandListeners(t *testing.T) {
	expanded := []interface{}{
		map[string]interface{}{
			"instance_port":     8000,
			"lb_port":           80,
			"instance_protocol": "http",
			"lb_protocol":       "http",
		},
	}
	listeners, err := expandListeners(expanded)
	if err != nil {
		t.Fatalf("bad: %#v", err)
	}

	expected := elb.Listener{
		InstancePort:     aws.Integer(8000),
		LoadBalancerPort: aws.Integer(80),
		InstanceProtocol: aws.String("http"),
		Protocol:         aws.String("http"),
	}

	if !reflect.DeepEqual(listeners[0], expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			listeners[0],
			expected)
	}

}

func Test_flattenHealthCheck(t *testing.T) {
	cases := []struct {
		Input  elb.HealthCheck
		Output []map[string]interface{}
	}{
		{
			Input: elb.HealthCheck{
				UnhealthyThreshold: aws.Integer(10),
				HealthyThreshold:   aws.Integer(10),
				Target:             aws.String("HTTP:80/"),
				Timeout:            aws.Integer(30),
				Interval:           aws.Integer(30),
			},
			Output: []map[string]interface{}{
				map[string]interface{}{
					"unhealthy_threshold": 10,
					"healthy_threshold":   10,
					"target":              "HTTP:80/",
					"timeout":             30,
					"interval":            30,
				},
			},
		},
	}

	for _, tc := range cases {
		output := flattenHealthCheck(&tc.Input)
		if !reflect.DeepEqual(output, tc.Output) {
			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
		}
	}
}

func Test_expandStringList(t *testing.T) {
	expanded := flatmap.Expand(testConf(), "availability_zones").([]interface{})
	stringList := expandStringList(expanded)
	expected := []string{
		"us-east-1a",
		"us-east-1b",
	}

	if !reflect.DeepEqual(stringList, expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			stringList,
			expected)
	}

}

func Test_expandParameters(t *testing.T) {
	expanded := []interface{}{
		map[string]interface{}{
			"name":         "character_set_client",
			"value":        "utf8",
			"apply_method": "immediate",
		},
	}
	parameters, err := expandParameters(expanded)
	if err != nil {
		t.Fatalf("bad: %#v", err)
	}

	expected := rds.Parameter{
		ParameterName:  aws.String("character_set_client"),
		ParameterValue: aws.String("utf8"),
		ApplyMethod:    aws.String("immediate"),
	}

	if !reflect.DeepEqual(parameters[0], expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			parameters[0],
			expected)
	}
}

func Test_flattenParameters(t *testing.T) {
	cases := []struct {
		Input  []rds.Parameter
		Output []map[string]interface{}
	}{
		{
			Input: []rds.Parameter{
				rds.Parameter{
					ParameterName:  aws.String("character_set_client"),
					ParameterValue: aws.String("utf8"),
				},
			},
			Output: []map[string]interface{}{
				map[string]interface{}{
					"name":  "character_set_client",
					"value": "utf8",
				},
			},
		},
	}

	for _, tc := range cases {
		output := flattenParameters(tc.Input)
		if !reflect.DeepEqual(output, tc.Output) {
			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
		}
	}
}
<commit_msg>add simple test for expandInstanceString<commit_after>package aws

import (
	"reflect"
	"testing"

	"github.com/hashicorp/aws-sdk-go/aws"
	"github.com/hashicorp/aws-sdk-go/gen/elb"
	"github.com/hashicorp/aws-sdk-go/gen/rds"
	"github.com/hashicorp/terraform/flatmap"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/goamz/ec2"
)

// Returns test configuration
func testConf() map[string]string {
	return map[string]string{
		"listener.#":                   "1",
		"listener.0.lb_port":           "80",
		"listener.0.lb_protocol":       "http",
		"listener.0.instance_port":     "8000",
		"listener.0.instance_protocol": "http",
		"availability_zones.#":         "2",
		"availability_zones.0":         "us-east-1a",
		"availability_zones.1":         "us-east-1b",
		"ingress.#":                    "1",
		"ingress.0.protocol":           "icmp",
		"ingress.0.from_port":          "1",
		"ingress.0.to_port":            "-1",
		"ingress.0.cidr_blocks.#":      "1",
		"ingress.0.cidr_blocks.0":      "0.0.0.0/0",
		"ingress.0.security_groups.#":  "2",
		"ingress.0.security_groups.0":  "sg-11111",
		"ingress.0.security_groups.1":  "foo/sg-22222",
	}
}

func Test_expandIPPerms(t *testing.T) {
	hash := func(v interface{}) int {
		return hashcode.String(v.(string))
	}

	expanded := []interface{}{
		map[string]interface{}{
			"protocol":    "icmp",
			"from_port":   1,
			"to_port":     -1,
			"cidr_blocks": []interface{}{"0.0.0.0/0"},
			"security_groups": schema.NewSet(hash, []interface{}{
				"sg-11111",
				"foo/sg-22222",
			}),
		},
		map[string]interface{}{
			"protocol":  "icmp",
			"from_port": 1,
			"to_port":   -1,
			"self":      true,
		},
	}
	perms := expandIPPerms("foo", expanded)

	expected := []ec2.IPPerm{
		ec2.IPPerm{
			Protocol:  "icmp",
			FromPort:  1,
			ToPort:    -1,
			SourceIPs: []string{"0.0.0.0/0"},
			SourceGroups: []ec2.UserSecurityGroup{
				ec2.UserSecurityGroup{
					OwnerId: "foo",
					Id:      "sg-22222",
				},
				ec2.UserSecurityGroup{
					Id: "sg-11111",
				},
			},
		},
		ec2.IPPerm{
			Protocol: "icmp",
			FromPort: 1,
			ToPort:   -1,
			SourceGroups: []ec2.UserSecurityGroup{
				ec2.UserSecurityGroup{
					Id: "foo",
				},
			},
		},
	}

	if !reflect.DeepEqual(perms, expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			perms[0],
			expected)
	}

}

func Test_flattenIPPerms(t *testing.T) {
	cases := []struct {
		Input  []ec2.IPPerm
		Output []map[string]interface{}
	}{
		{
			Input: []ec2.IPPerm{
				ec2.IPPerm{
					Protocol:  "icmp",
					FromPort:  1,
					ToPort:    -1,
					SourceIPs: []string{"0.0.0.0/0"},
					SourceGroups: []ec2.UserSecurityGroup{
						ec2.UserSecurityGroup{
							Id: "sg-11111",
						},
					},
				},
			},

			Output: []map[string]interface{}{
				map[string]interface{}{
					"protocol":        "icmp",
					"from_port":       1,
					"to_port":         -1,
					"cidr_blocks":     []string{"0.0.0.0/0"},
					"security_groups": []string{"sg-11111"},
				},
			},
		},

		{
			Input: []ec2.IPPerm{
				ec2.IPPerm{
					Protocol:     "icmp",
					FromPort:     1,
					ToPort:       -1,
					SourceIPs:    []string{"0.0.0.0/0"},
					SourceGroups: nil,
				},
			},

			Output: []map[string]interface{}{
				map[string]interface{}{
					"protocol":    "icmp",
					"from_port":   1,
					"to_port":     -1,
					"cidr_blocks": []string{"0.0.0.0/0"},
				},
			},
		},
		{
			Input: []ec2.IPPerm{
				ec2.IPPerm{
					Protocol:  "icmp",
					FromPort:  1,
					ToPort:    -1,
					SourceIPs: nil,
				},
			},

			Output: []map[string]interface{}{
				map[string]interface{}{
					"protocol":  "icmp",
					"from_port": 1,
					"to_port":   -1,
				},
			},
		},
	}

	for _, tc := range cases {
		output := flattenIPPerms(tc.Input)
		if !reflect.DeepEqual(output, tc.Output) {
			t.Fatalf("Input:\n\n%#v\n\nOutput:\n\n%#v", tc.Input, output)
		}
	}
}

func Test_expandListeners(t *testing.T) {
	expanded := []interface{}{
		map[string]interface{}{
			"instance_port":     8000,
			"lb_port":           80,
			"instance_protocol": "http",
			"lb_protocol":       "http",
		},
	}
	listeners, err := expandListeners(expanded)
	if err != nil {
		t.Fatalf("bad: %#v", err)
	}

	expected := elb.Listener{
		InstancePort:     aws.Integer(8000),
		LoadBalancerPort: aws.Integer(80),
		InstanceProtocol: aws.String("http"),
		Protocol:         aws.String("http"),
	}

	if !reflect.DeepEqual(listeners[0], expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			listeners[0],
			expected)
	}

}

func Test_flattenHealthCheck(t *testing.T) {
	cases := []struct {
		Input  elb.HealthCheck
		Output []map[string]interface{}
	}{
		{
			Input: elb.HealthCheck{
				UnhealthyThreshold: aws.Integer(10),
				HealthyThreshold:   aws.Integer(10),
				Target:             aws.String("HTTP:80/"),
				Timeout:            aws.Integer(30),
				Interval:           aws.Integer(30),
			},
			Output: []map[string]interface{}{
				map[string]interface{}{
					"unhealthy_threshold": 10,
					"healthy_threshold":   10,
					"target":              "HTTP:80/",
					"timeout":             30,
					"interval":            30,
				},
			},
		},
	}

	for _, tc := range cases {
		output := flattenHealthCheck(&tc.Input)
		if !reflect.DeepEqual(output, tc.Output) {
			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
		}
	}
}

func Test_expandStringList(t *testing.T) {
	expanded := flatmap.Expand(testConf(), "availability_zones").([]interface{})
	stringList := expandStringList(expanded)
	expected := []string{
		"us-east-1a",
		"us-east-1b",
	}

	if !reflect.DeepEqual(stringList, expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			stringList,
			expected)
	}

}

func Test_expandParameters(t *testing.T) {
	expanded := []interface{}{
		map[string]interface{}{
			"name":         "character_set_client",
			"value":        "utf8",
			"apply_method": "immediate",
		},
	}
	parameters, err := expandParameters(expanded)
	if err != nil {
		t.Fatalf("bad: %#v", err)
	}

	expected := rds.Parameter{
		ParameterName:  aws.String("character_set_client"),
		ParameterValue: aws.String("utf8"),
		ApplyMethod:    aws.String("immediate"),
	}

	if !reflect.DeepEqual(parameters[0], expected) {
		t.Fatalf(
			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
			parameters[0],
			expected)
	}
}

func Test_flattenParameters(t *testing.T) {
	cases := []struct {
		Input  []rds.Parameter
		Output []map[string]interface{}
	}{
		{
			Input: []rds.Parameter{
				rds.Parameter{
					ParameterName:  aws.String("character_set_client"),
					ParameterValue: aws.String("utf8"),
				},
			},
			Output: []map[string]interface{}{
				map[string]interface{}{
					"name":  "character_set_client",
					"value": "utf8",
				},
			},
		},
	}

	for _, tc := range cases {
		output := flattenParameters(tc.Input)
		if !reflect.DeepEqual(output, tc.Output) {
			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
		}
	}
}

func Test_expandInstanceString(t *testing.T) {

	expected := []elb.Instance{
		elb.Instance{aws.String("test-one")},
		elb.Instance{aws.String("test-two")},
	}

	ids := []interface{}{
		"test-one",
		"test-two",
	}

	expanded := expandInstanceString(ids)

	if !reflect.DeepEqual(expanded, expected) {
		t.Fatalf("Expand Instance String output did not match.\nGot:\n%#v\n\nexpected:\n%#v", expanded, expected)
	}
}
<|endoftext|>


<commit_before>package rpcd

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/Symantec/Dominator/lib/hash"
	"github.com/Symantec/Dominator/lib/objectcache"
	"github.com/Symantec/Dominator/lib/objectclient"
	"github.com/Symantec/Dominator/proto/sub"
	"io"
	"os"
	"path"
	"syscall"
)

func (t *rpcType) Fetch(request sub.FetchRequest,
	reply *sub.FetchResponse) error {
	rwLock.Lock()
	defer rwLock.Unlock()
	if fetchInProgress {
		return errors.New("fetch already in progress")
	}
	if updateInProgress {
		return errors.New("update in progress")
	}
	fetchInProgress = true
	go doFetch(request)
	return nil
}

func doFetch(request sub.FetchRequest) {
	defer clearFetchInProgress()
	objectServer := objectclient.NewObjectClient(request.ServerAddress)
	objectsReader, err := objectServer.GetObjects(request.Hashes)
	if err != nil {
		fmt.Printf("Error getting object reader:\t%s\n", err.Error())
		return
	}
	for _, hash := range request.Hashes {
		_, reader, err := objectsReader.NextObject()
		if err != nil {
			fmt.Println(err)
			return
		}
		err = readOne(hash, networkReaderContext.NewReader(reader))
		reader.Close()
		if err != nil {
			fmt.Println(err)
			return
		}
	}
	rescanObjectCacheChannel <- true
}

func readOne(hash hash.Hash, reader io.Reader) error {
	fmt.Printf("Reading: %x\n", hash) // TODO(rgooch): Remove debugging output.
	filename := path.Join(objectsDir, objectcache.HashToFilename(hash))
	dirname := path.Dir(filename)
	err := os.MkdirAll(dirname, syscall.S_IRUSR|syscall.S_IWUSR)
	if err != nil {
		return err
	}
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	defer writer.Flush()
	_, err = io.Copy(writer, reader)
	if err != nil {
		return errors.New(fmt.Sprintf("error copying: %s", err.Error()))
	}
	return nil
}

func clearFetchInProgress() {
	rwLock.Lock()
	defer rwLock.Unlock()
	fetchInProgress = false
}
<commit_msg>Add network benchmarking code to subd.Fetch() RPC handler.<commit_after>package rpcd

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/Symantec/Dominator/lib/hash"
	"github.com/Symantec/Dominator/lib/objectcache"
	"github.com/Symantec/Dominator/lib/objectclient"
	"github.com/Symantec/Dominator/proto/sub"
	"io"
	"os"
	"path"
	"syscall"
	"time"
)

func (t *rpcType) Fetch(request sub.FetchRequest,
	reply *sub.FetchResponse) error {
	rwLock.Lock()
	defer rwLock.Unlock()
	if fetchInProgress {
		return errors.New("fetch already in progress")
	}
	if updateInProgress {
		return errors.New("update in progress")
	}
	fetchInProgress = true
	go doFetch(request)
	return nil
}

func doFetch(request sub.FetchRequest) {
	defer clearFetchInProgress()
	objectServer := objectclient.NewObjectClient(request.ServerAddress)
	benchmark := false
	if networkReaderContext.MaximumSpeed() < 1 {
		benchmark = enoughBytesForBenchmark(objectServer, request)
		if benchmark {
			objectServer.SetExclusiveGetObjects(true)
		}
	}
	objectsReader, err := objectServer.GetObjects(request.Hashes)
	if err != nil {
		fmt.Printf("Error getting object reader:\t%s\n", err.Error())
		return
	}
	var totalLength uint64
	timeStart := time.Now()
	for _, hash := range request.Hashes {
		length, reader, err := objectsReader.NextObject()
		if err != nil {
			fmt.Println(err)
			return
		}
		err = readOne(hash, networkReaderContext.NewReader(reader))
		reader.Close()
		if err != nil {
			fmt.Println(err)
			return
		}
		totalLength += length
	}
	if benchmark {
		duration := time.Since(timeStart)
		speed := uint64(float64(totalLength) / duration.Seconds())
		file, err := os.Create(netbenchFilename)
		if err == nil {
			fmt.Fprintf(file, "%d\n", speed)
			file.Close()
		}
		networkReaderContext.InitialiseMaximumSpeed(speed)
	}
	rescanObjectCacheChannel <- true
}

func enoughBytesForBenchmark(objectServer *objectclient.ObjectClient,
	request sub.FetchRequest) bool {
	lengths, err := objectServer.CheckObjects(request.Hashes)
	if err != nil {
		return false
	}
	var totalLength uint64
	for _, length := range lengths {
		totalLength += length
	}
	if totalLength > 1024*1024*64 {
		return true
	}
	return false
}

func readOne(hash hash.Hash, reader io.Reader) error {
	fmt.Printf("Reading: %x\n", hash) // TODO(rgooch): Remove debugging output.
	filename := path.Join(objectsDir, objectcache.HashToFilename(hash))
	dirname := path.Dir(filename)
	err := os.MkdirAll(dirname, syscall.S_IRUSR|syscall.S_IWUSR)
	if err != nil {
		return err
	}
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	defer writer.Flush()
	_, err = io.Copy(writer, reader)
	if err != nil {
		return errors.New(fmt.Sprintf("error copying: %s", err.Error()))
	}
	return nil
}

func clearFetchInProgress() {
	rwLock.Lock()
	defer rwLock.Unlock()
	fetchInProgress = false
}
<|endoftext|>


<commit_before>package svfs

import (
	"os"
	"regexp"
	"strings"

	"github.com/ncw/swift"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"golang.org/x/net/context"
)

var (
	FolderRegex = regexp.MustCompile("^.+/$")
)

type Directory struct {
	name     string
	path     string
	s        *swift.Connection
	c        *swift.Container
	children []Node
}

func (d *Directory) Attr(ctx context.Context, a *fuse.Attr) error {
	a.Mode = os.ModeDir | 0600
	a.Size = uint64(4096)
	return nil
}

func (d *Directory) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
	// Create an empty object in swift
	path := d.path + req.Name
	w, err := d.s.ObjectCreate(d.c.Name, path, false, "", "application/octet-stream", nil)
	if err != nil {
		return nil, nil, fuse.EIO
	}
	if _, err := w.Write([]byte(nil)); err != nil {
		return nil, nil, fuse.EIO
	}
	w.Close()

	// Retrieve it
	obj, _, err := d.s.Object(d.c.Name, path)
	if err != nil {
		return nil, nil, fuse.EIO
	}

	// New node
	node := &Object{
		name: req.Name,
		path: path,
		s:    d.s,
		so:   &obj,
		c:    d.c,
	}

	// Get object handler handler
	h, err := node.open(fuse.OpenWriteOnly)
	if err != nil {
		return nil, nil, fuse.EIO
	}

	// Force cache eviction
	d.children = []Node{}

	return node, h, nil
}

func (d *Directory) Export() fuse.Dirent {
	return fuse.Dirent{
		Name: d.name,
		Type: fuse.DT_Dir,
	}
}

func (d *Directory) ReadDirAll(ctx context.Context) (entries []fuse.Dirent, err error) {
	dirs := make(map[string]bool)

	// Cache hit
	if len(d.children) > 0 {
		for _, child := range d.children {
			entries = append(entries, child.Export())
		}
		return entries, nil
	}

	// Fetch objects
	objects, err := d.s.ObjectsAll(d.c.Name, &swift.ObjectsOpts{
		Delimiter: '/',
		Prefix:    d.path,
	})
	if err != nil {
		return nil, err
	}

	// Fill cache
	for _, object := range objects {
		var (
			child    Node
			o        = object
			fileName = strings.TrimPrefix(o.Name, d.path)
		)
		// This is a directory
		if o.ContentType == "application/directory" && !FolderRegex.Match([]byte(o.Name)) {
			child = &Directory{
				s:    d.s,
				c:    d.c,
				path: o.Name + "/",
				name: fileName,
			}
			dirs[fileName] = true
		} else if o.PseudoDirectory &&
			FolderRegex.Match([]byte(o.Name)) && fileName != "" {
			// This is a pseudo directory. Add it only if the real directory is missing
			realName := fileName[:len(fileName)-1]
			if !dirs[realName] {
				child = &Directory{
					s:    d.s,
					c:    d.c,
					path: o.Name,
					name: realName,
				}
				dirs[realName] = true
			}
		} else if !FolderRegex.Match([]byte(o.Name)) {
			// This is a swift object
			child = &Object{
				path: o.Name,
				name: fileName,
				s:    d.s,
				c:    d.c,
				so:   &o,
				p:    d,
			}
		}

		if child != nil {
			d.children = append(d.children, child)
			entries = append(entries, child.Export())
		}
	}

	return entries, nil
}

func (d *Directory) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (fs.Node, error) {
	// Get children if this node was evicted from the kernel cache
	if len(d.children) == 0 && d.c != nil {
		d.ReadDirAll(ctx)
	}

	// Find matching child
	for _, item := range d.children {
		if item.Name() == req.Name {
			if n, ok := item.(*Container); ok {
				return n, nil
			}
			if n, ok := item.(*Directory); ok {
				return n, nil
			}
			if n, ok := item.(*Object); ok {
				return n, nil
			}
		}
	}

	return nil, fuse.ENOENT
}

func (d *Directory) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
	var (
		objName = req.Name + "/"
		absPath = d.path + objName
	)

	// Create the file in swift
	if err := d.s.ObjectPutBytes(d.c.Name, absPath, nil, "application/directory"); err != nil {
		return nil, fuse.EIO
	}

	// Cache eviction
	d.children = []Node{}

	// Directory object
	return &Directory{
		name: req.Name,
		path: absPath,
		s:    d.s,
		c:    d.c,
	}, nil
}

func (d *Directory) Name() string {
	return d.name
}

func (d *Directory) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
	// Delete from swift
	err := d.s.ObjectDelete(d.c.Name, d.path+req.Name)
	if err != nil && err != swift.ObjectNotFound {
		return err
	}

	// Cache eviction
	d.children = []Node{}

	return nil
}

func (d *Directory) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Node) error {
	// Not supported
	if _, ok := newDir.(*Root); ok {
		return fuse.ENOTSUP
	}
	// Swift move = copy + delete
	if t, ok := newDir.(*Container); ok {
		d.s.ObjectMove(d.c.Name, d.path+req.OldName, t.c.Name, t.path+req.NewName)
		t.children = []Node{}
		d.children = []Node{}
		return nil
	}
	if t, ok := newDir.(*Directory); ok {
		d.s.ObjectMove(d.c.Name, d.path+req.OldName, t.c.Name, t.path+req.NewName)
		t.children = []Node{}
		d.children = []Node{}
		return nil
	}
	return nil
}

var (
	_ Node           = (*Directory)(nil)
	_ fs.Node        = (*Directory)(nil)
	_ fs.NodeCreater = (*Directory)(nil)
	_ fs.NodeRemover = (*Directory)(nil)
	_ fs.NodeMkdirer = (*Directory)(nil)
	_ fs.NodeRenamer = (*Directory)(nil)
)
<commit_msg>Bugfix: directory removal for non-pseudo directories, fixes #16<commit_after>package svfs

import (
	"os"
	"regexp"
	"strings"

	"github.com/ncw/swift"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"golang.org/x/net/context"
)

var (
	FolderRegex = regexp.MustCompile("^.+/$")
)

type Directory struct {
	name     string
	path     string
	s        *swift.Connection
	c        *swift.Container
	children []Node
}

func (d *Directory) Attr(ctx context.Context, a *fuse.Attr) error {
	a.Mode = os.ModeDir | 0600
	a.Size = uint64(4096)
	return nil
}

func (d *Directory) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
	// Create an empty object in swift
	path := d.path + req.Name
	w, err := d.s.ObjectCreate(d.c.Name, path, false, "", "application/octet-stream", nil)
	if err != nil {
		return nil, nil, fuse.EIO
	}
	if _, err := w.Write([]byte(nil)); err != nil {
		return nil, nil, fuse.EIO
	}
	w.Close()

	// Retrieve it
	obj, _, err := d.s.Object(d.c.Name, path)
	if err != nil {
		return nil, nil, fuse.EIO
	}

	// New node
	node := &Object{
		name: req.Name,
		path: path,
		s:    d.s,
		so:   &obj,
		c:    d.c,
	}

	// Get object handler handler
	h, err := node.open(fuse.OpenWriteOnly)
	if err != nil {
		return nil, nil, fuse.EIO
	}

	// Force cache eviction
	d.children = []Node{}

	return node, h, nil
}

func (d *Directory) Export() fuse.Dirent {
	return fuse.Dirent{
		Name: d.name,
		Type: fuse.DT_Dir,
	}
}

func (d *Directory) ReadDirAll(ctx context.Context) (entries []fuse.Dirent, err error) {
	dirs := make(map[string]bool)

	// Cache hit
	if len(d.children) > 0 {
		for _, child := range d.children {
			entries = append(entries, child.Export())
		}
		return entries, nil
	}

	// Fetch objects
	objects, err := d.s.ObjectsAll(d.c.Name, &swift.ObjectsOpts{
		Delimiter: '/',
		Prefix:    d.path,
	})
	if err != nil {
		return nil, err
	}

	// Fill cache
	for _, object := range objects {
		var (
			child    Node
			o        = object
			fileName = strings.TrimPrefix(o.Name, d.path)
		)
		// This is a directory
		if o.ContentType == "application/directory" && !FolderRegex.Match([]byte(o.Name)) {
			child = &Directory{
				s:    d.s,
				c:    d.c,
				path: o.Name + "/",
				name: fileName,
			}
			dirs[fileName] = true
		} else if o.PseudoDirectory &&
			FolderRegex.Match([]byte(o.Name)) && fileName != "" {
			// This is a pseudo directory. Add it only if the real directory is missing
			realName := fileName[:len(fileName)-1]
			if !dirs[realName] {
				child = &Directory{
					s:    d.s,
					c:    d.c,
					path: o.Name,
					name: realName,
				}
				dirs[realName] = true
			}
		} else if !FolderRegex.Match([]byte(o.Name)) {
			// This is a swift object
			child = &Object{
				path: o.Name,
				name: fileName,
				s:    d.s,
				c:    d.c,
				so:   &o,
				p:    d,
			}
		}

		if child != nil {
			d.children = append(d.children, child)
			entries = append(entries, child.Export())
		}
	}

	return entries, nil
}

func (d *Directory) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (fs.Node, error) {
	// Get children if this node was evicted from the kernel cache
	if len(d.children) == 0 && d.c != nil {
		d.ReadDirAll(ctx)
	}

	// Find matching child
	for _, item := range d.children {
		if item.Name() == req.Name {
			if n, ok := item.(*Container); ok {
				return n, nil
			}
			if n, ok := item.(*Directory); ok {
				return n, nil
			}
			if n, ok := item.(*Object); ok {
				return n, nil
			}
		}
	}

	return nil, fuse.ENOENT
}

func (d *Directory) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
	var (
		objName = req.Name + "/"
		absPath = d.path + objName
	)

	// Create the file in swift
	if err := d.s.ObjectPutBytes(d.c.Name, absPath, nil, "application/directory"); err != nil {
		return nil, fuse.EIO
	}

	// Cache eviction
	d.children = []Node{}

	// Directory object
	return &Directory{
		name: req.Name,
		path: absPath,
		s:    d.s,
		c:    d.c,
	}, nil
}

func (d *Directory) Name() string {
	return d.name
}

func (d *Directory) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
	path := d.path + req.Name

	if req.Dir {
		path += "/"
	}

	// Delete from swift
	err := d.s.ObjectDelete(d.c.Name, path)
	if err != nil && err != swift.ObjectNotFound {
		return err
	}

	// Cache eviction
	d.children = []Node{}

	return nil
}

func (d *Directory) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Node) error {
	// Not supported
	if _, ok := newDir.(*Root); ok {
		return fuse.ENOTSUP
	}
	// Swift move = copy + delete
	if t, ok := newDir.(*Container); ok {
		d.s.ObjectMove(d.c.Name, d.path+req.OldName, t.c.Name, t.path+req.NewName)
		t.children = []Node{}
		d.children = []Node{}
		return nil
	}
	if t, ok := newDir.(*Directory); ok {
		d.s.ObjectMove(d.c.Name, d.path+req.OldName, t.c.Name, t.path+req.NewName)
		t.children = []Node{}
		d.children = []Node{}
		return nil
	}
	return nil
}

var (
	_ Node           = (*Directory)(nil)
	_ fs.Node        = (*Directory)(nil)
	_ fs.NodeCreater = (*Directory)(nil)
	_ fs.NodeRemover = (*Directory)(nil)
	_ fs.NodeMkdirer = (*Directory)(nil)
	_ fs.NodeRenamer = (*Directory)(nil)
)
<|endoftext|>


<commit_before>package sndfile

import "os"
import "testing"
import "fmt"
import "strings"
import "unsafe"

func TestGetLibVersion(t *testing.T) {
	s, _ := GetLibVersion()
	fmt.Println(s)
	if !strings.HasPrefix(s, "libsndfile") {
		t.Errorf("version string \"%s\" had unexpected prefix", s)
	}
}

func TestGetLogInfo(t *testing.T) {
	var i Info
	f, err := Open("fwerefrg", Read, &i)
//	fmt.Println(f)
//	fmt.Println(err)
	s, err := f.GetLogInfo()
	fmt.Println("TestGetLogInfo output: ", s)
	if err != nil {
		t.Error("TestGetLogInfo err: ", err)
	}
}

func TestFileCommands(t *testing.T) {
	var i Info
	f, err := Open("funky.aiff", ReadWrite, &i)
	if err != nil {
		t.Fatalf("open file failed %s", err)
	}

	max, err := f.CalcSignalMax()
	if err != nil {
		t.Fatalf("signal max failed %s", err)
	}

	fmt.Printf("max signal %f\n", max)

	max, err = f.CalcNormSignalMax()
	if err != nil {
		t.Fatalf("norm signal max failed %s", err)
	}

	fmt.Printf("norm max signal %f\n", max)

	maxarr, err := f.CalcMaxAllChannels()
	if err != nil {
		t.Fatalf("max all chans failed %s", err)
	}

	fmt.Printf("max all chans signal %v\n", maxarr)

	maxarr, err = f.CalcNormMaxAllChannels()
	if err != nil {
		t.Fatalf("max all chans failed %s", err)
	}

	fmt.Printf("norm max all chans signal %v\n", maxarr)

	max, ok := f.GetSignalMax()
	if !ok {
		t.Error("got unexpected failure from GetSignalMax with val ", max)
	}

	maxarr, ok = f.GetMaxAllChannels()
	if !ok {
		t.Error("got unexpected failure from GetMaxAllChannels with vals", maxarr)
	}

	f.Close()

}

func TestFormats(t *testing.T) {
	simpleformats := GetSimpleFormatCount()
	fmt.Println("--- Supported simple formats")
	for i := 0; i < simpleformats; i++ {
		f, name, ext, ok := GetSimpleFormat(i)
		fmt.Printf("%08x %s %s\n", f, name, ext)
		if !ok {
			t.Error("error from GetSimpleFormat()")
		}
	}

	fmt.Println("--- Supported formats")
	// following is straight from examples in libsndfile distribution
	majorcount := GetMajorFormatCount()
	subcount := GetSubFormatCount()
	for m := 0; m < majorcount; m++ {
		f, name, ext, ok := GetMajorFormatInfo(m)
		if ok {
			fmt.Printf("--- MAJOR 0x%08x %v Extension: .%v\n", f, name, ext)
			for s := 0; s < subcount; s++ {
				t, sname, sok := GetSubFormatInfo(s)
				var i Info
				i.Channels = 1
				i.Format = Format(f|t)
				if sok && FormatCheck(i) {
					fmt.Printf("   0x%08x %v %v\n", f|t, name, sname)
				} else {
//					fmt.Printf("no format pair 0x%x\n", f|t)
				}
			}
		} else {
			fmt.Printf("no format for number %v\n", m)
		}
	}
}

func isLittleEndian() bool {
	var i int32 = 0x01020304
	u := unsafe.Pointer(&i)
	pb := (*byte)(u)
	b := *pb
	return (b == 0x04)
}

func TestRawSwap(t *testing.T) {
	// set up file to be checked
	i := &Info{0, 44100, 1, SF_FORMAT_WAV|SF_FORMAT_PCM_16,0,0}
	f, err := Open("leout.wav", Write, i)
	if err != nil {
		t.Fatalf("couldn't open file for writing: %v", err)
	}
	if isLittleEndian() && f.RawNeedsEndianSwap() {
		t.Errorf("little endian file and little endian cpu shuld not report needing swap but does!")
	} else if !isLittleEndian() && !f.RawNeedsEndianSwap() {
		t.Errorf("little endian file and big endian machine should report needing swap, but doesn't!")
	}
	f.Close()
}

func TestGenericCmd(t *testing.T) {
	i := GenericCmd(nil, 0x1000, nil, 0)
	c := make([]byte, i)
	GenericCmd(nil, 0x1000, unsafe.Pointer(&c[0]), i)
	if !strings.HasPrefix(string(c), "libsndfile") {
		t.Errorf("version string \"%s\" had unexpected prefix", string(c))
	}
}

func TestTruncate(t *testing.T) {
	// first write 100 samples to a file
	var i Info
	i.Samplerate = 44100
	i.Channels = 1
	i.Format = SF_FORMAT_AIFF|SF_FORMAT_PCM_24
	os.Remove("truncout.aiff")
	f, err := Open("truncout.aiff", ReadWrite, &i)
	if err != nil {
		t.Fatalf("couldn't open file for output! %v", err)
	}

	var junk [100]int32
	written, err := f.WriteItems(junk[0:100])
	if written != 100 {
		t.Errorf("wrong written count %d", written)
	}

	f.WriteSync()

	f.Truncate(20)

	f.WriteSync()

	seek, err := f.Seek(0, Current)
	if seek != 20 {
		t.Errorf("wrong seek %v", seek)
	}
	if err != nil {
		t.Errorf("error! %v", err)
	}
	f.Close()
}

func TestMax(t *testing.T) {
	// open file with no peak chunk
	var i Info
	i.Samplerate = 44100
	i.Channels = 4
	i.Format = SF_FORMAT_AIFF|SF_FORMAT_PCM_24

	f, err := Open("addpeakchunk1.aiff", Write, &i)
	if err != nil {
		t.Fatalf("couldn't open file %v", err)
	}

	f.SetAddPeakChunk(false)
	err = f.WriteItems([]int32{1,2,1,2,-1,-2,-1,-2,2,4,2,4,-2,-4,-2,-4})
	if err != nil {
		t.Error("write err:",err)
	}
	f.Close()

	f, err = Open("addpeakchunk1.aiff", Read, &i)
	if err != nil {
		t.Fatalf("couldn't open file %v", err)
	}

	// calc signals
	// make sure peak chunk returns false
	f.Close()

	// repeat for peak chunk, making sure peak chunk returns same value
}<commit_msg>real test for peak chunks<commit_after>package sndfile

import "os"
import "reflect"
import "testing"
import "fmt"
import "strings"
import "unsafe"

func TestGetLibVersion(t *testing.T) {
	s, _ := GetLibVersion()
	fmt.Println(s)
	if !strings.HasPrefix(s, "libsndfile") {
		t.Errorf("version string \"%s\" had unexpected prefix", s)
	}
}

func TestGetLogInfo(t *testing.T) {
	var i Info
	f, err := Open("fwerefrg", Read, &i)
//	fmt.Println(f)
//	fmt.Println(err)
	s, err := f.GetLogInfo()
	fmt.Println("TestGetLogInfo output: ", s)
	if err != nil {
		t.Error("TestGetLogInfo err: ", err)
	}
}

func TestFileCommands(t *testing.T) {
	var i Info
	f, err := Open("funky.aiff", ReadWrite, &i)
	if err != nil {
		t.Fatalf("open file failed %s", err)
	}

	max, err := f.CalcSignalMax()
	if err != nil {
		t.Fatalf("signal max failed %s", err)
	}

	fmt.Printf("max signal %f\n", max)

	max, err = f.CalcNormSignalMax()
	if err != nil {
		t.Fatalf("norm signal max failed %s", err)
	}

	fmt.Printf("norm max signal %f\n", max)

	maxarr, err := f.CalcMaxAllChannels()
	if err != nil {
		t.Fatalf("max all chans failed %s", err)
	}

	fmt.Printf("max all chans signal %v\n", maxarr)

	maxarr, err = f.CalcNormMaxAllChannels()
	if err != nil {
		t.Fatalf("max all chans failed %s", err)
	}

	fmt.Printf("norm max all chans signal %v\n", maxarr)

	max, ok := f.GetSignalMax()
	if !ok {
		t.Error("got unexpected failure from GetSignalMax with val ", max)
	}

	maxarr, ok = f.GetMaxAllChannels()
	if !ok {
		t.Error("got unexpected failure from GetMaxAllChannels with vals", maxarr)
	}

	f.Close()

}

func TestFormats(t *testing.T) {
	simpleformats := GetSimpleFormatCount()
	fmt.Println("--- Supported simple formats")
	for i := 0; i < simpleformats; i++ {
		f, name, ext, ok := GetSimpleFormat(i)
		fmt.Printf("%08x %s %s\n", f, name, ext)
		if !ok {
			t.Error("error from GetSimpleFormat()")
		}
	}

	fmt.Println("--- Supported formats")
	// following is straight from examples in libsndfile distribution
	majorcount := GetMajorFormatCount()
	subcount := GetSubFormatCount()
	for m := 0; m < majorcount; m++ {
		f, name, ext, ok := GetMajorFormatInfo(m)
		if ok {
			fmt.Printf("--- MAJOR 0x%08x %v Extension: .%v\n", f, name, ext)
			for s := 0; s < subcount; s++ {
				t, sname, sok := GetSubFormatInfo(s)
				var i Info
				i.Channels = 1
				i.Format = Format(f|t)
				if sok && FormatCheck(i) {
					fmt.Printf("   0x%08x %v %v\n", f|t, name, sname)
				} else {
//					fmt.Printf("no format pair 0x%x\n", f|t)
				}
			}
		} else {
			fmt.Printf("no format for number %v\n", m)
		}
	}
}

func isLittleEndian() bool {
	var i int32 = 0x01020304
	u := unsafe.Pointer(&i)
	pb := (*byte)(u)
	b := *pb
	return (b == 0x04)
}

func TestRawSwap(t *testing.T) {
	// set up file to be checked
	i := &Info{0, 44100, 1, SF_FORMAT_WAV|SF_FORMAT_PCM_16,0,0}
	f, err := Open("leout.wav", Write, i)
	if err != nil {
		t.Fatalf("couldn't open file for writing: %v", err)
	}
	if isLittleEndian() && f.RawNeedsEndianSwap() {
		t.Errorf("little endian file and little endian cpu shuld not report needing swap but does!")
	} else if !isLittleEndian() && !f.RawNeedsEndianSwap() {
		t.Errorf("little endian file and big endian machine should report needing swap, but doesn't!")
	}
	f.Close()
}

func TestGenericCmd(t *testing.T) {
	i := GenericCmd(nil, 0x1000, nil, 0)
	c := make([]byte, i)
	GenericCmd(nil, 0x1000, unsafe.Pointer(&c[0]), i)
	if !strings.HasPrefix(string(c), "libsndfile") {
		t.Errorf("version string \"%s\" had unexpected prefix", string(c))
	}
}

func TestTruncate(t *testing.T) {
	// first write 100 samples to a file
	var i Info
	i.Samplerate = 44100
	i.Channels = 1
	i.Format = SF_FORMAT_AIFF|SF_FORMAT_PCM_24
	os.Remove("truncout.aiff")
	f, err := Open("truncout.aiff", ReadWrite, &i)
	if err != nil {
		t.Fatalf("couldn't open file for output! %v", err)
	}

	var junk [100]int32
	written, err := f.WriteItems(junk[0:100])
	if written != 100 {
		t.Errorf("wrong written count %d", written)
	}

	f.WriteSync()

	f.Truncate(20)

	f.WriteSync()

	seek, err := f.Seek(0, Current)
	if seek != 20 {
		t.Errorf("wrong seek %v", seek)
	}
	if err != nil {
		t.Errorf("error! %v", err)
	}
	f.Close()
}

func TestMax(t *testing.T) {
	// open file with no peak chunk
	var i Info
	i.Samplerate = 44100
	i.Channels = 4
	i.Format = SF_FORMAT_AIFF|SF_FORMAT_PCM_16

	f, err := Open("addpeakchunk1.aiff", Write, &i)
	if err != nil {
		t.Fatalf("couldn't open file %v", err)
	}

	f.SetAddPeakChunk(false)
	_, err = f.WriteItems([]int16{1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8})
	if err != nil {
		t.Error("write err:",err)
	}
	f.Close()

	f, err = Open("addpeakchunk1.aiff", Read, &i)
	if err != nil {
		t.Fatalf("couldn't open file %v", err)
	}

	// calc signals
	r, err := f.CalcSignalMax()
	if err != nil {
		t.Fatal("couldn't calculate signal max",err)
	}
	if r != 8.0 {
		t.Errorf("Signal max was %v\n", r)
	}

	r, err = f.CalcNormSignalMax()
	if err != nil {
		t.Fatal("couldn't calculate signal max",err)
	}
	if r != float64(8)/float64(0x8000) {
		t.Errorf("Signal max was %v not %v\n", r, float64(8)/float64(0x7fff))
	}

	ra, err := f.CalcMaxAllChannels()
	if err != nil {
		t.Fatal("couldn't calculate signal max",err)
	}
	if !reflect.DeepEqual(ra,[]float64{5.0,6.0,7.0,8.0}) {
		t.Errorf("Signal max was %v\n", ra)
	}

	ra, err = f.CalcNormMaxAllChannels()
	if err != nil {
		t.Fatal("couldn't calculate signal max",err)
	}
	if !reflect.DeepEqual(ra,[]float64{5.0/float64(0x8000),6.0/float64(0x8000),7.0/float64(0x8000),8.0/float64(0x8000)}) {
		t.Errorf("Signal max was %v\n", ra)
	}

	// make sure peak chunk returns false

	_, ok := f.GetSignalMax()
	if ok {
		t.Error("expected no peak chunk in file")
	}

	_, ok = f.GetMaxAllChannels()
	if ok {
		t.Error("expected no peak chunk in file")
	}

	f.Close()

	i.Format = SF_FORMAT_AIFF|SF_FORMAT_DOUBLE
	// repeat for peak chunk, making sure peak chunk returns same value
	f, err = Open("addpeakchunk1.aiff", Write, &i)
	if err != nil {
		t.Fatalf("couldn't open file %v", err)
	}

	f.SetAddPeakChunk(true)
	_, err = f.WriteItems([]int16{1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8})
	if err != nil {
		t.Error("write err:",err)
	}
	f.Close()

	f, err = Open("addpeakchunk1.aiff", Read, &i)
	if err != nil {
		t.Fatalf("couldn't open file %v", err)
	}

	// make sure peak chunk returns true

	r, ok = f.GetSignalMax()
	if !ok {
		t.Error("expected peak chunk in file")
	}
	if r != 8.0 {
		t.Errorf("unexpected peak value %v", r)
	}
	ra, ok = f.GetMaxAllChannels()
	if !ok {
		t.Error("expected peak chunk in file")
	}
	if !reflect.DeepEqual(ra,[]float64{5.0,6.0,7.0,8.0}) {
		t.Errorf("Signal max was %v\n", ra)
	}

}<|endoftext|>


<commit_before>//
// @Author: Geoffrey Bauduin <bauduin.geo@gmail.com>
//

package pushnotifications

import (
	"github.com/aws/aws-sdk-go/service/sns"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
    "encoding/json"
)

type PushNotification struct {
	sns		*sns.SNS
}

type Alert struct {
	Body			*string			`json:"body"`
	LocKey			*string			`json:"loc-key"`
	LocArgs			*[]interface{}	`json:"loc-args"`
	ActionLocKey	*string			`json:"action-loc-key"`
}

type Push struct {
	Alert       *string         `json:"alert,omitempty"`
    Sound       *string         `json:"sound,omitempty"`
    Data        interface{}     `json:"custom_data"`
	Badge		*int			`json:"badge,omitempty"`
}

type wrapper struct {
    APNS        string         `json:"APNS"`
    APNSSandbox string         `json:"APNS_SANDBOX"`
    Default     string         `json:"default"`
}

type iosPush struct {
    APS         Push           `json:"aps"`
}

// Create a push notification manager
func NewPushNotification (awsAccessKey string, awsSecretKey string, region string) *PushNotification {
	entity := new(PushNotification)
	cred := credentials.NewStaticCredentials(awsAccessKey, awsSecretKey, "")
	config := aws.NewConfig().WithRegion(region).WithCredentials(cred)
	sess := session.New(config)
	entity.sns = sns.New(sess)
	return entity
}

// Registers the endpoint into Amazon SNS
func (this *PushNotification) Register (token string, applicationARN string, userData string) (string, error) {
	params := &sns.CreatePlatformEndpointInput{
		PlatformApplicationArn: aws.String(applicationARN),
		Token: aws.String(token),
		Attributes: map[string]*string{
			"Token": aws.String(token),
			"CustomUserData": aws.String(userData),
			"Enabled": aws.String("true"),
		},
		CustomUserData: aws.String(userData),
	}
	resp, err := this.sns.CreatePlatformEndpoint(params)
	if err != nil {
		return "", err
	} else {
		return *resp.EndpointArn, nil
	}
}

// Removes an endpoint from Amazon SNS
func (this *PushNotification) Unregister (arn string) error {
	params := &sns.DeleteEndpointInput{
		EndpointArn: aws.String(arn),
	}
	_, err := this.sns.DeleteEndpoint(params)
	return err
}

// Sends a message to a particular endpoint from Amazon SNS
func (this *PushNotification) Send (arn string, data *Push) error {
    msg := wrapper{}
    ios := iosPush{
        APS: *data,
    }
    b, err := json.Marshal(ios)
    if err != nil {
        return err
    }
    msg.APNS = string(b[:])
    msg.APNSSandbox = msg.APNS
    msg.Default = msg.Default
    pushData, err := json.Marshal(msg)
    if err != nil {
        return err
    }
    m := string(pushData[:])
	params := &sns.PublishInput{
		Message: aws.String(m),
		MessageStructure: aws.String("json"),
		TargetArn: aws.String(arn),
	}
	_, err = this.sns.Publish(params)
	return err
}<commit_msg>added support for GCM<commit_after>//
// @Author: Geoffrey Bauduin <bauduin.geo@gmail.com>
//

package pushnotifications

import (
	"github.com/aws/aws-sdk-go/service/sns"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
    "encoding/json"
)

type PushNotification struct {
	sns		*sns.SNS
}

type Alert struct {
	Body			*string			`json:"body"`
	LocKey			*string			`json:"loc-key"`
	LocArgs			*[]interface{}	`json:"loc-args"`
	ActionLocKey	*string			`json:"action-loc-key"`
}

type Push struct {
	Alert       *string         `json:"alert,omitempty"`
    Sound       *string         `json:"sound,omitempty"`
    Data        interface{}     `json:"custom_data"`
	Badge		*int			`json:"badge,omitempty"`
}

type wrapper struct {
    APNS        string         	`json:"APNS"`
    APNSSandbox string         	`json:"APNS_SANDBOX"`
    Default     string         	`json:"default"`
	GCM			string			`json:"GCM"`
}

type iosPush struct {
    APS         Push           	`json:"aps"`
}

type gcmPush struct {
	Message		string			`json:"message"`
	Custom		interface{}		`json:"custom"`
}

type gcmPushWrapper struct {
	Data		gcmPush			`json:"data"`
}

// Create a push notification manager
func NewPushNotification (awsAccessKey string, awsSecretKey string, region string) *PushNotification {
	entity := new(PushNotification)
	cred := credentials.NewStaticCredentials(awsAccessKey, awsSecretKey, "")
	config := aws.NewConfig().WithRegion(region).WithCredentials(cred)
	sess := session.New(config)
	entity.sns = sns.New(sess)
	return entity
}

// Registers the endpoint into Amazon SNS
func (this *PushNotification) Register (token string, applicationARN string, userData string) (string, error) {
	params := &sns.CreatePlatformEndpointInput{
		PlatformApplicationArn: aws.String(applicationARN),
		Token: aws.String(token),
		Attributes: map[string]*string{
			"Token": aws.String(token),
			"CustomUserData": aws.String(userData),
			"Enabled": aws.String("true"),
		},
		CustomUserData: aws.String(userData),
	}
	resp, err := this.sns.CreatePlatformEndpoint(params)
	if err != nil {
		return "", err
	} else {
		return *resp.EndpointArn, nil
	}
}

// Removes an endpoint from Amazon SNS
func (this *PushNotification) Unregister (arn string) error {
	params := &sns.DeleteEndpointInput{
		EndpointArn: aws.String(arn),
	}
	_, err := this.sns.DeleteEndpoint(params)
	return err
}

// Sends a message to a particular endpoint from Amazon SNS
func (this *PushNotification) Send (arn string, data *Push) error {
    msg := wrapper{}
    ios := iosPush{
        APS: *data,
    }
    b, err := json.Marshal(ios)
    if err != nil {
        return err
    }
    msg.APNS = string(b[:])
    msg.APNSSandbox = msg.APNS
    msg.Default = *data.Alert.Body
	gcm := gcmPushWrapper{
		Data: gcmPush{
			Message: *data.Alert.Body,
			Custom: data.Data,
		},
	}
	b, err = json.Marshal(gcm)
	if err != nil {
		return err
	}
	msg.GCM = string(b[:])
    pushData, err := json.Marshal(msg)
    if err != nil {
        return err
    }
    m := string(pushData[:])
	params := &sns.PublishInput{
		Message: aws.String(m),
		MessageStructure: aws.String("json"),
		TargetArn: aws.String(arn),
	}
	_, err = this.sns.Publish(params)
	return err
}<|endoftext|>


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

/*

Gc is the generic label for the family of Go compilers
that function as part of the (modified) Plan 9 tool chain.  The C compiler
documentation at

	http://plan9.bell-labs.com/sys/doc/comp.pdf     (Tools overview)
	http://plan9.bell-labs.com/sys/doc/compiler.pdf (C compiler architecture)

gives the overall design of the tool chain.  Aside from a few adapted pieces,
such as the optimizer, the Go compilers are wholly new programs.

The compiler reads in a set of Go files, typically suffixed ".go".  They
must all be part of one package.  The output is a single intermediate file
representing the "binary assembly" of the compiled package, ready as input
for the linker (6l, etc.).

The generated files contain type information about the symbols exported by
the package and about types used by symbols imported by the package from
other packages. It is therefore not necessary when compiling client C of
package P to read the files of P's dependencies, only the compiled output
of P.

Usage: 6g [flags] *.go  (or 8g or 5g)

Flags:
	-o file
		output file, default 6.out for 6g, etc.
	-e
		normally the compiler quits after 10 errors; -e prints all errors
	-L
		show entire file path when printing line numbers in errors
	-I dir1 -I dir2
		add dir1 and dir2 to the list of paths to check for imported packages
	-N
		disable optimization
	-S
		write assembly language text to standard output
	-V
		print the compiler version

There are also a number of debugging flags; run the command with no arguments
to get a usage message.

*/
package documentation
<commit_msg>gc: update usage string in doc.go<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*

Gc is the generic label for the family of Go compilers
that function as part of the (modified) Plan 9 tool chain.  The C compiler
documentation at

	http://plan9.bell-labs.com/sys/doc/comp.pdf     (Tools overview)
	http://plan9.bell-labs.com/sys/doc/compiler.pdf (C compiler architecture)

gives the overall design of the tool chain.  Aside from a few adapted pieces,
such as the optimizer, the Go compilers are wholly new programs.

The compiler reads in a set of Go files, typically suffixed ".go".  They
must all be part of one package.  The output is a single intermediate file
representing the "binary assembly" of the compiled package, ready as input
for the linker (6l, etc.).

The generated files contain type information about the symbols exported by
the package and about types used by symbols imported by the package from
other packages. It is therefore not necessary when compiling client C of
package P to read the files of P's dependencies, only the compiled output
of P.

Usage:
	6g [flags] file...
The specified files must be Go source files and all part of the same package.
Substitute 6g with 8g or 5g where appropriate.

Flags:
	-o file
		output file, default 6.out for 6g, etc.
	-e
		normally the compiler quits after 10 errors; -e prints all errors
	-L
		show entire file path when printing line numbers in errors
	-I dir1 -I dir2
		add dir1 and dir2 to the list of paths to check for imported packages
	-N
		disable optimization
	-S
		write assembly language text to standard output
	-V
		print the compiler version

There are also a number of debugging flags; run the command with no arguments
to get a usage message.

*/
package documentation
<|endoftext|>


<commit_before>package swgohgg

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"strconv"
)

func (c *Client) Roster() (roster Roster, err error) {
	url := fmt.Sprintf("https://swgoh.gg/u/%s/collection/", c.profile)
	resp, err := c.hc.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("swgohgg: unexpected status code %d", resp.StatusCode)
	}
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, err
	}
	doc.Find(".collection-char-list .collection-char").Each(func(i int, s *goquery.Selection) {
		if s.HasClass("collection-char-missing") {
			return
		}
		char := parseChar(s)
		roster = append(roster, char)
	})
	return roster, nil
}

type Roster []*Char

func (r Roster) Contains(char string) bool {
	for i := range r {
		if r[i].Name == char {
			return true
		}
	}
	return false
}

func (r Roster) ContainsAll(chars ...string) bool {
	for _, char := range chars {
		if !r.Contains(char) {
			return false
		}
	}
	return true
}

type Char struct {
	Name  string
	Stars int
	Level int
	Gear  int
}

func (c *Char) String() string {
	if c == nil {
		return "nil"
	}
	return fmt.Sprintf("%s %d* G%d Lvl%d", c.Name, c.Stars, c.Gear, c.Level)
}

func parseChar(s *goquery.Selection) *Char {
	var char Char
	char.Name = s.Find(".collection-char-name-link").Text()
	char.Level, _ = strconv.Atoi(s.Find(".char-portrait-full-level").Text())
	char.Gear = gearLevel(s)
	char.Stars = stars(s)
	return &char
}

func stars(s *goquery.Selection) int {
	level := 0
	s.Find(".star").Each(func(i int, star *goquery.Selection) {
		if star.HasClass("star-inactive") {
			return
		}
		level++
	})
	return level
}

func gearLevel(s *goquery.Selection) int {
	switch s.Find(".char-portrait-full-gear-level").Text() {
	case "XII":
		return 12
	case "XI":
		return 11
	case "X":
		return 10
	case "IX":
		return 9
	case "VIII":
		return 8
	case "VII":
		return 7
	case "VI":
		return 6
	case "V":
		return 5
	case "IV":
		return 4
	case "III":
		return 3
	case "II":
		return 2
	case "I":
		return 1
	default:
		return -1
	}
}
<commit_msg>Display inactive characters as well by default.<commit_after>package swgohgg

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"strconv"
)

func (c *Client) Roster() (roster Roster, err error) {
	url := fmt.Sprintf("https://swgoh.gg/u/%s/collection/", c.profile)
	resp, err := c.hc.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("swgohgg: unexpected status code %d", resp.StatusCode)
	}
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, err
	}
	doc.Find(".collection-char-list .collection-char").Each(func(i int, s *goquery.Selection) {
		char := parseChar(s)
		roster = append(roster, char)
	})
	return roster, nil
}

type Roster []*Char

func (r Roster) Contains(char string) bool {
	for i := range r {
		if r[i].Name == char {
			return true
		}
	}
	return false
}

func (r Roster) ContainsAll(chars ...string) bool {
	for _, char := range chars {
		if !r.Contains(char) {
			return false
		}
	}
	return true
}

type Char struct {
	Name  string
	Stars int
	Level int
	Gear  int
}

func (c *Char) String() string {
	if c == nil {
		return "nil"
	}
	return fmt.Sprintf("%s %d* G%d Lvl%d", c.Name, c.Stars, c.Gear, c.Level)
}

func parseChar(s *goquery.Selection) *Char {
	var char Char
	char.Name = s.Find(".collection-char-name-link").Text()
	char.Level, _ = strconv.Atoi(s.Find(".char-portrait-full-level").Text())
	char.Gear = gearLevel(s)
	char.Stars = stars(s)
	return &char
}

func stars(s *goquery.Selection) int {
	level := 0
	s.Find(".star").Each(func(i int, star *goquery.Selection) {
		if star.HasClass("star-inactive") {
			return
		}
		level++
	})
	return level
}

func gearLevel(s *goquery.Selection) int {
	switch s.Find(".char-portrait-full-gear-level").Text() {
	case "XII":
		return 12
	case "XI":
		return 11
	case "X":
		return 10
	case "IX":
		return 9
	case "VIII":
		return 8
	case "VII":
		return 7
	case "VI":
		return 6
	case "V":
		return 5
	case "IV":
		return 4
	case "III":
		return 3
	case "II":
		return 2
	case "I":
		return 1
	default:
		return 0
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 ~ 2018 AlexStocks(https://github.com/AlexStocks).
// All rights reserved.  Use of this source code is
// governed by Apache License 2.0.

// ref: https://rogpeppe.wordpress.com/2009/12/01/concurrent-idioms-1-broadcasting-values-in-go-with-linked-channels/
package gxsync

import (
	"fmt"
)

var (
	ErrBroadcastClosed = fmt.Errorf("broadcast closed!")
)

type Node struct {
	next  chan Node
	value interface{}
}

type Broadcaster struct {
	registry chan chan (chan Node)
	data     chan<- interface{}
}

type Receiver struct {
	C chan Node
}

// create a new broadcaster object.
func NewBroadcaster() Broadcaster {
	registry := make(chan (chan (chan Node)))
	data := make(chan interface{})
	go func() {
		var (
			value  interface{}
			cursor chan Node
			node   chan Node
			reader chan chan Node
		)
		cursor = make(chan Node, 1)
		for {
			select {
			case value = <-data:
				if value == nil {
					cursor <- Node{}
					return
				}
				node = make(chan Node, 1)
				cursor <- Node{next: node, value: value}
				cursor = node
			case reader = <-registry:
				reader <- cursor
			}
		}
	}()
	return Broadcaster{
		registry: registry,
		data:     data,
	}
}

// start listening to the nodes.
func (b Broadcaster) Listen() Receiver {
	r := make(chan chan Node, 0)
	b.registry <- r
	return Receiver{<-r}
}

// Node a value to all listeners.
func (b Broadcaster) Write(value interface{}) (rerr error) {
	defer func() {
		if e := recover(); e != nil {
			rerr = fmt.Errorf("panic error:%value", e)
		}
	}()

	if value == nil {
		close(b.data)
		return
	}
	b.data <- value

	return
}

func (b Broadcaster) Close() { b.Write(nil) }

// read a value that has been broadcast,
// waiting until one is available if necessary.
func (r *Receiver) Read() (interface{}, error) {
	n := <-r.C
	value := n.value
	r.C <- n
	r.C = n.next

	if value == nil {
		return nil, ErrBroadcastClosed
	}

	return value, nil
}

func (r *Receiver) ReadChan() chan Node {
	return r.C
}

func (r *Receiver) ReadDone(n Node) (interface{}, error) {
	r.C <- n
	r.C = n.next

	if n.value == nil {
		return nil, ErrBroadcastClosed
	}

	return n.value, nil
}
<commit_msg>Rem: broadcast<commit_after><|endoftext|>


<commit_before>// Copyright 2013 The Go 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 strings_test

// Derived from bytes/compare_test.go.
// Benchmarks omitted since the underlying implementation is identical.

import (
	"internal/testenv"
	. "strings"
	"testing"
)

var compareTests = []struct {
	a, b string
	i    int
}{
	{"", "", 0},
	{"a", "", 1},
	{"", "a", -1},
	{"abc", "abc", 0},
	{"ab", "abc", -1},
	{"abc", "ab", 1},
	{"x", "ab", 1},
	{"ab", "x", -1},
	{"x", "a", 1},
	{"b", "x", -1},
	// test runtime·memeq's chunked implementation
	{"abcdefgh", "abcdefgh", 0},
	{"abcdefghi", "abcdefghi", 0},
	{"abcdefghi", "abcdefghj", -1},
}

func TestCompare(t *testing.T) {
	for _, tt := range compareTests {
		cmp := Compare(tt.a, tt.b)
		if cmp != tt.i {
			t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
		}
	}
}

func TestCompareIdenticalString(t *testing.T) {
	var s = "Hello Gophers!"
	if Compare(s, s) != 0 {
		t.Error("s != s")
	}
	if Compare(s, s[:1]) != 1 {
		t.Error("s > s[:1] failed")
	}
}

func TestCompareStrings(t *testing.T) {
	lengths := make([]int, 0) // lengths to test in ascending order
	for i := 0; i <= 128; i++ {
		lengths = append(lengths, i)
	}
	lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097)

	if !testing.Short() || testenv.Builder() != "" {
		lengths = append(lengths, 65535, 65536, 65537, 99999)
	}

	n := lengths[len(lengths)-1]
	a := make([]byte, n+1)
	b := make([]byte, n+1)
	lastLen := 0
	for _, len := range lengths {
		// randomish but deterministic data. No 0 or 255.
		for i := 0; i < len; i++ {
			a[i] = byte(1 + 31*i%254)
			b[i] = byte(1 + 31*i%254)
		}
		// data past the end is different
		for i := len; i <= n; i++ {
			a[i] = 8
			b[i] = 9
		}

		sa, sb := string(a), string(b)
		cmp := Compare(sa[:len], sb[:len])
		if cmp != 0 {
			t.Errorf(`CompareIdentical(%d) = %d`, len, cmp)
		}
		if len > 0 {
			cmp = Compare(sa[:len-1], sb[:len])
			if cmp != -1 {
				t.Errorf(`CompareAshorter(%d) = %d`, len, cmp)
			}
			cmp = Compare(sa[:len], sb[:len-1])
			if cmp != 1 {
				t.Errorf(`CompareBshorter(%d) = %d`, len, cmp)
			}
		}
		for k := lastLen; k < len; k++ {
			b[k] = a[k] - 1
			cmp = Compare(string(a[:len]), string(b[:len]))
			if cmp != 1 {
				t.Errorf(`CompareAbigger(%d,%d) = %d`, len, k, cmp)
			}
			b[k] = a[k] + 1
			cmp = Compare(string(a[:len]), string(b[:len]))
			if cmp != -1 {
				t.Errorf(`CompareBbigger(%d,%d) = %d`, len, k, cmp)
			}
			b[k] = a[k]
		}
		lastLen = len
	}
}
<commit_msg>strings: lower running time of TestCompareStrings<commit_after>// Copyright 2013 The Go 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 strings_test

// Derived from bytes/compare_test.go.
// Benchmarks omitted since the underlying implementation is identical.

import (
	"internal/testenv"
	. "strings"
	"testing"
	"unsafe"
)

var compareTests = []struct {
	a, b string
	i    int
}{
	{"", "", 0},
	{"a", "", 1},
	{"", "a", -1},
	{"abc", "abc", 0},
	{"ab", "abc", -1},
	{"abc", "ab", 1},
	{"x", "ab", 1},
	{"ab", "x", -1},
	{"x", "a", 1},
	{"b", "x", -1},
	// test runtime·memeq's chunked implementation
	{"abcdefgh", "abcdefgh", 0},
	{"abcdefghi", "abcdefghi", 0},
	{"abcdefghi", "abcdefghj", -1},
}

func TestCompare(t *testing.T) {
	for _, tt := range compareTests {
		cmp := Compare(tt.a, tt.b)
		if cmp != tt.i {
			t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
		}
	}
}

func TestCompareIdenticalString(t *testing.T) {
	var s = "Hello Gophers!"
	if Compare(s, s) != 0 {
		t.Error("s != s")
	}
	if Compare(s, s[:1]) != 1 {
		t.Error("s > s[:1] failed")
	}
}

func TestCompareStrings(t *testing.T) {
	// unsafeString converts a []byte to a string with no allocation.
	// The caller must not modify b while the result string is in use.
	unsafeString := func(b []byte) string {
		return *(*string)(unsafe.Pointer(&b))
	}

	lengths := make([]int, 0) // lengths to test in ascending order
	for i := 0; i <= 128; i++ {
		lengths = append(lengths, i)
	}
	lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097)

	if !testing.Short() || testenv.Builder() != "" {
		lengths = append(lengths, 65535, 65536, 65537, 99999)
	}

	n := lengths[len(lengths)-1]
	a := make([]byte, n+1)
	b := make([]byte, n+1)
	lastLen := 0
	for _, len := range lengths {
		// randomish but deterministic data. No 0 or 255.
		for i := 0; i < len; i++ {
			a[i] = byte(1 + 31*i%254)
			b[i] = byte(1 + 31*i%254)
		}
		// data past the end is different
		for i := len; i <= n; i++ {
			a[i] = 8
			b[i] = 9
		}

		sa, sb := unsafeString(a), unsafeString(b)
		cmp := Compare(sa[:len], sb[:len])
		if cmp != 0 {
			t.Errorf(`CompareIdentical(%d) = %d`, len, cmp)
		}
		if len > 0 {
			cmp = Compare(sa[:len-1], sb[:len])
			if cmp != -1 {
				t.Errorf(`CompareAshorter(%d) = %d`, len, cmp)
			}
			cmp = Compare(sa[:len], sb[:len-1])
			if cmp != 1 {
				t.Errorf(`CompareBshorter(%d) = %d`, len, cmp)
			}
		}
		for k := lastLen; k < len; k++ {
			b[k] = a[k] - 1
			cmp = Compare(unsafeString(a[:len]), unsafeString(b[:len]))
			if cmp != 1 {
				t.Errorf(`CompareAbigger(%d,%d) = %d`, len, k, cmp)
			}
			b[k] = a[k] + 1
			cmp = Compare(unsafeString(a[:len]), unsafeString(b[:len]))
			if cmp != -1 {
				t.Errorf(`CompareBbigger(%d,%d) = %d`, len, k, cmp)
			}
			b[k] = a[k]
		}
		lastLen = len
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 The Go 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 main

import (
	"fmt"
	"os"
	"runtime"
	"strings"
)

var cmdEnv = &Command{
	Run:       runEnv,
	UsageLine: "env [var ...]",
	Short:     "print Go environment information",
	Long: `
Env prints Go environment information.

By default env prints information as a shell script
(on Windows, a batch file).  If one or more variable
names is given as arguments,  env prints the value of
each named variable on its own line.
	`,
}

type envVar struct {
	name, value string
}

func mkEnv() []envVar {
	var b builder
	b.init()

	env := []envVar{
		{"GOARCH", goarch},
		{"GOBIN", gobin},
		{"GOCHAR", archChar},
		{"GOEXE", exeSuffix},
		{"GOHOSTARCH", runtime.GOARCH},
		{"GOHOSTOS", runtime.GOOS},
		{"GOOS", goos},
		{"GOPATH", os.Getenv("GOPATH")},
		{"GORACE", os.Getenv("GORACE")},
		{"GOROOT", goroot},
		{"GOTOOLDIR", toolDir},

		// disable escape codes in clang errors
		{"TERM", "dumb"},
	}

	if goos != "plan9" {
		cmd := b.gccCmd(".")
		env = append(env, envVar{"CC", cmd[0]})
		env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})
		cmd = b.gxxCmd(".")
		env = append(env, envVar{"CXX", cmd[0]})
	}

	if buildContext.CgoEnabled {
		env = append(env, envVar{"CGO_ENABLED", "1"})
	} else {
		env = append(env, envVar{"CGO_ENABLED", "0"})
	}

	return env
}

func findEnv(env []envVar, name string) string {
	for _, e := range env {
		if e.name == name {
			return e.value
		}
	}
	return ""
}

func runEnv(cmd *Command, args []string) {
	env := mkEnv()
	if len(args) > 0 {
		for _, name := range args {
			fmt.Printf("%s\n", findEnv(env, name))
		}
		return
	}

	switch runtime.GOOS {
	default:
		for _, e := range env {
			fmt.Printf("%s=\"%s\"\n", e.name, e.value)
		}
	case "plan9":
		for _, e := range env {
			fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
		}
	case "windows":
		for _, e := range env {
			fmt.Printf("set %s=%s\n", e.name, e.value)
		}
	}
}
<commit_msg>cmd/go: hide the "TERM" environment variable from "go env" It's implementation detail.<commit_after>// Copyright 2012 The Go 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 main

import (
	"fmt"
	"os"
	"runtime"
	"strings"
)

var cmdEnv = &Command{
	Run:       runEnv,
	UsageLine: "env [var ...]",
	Short:     "print Go environment information",
	Long: `
Env prints Go environment information.

By default env prints information as a shell script
(on Windows, a batch file).  If one or more variable
names is given as arguments,  env prints the value of
each named variable on its own line.
	`,
}

type envVar struct {
	name, value string
}

func mkEnv() []envVar {
	var b builder
	b.init()

	env := []envVar{
		{"GOARCH", goarch},
		{"GOBIN", gobin},
		{"GOCHAR", archChar},
		{"GOEXE", exeSuffix},
		{"GOHOSTARCH", runtime.GOARCH},
		{"GOHOSTOS", runtime.GOOS},
		{"GOOS", goos},
		{"GOPATH", os.Getenv("GOPATH")},
		{"GORACE", os.Getenv("GORACE")},
		{"GOROOT", goroot},
		{"GOTOOLDIR", toolDir},

		// disable escape codes in clang errors
		{"TERM", "dumb"},
	}

	if goos != "plan9" {
		cmd := b.gccCmd(".")
		env = append(env, envVar{"CC", cmd[0]})
		env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})
		cmd = b.gxxCmd(".")
		env = append(env, envVar{"CXX", cmd[0]})
	}

	if buildContext.CgoEnabled {
		env = append(env, envVar{"CGO_ENABLED", "1"})
	} else {
		env = append(env, envVar{"CGO_ENABLED", "0"})
	}

	return env
}

func findEnv(env []envVar, name string) string {
	for _, e := range env {
		if e.name == name {
			return e.value
		}
	}
	return ""
}

func runEnv(cmd *Command, args []string) {
	env := mkEnv()
	if len(args) > 0 {
		for _, name := range args {
			fmt.Printf("%s\n", findEnv(env, name))
		}
		return
	}

	for _, e := range env {
		if e.name != "TERM" {
			switch runtime.GOOS {
			default:
				fmt.Printf("%s=\"%s\"\n", e.name, e.value)
			case "plan9":
				fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
			case "windows":
				fmt.Printf("set %s=%s\n", e.name, e.value)
			}
		}
	}
}
<|endoftext|>


<commit_before>package premailer

import (
	"fmt"
	"log"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"

	"github.com/PuerkitoBio/goquery"
	"github.com/vanng822/css"
	"golang.org/x/net/html"
)

// Inteface of Premailer
type Premailer interface {
	// Transform process and inlining css
	// It start to collect the rules in the document style tags
	// Calculate specificity and sort the rules based on that
	// It then collects the affected elements
	// And applies the rules on those
	// The leftover rules will put back into a style element
	Transform() (string, error)
}

var unmergableSelector = regexp.MustCompile("(?i)\\:{1,2}(visited|active|hover|focus|link|root|in-range|invalid|valid|after|before|selection|target|first\\-(line|letter))|^\\@")
var notSupportedSelector = regexp.MustCompile("(?i)\\:(checked|disabled|enabled|lang)")

type premailer struct {
	doc       *goquery.Document
	elIdAttr  string
	elements  map[string]*elementRules
	rules     []*styleRule
	leftover  []*css.CSSRule
	allRules  [][]*css.CSSRule
	elementId int
	processed bool
	options   *Options
}

// NewPremailer return a new instance of Premailer
// It take a Document as argument and it shouldn't be nil
func NewPremailer(doc *goquery.Document, options *Options) Premailer {
	pr := premailer{}
	pr.doc = doc
	pr.rules = make([]*styleRule, 0)
	pr.allRules = make([][]*css.CSSRule, 0)
	pr.leftover = make([]*css.CSSRule, 0)
	pr.elements = make(map[string]*elementRules)
	pr.elIdAttr = "pr-el-id"
	if options == nil {
		options = NewOptions()
	}
	pr.options = options
	return &pr
}

func (pr *premailer) sortRules() {
	ruleIndex := 0
	for ruleSetIndex, rules := range pr.allRules {
		if rules == nil {
			continue
		}
		for _, rule := range rules {
			if rule.Type != css.STYLE_RULE {
				pr.leftover = append(pr.leftover, rule)
				continue
			}
			normalStyles := make(map[string]*css.CSSStyleDeclaration)
			importantStyles := make(map[string]*css.CSSStyleDeclaration)

			for prop, s := range rule.Style.Styles {
				if s.Important == 1 {
					importantStyles[prop] = s
				} else {
					normalStyles[prop] = s
				}
			}

			selectors := strings.Split(rule.Style.SelectorText, ",")
			for _, selector := range selectors {
				if unmergableSelector.MatchString(selector) || notSupportedSelector.MatchString(selector) {
					// cause longer css
					pr.leftover = append(pr.leftover, copyRule(selector, rule))
					continue
				}
				if strings.Contains(selector, "*") {
					// keep this?
					pr.leftover = append(pr.leftover, copyRule(selector, rule))
					continue
				}
				if len(normalStyles) > 0 {
					pr.rules = append(pr.rules, &styleRule{makeSpecificity(0, ruleSetIndex, ruleIndex, selector), selector, normalStyles})
					ruleIndex += 1
				}
				if len(importantStyles) > 0 {
					pr.rules = append(pr.rules, &styleRule{makeSpecificity(1, ruleSetIndex, ruleIndex, selector), selector, importantStyles})
					ruleIndex += 1
				}
			}
		}
	}
	sort.Sort(bySpecificity(pr.rules))
}

func (pr *premailer) collectRules() {
	var wg sync.WaitGroup
	pr.doc.Find("style:not([data-premailer='ignore'])").Each(func(_ int, s *goquery.Selection) {
		if media, exist := s.Attr("media"); exist && media != "all" {
			return
		}
		wg.Add(1)
		pr.allRules = append(pr.allRules, nil)
		go func(ruleSetIndex int) {
			defer func() {
				wg.Done()
				if r := recover(); r != nil {
					pr.allRules[ruleSetIndex] = nil
					log.Println("Got error when passing css")
					log.Println(r)
				}
			}()
			ss := css.Parse(s.Text())
			pr.allRules[ruleSetIndex] = ss.GetCSSRuleList()
			s.ReplaceWithHtml("")
		}(len(pr.allRules) - 1)
	})
	wg.Wait()

}

func (pr *premailer) collectElements() {
	for _, rule := range pr.rules {
		pr.doc.Find(rule.selector).Each(func(_ int, s *goquery.Selection) {
			if id, exist := s.Attr(pr.elIdAttr); exist {
				pr.elements[id].rules = append(pr.elements[id].rules, rule)
			} else {
				id := strconv.Itoa(pr.elementId)
				s.SetAttr(pr.elIdAttr, id)
				rules := make([]*styleRule, 0)
				rules = append(rules, rule)
				pr.elements[id] = &elementRules{element: s, rules: rules, cssToAttributes: pr.options.CssToAttributes}
				pr.elementId += 1
			}
		})

	}
}

func (pr *premailer) applyInline() {
	for _, element := range pr.elements {
		element.inline()
		element.element.RemoveAttr(pr.elIdAttr)
		if pr.options.RemoveClasses {
			element.element.RemoveAttr("class")
		}
	}
}

func (pr *premailer) addLeftover() {
	if len(pr.leftover) > 0 {
		headNode := pr.doc.Find("head")

		styleNode := &html.Node{}
		styleNode.Type = html.ElementNode
		styleNode.Data = "style"
		styleNode.Attr = []html.Attribute{html.Attribute{Key: "type", Val: "text/css"}}
		cssNode := &html.Node{}
		cssData := make([]string, 0, len(pr.leftover))
		for _, rule := range pr.leftover {
			if rule.Type == css.MEDIA_RULE {
				mcssData := make([]string, 0, len(rule.Rules))
				for _, mrule := range rule.Rules {
					mcssData = append(mcssData, makeRuleImportant(mrule))
				}
				cssData = append(cssData, fmt.Sprintf("%s %s{\n%s\n}\n",
					rule.Type.Text(),
					rule.Style.SelectorText,
					strings.Join(mcssData, "\n")))
			} else {
				cssData = append(cssData, makeRuleImportant(rule))
			}
		}
		cssNode.Data = strings.Join(cssData, "")
		cssNode.Type = html.TextNode
		styleNode.AppendChild(cssNode)
		headNode.AppendNodes(styleNode)
	}
}

// Transform process and inlining css
// It start to collect the rules in the document style tags
// Calculate specificity and sort the rules based on that
// It then collects the affected elements
// And applies the rules on those
// The leftover rules will put back into a style element
func (pr *premailer) Transform() (string, error) {
	if !pr.processed {
		pr.collectRules()
		pr.sortRules()
		pr.collectElements()
		pr.applyInline()
		pr.addLeftover()
	}
	return pr.doc.Html()
}
<commit_msg>Skip processing if already done<commit_after>package premailer

import (
	"fmt"
	"log"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"

	"github.com/PuerkitoBio/goquery"
	"github.com/vanng822/css"
	"golang.org/x/net/html"
)

// Inteface of Premailer
type Premailer interface {
	// Transform process and inlining css
	// It start to collect the rules in the document style tags
	// Calculate specificity and sort the rules based on that
	// It then collects the affected elements
	// And applies the rules on those
	// The leftover rules will put back into a style element
	Transform() (string, error)
}

var unmergableSelector = regexp.MustCompile("(?i)\\:{1,2}(visited|active|hover|focus|link|root|in-range|invalid|valid|after|before|selection|target|first\\-(line|letter))|^\\@")
var notSupportedSelector = regexp.MustCompile("(?i)\\:(checked|disabled|enabled|lang)")

type premailer struct {
	doc       *goquery.Document
	elIdAttr  string
	elements  map[string]*elementRules
	rules     []*styleRule
	leftover  []*css.CSSRule
	allRules  [][]*css.CSSRule
	elementId int
	processed bool
	options   *Options
}

// NewPremailer return a new instance of Premailer
// It take a Document as argument and it shouldn't be nil
func NewPremailer(doc *goquery.Document, options *Options) Premailer {
	pr := premailer{}
	pr.doc = doc
	pr.rules = make([]*styleRule, 0)
	pr.allRules = make([][]*css.CSSRule, 0)
	pr.leftover = make([]*css.CSSRule, 0)
	pr.elements = make(map[string]*elementRules)
	pr.elIdAttr = "pr-el-id"
	if options == nil {
		options = NewOptions()
	}
	pr.options = options
	return &pr
}

func (pr *premailer) sortRules() {
	ruleIndex := 0
	for ruleSetIndex, rules := range pr.allRules {
		if rules == nil {
			continue
		}
		for _, rule := range rules {
			if rule.Type != css.STYLE_RULE {
				pr.leftover = append(pr.leftover, rule)
				continue
			}
			normalStyles := make(map[string]*css.CSSStyleDeclaration)
			importantStyles := make(map[string]*css.CSSStyleDeclaration)

			for prop, s := range rule.Style.Styles {
				if s.Important == 1 {
					importantStyles[prop] = s
				} else {
					normalStyles[prop] = s
				}
			}

			selectors := strings.Split(rule.Style.SelectorText, ",")
			for _, selector := range selectors {
				if unmergableSelector.MatchString(selector) || notSupportedSelector.MatchString(selector) {
					// cause longer css
					pr.leftover = append(pr.leftover, copyRule(selector, rule))
					continue
				}
				if strings.Contains(selector, "*") {
					// keep this?
					pr.leftover = append(pr.leftover, copyRule(selector, rule))
					continue
				}
				if len(normalStyles) > 0 {
					pr.rules = append(pr.rules, &styleRule{makeSpecificity(0, ruleSetIndex, ruleIndex, selector), selector, normalStyles})
					ruleIndex += 1
				}
				if len(importantStyles) > 0 {
					pr.rules = append(pr.rules, &styleRule{makeSpecificity(1, ruleSetIndex, ruleIndex, selector), selector, importantStyles})
					ruleIndex += 1
				}
			}
		}
	}
	sort.Sort(bySpecificity(pr.rules))
}

func (pr *premailer) collectRules() {
	var wg sync.WaitGroup
	pr.doc.Find("style:not([data-premailer='ignore'])").Each(func(_ int, s *goquery.Selection) {
		if media, exist := s.Attr("media"); exist && media != "all" {
			return
		}
		wg.Add(1)
		pr.allRules = append(pr.allRules, nil)
		go func(ruleSetIndex int) {
			defer func() {
				wg.Done()
				if r := recover(); r != nil {
					pr.allRules[ruleSetIndex] = nil
					log.Println("Got error when passing css")
					log.Println(r)
				}
			}()
			ss := css.Parse(s.Text())
			pr.allRules[ruleSetIndex] = ss.GetCSSRuleList()
			s.ReplaceWithHtml("")
		}(len(pr.allRules) - 1)
	})
	wg.Wait()

}

func (pr *premailer) collectElements() {
	for _, rule := range pr.rules {
		pr.doc.Find(rule.selector).Each(func(_ int, s *goquery.Selection) {
			if id, exist := s.Attr(pr.elIdAttr); exist {
				pr.elements[id].rules = append(pr.elements[id].rules, rule)
			} else {
				id := strconv.Itoa(pr.elementId)
				s.SetAttr(pr.elIdAttr, id)
				rules := make([]*styleRule, 0)
				rules = append(rules, rule)
				pr.elements[id] = &elementRules{element: s, rules: rules, cssToAttributes: pr.options.CssToAttributes}
				pr.elementId += 1
			}
		})

	}
}

func (pr *premailer) applyInline() {
	for _, element := range pr.elements {
		element.inline()
		element.element.RemoveAttr(pr.elIdAttr)
		if pr.options.RemoveClasses {
			element.element.RemoveAttr("class")
		}
	}
}

func (pr *premailer) addLeftover() {
	if len(pr.leftover) > 0 {
		headNode := pr.doc.Find("head")

		styleNode := &html.Node{}
		styleNode.Type = html.ElementNode
		styleNode.Data = "style"
		styleNode.Attr = []html.Attribute{html.Attribute{Key: "type", Val: "text/css"}}
		cssNode := &html.Node{}
		cssData := make([]string, 0, len(pr.leftover))
		for _, rule := range pr.leftover {
			if rule.Type == css.MEDIA_RULE {
				mcssData := make([]string, 0, len(rule.Rules))
				for _, mrule := range rule.Rules {
					mcssData = append(mcssData, makeRuleImportant(mrule))
				}
				cssData = append(cssData, fmt.Sprintf("%s %s{\n%s\n}\n",
					rule.Type.Text(),
					rule.Style.SelectorText,
					strings.Join(mcssData, "\n")))
			} else {
				cssData = append(cssData, makeRuleImportant(rule))
			}
		}
		cssNode.Data = strings.Join(cssData, "")
		cssNode.Type = html.TextNode
		styleNode.AppendChild(cssNode)
		headNode.AppendNodes(styleNode)
	}
}

// Transform process and inlining css
// It start to collect the rules in the document style tags
// Calculate specificity and sort the rules based on that
// It then collects the affected elements
// And applies the rules on those
// The leftover rules will put back into a style element
func (pr *premailer) Transform() (string, error) {
	if !pr.processed {
		pr.collectRules()
		pr.sortRules()
		pr.collectElements()
		pr.applyInline()
		pr.addLeftover()
		pr.processed = true
	}
	return pr.doc.Html()
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"testing"
	"time"

	"tools/lib/util"
)

func TestParseLastCompletedBuildStatusJsonResponse(t *testing.T) {
	// "SUCCESS" status.
	input := `
	{
		"building": false,
		"fullDisplayName": "veyron-android-build #182",
		"result": "SUCCESS"
	}
	`
	expected := "SUCCESS"
	got, err := parseLastCompletedBuildStatusJsonResponse(strings.NewReader(input))
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if expected != got {
		t.Fatalf("want %v, got %v", expected, got)
	}

	// "FAILURE" status.
	input = `
	{
		"building": false,
		"fullDisplayName": "veyron-android-build #182",
		"result": "FAILURE"
	}
	`
	expected = "FAILURE"
	got, err = parseLastCompletedBuildStatusJsonResponse(strings.NewReader(input))
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if expected != got {
		t.Fatalf("want %v, got %v", expected, got)
	}
}

func TestParseJUnitReportFileWithoutFailedTests(t *testing.T) {
	// Report with no test failures.
	reportFileContent := `
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite name="ts1" tests="1" errors="0" failures="0" skip="0">
    <testcase classname="c1" name="n1" time="0">
    </testcase>
  </testsuite>
</testsuites>
	`
	seenTests := map[string]int{}
	expectedSeenTests := map[string]int{
		"c1::n1": 1,
	}
	expected := []string{}
	got, err := parseJUnitReportFileForFailedTestLinks(strings.NewReader(reportFileContent), seenTests)
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if !reflect.DeepEqual(expected, got) {
		t.Fatalf("want %v, got %v", expected, got)
	}
	if !reflect.DeepEqual(expectedSeenTests, seenTests) {
		t.Fatalf("want %v, got %v", expectedSeenTests, seenTests)
	}
}

func TestParseJUnitReportFileWithFailedTests(t *testing.T) {
	// Report with some test failures.
	// We have two test cases with the same classname+testname, and the second one is failed.
	reportFileContent := `
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite name="ts1" tests="1" errors="0" failures="1" skip="0">
    <testcase classname="package c1" name="n1" time="0">
		  <failure message="error">
# tools/presubmit
tools/go/src/tools/presubmit/main.go:106: undefined: test
		  </failure>
    </testcase>
  </testsuite>
  <testsuite name="ts2" tests="1" errors="0" failures="0" skip="0">
    <testcase classname="v.c2" name="n2" time="0">
    </testcase>
  </testsuite>
  <testsuite name="ts2" tests="1" errors="0" failures="1" skip="0">
    <testcase classname="v.c2" name="n2" time="0">
		  <failure message="error">
# some other errors.
		  </failure>
    </testcase>
  </testsuite>
</testsuites>
	`
	jenkinsBuildNumberFlag = 10
	seenTests := map[string]int{}
	expectedSeenTests := map[string]int{
		"package c1::n1": 1,
		"v::c2::n2":      2,
	}
	expected := []string{
		"- package c1::n1\nhttp://goto.google.com/vpst/10/testReport/%28root%29/package%20c1/n1",
		"- v::c2::n2\nhttp://goto.google.com/vpst/10/testReport/v/c2/n2_2",
	}
	got, err := parseJUnitReportFileForFailedTestLinks(strings.NewReader(reportFileContent), seenTests)
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if !reflect.DeepEqual(expected, got) {
		t.Fatalf("want %v, got %v", expected, got)
	}
	if !reflect.DeepEqual(expectedSeenTests, seenTests) {
		t.Fatalf("want %v, got %v", expectedSeenTests, seenTests)
	}
}

func TestSafePackageOrClassName(t *testing.T) {
	name := "name"
	expected := "name"
	if got := safePackageOrClassName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}

	name = "name\\0/a:b?c#d%e-f_g e"
	expected = "name_0_a_b_c_d_e-f_g e"
	if got := safePackageOrClassName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}
}

func TestSafeTestName(t *testing.T) {
	name := "name"
	expected := "name"
	if got := safeTestName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}

	name = "name-a b$c_d"
	expected = "name_a_b$c_d"
	if got := safeTestName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}
}

func createBuildCopFile(veyronRoot string, t *testing.T) {
	content := `<?xml version="1.0" ?>
<!--
  This file is auto generated by the following command:
  /google/data/ro/users/ji/jingjin/gen_rotation_file.par

  Please don't edit manually.
-->
<shifts>
  <shift>
    <primary>spetrovic</primary>
    <secondary>suharshs</secondary>
    <startDate>Nov 5, 2014 12:00:00 PM</startDate>
  </shift>
  <shift>
    <primary>suharshs</primary>
    <secondary>tilaks</secondary>
    <startDate>Nov 12, 2014 12:00:00 PM</startDate>
  </shift>
  <shift>
    <primary>jsimsa</primary>
    <secondary>toddw</secondary>
    <startDate>Nov 19, 2014 12:00:00 PM</startDate>
  </shift>
</shifts>`
	buildCopRotationsFile := filepath.Join(veyronRoot, "tools", "conf", "buildcop.xml")
	dir := filepath.Dir(buildCopRotationsFile)
	dirMode := os.FileMode(0700)
	if err := os.MkdirAll(dir, dirMode); err != nil {
		t.Fatalf("MkdirAll(%q, %v) failed: %v", dir, dirMode, err)
	}
	fileMode := os.FileMode(0644)
	if err := ioutil.WriteFile(buildCopRotationsFile, []byte(content), fileMode); err != nil {
		t.Fatalf("WriteFile(%q, %q, %v) failed: %v", buildCopRotationsFile, content, fileMode, err)
	}
}

func TestBuildCop(t *testing.T) {
	// Setup a fake VEYRON_ROOT.
	dir, prefix := "", ""
	tmpDir, err := ioutil.TempDir(dir, prefix)
	if err != nil {
		t.Fatalf("TempDir(%v, %v) failed: %v", dir, prefix, err)
	}
	defer os.RemoveAll(tmpDir)
	oldRoot, err := util.VeyronRoot()
	if err := os.Setenv("VEYRON_ROOT", tmpDir); err != nil {
		t.Fatalf("%v", err)
	}
	veyronRoot = tmpDir
	defer os.Setenv("VEYRON_ROOT", oldRoot)

	// Create a buildcop.xml file.
	createBuildCopFile(tmpDir, t)

	ctx := util.DefaultContext()
	type testCase struct {
		targetTime       time.Time
		expectedBuildCop string
	}
	testCases := []testCase{
		testCase{
			targetTime:       time.Date(2013, time.November, 5, 12, 0, 0, 0, time.Local),
			expectedBuildCop: "",
		},
		testCase{
			targetTime:       time.Date(2014, time.November, 5, 12, 0, 0, 0, time.Local),
			expectedBuildCop: "spetrovic",
		},
		testCase{
			targetTime:       time.Date(2014, time.November, 5, 14, 0, 0, 0, time.Local),
			expectedBuildCop: "spetrovic",
		},
		testCase{
			targetTime:       time.Date(2014, time.November, 20, 14, 0, 0, 0, time.Local),
			expectedBuildCop: "jsimsa",
		},
	}
	for _, test := range testCases {
		got, err := buildCop(ctx, test.targetTime)
		if err != nil {
			t.Fatalf("want no errors, got: %v", err)
		}
		if test.expectedBuildCop != got {
			t.Fatalf("want %v, got %v", test.expectedBuildCop, got)
		}
	}
}
<commit_msg>TBR: test sending email on failed tests.<commit_after>package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"testing"
	"time"

	"tools/lib/util"
)

func TestParseLastCompletedBuildStatusJsonResponse(t *testing.T) {
	// "SUCCESS" status.
	input := `
	{
		"building": false,
		"fullDisplayName": "veyron-android-build #182",
		"result": "SUCCESS"
	}
	`
	expected := "SUCCESS"
	got, err := parseLastCompletedBuildStatusJsonResponse(strings.NewReader(input))
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if expected != got {
		t.Fatalf("want %v, got %v", expected, got)
	}

	// "FAILURE" status.
	input = `
	{
		"building": false,
		"fullDisplayName": "veyron-android-build #182",
		"result": "FAILURE"
	}
	`
	expected = "FAILURE"
	got, err = parseLastCompletedBuildStatusJsonResponse(strings.NewReader(input))
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if expected != got {
		t.Fatalf("want %v, got %v", expected, got)
	}
}

func TestParseJUnitReportFileWithoutFailedTests(t *testing.T) {
	// Report with no test failures.
	reportFileContent := `
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite name="ts1" tests="1" errors="0" failures="0" skip="0">
    <testcase classname="c1" name="n1" time="0">
    </testcase>
  </testsuite>
</testsuites>
	`
	seenTests := map[string]int{}
	expectedSeenTests := map[string]int{
		"c1::n1": 1,
	}
	expected := []string{}
	got, err := parseJUnitReportFileForFailedTestLinks(strings.NewReader(reportFileContent), seenTests)
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if !reflect.DeepEqual(expected, got) {
		t.Fatalf("want %v, got %v", expected, got)
	}
	if !reflect.DeepEqual(expectedSeenTests, seenTests) {
		t.Fatalf("want %v, got %v", expectedSeenTests, seenTests)
	}
}

func TestParseJUnitReportFileWithFailedTests(t *testing.T) {
	// Report with some test failures.
	// We have two test cases with the same classname+testname, and the second one is failed.
	reportFileContent := `
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite name="ts1" tests="1" errors="0" failures="1" skip="0">
    <testcase classname="package c1" name="n1" time="0">
		  <failure message="error">
# tools/presubmit
tools/go/src/tools/presubmit/main.go:106: undefined: test
		  </failure>
    </testcase>
  </testsuite>
  <testsuite name="ts2" tests="1" errors="0" failures="0" skip="0">
    <testcase classname="v.c2" name="n2" time="0">
    </testcase>
  </testsuite>
  <testsuite name="ts2" tests="1" errors="0" failures="1" skip="0">
    <testcase classname="v.c2" name="n2" time="0">
		  <failure message="error">
# some other errors.
		  </failure>
    </testcase>
  </testsuite>
</testsuites>
	`
	jenkinsBuildNumberFlag = 10
	seenTests := map[string]int{}
	expectedSeenTests := map[string]int{
		"package c1::n1": 1,
		"v::c2::n2":      2,
	}
	expected := []string{
		"- package c1::n1\nhttp://goto.google.com/vpst/10/testReport/%28root%29/package%20c1/n1",
		"- v::c2::n2\nhttp://goto.google.com/vpst/10/testReport/v/c2/n2_2",
	}
	got, err := parseJUnitReportFileForFailedTestLinks(strings.NewReader(reportFileContent), seenTests)
	if err != nil {
		t.Fatalf("want no errors, got: %v", err)
	}
	if !reflect.DeepEqual(expected, got) {
		t.Fatalf("want %v, got %v", expected, got)
	}
	if !reflect.DeepEqual(expectedSeenTests, seenTests) {
		t.Fatalf("want %v, got %v", expectedSeenTests, seenTests)
	}
}

func TestSafePackageOrClassName(t *testing.T) {
	name := "name"
	expected := "name"
	if got := safePackageOrClassName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}

	name = "name\\0/a:b?c#d%e-f_g e"
	expected = "name_0_a_b_c_d_e-f_g e"
	if got := safePackageOrClassName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}
}

func TestSafeTestName(t *testing.T) {
	name := "name"
	expected := "name"
	if got := safeTestName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}

	name = "name-a b$c_d"
	expected = "name_a_b$c_d"
	if got := safeTestName(name); expected != got {
		t.Fatalf("want %q, got %q", expected, got)
	}
}

func createBuildCopFile(veyronRoot string, t *testing.T) {
	content := `<?xml version="1.0" ?>
<!--
  This file is auto generated by the following command:
  /google/data/ro/users/ji/jingjin/gen_rotation_file.par

  Please don't edit manually.
-->
<shifts>
  <shift>
    <primary>spetrovic</primary>
    <secondary>suharshs</secondary>
    <startDate>Nov 5, 2014 12:00:00 PM</startDate>
  </shift>
  <shift>
    <primary>suharshs</primary>
    <secondary>tilaks</secondary>
    <startDate>Nov 12, 2014 12:00:00 PM</startDate>
  </shift>
  <shift>
    <primary>jsimsa</primary>
    <secondary>toddw</secondary>
    <startDate>Nov 19, 2014 12:00:00 PM</startDate>
  </shift>
</shifts>`
	buildCopRotationsFile := filepath.Join(veyronRoot, "tools", "conf", "buildcop.xml")
	dir := filepath.Dir(buildCopRotationsFile)
	dirMode := os.FileMode(0700)
	if err := os.MkdirAll(dir, dirMode); err != nil {
		t.Fatalf("MkdirAll(%q, %v) failed: %v", dir, dirMode, err)
	}
	fileMode := os.FileMode(0644)
	if err := ioutil.WriteFile(buildCopRotationsFile, []byte(content), fileMode); err != nil {
		t.Fatalf("WriteFile(%q, %q, %v) failed: %v", buildCopRotationsFile, content, fileMode, err)
	}
}

func TestBuildCop(t *testing.T) {
	// Setup a fake VEYRON_ROOT.
	dir, prefix := "", ""
	tmpDir, err := ioutil.TempDir(dir, prefix)
	if err != nil {
		t.Fatalf("TempDir(%v, %v) failed: %v", dir, prefix, err)
	}
	defer os.RemoveAll(tmpDir)
	oldRoot, err := util.VeyronRoot()
	if err := os.Setenv("VEYRON_ROOT", tmpDir); err != nil {
		t.Fatalf("%v", err)
	}
	veyronRoot = tmpDir
	defer os.Setenv("VEYRON_ROOT", oldRoot)

	// Create a buildcop.xml file.
	createBuildCopFile(tmpDir, t)

	ctx := util.DefaultContext()
	type testCase struct {
		targetTime       time.Time
		expectedBuildCop string
	}
	testCases := []testCase{
		testCase{
			targetTime:       time.Date(2013, time.November, 5, 12, 0, 0, 0, time.Local),
			expectedBuildCop: "",
		},
		testCase{
			targetTime:       time.Date(2014, time.November, 5, 12, 0, 0, 0, time.Local),
			expectedBuildCop: "spetrovic",
		},
		testCase{
			targetTime:       time.Date(2014, time.November, 5, 14, 0, 0, 0, time.Local),
			expectedBuildCop: "spetrovic",
		},
		testCase{
			targetTime:       time.Date(2014, time.November, 20, 14, 0, 0, 0, time.Local),
			expectedBuildCop: "jsimsaa",
		},
	}
	for _, test := range testCases {
		got, err := buildCop(ctx, test.targetTime)
		if err != nil {
			t.Fatalf("want no errors, got: %v", err)
		}
		if test.expectedBuildCop != got {
			t.Fatalf("want %v, got %v", test.expectedBuildCop, got)
		}
	}
}
<|endoftext|>