<commit_before>package q

import "github.com/leeola/kala/q/operators"

type Constraint struct {
	// Operator
	Operator    string
	Field       string
	Value       interface{}
	Constraints []Constraint
}

// Query is a generic method to construct a query in the index implementation.
//
// Eg, if mysql is the index, a Query would be constructed into a SQL string.
// Furthermore, the generic constraints allow for any type of keywords/etc
// to be used by the underlying indexer implementation. FullTextSearch for
// example is a more niche feature, and not supported by many indexers.
type Query struct {
	SortBy         string
	SortDescending bool
	SkipBy         int
	LimitBy        int
	Constraint     Constraint
}

func New() *Query {
	return &Query{}
}

func (q *Query) Limit(l int) *Query {
	q.LimitBy = l
	return q
}

func (q *Query) Skip(s int) *Query {
	q.SkipBy = s
	return q
}

func (q *Query) Sort(field string, descending bool) *Query {
	q.SortBy = field
	q.SortDescending = descending
	return q
}

func (q *Query) And(c ...Constraint) *Query {
	q.Const(And(c...))
	return q
}

func (q *Query) Const(c Constraint) *Query {
	q.Constraint = c
	return q
}

func (q *Query) Or(c ...Constraint) *Query {
	q.Const(Or(c...))
	return q
}

func And(c ...Constraint) Constraint {
	return Constraint{
		Operator:    operators.Equal,
		Constraints: c,
	}
}

func Eq(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.Equal,
		Field:    field,
		Value:    value,
	}
}

func Gt(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThan,
		Field:    field,
		Value:    value,
	}
}

func Gte(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThanOrEqual,
		Field:    field,
		Value:    value,
	}
}

func In(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.In,
		Field:    field,
		Value:    value,
	}
}

func Lt(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThan,
		Field:    field,
		Value:    value,
	}
}

func Lte(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThan,
		Field:    field,
		Value:    value,
	}
}

func Not(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.Not,
		Field:    field,
		Value:    value,
	}
}

func Or(c ...Constraint) Constraint {
	return Constraint{
		Operator:    operators.Or,
		Constraints: c,
	}
}

func Re(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.Regex,
		Field:    field,
		Value:    value,
	}
}
<commit_msg>fix: Not function operator now functions like And/Or operators.<commit_after>package q

import "github.com/leeola/kala/q/operators"

type Constraint struct {
	// Operator
	Operator    string
	Field       string
	Value       interface{}
	Constraints []Constraint
}

// Query is a generic method to construct a query in the index implementation.
//
// Eg, if mysql is the index, a Query would be constructed into a SQL string.
// Furthermore, the generic constraints allow for any type of keywords/etc
// to be used by the underlying indexer implementation. FullTextSearch for
// example is a more niche feature, and not supported by many indexers.
type Query struct {
	SortBy         string
	SortDescending bool
	SkipBy         int
	LimitBy        int
	Constraint     Constraint
}

func New() *Query {
	return &Query{}
}

func (q *Query) Limit(l int) *Query {
	q.LimitBy = l
	return q
}

func (q *Query) Skip(s int) *Query {
	q.SkipBy = s
	return q
}

func (q *Query) Sort(field string, descending bool) *Query {
	q.SortBy = field
	q.SortDescending = descending
	return q
}

func (q *Query) And(c ...Constraint) *Query {
	q.Const(And(c...))
	return q
}

func (q *Query) Const(c Constraint) *Query {
	q.Constraint = c
	return q
}

func (q *Query) Or(c ...Constraint) *Query {
	q.Const(Or(c...))
	return q
}

func And(c ...Constraint) Constraint {
	return Constraint{
		Operator:    operators.Equal,
		Constraints: c,
	}
}

func Eq(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.Equal,
		Field:    field,
		Value:    value,
	}
}

func Gt(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThan,
		Field:    field,
		Value:    value,
	}
}

func Gte(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThanOrEqual,
		Field:    field,
		Value:    value,
	}
}

func In(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.In,
		Field:    field,
		Value:    value,
	}
}

func Lt(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThan,
		Field:    field,
		Value:    value,
	}
}

func Lte(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.GreaterThan,
		Field:    field,
		Value:    value,
	}
}

func Not(c ...Constraint) Constraint {
	return Constraint{
		Operator:    operators.Not,
		Constraints: c,
	}
}

func Or(c ...Constraint) Constraint {
	return Constraint{
		Operator: operators.Or,
	}
}

func Re(field string, value interface{}) Constraint {
	return Constraint{
		Operator: operators.Regex,
		Field:    field,
		Value:    value,
	}
}
<|endoftext|>


<commit_before>package ltxref

import (
	"sort"
	"strings"

	"github.com/renstrom/fuzzysearch/fuzzy"
)

func (l *Ltxref) AddCommand(commandname string, pkg string) (*Command, error) {
	cmd := NewCommand()
	cmd.Name = commandname
	if pkg == "" {
		l.Commands = append(l.Commands, cmd)
		sort.Sort(l.Commands)
	} else {
		p := l.GetPackageWithName(pkg)
		p.Commands = append(p.Commands, cmd)
		sort.Sort(p.Commands)
	}
	return cmd, nil
}

func (l *Ltxref) AddDocumentClass(dcname string) (*DocumentClass, error) {
	dc := NewDocumentClass()
	dc.Name = dcname
	l.DocumentClasses = append(l.DocumentClasses, dc)
	sort.Sort(l.DocumentClasses)
	return dc, nil
}

func (l *Ltxref) AddEnvironment(envname string) (*Environment, error) {
	env := NewEnvironment()
	env.Name = envname
	l.Environments = append(l.Environments, env)
	sort.Sort(l.Environments)
	return env, nil
}

func (l *Ltxref) AddPackage(pkgname string) (*Package, error) {
	pkg := NewPackage()
	pkg.Name = pkgname
	l.Packages = append(l.Packages, pkg)
	sort.Sort(l.Packages)
	return pkg, nil
}

// packagename may be empty for the kernel commands
func (l *Ltxref) GetCommandFromPackage(commandname string, packagename string) *Command {
	var cmdlist []*Command
	// Needs better implementation!
	if packagename != "" {
		for _, v := range l.Packages {
			if v.Name == packagename {
				cmdlist = v.Commands
				break
			}
		}
	} else {
		cmdlist = l.Commands
	}

	for _, v := range cmdlist {
		if v.Name == commandname {
			return v
		}
	}
	return nil
}

func (l *Ltxref) GetDocumentClass(name string) *DocumentClass {
	for _, class := range l.DocumentClasses {
		if class.Name == name {
			return class
		}
	}
	return nil
}

func (l *Ltxref) GetEnvironmentWithName(name string) *Environment {
	for _, env := range l.Environments {
		if env.Name == name {
			return env
		}
	}
	return nil
}

func (l *Ltxref) GetPackageWithName(name string) *Package {
	for _, pkg := range l.Packages {
		if pkg.Name == name {
			return pkg
		}
	}
	return nil
}

// Returns all tags in alphabetical order.
func (l *Ltxref) Tags() []string {
	// Needs better implementation!
	tags := make(map[string]bool)
	for _, command := range l.Commands {
		for _, label := range command.Label {
			tags[label] = true
		}
	}
	for _, v := range l.Environments {
		for _, label := range v.Label {
			tags[label] = true
		}
	}

	for _, v := range l.Packages {
		for _, label := range v.Label {
			tags[label] = true
		}
		for _, cmd := range v.Commands {
			for _, label := range cmd.Label {
				tags[label] = true
			}

		}
	}
	for _, v := range l.DocumentClasses {
		for _, label := range v.Label {
			tags[label] = true
		}
	}

	mk := make([]string, len(tags))
	i := 0
	for k, _ := range tags {
		mk[i] = k
		i++
	}
	sort.Strings(mk)
	return mk
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterCommands(like string, tag string) Commands {
	var commandsThatMatch Commands
	like = strings.ToLower(like)
	tag = strings.ToLower(tag)

	for _, command := range l.Commands {
		if (like == "" || fuzzy.Match(like, command.Name)) && (tag == "" || hasTag(command.Label, tag)) {
			commandsThatMatch = append(commandsThatMatch, command)
		}
	}
	return commandsThatMatch
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterEnvironments(like string, tag string) Environments {
	if like == "" && tag == "" {
		return l.Environments
	} else {
		like = strings.ToLower(like)
		tag = strings.ToLower(tag)
	}
	var itemsThatMatch Environments
	for _, item := range l.Environments {
		if fuzzy.Match(like, item.Name) && (tag == "" || hasTag(item.Label, tag)) {
			itemsThatMatch = append(itemsThatMatch, item)
		}
	}
	return itemsThatMatch
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterDocumentClasses(like string, tag string) DocumentClasses {
	if like == "" && tag == "" {
		return l.DocumentClasses
	} else {
		like = strings.ToLower(like)
		tag = strings.ToLower(tag)
	}
	var itemsThatMatch DocumentClasses
	for _, item := range l.DocumentClasses {
		if fuzzy.Match(like, item.Name) && (tag == "" || hasTag(item.Label, tag)) {
			itemsThatMatch = append(itemsThatMatch, item)
		}
	}
	return itemsThatMatch
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterPackages(like string, tag string) []*Package {
	if like == "" && tag == "" {
		return l.Packages
	} else {
		like = strings.ToLower(like)
		tag = strings.ToLower(tag)
	}
	var itemsThatMatch []*Package
	for _, item := range l.Packages {
		if fuzzy.Match(like, item.Name) && (tag == "" || hasTag(item.Label, tag)) {
			itemsThatMatch = append(itemsThatMatch, item)
		}
	}
	return itemsThatMatch
}

// Return true if command c has the given label (tag)
func hasTag(labels []string, label string) bool {
	for _, v := range labels {
		if v == label {
			return true
		}
	}
	return false
}
<commit_msg>Filter expert commands<commit_after>package ltxref

import (
	"sort"
	"strings"

	"github.com/renstrom/fuzzysearch/fuzzy"
)

func (l *Ltxref) AddCommand(commandname string, pkg string) (*Command, error) {
	cmd := NewCommand()
	cmd.Name = commandname
	if pkg == "" {
		l.Commands = append(l.Commands, cmd)
		sort.Sort(l.Commands)
	} else {
		p := l.GetPackageWithName(pkg)
		p.Commands = append(p.Commands, cmd)
		sort.Sort(p.Commands)
	}
	return cmd, nil
}

func (l *Ltxref) AddDocumentClass(dcname string) (*DocumentClass, error) {
	dc := NewDocumentClass()
	dc.Name = dcname
	l.DocumentClasses = append(l.DocumentClasses, dc)
	sort.Sort(l.DocumentClasses)
	return dc, nil
}

func (l *Ltxref) AddEnvironment(envname string) (*Environment, error) {
	env := NewEnvironment()
	env.Name = envname
	l.Environments = append(l.Environments, env)
	sort.Sort(l.Environments)
	return env, nil
}

func (l *Ltxref) AddPackage(pkgname string) (*Package, error) {
	pkg := NewPackage()
	pkg.Name = pkgname
	l.Packages = append(l.Packages, pkg)
	sort.Sort(l.Packages)
	return pkg, nil
}

// packagename may be empty for the kernel commands
func (l *Ltxref) GetCommandFromPackage(commandname string, packagename string) *Command {
	var cmdlist []*Command
	// Needs better implementation!
	if packagename != "" {
		for _, v := range l.Packages {
			if v.Name == packagename {
				cmdlist = v.Commands
				break
			}
		}
	} else {
		cmdlist = l.Commands
	}

	for _, v := range cmdlist {
		if v.Name == commandname {
			return v
		}
	}
	return nil
}

func (l *Ltxref) GetDocumentClass(name string) *DocumentClass {
	for _, class := range l.DocumentClasses {
		if class.Name == name {
			return class
		}
	}
	return nil
}

func (l *Ltxref) GetEnvironmentWithName(name string) *Environment {
	for _, env := range l.Environments {
		if env.Name == name {
			return env
		}
	}
	return nil
}

func (l *Ltxref) GetPackageWithName(name string) *Package {
	for _, pkg := range l.Packages {
		if pkg.Name == name {
			return pkg
		}
	}
	return nil
}

// Returns all tags in alphabetical order.
func (l *Ltxref) Tags() []string {
	// Needs better implementation!
	tags := make(map[string]bool)
	for _, command := range l.Commands {
		for _, label := range command.Label {
			tags[label] = true
		}
	}
	for _, v := range l.Environments {
		for _, label := range v.Label {
			tags[label] = true
		}
	}

	for _, v := range l.Packages {
		for _, label := range v.Label {
			tags[label] = true
		}
		for _, cmd := range v.Commands {
			for _, label := range cmd.Label {
				tags[label] = true
			}

		}
	}
	for _, v := range l.DocumentClasses {
		for _, label := range v.Label {
			tags[label] = true
		}
	}

	mk := make([]string, len(tags))
	i := 0
	for k, _ := range tags {
		mk[i] = k
		i++
	}
	sort.Strings(mk)
	return mk
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterCommands(like string, tag string, showexpert bool) Commands {
	var commandsThatMatch Commands
	like = strings.ToLower(like)
	tag = strings.ToLower(tag)

	for _, command := range l.Commands {
		if (like == "" || fuzzy.Match(like, command.Name)) && (tag == "" || hasTag(command.Label, tag)) {
			if !showexpert && command.Level != "expert" || showexpert {
				commandsThatMatch = append(commandsThatMatch, command)
			}

		}
	}
	return commandsThatMatch
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterEnvironments(like string, tag string, showexpert bool) Environments {
	if like == "" && tag == "" && showexpert {
		return l.Environments
	} else {
		like = strings.ToLower(like)
		tag = strings.ToLower(tag)
	}
	var itemsThatMatch Environments
	for _, item := range l.Environments {
		if fuzzy.Match(like, item.Name) && (tag == "" || hasTag(item.Label, tag)) {
			if !showexpert && item.Level != "expert" || showexpert {
				itemsThatMatch = append(itemsThatMatch, item)
			}
		}
	}
	return itemsThatMatch
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterDocumentClasses(like string, tag string, showexpert bool) DocumentClasses {
	if like == "" && tag == "" && showexpert {
		return l.DocumentClasses
	} else {
		like = strings.ToLower(like)
		tag = strings.ToLower(tag)
	}
	var itemsThatMatch DocumentClasses
	for _, item := range l.DocumentClasses {
		if fuzzy.Match(like, item.Name) && (tag == "" || hasTag(item.Label, tag)) {
			if !showexpert && item.Level != "expert" || showexpert {
				itemsThatMatch = append(itemsThatMatch, item)
			}
		}
	}
	return itemsThatMatch
}

// Case insensitive fuzzy match.
func (l *Ltxref) FilterPackages(like string, tag string) []*Package {
	if like == "" && tag == "" {
		return l.Packages
	} else {
		like = strings.ToLower(like)
		tag = strings.ToLower(tag)
	}
	var itemsThatMatch []*Package
	for _, item := range l.Packages {
		if fuzzy.Match(like, item.Name) && (tag == "" || hasTag(item.Label, tag)) {
			itemsThatMatch = append(itemsThatMatch, item)
		} else {
			for _, command := range item.Commands {
				if (like == "" || fuzzy.Match(like, command.Name)) && (tag == "" || hasTag(command.Label, tag)) {
					itemsThatMatch = append(itemsThatMatch, item)
					break
				}
			}

		}
	}
	return itemsThatMatch
}

// Return true if command c has the given label (tag)
func hasTag(labels []string, label string) bool {
	for _, v := range labels {
		if v == label {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"testing"

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

// These tests ensure that the code generator generates valid code that can be built
// in combination with Thrift's autogenerated code.

func TestAllThrift(t *testing.T) {
	files, err := ioutil.ReadDir("test_files")
	require.NoError(t, err, "Cannot read test_files directory: %v", err)

	for _, f := range files {
		fname := f.Name()
		if f.IsDir() || filepath.Ext(fname) != ".thrift" {
			continue
		}

		if err := runBuildTest(t, filepath.Join("test_files", fname)); err != nil {
			t.Errorf("Thrift file %v failed: %v", fname, err)
		}
	}
}

func TestIncludeThrift(t *testing.T) {
	dirs, err := ioutil.ReadDir("test_files/include_test")
	require.NoError(t, err, "Cannot read test_files/include_test directory: %v", err)

	for _, d := range dirs {
		dname := d.Name()
		if !d.IsDir() {
			continue
		}

		thriftFile := filepath.Join(dname, path.Base(dname)+".thrift")
		if err := runBuildTest(t, filepath.Join("test_files/include_test/", thriftFile)); err != nil {
			t.Errorf("Thrift test %v failed: %v", dname, err)
		}
	}
}

func TestMultipleFiles(t *testing.T) {
	if err := runBuildTest(t, filepath.Join("test_files", "multi_test", "file1.thrift")); err != nil {
		t.Errorf("Multiple file test failed: %v", err)
	}
}

func TestExternalTemplate(t *testing.T) {
	template1 := `package {{ .Package }}

{{ range .AST.Services }}
// Service {{ .Name }} has {{ len .Methods }} methods.
{{ range .Methods }}
// func {{ .Name | goPublicName }} ({{ range .Arguments }}{{ .Type | goType }}, {{ end }}) ({{ if .ReturnType }}{{ .ReturnType | goType }}{{ end }}){{ end }}
{{ end }}
	`
	templateFile := writeTempFile(t, template1)
	defer os.Remove(templateFile)

	expected := `package service_extend

// Service S1 has 1 methods.

// func M1 ([]byte, ) ([]byte)

// Service S2 has 1 methods.

// func M2 (*S, int32, ) (*S)

// Service S3 has 1 methods.

// func M3 () ()
`

	opts := processOptions{
		InputFile:     "test_files/service_extend.thrift",
		TemplateFiles: []string{templateFile},
	}
	checks := func(dir string) error {
		dir = filepath.Join(dir, "service_extend")
		if err := checkDirectoryFiles(dir, 6); err != nil {
			return err
		}

		// Verify the contents of the extra file.
		outFile := filepath.Join(dir, packageName(templateFile)+"-service_extend.go")
		return verifyFileContents(outFile, expected)
	}
	if err := runTest(t, opts, checks); err != nil {
		t.Errorf("Failed to run test: %v", err)
	}
}

func writeTempFile(t *testing.T, contents string) string {
	tempFile, err := ioutil.TempFile("", "temp")
	require.NoError(t, err, "Failed to create temp file")
	tempFile.Close()
	require.NoError(t, ioutil.WriteFile(tempFile.Name(), []byte(contents), 0666),
		"Write temp file failed")
	return tempFile.Name()
}

func verifyFileContents(filename, expected string) error {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	bytesStr := string(bytes)
	if bytesStr != expected {
		return fmt.Errorf("file contents mismatch. got:\n%vexpected:\n%v", bytesStr, expected)
	}

	return nil
}

func copyFile(src, dst string) error {
	f, err := os.Open(src)
	if err != nil {
		return err
	}
	defer f.Close()

	writeF, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		return err
	}
	defer writeF.Close()

	_, err = io.Copy(writeF, f)
	return err
}

// setupDirectory creates a temporary directory.
func setupDirectory(thriftFile string) (string, error) {
	tempDir, err := ioutil.TempDir("", "thrift-gen")
	if err != nil {
		return "", err
	}

	return tempDir, nil
}

func createAdditionalTestFile(thriftFile, tempDir string) error {
	f, err := os.Open(thriftFile)
	if err != nil {
		return err
	}

	var writer io.Writer
	rdr := bufio.NewReader(f)
	for {
		line, err := rdr.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				return nil
			}
		}

		if strings.HasPrefix(line, "//Go code:") {
			fileName := strings.TrimSpace(strings.TrimPrefix(line, "//Go code:"))
			outFile := filepath.Join(tempDir, fileName)
			f, err := os.OpenFile(outFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
			if err != nil {
				return err
			}
			defer f.Close()
			writer = f
		} else if writer != nil {
			if strings.HasPrefix(line, "//") {
				writer.Write([]byte(strings.TrimPrefix(line, "//")))
			} else {
				return nil
			}
		}
	}
}

func checkDirectoryFiles(dir string, n int) error {
	dirContents, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}

	if len(dirContents) < n {
		return fmt.Errorf("expected to generate at least %v files, but found: %v", n, len(dirContents))
	}

	return nil
}

func runBuildTest(t *testing.T, thriftFile string) error {
	extraChecks := func(dir string) error {
		return checkDirectoryFiles(filepath.Join(dir, packageName(thriftFile)), 4)
	}

	opts := processOptions{InputFile: thriftFile}
	return runTest(t, opts, extraChecks)
}

func runTest(t *testing.T, opts processOptions, extraChecks func(string) error) error {
	tempDir, err := ioutil.TempDir("", "thrift-gen")
	if err != nil {
		return err
	}

	// Generate code from the Thrift file.
	*packagePrefix = "../"
	opts.GenerateThrift = true
	opts.OutputDir = tempDir
	if err := processFile(opts); err != nil {
		return fmt.Errorf("processFile(%s) in %q failed: %v", opts.InputFile, tempDir, err)
	}

	// Create any extra Go files as specified in the Thrift file.
	if err := createAdditionalTestFile(opts.InputFile, tempDir); err != nil {
		return fmt.Errorf("failed creating additional test files for %s in %q: %v", opts.InputFile, tempDir, err)
	}

	// Run go build to ensure that the generated code builds.
	cmd := exec.Command("go", "build", "./...")
	cmd.Dir = tempDir
	// NOTE: we check output, since go build ./... returns 0 status code on failure:
	// https://github.com/golang/go/issues/11407
	if output, err := cmd.CombinedOutput(); err != nil || len(output) > 0 {
		return fmt.Errorf("Build in %q failed.\nError: %v Output:\n%v\n", tempDir, err, string(output))
	}

	// Run any extra checks the user may want.
	if err := extraChecks(tempDir); err != nil {
		return err
	}

	// Only delete the temp directory on success.
	os.RemoveAll(tempDir)
	return nil
}
<commit_msg>Fix lint failure in compile_test (#536)<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"testing"

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

// These tests ensure that the code generator generates valid code that can be built
// in combination with Thrift's autogenerated code.

func TestAllThrift(t *testing.T) {
	files, err := ioutil.ReadDir("test_files")
	require.NoError(t, err, "Cannot read test_files directory: %v", err)

	for _, f := range files {
		fname := f.Name()
		if f.IsDir() || filepath.Ext(fname) != ".thrift" {
			continue
		}

		if err := runBuildTest(t, filepath.Join("test_files", fname)); err != nil {
			t.Errorf("Thrift file %v failed: %v", fname, err)
		}
	}
}

func TestIncludeThrift(t *testing.T) {
	dirs, err := ioutil.ReadDir("test_files/include_test")
	require.NoError(t, err, "Cannot read test_files/include_test directory: %v", err)

	for _, d := range dirs {
		dname := d.Name()
		if !d.IsDir() {
			continue
		}

		thriftFile := filepath.Join(dname, path.Base(dname)+".thrift")
		if err := runBuildTest(t, filepath.Join("test_files/include_test/", thriftFile)); err != nil {
			t.Errorf("Thrift test %v failed: %v", dname, err)
		}
	}
}

func TestMultipleFiles(t *testing.T) {
	if err := runBuildTest(t, filepath.Join("test_files", "multi_test", "file1.thrift")); err != nil {
		t.Errorf("Multiple file test failed: %v", err)
	}
}

func TestExternalTemplate(t *testing.T) {
	template1 := `package {{ .Package }}

{{ range .AST.Services }}
// Service {{ .Name }} has {{ len .Methods }} methods.
{{ range .Methods }}
// func {{ .Name | goPublicName }} ({{ range .Arguments }}{{ .Type | goType }}, {{ end }}) ({{ if .ReturnType }}{{ .ReturnType | goType }}{{ end }}){{ end }}
{{ end }}
	`
	templateFile := writeTempFile(t, template1)
	defer os.Remove(templateFile)

	expected := `package service_extend

// Service S1 has 1 methods.

// func M1 ([]byte, ) ([]byte)

// Service S2 has 1 methods.

// func M2 (*S, int32, ) (*S)

// Service S3 has 1 methods.

// func M3 () ()
`

	opts := processOptions{
		InputFile:     "test_files/service_extend.thrift",
		TemplateFiles: []string{templateFile},
	}
	checks := func(dir string) error {
		dir = filepath.Join(dir, "service_extend")
		if err := checkDirectoryFiles(dir, 6); err != nil {
			return err
		}

		// Verify the contents of the extra file.
		outFile := filepath.Join(dir, packageName(templateFile)+"-service_extend.go")
		return verifyFileContents(outFile, expected)
	}
	if err := runTest(t, opts, checks); err != nil {
		t.Errorf("Failed to run test: %v", err)
	}
}

func writeTempFile(t *testing.T, contents string) string {
	tempFile, err := ioutil.TempFile("", "temp")
	require.NoError(t, err, "Failed to create temp file")
	tempFile.Close()
	require.NoError(t, ioutil.WriteFile(tempFile.Name(), []byte(contents), 0666),
		"Write temp file failed")
	return tempFile.Name()
}

func verifyFileContents(filename, expected string) error {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	bytesStr := string(bytes)
	if bytesStr != expected {
		return fmt.Errorf("file contents mismatch. got:\n%vexpected:\n%v", bytesStr, expected)
	}

	return nil
}

func copyFile(src, dst string) error {
	f, err := os.Open(src)
	if err != nil {
		return err
	}
	defer f.Close()

	writeF, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		return err
	}
	defer writeF.Close()

	_, err = io.Copy(writeF, f)
	return err
}

// setupDirectory creates a temporary directory.
func setupDirectory(thriftFile string) (string, error) {
	tempDir, err := ioutil.TempDir("", "thrift-gen")
	if err != nil {
		return "", err
	}

	return tempDir, nil
}

func createAdditionalTestFile(thriftFile, tempDir string) error {
	f, err := os.Open(thriftFile)
	if err != nil {
		return err
	}

	var writer io.Writer
	rdr := bufio.NewReader(f)
	for {
		line, err := rdr.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				return nil
			}
		}

		if strings.HasPrefix(line, "//Go code:") {
			fileName := strings.TrimSpace(strings.TrimPrefix(line, "//Go code:"))
			outFile := filepath.Join(tempDir, fileName)
			f, err := os.OpenFile(outFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
			if err != nil {
				return err
			}
			defer f.Close()
			writer = f
		} else if writer != nil {
			if strings.HasPrefix(line, "//") {
				writer.Write([]byte(strings.TrimPrefix(line, "//")))
			} else {
				return nil
			}
		}
	}
}

func checkDirectoryFiles(dir string, n int) error {
	dirContents, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}

	if len(dirContents) < n {
		return fmt.Errorf("expected to generate at least %v files, but found: %v", n, len(dirContents))
	}

	return nil
}

func runBuildTest(t *testing.T, thriftFile string) error {
	extraChecks := func(dir string) error {
		return checkDirectoryFiles(filepath.Join(dir, packageName(thriftFile)), 4)
	}

	opts := processOptions{InputFile: thriftFile}
	return runTest(t, opts, extraChecks)
}

func runTest(t *testing.T, opts processOptions, extraChecks func(string) error) error {
	tempDir, err := ioutil.TempDir("", "thrift-gen")
	if err != nil {
		return err
	}

	// Generate code from the Thrift file.
	*packagePrefix = "../"
	opts.GenerateThrift = true
	opts.OutputDir = tempDir
	if err := processFile(opts); err != nil {
		return fmt.Errorf("processFile(%s) in %q failed: %v", opts.InputFile, tempDir, err)
	}

	// Create any extra Go files as specified in the Thrift file.
	if err := createAdditionalTestFile(opts.InputFile, tempDir); err != nil {
		return fmt.Errorf("failed creating additional test files for %s in %q: %v", opts.InputFile, tempDir, err)
	}

	// Run go build to ensure that the generated code builds.
	cmd := exec.Command("go", "build", "./...")
	cmd.Dir = tempDir
	// NOTE: we check output, since go build ./... returns 0 status code on failure:
	// https://github.com/golang/go/issues/11407
	if output, err := cmd.CombinedOutput(); err != nil || len(output) > 0 {
		return fmt.Errorf("build in %q failed.\nError: %v Output:\n%v", tempDir, err, string(output))
	}

	// Run any extra checks the user may want.
	if err := extraChecks(tempDir); err != nil {
		return err
	}

	// Only delete the temp directory on success.
	os.RemoveAll(tempDir)
	return nil
}
<|endoftext|>


<commit_before>package project

import (
	"fmt"
	"strings"

	"github.com/pkg/errors"

	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
)

// Default is the string used for a default project.
const Default = "default"

// separator is used to delimit the project name from the suffix.
const separator = "_"

// Instance adds the "<project>_" prefix to instance name when the given project name is not "default".
func Instance(projectName string, instanceName string) string {
	if projectName != Default {
		return fmt.Sprintf("%s%s%s", projectName, separator, instanceName)
	}

	return instanceName
}

// DNS adds ".<project>" as a suffix to instance name when the given project name is not "default".
func DNS(projectName string, instanceName string) string {
	if projectName != Default {
		return fmt.Sprintf("%s.%s", instanceName, projectName)
	}

	return instanceName
}

// InstanceParts takes a project prefixed Instance name string and returns the project and instance name.
// If a non-project prefixed Instance name is supplied, then the project is returned as "default" and the instance
// name is returned unmodified in the 2nd return value. This is suitable for passing back into Prefix().
// Note: This should only be used with Instance names (because they cannot contain the project separator) and this
// function relies on this rule as project names can contain the project separator.
func InstanceParts(projectInstanceName string) (string, string) {
	i := strings.LastIndex(projectInstanceName, separator)
	if i < 0 {
		// This string is not project prefixed or is part of default project.
		return Default, projectInstanceName
	}

	// As project names can container separator, we effectively split once from the right hand side as
	// Instance names are not allowed to container the separator value.
	return projectInstanceName[0:i], projectInstanceName[i+1:]
}

// StorageVolume adds the "<project>_prefix" to the storage volume name. Even if the project name is "default".
func StorageVolume(projectName string, storageVolumeName string) string {
	return fmt.Sprintf("%s%s%s", projectName, separator, storageVolumeName)
}

// StorageVolumeParts takes a project prefixed storage volume name and returns the project and storage volume
// name as separate variables.
func StorageVolumeParts(projectStorageVolumeName string) (string, string) {
	parts := strings.SplitN(projectStorageVolumeName, "_", 2)
	return parts[0], parts[1]
}

// StorageVolumeProject returns the project name to use to for the volume based on the requested project.
// For custom volume type, if the project specified has the "features.storage.volumes" flag enabled then the
// project name is returned, otherwise the default project name is returned. For all other volume types the
// supplied project name is returned.
func StorageVolumeProject(c *db.Cluster, projectName string, volumeType int) (string, error) {
	// Non-custom volumes always use the project specified. Optimisation to avoid loading project record.
	if volumeType != db.StoragePoolVolumeTypeCustom {
		return projectName, nil
	}

	project, err := c.GetProject(projectName)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to load project %q", projectName)
	}

	return StorageVolumeProjectFromRecord(project, volumeType)
}

// StorageVolumeProjectFromRecord returns the project name to use to for the volume based on the requested project.
// For custom volume type, if the project specified has the "features.storage.volumes" flag enabled then the
// project name is returned, otherwise the default project name is returned. For all other volume types the
// supplied project's name is returned.
func StorageVolumeProjectFromRecord(p *api.Project, volumeType int) (string, error) {
	// Non-custom volumes always use the project specified.
	if volumeType != db.StoragePoolVolumeTypeCustom {
		return p.Name, nil
	}

	// Custom volumes only use the project specified if the project has the features.storage.volumes feature
	// enabled, otherwise the legacy behaviour of using the default project for custom volumes is used.
	if shared.IsTrue(p.Config["features.storage.volumes"]) {
		return p.Name, nil
	}

	return Default, nil
}

// NetworkProject returns the project name to use for the network based on the requested project.
// If the project specified has the "features.networks" flag enabled then the project name is returned,
// otherwise the default project name is returned. The second return value is the project's config if non-default
// project is being returned, nil if not.
func NetworkProject(c *db.Cluster, projectName string) (string, map[string]string, error) {
	project, err := c.GetProject(projectName)
	if err != nil {
		return "", nil, errors.Wrapf(err, "Failed to load project %q", projectName)
	}

	// Networks only use the project specified if the project has the features.networks feature enabled,
	// otherwise the legacy behaviour of using the default project for networks is used.
	if shared.IsTrue(project.Config["features.networks"]) {
		return projectName, project.Config, nil
	}

	return Default, nil, nil
}
<commit_msg>lxd/project/project: Updates StorageVolumeProjectFromRecord to not return error (as never populated)<commit_after>package project

import (
	"fmt"
	"strings"

	"github.com/pkg/errors"

	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
)

// Default is the string used for a default project.
const Default = "default"

// separator is used to delimit the project name from the suffix.
const separator = "_"

// Instance adds the "<project>_" prefix to instance name when the given project name is not "default".
func Instance(projectName string, instanceName string) string {
	if projectName != Default {
		return fmt.Sprintf("%s%s%s", projectName, separator, instanceName)
	}

	return instanceName
}

// DNS adds ".<project>" as a suffix to instance name when the given project name is not "default".
func DNS(projectName string, instanceName string) string {
	if projectName != Default {
		return fmt.Sprintf("%s.%s", instanceName, projectName)
	}

	return instanceName
}

// InstanceParts takes a project prefixed Instance name string and returns the project and instance name.
// If a non-project prefixed Instance name is supplied, then the project is returned as "default" and the instance
// name is returned unmodified in the 2nd return value. This is suitable for passing back into Prefix().
// Note: This should only be used with Instance names (because they cannot contain the project separator) and this
// function relies on this rule as project names can contain the project separator.
func InstanceParts(projectInstanceName string) (string, string) {
	i := strings.LastIndex(projectInstanceName, separator)
	if i < 0 {
		// This string is not project prefixed or is part of default project.
		return Default, projectInstanceName
	}

	// As project names can container separator, we effectively split once from the right hand side as
	// Instance names are not allowed to container the separator value.
	return projectInstanceName[0:i], projectInstanceName[i+1:]
}

// StorageVolume adds the "<project>_prefix" to the storage volume name. Even if the project name is "default".
func StorageVolume(projectName string, storageVolumeName string) string {
	return fmt.Sprintf("%s%s%s", projectName, separator, storageVolumeName)
}

// StorageVolumeParts takes a project prefixed storage volume name and returns the project and storage volume
// name as separate variables.
func StorageVolumeParts(projectStorageVolumeName string) (string, string) {
	parts := strings.SplitN(projectStorageVolumeName, "_", 2)
	return parts[0], parts[1]
}

// StorageVolumeProject returns the project name to use to for the volume based on the requested project.
// For custom volume type, if the project specified has the "features.storage.volumes" flag enabled then the
// project name is returned, otherwise the default project name is returned. For all other volume types the
// supplied project name is returned.
func StorageVolumeProject(c *db.Cluster, projectName string, volumeType int) (string, error) {
	// Non-custom volumes always use the project specified. Optimisation to avoid loading project record.
	if volumeType != db.StoragePoolVolumeTypeCustom {
		return projectName, nil
	}

	project, err := c.GetProject(projectName)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to load project %q", projectName)
	}

	return StorageVolumeProjectFromRecord(project, volumeType), nil
}

// StorageVolumeProjectFromRecord returns the project name to use to for the volume based on the supplied project.
// For custom volume type, if the project supplied has the "features.storage.volumes" flag enabled then the
// project name is returned, otherwise the default project name is returned. For all other volume types the
// supplied project's name is returned.
func StorageVolumeProjectFromRecord(p *api.Project, volumeType int) string {
	// Non-custom volumes always use the project specified.
	if volumeType != db.StoragePoolVolumeTypeCustom {
		return p.Name
	}

	// Custom volumes only use the project specified if the project has the features.storage.volumes feature
	// enabled, otherwise the legacy behaviour of using the default project for custom volumes is used.
	if shared.IsTrue(p.Config["features.storage.volumes"]) {
		return p.Name
	}

	return Default
}

// NetworkProject returns the project name to use for the network based on the requested project.
// If the project specified has the "features.networks" flag enabled then the project name is returned,
// otherwise the default project name is returned. The second return value is the project's config if non-default
// project is being returned, nil if not.
func NetworkProject(c *db.Cluster, projectName string) (string, map[string]string, error) {
	project, err := c.GetProject(projectName)
	if err != nil {
		return "", nil, errors.Wrapf(err, "Failed to load project %q", projectName)
	}

	// Networks only use the project specified if the project has the features.networks feature enabled,
	// otherwise the legacy behaviour of using the default project for networks is used.
	if shared.IsTrue(project.Config["features.networks"]) {
		return projectName, project.Config, nil
	}

	return Default, nil, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 The Upspin 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 gcs

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"testing"
	"time"

	"upspin.io/cloud/storage"
	"upspin.io/log"
)

const testBucketName = "upspin-test-scratch"

var (
	client      storage.Storage
	testDataStr = fmt.Sprintf("This is test at %v", time.Now())
	testData    = []byte(testDataStr)
	fileName    = fmt.Sprintf("test-file-%d", time.Now().Second())
)

// This is more of a regression test as it uses the running cloud
// storage in prod. However, since GCP is always available, we accept
// to rely on it.
func TestPutGetAndDownload(t *testing.T) {
	link, err := client.Put(fileName, testData)
	if err != nil {
		t.Fatalf("Can't put: %v", err)
	}
	if !strings.HasPrefix(link, "https://") {
		t.Errorf("Link is not HTTPS")
	}
	retLink, err := client.Get(fileName)
	if err != nil {
		t.Fatalf("Can't get: %v", err)
	}
	if retLink != link {
		t.Errorf("Not the same link as stored: %v vs received: %v", link, retLink)
	}
	resp, err := http.Get(retLink)
	if err != nil {
		t.Errorf("Couldn't get link: %v", err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatalf("Can't read HTTP body: %v", err)
	}
	if string(data) != testDataStr {
		t.Errorf("Expected %q got %q", testDataStr, string(data))
	}
	// Check that Download yields the same data
	bytes, err := client.Download(fileName)
	if err != nil {
		t.Fatal(err)
	}
	if string(bytes) != testDataStr {
		t.Errorf("Expected %q got %q", testDataStr, string(bytes))
	}
}

func Put(t *testing.T, path string) {
	_, err := client.Put(path, testData)
	if err != nil {
		t.Fatal(err)
	}
}

func setupDirectoryTree(t *testing.T) {
	Put(t, "a")
	Put(t, "a/b")
	Put(t, "a/b/c")
	Put(t, "a/b/c/d1")
	Put(t, "a/b/c/d2")
	Put(t, "a/b/c/d1/e11")
	Put(t, "a/b/c/d1/e12")
	Put(t, "a/b/c/d1/e13")
	Put(t, "a/b/c/d2/e21")
	Put(t, "a/b/c/d2/e22")
	Put(t, "a/b/c/d2/e23")
}

func TestList(t *testing.T) {
	setupDirectoryTree(t)
	type testResult struct {
		prefix   string
		depth    int
		expected []string
	}

	tests := []testResult{
		testResult{
			prefix: "a/b",
			depth:  0,
			expected: []string{
				"a/b",
			},
		},
		testResult{
			prefix: "a/b",
			depth:  1,
			expected: []string{
				"a/b",
				"a/b/c",
			},
		},
		testResult{
			prefix: "a/b",
			depth:  2,
			expected: []string{
				"a/b",
				"a/b/c",
				"a/b/c/d1",
				"a/b/c/d2",
			},
		},
		testResult{
			prefix: "a/b",
			depth:  3,
			expected: []string{
				"a/b",
				"a/b/c",
				"a/b/c/d1",
				"a/b/c/d1/e11",
				"a/b/c/d1/e12",
				"a/b/c/d1/e13",
				"a/b/c/d2",
				"a/b/c/d2/e21",
				"a/b/c/d2/e22",
				"a/b/c/d2/e23",
			},
		},
		testResult{
			prefix: "a",
			depth:  4,
			expected: []string{
				"a",
				"a/b",
				"a/b/c",
				"a/b/c/d1",
				"a/b/c/d1/e11",
				"a/b/c/d1/e12",
				"a/b/c/d1/e13",
				"a/b/c/d2",
				"a/b/c/d2/e21",
				"a/b/c/d2/e22",
				"a/b/c/d2/e23",
			},
		},
	}
	for i := range tests {
		testListPrefix(t, tests[i].prefix, tests[i].depth, tests[i].expected)
	}
}

func contains(needle string, haystack []string) bool {
	for _, elem := range haystack {
		if elem == needle {
			return true
		}
	}
	return false
}

func testListPrefix(t *testing.T, prefix string, depth int, expected []string) {
	names, err := client.ListPrefix(prefix, depth)
	if err != nil {
		t.Fatalf("Error in client.List: %v", err)
	}
	t.Logf("Prefix: got: %+v", names)
	if len(names) != len(expected) {
		t.Fatalf("Expected %d results, got %d", len(expected), len(names))
	}
	for _, e := range expected {
		if !contains(e, names) {
			t.Errorf("%s %d: %q not found", prefix, depth, e)
		}
	}
}

func TestListDir(t *testing.T) {
	prefix := "a/b/c/d1/"
	names, err := client.ListDir(prefix)
	if err != nil {
		t.Fatalf("Error in client.List: %v", err)
	}
	expected := []string{prefix + "e11", prefix + "e12", prefix + "e13"}
	if len(names) != len(expected) {
		t.Fatalf("Expected 3 results, got %d", len(names))
	}
	for _, e := range expected {
		if !contains(e, names) {
			t.Errorf("Expected %q, not found", e)
		}
	}
}

func TestDelete(t *testing.T) {
	_, err := client.Put(fileName, testData)
	if err != nil {
		t.Fatal(err)
	}
	err = client.Delete(fileName)
	if err != nil {
		t.Fatalf("Expected no errors, got %v", err)
	}
	// Test the side effect after Delete.
	_, err = client.Get(fileName)
	if err == nil {
		t.Fatal("Expected an error, but got none")
	}
}

func TestMain(m *testing.M) {
	flag.Parse()
	if testing.Short() {
		log.Print("cloud/storage/gcs: skipping network-based tests while -test.short specified")
		os.Exit(0)
	}

	// Create client that writes to test bucket.
	var err error
	client, err = storage.Dial("GCS",
		storage.WithKeyValue("gcpBucketName", testBucketName),
		storage.WithKeyValue("defaultACL", PublicRead))
	if err != nil {
		log.Fatalf("cloud/storage/gcs: couldn't set up client: %v", err)
	}

	code := m.Run()

	// Clean up.
	const verbose = true
	if err := client.(*gcsImpl).EmptyBucket(verbose); err != nil {
		log.Printf("cloud/storage/gcs: EmptyBucket failed: %v", err)
	}

	os.Exit(code)
}
<commit_msg>cloud/storage/gcs: disable test unless magic flag is set<commit_after>// Copyright 2016 The Upspin 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 gcs

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"testing"
	"time"

	"upspin.io/cloud/storage"
	"upspin.io/log"
)

const testBucketName = "upspin-test-scratch"

var (
	client      storage.Storage
	testDataStr = fmt.Sprintf("This is test at %v", time.Now())
	testData    = []byte(testDataStr)
	fileName    = fmt.Sprintf("test-file-%d", time.Now().Second())

	useGcloud = flag.Bool("use_gcloud", false, "enable to run google cloud tests; requires gcloud auth login")
)

// This is more of a regression test as it uses the running cloud
// storage in prod. However, since GCP is always available, we accept
// to rely on it.
func TestPutGetAndDownload(t *testing.T) {
	link, err := client.Put(fileName, testData)
	if err != nil {
		t.Fatalf("Can't put: %v", err)
	}
	if !strings.HasPrefix(link, "https://") {
		t.Errorf("Link is not HTTPS")
	}
	retLink, err := client.Get(fileName)
	if err != nil {
		t.Fatalf("Can't get: %v", err)
	}
	if retLink != link {
		t.Errorf("Not the same link as stored: %v vs received: %v", link, retLink)
	}
	resp, err := http.Get(retLink)
	if err != nil {
		t.Errorf("Couldn't get link: %v", err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatalf("Can't read HTTP body: %v", err)
	}
	if string(data) != testDataStr {
		t.Errorf("Expected %q got %q", testDataStr, string(data))
	}
	// Check that Download yields the same data
	bytes, err := client.Download(fileName)
	if err != nil {
		t.Fatal(err)
	}
	if string(bytes) != testDataStr {
		t.Errorf("Expected %q got %q", testDataStr, string(bytes))
	}
}

func Put(t *testing.T, path string) {
	_, err := client.Put(path, testData)
	if err != nil {
		t.Fatal(err)
	}
}

func setupDirectoryTree(t *testing.T) {
	Put(t, "a")
	Put(t, "a/b")
	Put(t, "a/b/c")
	Put(t, "a/b/c/d1")
	Put(t, "a/b/c/d2")
	Put(t, "a/b/c/d1/e11")
	Put(t, "a/b/c/d1/e12")
	Put(t, "a/b/c/d1/e13")
	Put(t, "a/b/c/d2/e21")
	Put(t, "a/b/c/d2/e22")
	Put(t, "a/b/c/d2/e23")
}

func TestList(t *testing.T) {
	setupDirectoryTree(t)
	type testResult struct {
		prefix   string
		depth    int
		expected []string
	}

	tests := []testResult{
		testResult{
			prefix: "a/b",
			depth:  0,
			expected: []string{
				"a/b",
			},
		},
		testResult{
			prefix: "a/b",
			depth:  1,
			expected: []string{
				"a/b",
				"a/b/c",
			},
		},
		testResult{
			prefix: "a/b",
			depth:  2,
			expected: []string{
				"a/b",
				"a/b/c",
				"a/b/c/d1",
				"a/b/c/d2",
			},
		},
		testResult{
			prefix: "a/b",
			depth:  3,
			expected: []string{
				"a/b",
				"a/b/c",
				"a/b/c/d1",
				"a/b/c/d1/e11",
				"a/b/c/d1/e12",
				"a/b/c/d1/e13",
				"a/b/c/d2",
				"a/b/c/d2/e21",
				"a/b/c/d2/e22",
				"a/b/c/d2/e23",
			},
		},
		testResult{
			prefix: "a",
			depth:  4,
			expected: []string{
				"a",
				"a/b",
				"a/b/c",
				"a/b/c/d1",
				"a/b/c/d1/e11",
				"a/b/c/d1/e12",
				"a/b/c/d1/e13",
				"a/b/c/d2",
				"a/b/c/d2/e21",
				"a/b/c/d2/e22",
				"a/b/c/d2/e23",
			},
		},
	}
	for i := range tests {
		testListPrefix(t, tests[i].prefix, tests[i].depth, tests[i].expected)
	}
}

func contains(needle string, haystack []string) bool {
	for _, elem := range haystack {
		if elem == needle {
			return true
		}
	}
	return false
}

func testListPrefix(t *testing.T, prefix string, depth int, expected []string) {
	names, err := client.ListPrefix(prefix, depth)
	if err != nil {
		t.Fatalf("Error in client.List: %v", err)
	}
	t.Logf("Prefix: got: %+v", names)
	if len(names) != len(expected) {
		t.Fatalf("Expected %d results, got %d", len(expected), len(names))
	}
	for _, e := range expected {
		if !contains(e, names) {
			t.Errorf("%s %d: %q not found", prefix, depth, e)
		}
	}
}

func TestListDir(t *testing.T) {
	prefix := "a/b/c/d1/"
	names, err := client.ListDir(prefix)
	if err != nil {
		t.Fatalf("Error in client.List: %v", err)
	}
	expected := []string{prefix + "e11", prefix + "e12", prefix + "e13"}
	if len(names) != len(expected) {
		t.Fatalf("Expected 3 results, got %d", len(names))
	}
	for _, e := range expected {
		if !contains(e, names) {
			t.Errorf("Expected %q, not found", e)
		}
	}
}

func TestDelete(t *testing.T) {
	_, err := client.Put(fileName, testData)
	if err != nil {
		t.Fatal(err)
	}
	err = client.Delete(fileName)
	if err != nil {
		t.Fatalf("Expected no errors, got %v", err)
	}
	// Test the side effect after Delete.
	_, err = client.Get(fileName)
	if err == nil {
		t.Fatal("Expected an error, but got none")
	}
}

func TestMain(m *testing.M) {
	flag.Parse()
	if !*useGcloud {
		log.Printf(`

cloud/storage/gcs: skipping test as it requires GCS access. To enable this test,
ensure you are authenticated to a GCP project that has editor permissions to a
GCS bucket called 'upspin-test-scratch' and then set this test's flag
--use_gcloud.

`)
		os.Exit(0)
	}

	// Create client that writes to test bucket.
	var err error
	client, err = storage.Dial("GCS",
		storage.WithKeyValue("gcpBucketName", testBucketName),
		storage.WithKeyValue("defaultACL", PublicRead))
	if err != nil {
		log.Fatalf("cloud/storage/gcs: couldn't set up client: %v", err)
	}

	code := m.Run()

	// Clean up.
	const verbose = true
	if err := client.(*gcsImpl).EmptyBucket(verbose); err != nil {
		log.Printf("cloud/storage/gcs: EmptyBucket failed: %v", err)
	}

	os.Exit(code)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package main

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "0.4.0"
<commit_msg>Cluster-autoscaler: bump version to 0.5.0-alpha1 in preparation for the next release<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package main

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "0.5.0-alpha1"
<|endoftext|>


<commit_before>// Copyright 2016 The nvim-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 pathutil

import (
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/neovim/go-client/nvim"
)

var pkgPathutil = "pathutil"

// Chdir changes the vim current working directory.
// The returned function restores working directory to `getcwd()` result path
// and unlocks the mutex.
func Chdir(v *nvim.Nvim, dir string) func() {
	var (
		m   sync.Mutex
		cwd interface{}
	)
	m.Lock()
	if err := v.Eval("getcwd()", &cwd); err != nil {
		return nil
	}
	v.SetCurrentDirectory(dir)
	return func() {
		v.SetCurrentDirectory(cwd.(string))
		m.Unlock()
	}
}

func TrimGoPath(p string) string {
	p = strings.TrimPrefix(p, os.Getenv("GOPATH")) + string(filepath.Separator)
	switch p[:4] {
	case "/bin", "/pkg", "/src":
		return filepath.Clean(p[5:])
	default:
		return filepath.Clean(p)
	}
}

// JoinGoPath joins the $GOPATH + "src" to p
func JoinGoPath(p string) string {
	return filepath.Join(os.Getenv("GOPATH"), "src", p)
}

// ShortFilePath return the simply trim cwd into p.
func ShortFilePath(p, cwd string) string {
	return strings.Replace(p, cwd, ".", 1)
}

// Rel wrapper of filepath.Rel function that return only one variable.
func Rel(cwd, f string) string {
	rel, err := filepath.Rel(cwd, f)
	if err != nil {
		return f
	}
	return rel
}

// ExpandGoRoot expands the "$GOROOT" include from p.
func ExpandGoRoot(p string) string {
	if strings.Index(p, "$GOROOT") != -1 {
		return strings.Replace(p, "$GOROOT", runtime.GOROOT(), 1)
	}

	return p // Not hit
}

// IsDir returns whether the filename is directory.
func IsDir(filename string) bool {
	fi, err := os.Stat(filename)
	return err == nil && fi.IsDir()
}

// IsExist returns whether the filename is exists.
func IsExist(filename string) bool {
	_, err := os.Stat(filename)
	return err == nil
}

// IsGoFile returns whether the filename is exists.
func IsGoFile(filename string) bool {
	f, err := os.Stat(filename)
	return err == nil && filepath.Ext(f.Name()) == ".go"
}
<commit_msg>pathutil: Fix IsExist return condition<commit_after>// Copyright 2016 The nvim-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 pathutil

import (
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/neovim/go-client/nvim"
)

var pkgPathutil = "pathutil"

// Chdir changes the vim current working directory.
// The returned function restores working directory to `getcwd()` result path
// and unlocks the mutex.
func Chdir(v *nvim.Nvim, dir string) func() {
	var (
		m   sync.Mutex
		cwd interface{}
	)
	m.Lock()
	if err := v.Eval("getcwd()", &cwd); err != nil {
		return nil
	}
	v.SetCurrentDirectory(dir)
	return func() {
		v.SetCurrentDirectory(cwd.(string))
		m.Unlock()
	}
}

func TrimGoPath(p string) string {
	p = strings.TrimPrefix(p, os.Getenv("GOPATH")) + string(filepath.Separator)
	switch p[:4] {
	case "/bin", "/pkg", "/src":
		return filepath.Clean(p[5:])
	default:
		return filepath.Clean(p)
	}
}

// JoinGoPath joins the $GOPATH + "src" to p
func JoinGoPath(p string) string {
	return filepath.Join(os.Getenv("GOPATH"), "src", p)
}

// ShortFilePath return the simply trim cwd into p.
func ShortFilePath(p, cwd string) string {
	return strings.Replace(p, cwd, ".", 1)
}

// Rel wrapper of filepath.Rel function that return only one variable.
func Rel(cwd, f string) string {
	rel, err := filepath.Rel(cwd, f)
	if err != nil {
		return f
	}
	return rel
}

// ExpandGoRoot expands the "$GOROOT" include from p.
func ExpandGoRoot(p string) string {
	if strings.Index(p, "$GOROOT") != -1 {
		return strings.Replace(p, "$GOROOT", runtime.GOROOT(), 1)
	}

	return p // Not hit
}

// IsDir returns whether the filename is directory.
func IsDir(filename string) bool {
	fi, err := os.Stat(filename)
	return err == nil && fi.IsDir()
}

// IsExist returns whether the filename is exists.
func IsExist(filename string) bool {
	_, err := os.Stat(filename)
	return !os.IsNotExist(err) || err == nil
}

// IsGoFile returns whether the filename is exists.
func IsGoFile(filename string) bool {
	f, err := os.Stat(filename)
	return err == nil && filepath.Ext(f.Name()) == ".go"
}
<|endoftext|>


<commit_before>// Copyright 2010 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 rand

import (
	"bytes"
	"compress/flate"
	"testing"
)

func TestRead(t *testing.T) {
	var n int = 4e6
	if testing.Short() {
		n = 1e5
	}
	b := make([]byte, n)
	n, err := Read(b)
	if n != len(b) || err != nil {
		t.Fatalf("Read(buf) = %d, %s", n, err)
	}

	var z bytes.Buffer
	f, _ := flate.NewWriter(&z, 5)
	f.Write(b)
	f.Close()
	if z.Len() < len(b)*99/100 {
		t.Fatalf("Compressed %d -> %d", len(b), z.Len())
	}
}
<commit_msg>crypto/rand: use io.ReadFull in test<commit_after>// Copyright 2010 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 rand

import (
	"bytes"
	"compress/flate"
	"io"
	"testing"
)

func TestRead(t *testing.T) {
	var n int = 4e6
	if testing.Short() {
		n = 1e5
	}
	b := make([]byte, n)
	n, err := io.ReadFull(Reader, b)
	if n != len(b) || err != nil {
		t.Fatalf("ReadFull(buf) = %d, %s", n, err)
	}

	var z bytes.Buffer
	f, _ := flate.NewWriter(&z, 5)
	f.Write(b)
	f.Close()
	if z.Len() < len(b)*99/100 {
		t.Fatalf("Compressed %d -> %d", len(b), z.Len())
	}
}
<|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.

package hex

import (
	"bytes"
	"testing"
)

type encDecTest struct {
	enc string
	dec []byte
}

var encDecTests = []encDecTest{
	{"", []byte{}},
	{"0001020304050607", []byte{0, 1, 2, 3, 4, 5, 6, 7}},
	{"08090a0b0c0d0e0f", []byte{8, 9, 10, 11, 12, 13, 14, 15}},
	{"f0f1f2f3f4f5f6f7", []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}},
	{"f8f9fafbfcfdfeff", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}},
	{"67", []byte{'g'}},
	{"e3a1", []byte{0xe3, 0xa1}},
}

func TestEncode(t *testing.T) {
	for i, test := range encDecTests {
		dst := make([]byte, EncodedLen(len(test.dec)))
		n := Encode(dst, test.dec)
		if n != len(dst) {
			t.Errorf("#%d: bad return value: got: %d want: %d", i, n, len(dst))
		}
		if string(dst) != test.enc {
			t.Errorf("#%d: got: %#v want: %#v", i, dst, test.enc)
		}
	}
}

func TestDecode(t *testing.T) {
	// Case for decoding uppercase hex characters, since
	// Encode always uses lowercase.
	decTests := append(encDecTests, encDecTest{"F8F9FAFBFCFDFEFF", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}})
	for i, test := range decTests {
		dst := make([]byte, DecodedLen(len(test.enc)))
		n, err := Decode(dst, []byte(test.enc))
		if err != nil {
			t.Errorf("#%d: bad return value: got:%d want:%d", i, n, len(dst))
		} else if !bytes.Equal(dst, test.dec) {
			t.Errorf("#%d: got: %#v want: %#v", i, dst, test.dec)
		}
	}
}

func TestEncodeToString(t *testing.T) {
	for i, test := range encDecTests {
		s := EncodeToString(test.dec)
		if s != test.enc {
			t.Errorf("#%d got:%s want:%s", i, s, test.enc)
		}
	}
}

func TestDecodeString(t *testing.T) {
	for i, test := range encDecTests {
		dst, err := DecodeString(test.enc)
		if err != nil {
			t.Errorf("#%d: unexpected err value: %s", i, err)
			continue
		}
		if !bytes.Equal(dst, test.dec) {
			t.Errorf("#%d: got: %#v want: #%v", i, dst, test.dec)
		}
	}
}

type errTest struct {
	in  string
	err string
}

var errTests = []errTest{
	{"0", "encoding/hex: odd length hex string"},
	{"0g", "encoding/hex: invalid byte: U+0067 'g'"},
	{"0\x01", "encoding/hex: invalid byte: U+0001"},
}

func TestInvalidErr(t *testing.T) {
	for i, test := range errTests {
		dst := make([]byte, DecodedLen(len(test.in)))
		_, err := Decode(dst, []byte(test.in))
		if err == nil {
			t.Errorf("#%d: expected error; got none", i)
		} else if err.Error() != test.err {
			t.Errorf("#%d: got: %v want: %v", i, err, test.err)
		}
	}
}

func TestInvalidStringErr(t *testing.T) {
	for i, test := range errTests {
		_, err := DecodeString(test.in)
		if err == nil {
			t.Errorf("#%d: expected error; got none", i)
		} else if err.Error() != test.err {
			t.Errorf("#%d: got: %v want: %v", i, err, test.err)
		}
	}
}

func TestDumper(t *testing.T) {
	var in [40]byte
	for i := range in {
		in[i] = byte(i + 30)
	}

	for stride := 1; stride < len(in); stride++ {
		var out bytes.Buffer
		dumper := Dumper(&out)
		done := 0
		for done < len(in) {
			todo := done + stride
			if todo > len(in) {
				todo = len(in)
			}
			dumper.Write(in[done:todo])
			done = todo
		}

		dumper.Close()
		if !bytes.Equal(out.Bytes(), expectedHexDump) {
			t.Errorf("stride: %d failed. got:\n%s\nwant:\n%s", stride, out.Bytes(), expectedHexDump)
		}
	}
}

func TestDump(t *testing.T) {
	var in [40]byte
	for i := range in {
		in[i] = byte(i + 30)
	}

	out := []byte(Dump(in[:]))
	if !bytes.Equal(out, expectedHexDump) {
		t.Errorf("got:\n%s\nwant:\n%s", out, expectedHexDump)
	}
}

var expectedHexDump = []byte(`00000000  1e 1f 20 21 22 23 24 25  26 27 28 29 2a 2b 2c 2d  |.. !"#$%&'()*+,-|
00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
00000020  3e 3f 40 41 42 43 44 45                           |>?@ABCDE|
`)
<commit_msg>encoding/hex: add Decode error test case<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.

package hex

import (
	"bytes"
	"testing"
)

type encDecTest struct {
	enc string
	dec []byte
}

var encDecTests = []encDecTest{
	{"", []byte{}},
	{"0001020304050607", []byte{0, 1, 2, 3, 4, 5, 6, 7}},
	{"08090a0b0c0d0e0f", []byte{8, 9, 10, 11, 12, 13, 14, 15}},
	{"f0f1f2f3f4f5f6f7", []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}},
	{"f8f9fafbfcfdfeff", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}},
	{"67", []byte{'g'}},
	{"e3a1", []byte{0xe3, 0xa1}},
}

func TestEncode(t *testing.T) {
	for i, test := range encDecTests {
		dst := make([]byte, EncodedLen(len(test.dec)))
		n := Encode(dst, test.dec)
		if n != len(dst) {
			t.Errorf("#%d: bad return value: got: %d want: %d", i, n, len(dst))
		}
		if string(dst) != test.enc {
			t.Errorf("#%d: got: %#v want: %#v", i, dst, test.enc)
		}
	}
}

func TestDecode(t *testing.T) {
	// Case for decoding uppercase hex characters, since
	// Encode always uses lowercase.
	decTests := append(encDecTests, encDecTest{"F8F9FAFBFCFDFEFF", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}})
	for i, test := range decTests {
		dst := make([]byte, DecodedLen(len(test.enc)))
		n, err := Decode(dst, []byte(test.enc))
		if err != nil {
			t.Errorf("#%d: bad return value: got:%d want:%d", i, n, len(dst))
		} else if !bytes.Equal(dst, test.dec) {
			t.Errorf("#%d: got: %#v want: %#v", i, dst, test.dec)
		}
	}
}

func TestEncodeToString(t *testing.T) {
	for i, test := range encDecTests {
		s := EncodeToString(test.dec)
		if s != test.enc {
			t.Errorf("#%d got:%s want:%s", i, s, test.enc)
		}
	}
}

func TestDecodeString(t *testing.T) {
	for i, test := range encDecTests {
		dst, err := DecodeString(test.enc)
		if err != nil {
			t.Errorf("#%d: unexpected err value: %s", i, err)
			continue
		}
		if !bytes.Equal(dst, test.dec) {
			t.Errorf("#%d: got: %#v want: #%v", i, dst, test.dec)
		}
	}
}

type errTest struct {
	in  string
	err string
}

var errTests = []errTest{
	{"0", "encoding/hex: odd length hex string"},
	{"0g", "encoding/hex: invalid byte: U+0067 'g'"},
	{"00gg", "encoding/hex: invalid byte: U+0067 'g'"},
	{"0\x01", "encoding/hex: invalid byte: U+0001"},
}

func TestInvalidErr(t *testing.T) {
	for i, test := range errTests {
		dst := make([]byte, DecodedLen(len(test.in)))
		_, err := Decode(dst, []byte(test.in))
		if err == nil {
			t.Errorf("#%d: expected error; got none", i)
		} else if err.Error() != test.err {
			t.Errorf("#%d: got: %v want: %v", i, err, test.err)
		}
	}
}

func TestInvalidStringErr(t *testing.T) {
	for i, test := range errTests {
		_, err := DecodeString(test.in)
		if err == nil {
			t.Errorf("#%d: expected error; got none", i)
		} else if err.Error() != test.err {
			t.Errorf("#%d: got: %v want: %v", i, err, test.err)
		}
	}
}

func TestDumper(t *testing.T) {
	var in [40]byte
	for i := range in {
		in[i] = byte(i + 30)
	}

	for stride := 1; stride < len(in); stride++ {
		var out bytes.Buffer
		dumper := Dumper(&out)
		done := 0
		for done < len(in) {
			todo := done + stride
			if todo > len(in) {
				todo = len(in)
			}
			dumper.Write(in[done:todo])
			done = todo
		}

		dumper.Close()
		if !bytes.Equal(out.Bytes(), expectedHexDump) {
			t.Errorf("stride: %d failed. got:\n%s\nwant:\n%s", stride, out.Bytes(), expectedHexDump)
		}
	}
}

func TestDump(t *testing.T) {
	var in [40]byte
	for i := range in {
		in[i] = byte(i + 30)
	}

	out := []byte(Dump(in[:]))
	if !bytes.Equal(out, expectedHexDump) {
		t.Errorf("got:\n%s\nwant:\n%s", out, expectedHexDump)
	}
}

var expectedHexDump = []byte(`00000000  1e 1f 20 21 22 23 24 25  26 27 28 29 2a 2b 2c 2d  |.. !"#$%&'()*+,-|
00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
00000020  3e 3f 40 41 42 43 44 45                           |>?@ABCDE|
`)
<|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.

package png

import (
	"bufio"
	"fmt"
	"image"
	"image/color"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

var filenames = []string{
	"basn0g01",
	"basn0g01-30",
	"basn0g02",
	"basn0g02-29",
	"basn0g04",
	"basn0g04-31",
	"basn0g08",
	"basn0g16",
	"basn2c08",
	"basn2c16",
	"basn3p01",
	"basn3p02",
	"basn3p04",
	"basn3p08",
	"basn3p08-trns",
	"basn4a08",
	"basn4a16",
	"basn6a08",
	"basn6a16",
}

var filenamesPaletted = []string{
	"basn3p01",
	"basn3p02",
	"basn3p04",
	"basn3p08",
	"basn3p08-trns",
}

var filenamesShort = []string{
	"basn0g01",
	"basn0g04-31",
	"basn6a16",
}

func readPNG(filename string) (image.Image, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return Decode(f)
}

// An approximation of the sng command-line tool.
func sng(w io.WriteCloser, filename string, png image.Image) {
	defer w.Close()
	bounds := png.Bounds()
	cm := png.ColorModel()
	var bitdepth int
	switch cm {
	case color.RGBAModel, color.NRGBAModel, color.AlphaModel, color.GrayModel:
		bitdepth = 8
	default:
		bitdepth = 16
	}
	cpm, _ := cm.(color.Palette)
	var paletted *image.Paletted
	if cpm != nil {
		switch {
		case len(cpm) <= 2:
			bitdepth = 1
		case len(cpm) <= 4:
			bitdepth = 2
		case len(cpm) <= 16:
			bitdepth = 4
		default:
			bitdepth = 8
		}
		paletted = png.(*image.Paletted)
	}

	// Write the filename and IHDR.
	io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
	fmt.Fprintf(w, "    width: %d; height: %d; bitdepth: %d;\n", bounds.Dx(), bounds.Dy(), bitdepth)
	switch {
	case cm == color.RGBAModel, cm == color.RGBA64Model:
		io.WriteString(w, "    using color;\n")
	case cm == color.NRGBAModel, cm == color.NRGBA64Model:
		io.WriteString(w, "    using color alpha;\n")
	case cm == color.GrayModel, cm == color.Gray16Model:
		io.WriteString(w, "    using grayscale;\n")
	case cpm != nil:
		io.WriteString(w, "    using color palette;\n")
	default:
		io.WriteString(w, "unknown PNG decoder color model\n")
	}
	io.WriteString(w, "}\n")

	// We fake a gAMA output. The test files have a gAMA chunk but the go PNG parser ignores it
	// (the PNG spec section 11.3 says "Ancillary chunks may be ignored by a decoder").
	io.WriteString(w, "gAMA {1.0000}\n")

	// Write the PLTE and tRNS (if applicable).
	if cpm != nil {
		lastAlpha := -1
		io.WriteString(w, "PLTE {\n")
		for i, c := range cpm {
			var r, g, b, a uint8
			switch c := c.(type) {
			case color.RGBA:
				r, g, b, a = c.R, c.G, c.B, 0xff
			case color.NRGBA:
				r, g, b, a = c.R, c.G, c.B, c.A
			default:
				panic("unknown palette color type")
			}
			if a != 0xff {
				lastAlpha = i
			}
			fmt.Fprintf(w, "    (%3d,%3d,%3d)     # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
		}
		io.WriteString(w, "}\n")
		if lastAlpha != -1 {
			io.WriteString(w, "tRNS {\n")
			for i := 0; i <= lastAlpha; i++ {
				_, _, _, a := cpm[i].RGBA()
				a >>= 8
				fmt.Fprintf(w, " %d", a)
			}
			io.WriteString(w, "}\n")
		}
	}

	// Write the IMAGE.
	io.WriteString(w, "IMAGE {\n    pixels hex\n")
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		switch {
		case cm == color.GrayModel:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				gray := png.At(x, y).(color.Gray)
				fmt.Fprintf(w, "%02x", gray.Y)
			}
		case cm == color.Gray16Model:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				gray16 := png.At(x, y).(color.Gray16)
				fmt.Fprintf(w, "%04x ", gray16.Y)
			}
		case cm == color.RGBAModel:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				rgba := png.At(x, y).(color.RGBA)
				fmt.Fprintf(w, "%02x%02x%02x ", rgba.R, rgba.G, rgba.B)
			}
		case cm == color.RGBA64Model:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				rgba64 := png.At(x, y).(color.RGBA64)
				fmt.Fprintf(w, "%04x%04x%04x ", rgba64.R, rgba64.G, rgba64.B)
			}
		case cm == color.NRGBAModel:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				nrgba := png.At(x, y).(color.NRGBA)
				fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
			}
		case cm == color.NRGBA64Model:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				nrgba64 := png.At(x, y).(color.NRGBA64)
				fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
			}
		case cpm != nil:
			var b, c int
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				b = b<<uint(bitdepth) | int(paletted.ColorIndexAt(x, y))
				c++
				if c == 8/bitdepth {
					fmt.Fprintf(w, "%02x", b)
					b = 0
					c = 0
				}
			}
		}
		io.WriteString(w, "\n")
	}
	io.WriteString(w, "}\n")
}

func TestReader(t *testing.T) {
	names := filenames
	if testing.Short() {
		names = filenamesShort
	}
	for _, fn := range names {
		// Read the .png file.
		img, err := readPNG("testdata/pngsuite/" + fn + ".png")
		if err != nil {
			t.Error(fn, err)
			continue
		}

		if fn == "basn4a16" {
			// basn4a16.sng is gray + alpha but sng() will produce true color + alpha
			// so we just check a single random pixel.
			c := img.At(2, 1).(color.NRGBA64)
			if c.R != 0x11a7 || c.G != 0x11a7 || c.B != 0x11a7 || c.A != 0x1085 {
				t.Error(fn, fmt.Errorf("wrong pixel value at (2, 1): %x", c))
			}
			continue
		}

		piper, pipew := io.Pipe()
		pb := bufio.NewScanner(piper)
		go sng(pipew, fn, img)
		defer piper.Close()

		// Read the .sng file.
		sf, err := os.Open("testdata/pngsuite/" + fn + ".sng")
		if err != nil {
			t.Error(fn, err)
			continue
		}
		defer sf.Close()
		sb := bufio.NewScanner(sf)
		if err != nil {
			t.Error(fn, err)
			continue
		}

		// Compare the two, in SNG format, line by line.
		for {
			pdone := pb.Scan()
			sdone := sb.Scan()
			if pdone && sdone {
				break
			}
			if pdone || sdone {
				t.Errorf("%s: Different sizes", fn)
				break
			}
			ps := pb.Text()
			ss := sb.Text()
			if ps != ss {
				t.Errorf("%s: Mismatch\n%sversus\n%s\n", fn, ps, ss)
				break
			}
		}
		if pb.Err() != nil {
			t.Error(fn, pb.Err())
		}
		if sb.Err() != nil {
			t.Error(fn, sb.Err())
		}
	}
}

var readerErrors = []struct {
	file string
	err  string
}{
	{"invalid-zlib.png", "zlib: invalid checksum"},
	{"invalid-crc32.png", "invalid checksum"},
	{"invalid-noend.png", "unexpected EOF"},
	{"invalid-trunc.png", "unexpected EOF"},
}

func TestReaderError(t *testing.T) {
	for _, tt := range readerErrors {
		img, err := readPNG("testdata/" + tt.file)
		if err == nil {
			t.Errorf("decoding %s: missing error", tt.file)
			continue
		}
		if !strings.Contains(err.Error(), tt.err) {
			t.Errorf("decoding %s: %s, want %s", tt.file, err, tt.err)
		}
		if img != nil {
			t.Errorf("decoding %s: have image + error", tt.file)
		}
	}
}

func TestPalettedDecodeConfig(t *testing.T) {
	for _, fn := range filenamesPaletted {
		f, err := os.Open("testdata/pngsuite/" + fn + ".png")
		if err != nil {
			t.Errorf("%s: open failed: %v", fn, err)
			continue
		}
		defer f.Close()
		cfg, err := DecodeConfig(f)
		if err != nil {
			t.Errorf("%s: %v", fn, err)
			continue
		}
		pal, ok := cfg.ColorModel.(color.Palette)
		if !ok {
			t.Errorf("%s: expected paletted color model", fn)
			continue
		}
		if pal == nil {
			t.Errorf("%s: palette not initialized", fn)
			continue
		}
	}
}

func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
	b.StopTimer()
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		b.Fatal(err)
	}
	s := string(data)
	cfg, err := DecodeConfig(strings.NewReader(s))
	if err != nil {
		b.Fatal(err)
	}
	b.SetBytes(int64(cfg.Width * cfg.Height * bytesPerPixel))
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		Decode(strings.NewReader(s))
	}
}

func BenchmarkDecodeGray(b *testing.B) {
	benchmarkDecode(b, "testdata/benchGray.png", 1)
}

func BenchmarkDecodeNRGBAGradient(b *testing.B) {
	benchmarkDecode(b, "testdata/benchNRGBA-gradient.png", 4)
}

func BenchmarkDecodeNRGBAOpaque(b *testing.B) {
	benchmarkDecode(b, "testdata/benchNRGBA-opaque.png", 4)
}

func BenchmarkDecodePaletted(b *testing.B) {
	benchmarkDecode(b, "testdata/benchPaletted.png", 1)
}

func BenchmarkDecodeRGB(b *testing.B) {
	benchmarkDecode(b, "testdata/benchRGB.png", 4)
}
<commit_msg>image/png: fix compare-to-golden-file test.<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.

package png

import (
	"bufio"
	"fmt"
	"image"
	"image/color"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

var filenames = []string{
	"basn0g01",
	"basn0g01-30",
	"basn0g02",
	"basn0g02-29",
	"basn0g04",
	"basn0g04-31",
	"basn0g08",
	"basn0g16",
	"basn2c08",
	"basn2c16",
	"basn3p01",
	"basn3p02",
	"basn3p04",
	"basn3p08",
	"basn3p08-trns",
	"basn4a08",
	"basn4a16",
	"basn6a08",
	"basn6a16",
}

var filenamesPaletted = []string{
	"basn3p01",
	"basn3p02",
	"basn3p04",
	"basn3p08",
	"basn3p08-trns",
}

var filenamesShort = []string{
	"basn0g01",
	"basn0g04-31",
	"basn6a16",
}

func readPNG(filename string) (image.Image, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return Decode(f)
}

// An approximation of the sng command-line tool.
func sng(w io.WriteCloser, filename string, png image.Image) {
	defer w.Close()
	bounds := png.Bounds()
	cm := png.ColorModel()
	var bitdepth int
	switch cm {
	case color.RGBAModel, color.NRGBAModel, color.AlphaModel, color.GrayModel:
		bitdepth = 8
	default:
		bitdepth = 16
	}
	cpm, _ := cm.(color.Palette)
	var paletted *image.Paletted
	if cpm != nil {
		switch {
		case len(cpm) <= 2:
			bitdepth = 1
		case len(cpm) <= 4:
			bitdepth = 2
		case len(cpm) <= 16:
			bitdepth = 4
		default:
			bitdepth = 8
		}
		paletted = png.(*image.Paletted)
	}

	// Write the filename and IHDR.
	io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
	fmt.Fprintf(w, "    width: %d; height: %d; bitdepth: %d;\n", bounds.Dx(), bounds.Dy(), bitdepth)
	switch {
	case cm == color.RGBAModel, cm == color.RGBA64Model:
		io.WriteString(w, "    using color;\n")
	case cm == color.NRGBAModel, cm == color.NRGBA64Model:
		io.WriteString(w, "    using color alpha;\n")
	case cm == color.GrayModel, cm == color.Gray16Model:
		io.WriteString(w, "    using grayscale;\n")
	case cpm != nil:
		io.WriteString(w, "    using color palette;\n")
	default:
		io.WriteString(w, "unknown PNG decoder color model\n")
	}
	io.WriteString(w, "}\n")

	// We fake a gAMA output. The test files have a gAMA chunk but the go PNG parser ignores it
	// (the PNG spec section 11.3 says "Ancillary chunks may be ignored by a decoder").
	io.WriteString(w, "gAMA {1.0000}\n")

	// Write the PLTE and tRNS (if applicable).
	if cpm != nil {
		lastAlpha := -1
		io.WriteString(w, "PLTE {\n")
		for i, c := range cpm {
			var r, g, b, a uint8
			switch c := c.(type) {
			case color.RGBA:
				r, g, b, a = c.R, c.G, c.B, 0xff
			case color.NRGBA:
				r, g, b, a = c.R, c.G, c.B, c.A
			default:
				panic("unknown palette color type")
			}
			if a != 0xff {
				lastAlpha = i
			}
			fmt.Fprintf(w, "    (%3d,%3d,%3d)     # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
		}
		io.WriteString(w, "}\n")
		if lastAlpha != -1 {
			io.WriteString(w, "tRNS {\n")
			for i := 0; i <= lastAlpha; i++ {
				_, _, _, a := cpm[i].RGBA()
				a >>= 8
				fmt.Fprintf(w, " %d", a)
			}
			io.WriteString(w, "}\n")
		}
	}

	// Write the IMAGE.
	io.WriteString(w, "IMAGE {\n    pixels hex\n")
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		switch {
		case cm == color.GrayModel:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				gray := png.At(x, y).(color.Gray)
				fmt.Fprintf(w, "%02x", gray.Y)
			}
		case cm == color.Gray16Model:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				gray16 := png.At(x, y).(color.Gray16)
				fmt.Fprintf(w, "%04x ", gray16.Y)
			}
		case cm == color.RGBAModel:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				rgba := png.At(x, y).(color.RGBA)
				fmt.Fprintf(w, "%02x%02x%02x ", rgba.R, rgba.G, rgba.B)
			}
		case cm == color.RGBA64Model:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				rgba64 := png.At(x, y).(color.RGBA64)
				fmt.Fprintf(w, "%04x%04x%04x ", rgba64.R, rgba64.G, rgba64.B)
			}
		case cm == color.NRGBAModel:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				nrgba := png.At(x, y).(color.NRGBA)
				fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
			}
		case cm == color.NRGBA64Model:
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				nrgba64 := png.At(x, y).(color.NRGBA64)
				fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
			}
		case cpm != nil:
			var b, c int
			for x := bounds.Min.X; x < bounds.Max.X; x++ {
				b = b<<uint(bitdepth) | int(paletted.ColorIndexAt(x, y))
				c++
				if c == 8/bitdepth {
					fmt.Fprintf(w, "%02x", b)
					b = 0
					c = 0
				}
			}
		}
		io.WriteString(w, "\n")
	}
	io.WriteString(w, "}\n")
}

func TestReader(t *testing.T) {
	names := filenames
	if testing.Short() {
		names = filenamesShort
	}
	for _, fn := range names {
		// Read the .png file.
		img, err := readPNG("testdata/pngsuite/" + fn + ".png")
		if err != nil {
			t.Error(fn, err)
			continue
		}

		if fn == "basn4a16" {
			// basn4a16.sng is gray + alpha but sng() will produce true color + alpha
			// so we just check a single random pixel.
			c := img.At(2, 1).(color.NRGBA64)
			if c.R != 0x11a7 || c.G != 0x11a7 || c.B != 0x11a7 || c.A != 0x1085 {
				t.Error(fn, fmt.Errorf("wrong pixel value at (2, 1): %x", c))
			}
			continue
		}

		piper, pipew := io.Pipe()
		pb := bufio.NewScanner(piper)
		go sng(pipew, fn, img)
		defer piper.Close()

		// Read the .sng file.
		sf, err := os.Open("testdata/pngsuite/" + fn + ".sng")
		if err != nil {
			t.Error(fn, err)
			continue
		}
		defer sf.Close()
		sb := bufio.NewScanner(sf)
		if err != nil {
			t.Error(fn, err)
			continue
		}

		// Compare the two, in SNG format, line by line.
		for {
			pdone := !pb.Scan()
			sdone := !sb.Scan()
			if pdone && sdone {
				break
			}
			if pdone || sdone {
				t.Errorf("%s: Different sizes", fn)
				break
			}
			ps := pb.Text()
			ss := sb.Text()
			if ps != ss {
				t.Errorf("%s: Mismatch\n%sversus\n%s\n", fn, ps, ss)
				break
			}
		}
		if pb.Err() != nil {
			t.Error(fn, pb.Err())
		}
		if sb.Err() != nil {
			t.Error(fn, sb.Err())
		}
	}
}

var readerErrors = []struct {
	file string
	err  string
}{
	{"invalid-zlib.png", "zlib: invalid checksum"},
	{"invalid-crc32.png", "invalid checksum"},
	{"invalid-noend.png", "unexpected EOF"},
	{"invalid-trunc.png", "unexpected EOF"},
}

func TestReaderError(t *testing.T) {
	for _, tt := range readerErrors {
		img, err := readPNG("testdata/" + tt.file)
		if err == nil {
			t.Errorf("decoding %s: missing error", tt.file)
			continue
		}
		if !strings.Contains(err.Error(), tt.err) {
			t.Errorf("decoding %s: %s, want %s", tt.file, err, tt.err)
		}
		if img != nil {
			t.Errorf("decoding %s: have image + error", tt.file)
		}
	}
}

func TestPalettedDecodeConfig(t *testing.T) {
	for _, fn := range filenamesPaletted {
		f, err := os.Open("testdata/pngsuite/" + fn + ".png")
		if err != nil {
			t.Errorf("%s: open failed: %v", fn, err)
			continue
		}
		defer f.Close()
		cfg, err := DecodeConfig(f)
		if err != nil {
			t.Errorf("%s: %v", fn, err)
			continue
		}
		pal, ok := cfg.ColorModel.(color.Palette)
		if !ok {
			t.Errorf("%s: expected paletted color model", fn)
			continue
		}
		if pal == nil {
			t.Errorf("%s: palette not initialized", fn)
			continue
		}
	}
}

func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
	b.StopTimer()
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		b.Fatal(err)
	}
	s := string(data)
	cfg, err := DecodeConfig(strings.NewReader(s))
	if err != nil {
		b.Fatal(err)
	}
	b.SetBytes(int64(cfg.Width * cfg.Height * bytesPerPixel))
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		Decode(strings.NewReader(s))
	}
}

func BenchmarkDecodeGray(b *testing.B) {
	benchmarkDecode(b, "testdata/benchGray.png", 1)
}

func BenchmarkDecodeNRGBAGradient(b *testing.B) {
	benchmarkDecode(b, "testdata/benchNRGBA-gradient.png", 4)
}

func BenchmarkDecodeNRGBAOpaque(b *testing.B) {
	benchmarkDecode(b, "testdata/benchNRGBA-opaque.png", 4)
}

func BenchmarkDecodePaletted(b *testing.B) {
	benchmarkDecode(b, "testdata/benchPaletted.png", 1)
}

func BenchmarkDecodeRGB(b *testing.B) {
	benchmarkDecode(b, "testdata/benchRGB.png", 4)
}
<|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.

package iotest

import (
	"io";
	"log";
	"os";
)

type writeLogger struct {
	prefix	string;
	w	io.Writer;
}

func (l *writeLogger) Write(p []byte) (n int, err os.Error) {
	n, err = l.w.Write(p);
	if err != nil {
		log.Stdoutf("%s %x: %v", l.prefix, p[0:n], err)
	} else {
		log.Stdoutf("%s %x", l.prefix, p[0:n])
	}
	return;
}

// NewWriteLogger returns a writer that behaves like w except
// that it logs (using log.Stdout) each write to standard output,
// printing the prefix and the hexadecimal data written.
func NewWriteLogger(prefix string, w io.Writer) io.Writer {
	return &writeLogger{prefix, w}
}

type readLogger struct {
	prefix	string;
	r	io.Reader;
}

func (l *readLogger) Read(p []byte) (n int, err os.Error) {
	n, err = l.r.Read(p);
	if err != nil {
		log.Stdoutf("%s %x: %v", l.prefix, p[0:n], err)
	} else {
		log.Stdoutf("%s %x", l.prefix, p[0:n])
	}
	return;
}

// NewReadLogger returns a writer that behaves like w except
// that it logs (using log.Stdout) each write to standard output,
// printing the prefix and the hexadecimal data written.
func NewReadLogger(prefix string, r io.Reader) io.Reader {
	return &readLogger{prefix, r}
}
<commit_msg>Fix doc striing for NewReadLogger.<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.

package iotest

import (
	"io";
	"log";
	"os";
)

type writeLogger struct {
	prefix	string;
	w	io.Writer;
}

func (l *writeLogger) Write(p []byte) (n int, err os.Error) {
	n, err = l.w.Write(p);
	if err != nil {
		log.Stdoutf("%s %x: %v", l.prefix, p[0:n], err)
	} else {
		log.Stdoutf("%s %x", l.prefix, p[0:n])
	}
	return;
}

// NewWriteLogger returns a writer that behaves like w except
// that it logs (using log.Stdout) each write to standard output,
// printing the prefix and the hexadecimal data written.
func NewWriteLogger(prefix string, w io.Writer) io.Writer {
	return &writeLogger{prefix, w}
}

type readLogger struct {
	prefix	string;
	r	io.Reader;
}

func (l *readLogger) Read(p []byte) (n int, err os.Error) {
	n, err = l.r.Read(p);
	if err != nil {
		log.Stdoutf("%s %x: %v", l.prefix, p[0:n], err)
	} else {
		log.Stdoutf("%s %x", l.prefix, p[0:n])
	}
	return;
}

// NewReadLogger returns a reader that behaves like r except
// that it logs (using log.Stdout) each read to standard output,
// printing the prefix and the hexadecimal data written.
func NewReadLogger(prefix string, r io.Reader) io.Reader {
	return &readLogger{prefix, r}
}
<|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.

package time

import (
	"errors"
	"syscall"
)

// TODO(rsc): Fall back to copy of zoneinfo files.

// BUG(brainman,rsc): On Windows, the operating system does not provide complete
// time zone information.
// The implementation assumes that this year's rules for daylight savings
// time apply to all previous and future years as well.
// Also, time zone abbreviations are unavailable.  The implementation constructs
// them using the capital letters from a longer time zone description.

// abbrev returns the abbreviation to use for the given zone name.
func abbrev(name []uint16) string {
	// name is 'Pacific Standard Time' but we want 'PST'.
	// Extract just capital letters.  It's not perfect but the
	// information we need is not available from the kernel.
	// Because time zone abbreviations are not unique,
	// Windows refuses to expose them.
	//
	// http://social.msdn.microsoft.com/Forums/eu/vclanguage/thread/a87e1d25-fb71-4fe0-ae9c-a9578c9753eb
	// http://stackoverflow.com/questions/4195948/windows-time-zone-abbreviations-in-asp-net
	var short []rune
	for _, c := range name {
		if 'A' <= c && c <= 'Z' {
			short = append(short, rune(c))
		}
	}
	return string(short)
}

// pseudoUnix returns the pseudo-Unix time (seconds since Jan 1 1970 *LOCAL TIME*)
// denoted by the system date+time d in the given year.
// It is up to the caller to convert this local time into a UTC-based time.
func pseudoUnix(year int, d *syscall.Systemtime) int64 {
	// Windows specifies daylight savings information in "day in month" format:
	// d.Month is month number (1-12)
	// d.DayOfWeek is appropriate weekday (Sunday=0 to Saturday=6)
	// d.Day is week within the month (1 to 5, where 5 is last week of the month)
	// d.Hour, d.Minute and d.Second are absolute time
	day := 1
	t := Date(year, Month(d.Month), day, int(d.Hour), int(d.Minute), int(d.Second), 0, UTC)
	i := int(d.DayOfWeek) - int(t.Weekday())
	if i < 0 {
		i += 7
	}
	day += i
	if week := int(d.Day) - 1; week < 4 {
		day += week * 7
	} else {
		// "Last" instance of the day.
		day += 4 * 7
		if day > daysIn(Month(d.Month), year) {
			day -= 7
		}
	}
	return t.sec + int64(day-1)*secondsPerDay
}

func initLocalFromTZI(i *syscall.Timezoneinformation) {
	l := &localLoc

	nzone := 1
	if i.StandardDate.Month > 0 {
		nzone++
	}
	l.zone = make([]zone, nzone)

	std := &l.zone[0]
	std.name = abbrev(i.StandardName[0:])
	if nzone == 1 {
		// No daylight savings.
		std.offset = -int(i.Bias) * 60
		l.cacheStart = -1 << 63
		l.cacheEnd = 1<<63 - 1
		l.cacheZone = std
		return
	}

	// StandardBias must be ignored if StandardDate is not set,
	// so this computation is delayed until after the nzone==1
	// return above.
	std.offset = -int(i.Bias+i.StandardBias) * 60

	dst := &l.zone[1]
	dst.name = abbrev(i.DaylightName[0:])
	dst.offset = -int(i.Bias+i.DaylightBias) * 60
	dst.isDST = true

	// Arrange so that d0 is first transition date, d1 second,
	// i0 is index of zone after first transition, i1 second.
	d0 := &i.StandardDate
	d1 := &i.DaylightDate
	i0 := 0
	i1 := 1
	if d0.Month > d1.Month {
		d0, d1 = d1, d0
		i0, i1 = i1, i0
	}

	// 2 tx per year, 100 years on each side of this year
	l.tx = make([]zoneTrans, 400)

	t := Now().UTC()
	year := t.Year()
	txi := 0
	for y := year - 100; y < year+100; y++ {
		tx := &l.tx[txi]
		tx.when = pseudoUnix(y, d0) - int64(l.zone[i1].offset)
		tx.index = uint8(i0)
		txi++

		tx = &l.tx[txi]
		tx.when = pseudoUnix(y, d1) - int64(l.zone[i0].offset)
		tx.index = uint8(i1)
		txi++
	}
}

var usPacific = syscall.Timezoneinformation{
	Bias: 8 * 60,
	StandardName: [32]uint16{
		'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
	},
	StandardDate: syscall.Systemtime{Month: 11, Day: 1, Hour: 2},
	DaylightName: [32]uint16{
		'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
	},
	DaylightDate: syscall.Systemtime{Month: 3, Day: 2, Hour: 2},
	DaylightBias: -60,
}

func initTestingZone() {
	initLocalFromTZI(&usPacific)
}

func initLocal() {
	var i syscall.Timezoneinformation
	if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
		localLoc.name = "UTC"
		return
	}
	initLocalFromTZI(&i)
}

// TODO(rsc): Implement.
func loadLocation(name string) (*Location, error) {
	return nil, errors.New("unknown time zone " + name)
}
<commit_msg>time: fix windows build<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.

package time

import (
	"errors"
	"syscall"
)

// TODO(rsc): Fall back to copy of zoneinfo files.

// BUG(brainman,rsc): On Windows, the operating system does not provide complete
// time zone information.
// The implementation assumes that this year's rules for daylight savings
// time apply to all previous and future years as well.
// Also, time zone abbreviations are unavailable.  The implementation constructs
// them using the capital letters from a longer time zone description.

// abbrev returns the abbreviation to use for the given zone name.
func abbrev(name []uint16) string {
	// name is 'Pacific Standard Time' but we want 'PST'.
	// Extract just capital letters.  It's not perfect but the
	// information we need is not available from the kernel.
	// Because time zone abbreviations are not unique,
	// Windows refuses to expose them.
	//
	// http://social.msdn.microsoft.com/Forums/eu/vclanguage/thread/a87e1d25-fb71-4fe0-ae9c-a9578c9753eb
	// http://stackoverflow.com/questions/4195948/windows-time-zone-abbreviations-in-asp-net
	var short []rune
	for _, c := range name {
		if 'A' <= c && c <= 'Z' {
			short = append(short, rune(c))
		}
	}
	return string(short)
}

// pseudoUnix returns the pseudo-Unix time (seconds since Jan 1 1970 *LOCAL TIME*)
// denoted by the system date+time d in the given year.
// It is up to the caller to convert this local time into a UTC-based time.
func pseudoUnix(year int, d *syscall.Systemtime) int64 {
	// Windows specifies daylight savings information in "day in month" format:
	// d.Month is month number (1-12)
	// d.DayOfWeek is appropriate weekday (Sunday=0 to Saturday=6)
	// d.Day is week within the month (1 to 5, where 5 is last week of the month)
	// d.Hour, d.Minute and d.Second are absolute time
	day := 1
	t := Date(year, Month(d.Month), day, int(d.Hour), int(d.Minute), int(d.Second), 0, UTC)
	i := int(d.DayOfWeek) - int(t.Weekday())
	if i < 0 {
		i += 7
	}
	day += i
	if week := int(d.Day) - 1; week < 4 {
		day += week * 7
	} else {
		// "Last" instance of the day.
		day += 4 * 7
		if day > daysIn(Month(d.Month), year) {
			day -= 7
		}
	}
	return t.sec + int64(day-1)*secondsPerDay + internalToUnix
}

func initLocalFromTZI(i *syscall.Timezoneinformation) {
	l := &localLoc

	nzone := 1
	if i.StandardDate.Month > 0 {
		nzone++
	}
	l.zone = make([]zone, nzone)

	std := &l.zone[0]
	std.name = abbrev(i.StandardName[0:])
	if nzone == 1 {
		// No daylight savings.
		std.offset = -int(i.Bias) * 60
		l.cacheStart = -1 << 63
		l.cacheEnd = 1<<63 - 1
		l.cacheZone = std
		return
	}

	// StandardBias must be ignored if StandardDate is not set,
	// so this computation is delayed until after the nzone==1
	// return above.
	std.offset = -int(i.Bias+i.StandardBias) * 60

	dst := &l.zone[1]
	dst.name = abbrev(i.DaylightName[0:])
	dst.offset = -int(i.Bias+i.DaylightBias) * 60
	dst.isDST = true

	// Arrange so that d0 is first transition date, d1 second,
	// i0 is index of zone after first transition, i1 second.
	d0 := &i.StandardDate
	d1 := &i.DaylightDate
	i0 := 0
	i1 := 1
	if d0.Month > d1.Month {
		d0, d1 = d1, d0
		i0, i1 = i1, i0
	}

	// 2 tx per year, 100 years on each side of this year
	l.tx = make([]zoneTrans, 400)

	t := Now().UTC()
	year := t.Year()
	txi := 0
	for y := year - 100; y < year+100; y++ {
		tx := &l.tx[txi]
		tx.when = pseudoUnix(y, d0) - int64(l.zone[i1].offset)
		tx.index = uint8(i0)
		txi++

		tx = &l.tx[txi]
		tx.when = pseudoUnix(y, d1) - int64(l.zone[i0].offset)
		tx.index = uint8(i1)
		txi++
	}
}

var usPacific = syscall.Timezoneinformation{
	Bias: 8 * 60,
	StandardName: [32]uint16{
		'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
	},
	StandardDate: syscall.Systemtime{Month: 11, Day: 1, Hour: 2},
	DaylightName: [32]uint16{
		'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
	},
	DaylightDate: syscall.Systemtime{Month: 3, Day: 2, Hour: 2},
	DaylightBias: -60,
}

func initTestingZone() {
	initLocalFromTZI(&usPacific)
}

func initLocal() {
	var i syscall.Timezoneinformation
	if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
		localLoc.name = "UTC"
		return
	}
	initLocalFromTZI(&i)
}

// TODO(rsc): Implement.
func loadLocation(name string) (*Location, error) {
	return nil, errors.New("unknown time zone " + name)
}
<|endoftext|>