<commit_before>package main_test

import (
	"context"
	"crypto/tls"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"testing"

	"github.com/jackc/pgx/v4"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/vaughan0/go-ini"
)

func TestMain(m *testing.M) {
	err := exec.Command("go", "build", "-o", "tmp/tern").Run()
	if err != nil {
		fmt.Println("Failed to build tern binary:", err)
		os.Exit(1)
	}

	os.Exit(m.Run())
}

func readConfig(path string) (*pgx.ConnConfig, error) {
	file, err := ini.LoadFile(path)
	if err != nil {
		return nil, err
	}

	cp, _ := pgx.ParseConfig("")
	if s, ok := file.Get("database", "host"); ok {
		cp.Host = s
	}
	if p, ok := file.Get("database", "port"); ok {
		n, err := strconv.ParseUint(p, 10, 16)
		cp.Port = uint16(n)
		if err != nil {
			return nil, err
		}
	}

	if s, ok := file.Get("database", "database"); ok {
		cp.Database = s
	}
	if s, ok := file.Get("database", "user"); ok {
		cp.User = s
	}
	if s, ok := file.Get("database", "Password"); ok {
		cp.Password = s
	}

	return cp, nil
}

func connectConn(t *testing.T) *pgx.Conn {
	ctx := context.Background()
	connConfig, err := readConfig("testdata/tern.conf")
	require.NoError(t, err)

	connConfig.TLSConfig = &tls.Config{InsecureSkipVerify: true}

	conn, err := pgx.ConnectConfig(ctx, connConfig)
	if err != nil {
		connConfig.TLSConfig = nil
		conn, err = pgx.ConnectConfig(ctx, connConfig)
	}
	require.NoError(t, err)

	return conn
}

func tableExists(t *testing.T, tableName string) bool {
	ctx := context.Background()
	conn := connectConn(t)
	defer conn.Close(ctx)

	var exists bool
	err := conn.QueryRow(
		ctx,
		"select exists(select 1 from information_schema.tables where table_catalog=current_database() and table_name=$1)",
		tableName,
	).Scan(&exists)
	if err != nil {
		t.Fatal(err)
	}

	return exists
}

func currentVersion(t *testing.T) int32 {
	output := tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	re := regexp.MustCompile(`version:\s+(\d+)`)
	match := re.FindStringSubmatch(output)
	if match == nil {
		t.Fatalf("could not extract current version from status:\n%s", output)
	}

	n, err := strconv.ParseInt(match[1], 10, 32)
	if err != nil {
		t.Fatal(err)
	}

	return int32(n)
}

func tern(t *testing.T, args ...string) string {
	cmd := exec.Command("tmp/tern", args...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("tern failed with: %v\noutput:\n%v", err, string(output))
	}

	return string(output)
}

func TestInitWithoutDirectory(t *testing.T) {
	defer func() {
		os.Remove("tern.conf")
		os.Remove("001_create_people.sql.example")
	}()

	tern(t, "init")

	expectedFiles := []string{"tern.conf", "001_create_people.sql.example"}
	for _, f := range expectedFiles {
		_, err := os.Stat(f)
		if err != nil {
			t.Errorf(`Expected init to create "%s", but it didn't: %v`, f, err)
		}
	}
}

func TestInitWithDirectory(t *testing.T) {
	defer func() {
		os.RemoveAll("tmp/init")
	}()

	tern(t, "init", "tmp/init")

	expectedFiles := []string{"tmp/init/tern.conf", "tmp/init/001_create_people.sql.example"}
	for _, f := range expectedFiles {
		_, err := os.Stat(f)
		if err != nil {
			t.Errorf(`Expected init to create "%s", but it didn't: %v`, f, err)
		}
	}
}

func TestNew(t *testing.T) {
	path := "tmp/new"
	defer func() {
		os.RemoveAll(path)
	}()

	tern(t, "init", path)
	tern(t, "new", "-m", path, "first")
	tern(t, "new", "-m", path, "second")

	expectedFiles := []string{"tmp/new/001_first.sql", "tmp/new/002_second.sql"}
	for _, f := range expectedFiles {
		_, err := os.Stat(f)
		if err != nil {
			t.Errorf(`Expected init to create "%s", but it didn't: %v`, f, err)
		}
	}
}

func TestMigrate(t *testing.T) {
	tests := []struct {
		args              []string
		expectedExists    []string
		expectedNotExists []string
		expectedVersion   int32
	}{
		{[]string{"-d", "0"}, []string{}, []string{"t1", "t2"}, 0},
		{[]string{}, []string{"t1", "t2"}, []string{}, 2},
		{[]string{"-d", "1"}, []string{"t1"}, []string{"t2"}, 1},
		{[]string{"-d", "-1"}, []string{}, []string{"t1", "t2"}, 0},
		{[]string{"-d", "+1"}, []string{"t1"}, []string{"t2"}, 1},
		{[]string{"-d", "+1"}, []string{"t1", "t2"}, []string{}, 2},
		{[]string{"-d", "-+1"}, []string{"t1", "t2"}, []string{}, 2},
	}

	for i, tt := range tests {
		baseArgs := []string{"migrate", "-m", "testdata", "-c", "testdata/tern.conf"}
		args := append(baseArgs, tt.args...)

		tern(t, args...)

		for _, tableName := range tt.expectedExists {
			if !tableExists(t, tableName) {
				t.Fatalf("%d. Expected table %s to exist, but it doesn't", i, tableName)
			}
		}

		for _, tableName := range tt.expectedNotExists {
			if tableExists(t, tableName) {
				t.Fatalf("%d. Expected table %s to not exist, but it does", i, tableName)
			}
		}

		if currentVersion(t) != tt.expectedVersion {
			t.Fatalf(`Expected current version to be %d, but it was %d`, tt.expectedVersion, currentVersion(t))
		}
	}
}

func TestStatus(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	output := tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}

	// Up all the way
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf")

	output = tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	expected = `status:   up to date
version:  2 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}

	// Back one
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "1")

	output = tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	expected = `status:   migration(s) pending
version:  1 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestInstallCode(t *testing.T) {
	tern(t, "install-code", "-c", "testdata/tern.conf", "testdata/code")

	conn := connectConn(t)
	defer conn.Close(context.Background())

	var n int
	err := conn.QueryRow(context.Background(), "select add(1,2)").Scan(&n)
	require.NoError(t, err)
	assert.Equal(t, 3, n)
}

func TestCLIArgsWithoutConfigFile(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	connConfig, err := readConfig("testdata/tern.conf")
	if err != nil {
		t.Fatal(err)
	}

	output := tern(t, "status",
		"-m", "testdata",
		"--host", connConfig.Host,
		"--port", strconv.FormatInt(int64(connConfig.Port), 10),
		"--user", connConfig.User,
		"--password", connConfig.Password,
		"--database", connConfig.Database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestConfigFileTemplateEvalWithEnvVar(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	connConfig, err := readConfig("testdata/tern.conf")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Setenv("TERNHOST", connConfig.Host)
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		err := os.Unsetenv("TERNHOST")
		if err != nil {
			t.Fatal(err)
		}
	}()

	output := tern(t, "status",
		"-c", "testdata/tern-envvar-deprecated.conf",
		"-m", "testdata",
		"--port", strconv.FormatInt(int64(connConfig.Port), 10),
		"--user", connConfig.User,
		"--password", connConfig.Password,
		"--database", connConfig.Database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestConfigFileTemplateEvalWithDeprecatedEnvVar(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	connConfig, err := readConfig("testdata/tern.conf")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Setenv("TERNHOST", connConfig.Host)
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		err := os.Unsetenv("TERNHOST")
		if err != nil {
			t.Fatal(err)
		}
	}()

	output := tern(t, "status",
		"-c", "testdata/tern-envvar-deprecated.conf",
		"-m", "testdata",
		"--port", strconv.FormatInt(int64(connConfig.Port), 10),
		"--user", connConfig.User,
		"--password", connConfig.Password,
		"--database", connConfig.Database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestSSHTunnel(t *testing.T) {
	host := os.Getenv("TERN_HOST")
	if host == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_HOST environment variable")
	}

	user := os.Getenv("TERN_USER")
	if user == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_USER environment variable")
	}

	password := os.Getenv("TERN_PASSWORD")
	if password == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_PASSWORD environment variable")
	}

	database := os.Getenv("TERN_DATABASE")
	if database == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_DATABASE environment variable")
	}

	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	output := tern(t, "status",
		"-m", "testdata",
		"--ssh-host", "localhost",
		"--host", host,
		"--user", user,
		"--password", password,
		"--database", database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}
<commit_msg>Fix test<commit_after>package main_test

import (
	"context"
	"crypto/tls"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"testing"

	"github.com/jackc/pgx/v4"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/vaughan0/go-ini"
)

func TestMain(m *testing.M) {
	err := exec.Command("go", "build", "-o", "tmp/tern").Run()
	if err != nil {
		fmt.Println("Failed to build tern binary:", err)
		os.Exit(1)
	}

	os.Exit(m.Run())
}

func readConfig(path string) (*pgx.ConnConfig, error) {
	file, err := ini.LoadFile(path)
	if err != nil {
		return nil, err
	}

	cp, _ := pgx.ParseConfig("")
	if s, ok := file.Get("database", "host"); ok {
		cp.Host = s
	}
	if p, ok := file.Get("database", "port"); ok {
		n, err := strconv.ParseUint(p, 10, 16)
		cp.Port = uint16(n)
		if err != nil {
			return nil, err
		}
	}

	if s, ok := file.Get("database", "database"); ok {
		cp.Database = s
	}
	if s, ok := file.Get("database", "user"); ok {
		cp.User = s
	}
	if s, ok := file.Get("database", "Password"); ok {
		cp.Password = s
	}

	return cp, nil
}

func connectConn(t *testing.T) *pgx.Conn {
	ctx := context.Background()
	connConfig, err := readConfig("testdata/tern.conf")
	require.NoError(t, err)

	connConfig.TLSConfig = &tls.Config{InsecureSkipVerify: true}

	conn, err := pgx.ConnectConfig(ctx, connConfig)
	if err != nil {
		connConfig.TLSConfig = nil
		conn, err = pgx.ConnectConfig(ctx, connConfig)
	}
	require.NoError(t, err)

	return conn
}

func tableExists(t *testing.T, tableName string) bool {
	ctx := context.Background()
	conn := connectConn(t)
	defer conn.Close(ctx)

	var exists bool
	err := conn.QueryRow(
		ctx,
		"select exists(select 1 from information_schema.tables where table_catalog=current_database() and table_name=$1)",
		tableName,
	).Scan(&exists)
	if err != nil {
		t.Fatal(err)
	}

	return exists
}

func currentVersion(t *testing.T) int32 {
	output := tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	re := regexp.MustCompile(`version:\s+(\d+)`)
	match := re.FindStringSubmatch(output)
	if match == nil {
		t.Fatalf("could not extract current version from status:\n%s", output)
	}

	n, err := strconv.ParseInt(match[1], 10, 32)
	if err != nil {
		t.Fatal(err)
	}

	return int32(n)
}

func tern(t *testing.T, args ...string) string {
	cmd := exec.Command("tmp/tern", args...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("tern failed with: %v\noutput:\n%v", err, string(output))
	}

	return string(output)
}

func TestInitWithoutDirectory(t *testing.T) {
	defer func() {
		os.Remove("tern.conf")
		os.Remove("001_create_people.sql.example")
	}()

	tern(t, "init")

	expectedFiles := []string{"tern.conf", "001_create_people.sql.example"}
	for _, f := range expectedFiles {
		_, err := os.Stat(f)
		if err != nil {
			t.Errorf(`Expected init to create "%s", but it didn't: %v`, f, err)
		}
	}
}

func TestInitWithDirectory(t *testing.T) {
	defer func() {
		os.RemoveAll("tmp/init")
	}()

	tern(t, "init", "tmp/init")

	expectedFiles := []string{"tmp/init/tern.conf", "tmp/init/001_create_people.sql.example"}
	for _, f := range expectedFiles {
		_, err := os.Stat(f)
		if err != nil {
			t.Errorf(`Expected init to create "%s", but it didn't: %v`, f, err)
		}
	}
}

func TestNew(t *testing.T) {
	path := "tmp/new"
	defer func() {
		os.RemoveAll(path)
	}()

	tern(t, "init", path)
	tern(t, "new", "-m", path, "first")
	tern(t, "new", "-m", path, "second")

	expectedFiles := []string{"tmp/new/001_first.sql", "tmp/new/002_second.sql"}
	for _, f := range expectedFiles {
		_, err := os.Stat(f)
		if err != nil {
			t.Errorf(`Expected init to create "%s", but it didn't: %v`, f, err)
		}
	}
}

func TestMigrate(t *testing.T) {
	tests := []struct {
		args              []string
		expectedExists    []string
		expectedNotExists []string
		expectedVersion   int32
	}{
		{[]string{"-d", "0"}, []string{}, []string{"t1", "t2"}, 0},
		{[]string{}, []string{"t1", "t2"}, []string{}, 2},
		{[]string{"-d", "1"}, []string{"t1"}, []string{"t2"}, 1},
		{[]string{"-d", "-1"}, []string{}, []string{"t1", "t2"}, 0},
		{[]string{"-d", "+1"}, []string{"t1"}, []string{"t2"}, 1},
		{[]string{"-d", "+1"}, []string{"t1", "t2"}, []string{}, 2},
		{[]string{"-d", "-+1"}, []string{"t1", "t2"}, []string{}, 2},
	}

	for i, tt := range tests {
		baseArgs := []string{"migrate", "-m", "testdata", "-c", "testdata/tern.conf"}
		args := append(baseArgs, tt.args...)

		tern(t, args...)

		for _, tableName := range tt.expectedExists {
			if !tableExists(t, tableName) {
				t.Fatalf("%d. Expected table %s to exist, but it doesn't", i, tableName)
			}
		}

		for _, tableName := range tt.expectedNotExists {
			if tableExists(t, tableName) {
				t.Fatalf("%d. Expected table %s to not exist, but it does", i, tableName)
			}
		}

		if currentVersion(t) != tt.expectedVersion {
			t.Fatalf(`Expected current version to be %d, but it was %d`, tt.expectedVersion, currentVersion(t))
		}
	}
}

func TestStatus(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	output := tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}

	// Up all the way
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf")

	output = tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	expected = `status:   up to date
version:  2 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}

	// Back one
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "1")

	output = tern(t, "status", "-m", "testdata", "-c", "testdata/tern.conf")
	expected = `status:   migration(s) pending
version:  1 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestInstallCode(t *testing.T) {
	tern(t, "code", "install", "-c", "testdata/tern.conf", "testdata/code")

	conn := connectConn(t)
	defer conn.Close(context.Background())

	var n int
	err := conn.QueryRow(context.Background(), "select add(1,2)").Scan(&n)
	require.NoError(t, err)
	assert.Equal(t, 3, n)
}

func TestCLIArgsWithoutConfigFile(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	connConfig, err := readConfig("testdata/tern.conf")
	if err != nil {
		t.Fatal(err)
	}

	output := tern(t, "status",
		"-m", "testdata",
		"--host", connConfig.Host,
		"--port", strconv.FormatInt(int64(connConfig.Port), 10),
		"--user", connConfig.User,
		"--password", connConfig.Password,
		"--database", connConfig.Database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestConfigFileTemplateEvalWithEnvVar(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	connConfig, err := readConfig("testdata/tern.conf")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Setenv("TERNHOST", connConfig.Host)
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		err := os.Unsetenv("TERNHOST")
		if err != nil {
			t.Fatal(err)
		}
	}()

	output := tern(t, "status",
		"-c", "testdata/tern-envvar-deprecated.conf",
		"-m", "testdata",
		"--port", strconv.FormatInt(int64(connConfig.Port), 10),
		"--user", connConfig.User,
		"--password", connConfig.Password,
		"--database", connConfig.Database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestConfigFileTemplateEvalWithDeprecatedEnvVar(t *testing.T) {
	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	connConfig, err := readConfig("testdata/tern.conf")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Setenv("TERNHOST", connConfig.Host)
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		err := os.Unsetenv("TERNHOST")
		if err != nil {
			t.Fatal(err)
		}
	}()

	output := tern(t, "status",
		"-c", "testdata/tern-envvar-deprecated.conf",
		"-m", "testdata",
		"--port", strconv.FormatInt(int64(connConfig.Port), 10),
		"--user", connConfig.User,
		"--password", connConfig.Password,
		"--database", connConfig.Database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}

func TestSSHTunnel(t *testing.T) {
	host := os.Getenv("TERN_HOST")
	if host == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_HOST environment variable")
	}

	user := os.Getenv("TERN_USER")
	if user == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_USER environment variable")
	}

	password := os.Getenv("TERN_PASSWORD")
	if password == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_PASSWORD environment variable")
	}

	database := os.Getenv("TERN_DATABASE")
	if database == "" {
		t.Skip("Skipping SSH Tunnel test due to missing TERN_DATABASE environment variable")
	}

	// Ensure database is in clean state
	tern(t, "migrate", "-m", "testdata", "-c", "testdata/tern.conf", "-d", "0")

	output := tern(t, "status",
		"-m", "testdata",
		"--ssh-host", "localhost",
		"--host", host,
		"--user", user,
		"--password", password,
		"--database", database,
	)
	expected := `status:   migration(s) pending
version:  0 of 2`
	if !strings.Contains(output, expected) {
		t.Errorf("Expected status output to contain `%s`, but it didn't. Output:\n%s", expected, output)
	}
}
<|endoftext|>


<commit_before>// errchk $G -e $D/$F.go

// 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 main

func sum(args ...int) int { return 0 }

var (
	_ = sum(1, 2, 3)
	_ = sum()
	_ = sum(1.0, 2.0)
	_ = sum(1.5)      // ERROR "integer"
	_ = sum("hello")  // ERROR "convert"
	_ = sum([]int{1}) // ERROR "slice literal.*as type int"
)

type T []T

func funny(args ...T) int { return 0 }

var (
	_ = funny(nil)
	_ = funny(nil, nil)
	_ = funny([]T{}) // ok because []T{} is a T; passes []T{[]T{}}
)
<commit_msg>Match gccgo error messages.<commit_after>// errchk $G -e $D/$F.go

// 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 main

func sum(args ...int) int { return 0 }

var (
	_ = sum(1, 2, 3)
	_ = sum()
	_ = sum(1.0, 2.0)
	_ = sum(1.5)      // ERROR "integer"
	_ = sum("hello")  // ERROR "convert|incompatible"
	_ = sum([]int{1}) // ERROR "slice literal.*as type int|incompatible"
)

type T []T

func funny(args ...T) int { return 0 }

var (
	_ = funny(nil)
	_ = funny(nil, nil)
	_ = funny([]T{}) // ok because []T{} is a T; passes []T{[]T{}}
)
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type Item struct {
	People     int       `json:"people"`
	Attendant  int       `json:"attendant"`
	Image      string    `json:"image"`
	CreateTime time.Time `json:"createtime"`
}

// Target server
const ItemURL = "https://testgcsserver.appspot.com/api/0.1/"
// const ItemURL = "http://127.0.0.1:8080/api/0.1/"

const ItemMinPeople = 2
const ItemMaxPeople = 5

// Pring an Item
func (b Item) String() string {
	s := ""
	s += fmt.Sprintln("People:", b.People)
	s += fmt.Sprintln("Attendant:", b.Attendant)
	s += fmt.Sprintln("Image:", b.Image)
	s += fmt.Sprintln("CreateTime:", b.CreateTime)
	return s
}

func queryAll() {
	// Send request
	resp, err := http.Get(ItemURL + "items")
	if err != nil {
		fmt.Println(err)
		return
	}

	// Print status
	fmt.Println(resp.Status, resp.StatusCode)

	// Get body
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Decode body
	var items map[string]Item = make(map[string]Item)
	if resp.StatusCode == http.StatusOK {
		// Decode as JSON
		if err := json.Unmarshal(body, &items); err != nil {
			fmt.Println(err, "in decoding JSON")
			return
		}
		for i, v := range items {
			fmt.Println("-------------------------------")
			fmt.Println("Key:", i)
			fmt.Println(v)
		}
		fmt.Println("Total", len(items), "items")
	} else {
		// Decode as text
		fmt.Printf("%s", body)
	}
}

func queryItem() {
	// Make URL
	var u *url.URL
	var err error
	if u, err = url.ParseRequestURI(ItemURL + "items"); err != nil {
		fmt.Println(err, "in making URL")
		return
	}
	var q url.Values = u.Query()
	q.Add("People", rand.Intn(ItemMaxPeople - ItemMinPeople) + ItemMinPeople)
	u.RawQuery = q.Encode()

	// Send request
	resp, err := http.Get(u.String())
	if err != nil {
		fmt.Println(err)
		return
	}

	// Print status
	fmt.Println(resp.Status, resp.StatusCode)

	// Get body
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Decode body
	var items map[string]Item = make(map[string]Item)
	if resp.StatusCode == http.StatusOK {
		// Decode as JSON
		if err := json.Unmarshal(body, &items); err != nil {
			fmt.Println(err, "in decoding JSON")
			return
		}
		for i, v := range items {
			fmt.Println("-------------------------------")
			fmt.Println("Key:", i)
			fmt.Println(v)
		}
		fmt.Println("Total", len(items), "items")
	} else {
		// Decode as text
		fmt.Printf("%s", body)
	}
}

// Return
// int = 0: success
//       1: failed
// string is the new item's unique key
func storeItem(imgUrl string) (r int, key string) {
	// Return value
	r = 0
	key = ""

	// Make body
	item := Item{
		People:     rand.Intn(rand.Intn(ItemMaxPeople - ItemMinPeople) + ItemMinPeople),
		Attendant:  1,
		Image:      imgUrl,
		CreateTime: time.Now(),
	}
	b, err := json.Marshal(item)
	if err != nil {
		fmt.Println(err, "in encoding a item as JSON")
		r = 1
		return
	}

	// Send request
	resp, err := http.Post(ItemURL+"items", "application/json", bytes.NewReader(b))
	if err != nil {
		fmt.Println(err)
		r = 1
		return
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode != http.StatusCreated {
		r = 1
		return
	}
	url, err := resp.Location()
	if err != nil {
		fmt.Println(err, "in getting location from response")
		return
	}
	fmt.Println("Location is", url)

	// Get key from URL
	tokens := strings.Split(url.Path, "/")
	var keyIndexInTokens int = 0
	for i, v := range tokens {
		if v == "items" {
			keyIndexInTokens = i + 1
		}
	}
	if keyIndexInTokens >= len(tokens) {
		fmt.Println("Key is not given")
		return
	}
	key = tokens[keyIndexInTokens]
	if key == "" {
		fmt.Println("Key is empty")
		return
	}
	return
}

// Return 0: success
// Return 1: failed
func deleteItem(key string) int {
	// Send request
	pReq, err := http.NewRequest("DELETE", ItemURL+"items/"+key, nil)
	if err != nil {
		fmt.Println(err, "in making request")
		return 1
	}
	resp, err := http.DefaultClient.Do(pReq)
	if err != nil {
		fmt.Println(err, "in sending request")
		return 1
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode == http.StatusOK {
		return 0
	} else {
		return 1
	}
}

// Return 0: success
// Return 1: failed
func deleteAll() int {
	// Send request
	pReq, err := http.NewRequest("DELETE", ItemURL+"items", nil)
	if err != nil {
		fmt.Println(err, "in making request")
		return 1
	}
	resp, err := http.DefaultClient.Do(pReq)
	if err != nil {
		fmt.Println(err, "in sending request")
		return 1
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode == http.StatusOK {
		return 0
	} else {
		return 1
	}
}

// Return
// int = 0: success
//       1: failed
// TODO: return the new item's unique key as a string
func storeImage() (r int) {
	// Return value
	r = 0

	// Read file
	b, err := ioutil.ReadFile("Hydrangeas.jpg")
	if err != nil {
		fmt.Println(err, "in reading file")
		r = 1
		return
	}

	// Vernon debug
	fmt.Println("File length:", len(b))

	// Send request
	resp, err := http.Post(ItemURL+"storeImage", "image/jpeg", bytes.NewReader(b))
	if err != nil {
		fmt.Println(err)
		r = 1
		return
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode != http.StatusCreated {
		// Get data from body
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err, "in reading body")
			r = 1
			return
		}
		fmt.Printf("%s\n", b)

		r = 1
		return
	}
	url, err := resp.Location()
	if err != nil {
		fmt.Println(err, "in getting location from response")
		return
	}
	fmt.Println("Location is", url)

	// Get key from URL
	// tokens := strings.Split(url.Path, "/")
	// var keyIndexInTokens int = 0
	// for i, v := range tokens {
	// 	if v == "items" {
	// 		keyIndexInTokens = i + 1
	// 	}
	// }
	// if keyIndexInTokens >= len(tokens) {
	// 	fmt.Println("Key is not given")
	// 	return
	// }
	// key = tokens[keyIndexInTokens]
	// if key == "" {
	// 	fmt.Println("Key is empty")
	// 	return
	// }
	return
}

// TODO: design a test plan
func main() {
	storeImage()
	// // Random seed
	// rand.Seed(time.Now().Unix())

	// // Test suite
	// fmt.Println("========================================")
	// if storeTen() != 0 {
	// 	fmt.Println("Store items failed")
	// 	return
	// } else {
	// 	fmt.Println("Store 10 items")
	// }
	// fmt.Println("========================================")
	// r, key := storeItem()
	// if r != 0 {
	// 	fmt.Println("Store a item failed")
	// 	return
	// } else {
	// 	fmt.Println("Store a item in key", key)
	// }
	// fmt.Println("========================================")
	// queryAll()
	// fmt.Println("========================================")
	// queryItem()
	// fmt.Println("========================================")
	// if deleteItem(key) != 0 {
	// 	fmt.Println("Failed to delete item key", key)
	// 	return
	// } else {
	// 	fmt.Println("Delete item key", key)
	// }
	// fmt.Println("========================================")
	// if deleteAll() != 0 {
	// 	fmt.Println("Delete failed")
	// 	return
	// } else {
	// 	fmt.Println("Delete all")
	// }
}
<commit_msg>Finish test plan. TODO: strange people value in queryItem()<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type Item struct {
	People     int       `json:"people"`
	Attendant  int       `json:"attendant"`
	Image      string    `json:"image"`
	CreateTime time.Time `json:"createtime"`
}

// Target server
const ItemURL = "https://testgcsserver.appspot.com/api/0.1/"
// const ItemURL = "http://127.0.0.1:8080/api/0.1/"

const ItemMinPeople = 2
const ItemMaxPeople = 5

// Pring an Item
func (b Item) String() string {
	s := ""
	s += fmt.Sprintln("People:", b.People)
	s += fmt.Sprintln("Attendant:", b.Attendant)
	s += fmt.Sprintln("Image:", b.Image)
	s += fmt.Sprintln("CreateTime:", b.CreateTime)
	return s
}

func queryAll() {
	// Send request
	resp, err := http.Get(ItemURL + "items")
	if err != nil {
		fmt.Println(err)
		return
	}

	// Print status
	fmt.Println(resp.Status, resp.StatusCode)

	// Get body
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Decode body
	var items map[string]Item = make(map[string]Item)
	if resp.StatusCode == http.StatusOK {
		// Decode as JSON
		if err := json.Unmarshal(body, &items); err != nil {
			fmt.Println(err, "in decoding JSON")
			return
		}
		for i, v := range items {
			fmt.Println("-------------------------------")
			fmt.Println("Key:", i)
			fmt.Println(v)
		}
		fmt.Println("Total", len(items), "items")
	} else {
		// Decode as text
		fmt.Printf("%s", body)
	}
}

func queryItem() {
	// Make URL
	var u *url.URL
	var err error
	if u, err = url.ParseRequestURI(ItemURL + "items"); err != nil {
		fmt.Println(err, "in making URL")
		return
	}
	var q url.Values = u.Query()
	var people int = rand.Intn(ItemMaxPeople - ItemMinPeople) + ItemMinPeople
	q.Add("People", strconv.Itoa(people))
	u.RawQuery = q.Encode()
	fmt.Println("Query people = ", people)

	// Send request
	resp, err := http.Get(u.String())
	if err != nil {
		fmt.Println(err)
		return
	}

	// Print status
	fmt.Println(resp.Status, resp.StatusCode)

	// Get body
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Decode body
	var items map[string]Item = make(map[string]Item)
	if resp.StatusCode == http.StatusOK {
		// Decode as JSON
		if err := json.Unmarshal(body, &items); err != nil {
			fmt.Println(err, "in decoding JSON")
			return
		}
		for i, v := range items {
			fmt.Println("-------------------------------")
			fmt.Println("Key:", i)
			fmt.Println(v)
		}
		fmt.Println("Total", len(items), "items")
	} else {
		// Decode as text
		fmt.Printf("%s", body)
	}
}

// Return
// int = 0: success
//       1: failed
// string is the new item's unique key
func storeItem(imgUrl string) (r int, key string) {
	// Return value
	r = 0
	key = ""

	// Make body
	item := Item{
		People:     (rand.Intn(ItemMaxPeople - ItemMinPeople) + ItemMinPeople),
		Attendant:  1,
		Image:      imgUrl,
		CreateTime: time.Now(),
	}
	b, err := json.Marshal(item)
	if err != nil {
		fmt.Println(err, "in encoding a item as JSON")
		r = 1
		return
	}

	// Send request
	resp, err := http.Post(ItemURL+"items", "application/json", bytes.NewReader(b))
	if err != nil {
		fmt.Println(err)
		r = 1
		return
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode != http.StatusCreated {
		r = 1
		return
	}
	url, err := resp.Location()
	if err != nil {
		fmt.Println(err, "in getting location from response")
		return
	}
	fmt.Println("Location is", url)

	// Get key from URL
	tokens := strings.Split(url.Path, "/")
	var keyIndexInTokens int = 0
	for i, v := range tokens {
		if v == "items" {
			keyIndexInTokens = i + 1
		}
	}
	if keyIndexInTokens >= len(tokens) {
		fmt.Println("Key is not given")
		return
	}
	key = tokens[keyIndexInTokens]
	if key == "" {
		fmt.Println("Key is empty")
		return
	}
	return
}

// Return 0: success
// Return 1: failed
func deleteItem(key string) int {
	// Send request
	pReq, err := http.NewRequest("DELETE", ItemURL+"items/"+key, nil)
	if err != nil {
		fmt.Println(err, "in making request")
		return 1
	}
	resp, err := http.DefaultClient.Do(pReq)
	if err != nil {
		fmt.Println(err, "in sending request")
		return 1
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode == http.StatusOK {
		return 0
	} else {
		return 1
	}
}

// Return 0: success
// Return 1: failed
func deleteAll() int {
	// Send request
	pReq, err := http.NewRequest("DELETE", ItemURL+"items", nil)
	if err != nil {
		fmt.Println(err, "in making request")
		return 1
	}
	resp, err := http.DefaultClient.Do(pReq)
	if err != nil {
		fmt.Println(err, "in sending request")
		return 1
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode == http.StatusOK {
		return 0
	} else {
		return 1
	}
}

// Return
// url = "http://xxx": success
//       "": failed
func storeImage() (urlstring string) {
	// Return value
	urlstring = ""

	// Read file
	b, err := ioutil.ReadFile("Hydrangeas.jpg")
	if err != nil {
		fmt.Println(err, "in reading file")
		return
	}

	// Vernon debug
	fmt.Println("File length:", len(b))

	// Send request
	resp, err := http.Post(ItemURL+"storeImage", "image/jpeg", bytes.NewReader(b))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status, resp.StatusCode)
	if resp.StatusCode != http.StatusCreated {
		// Get data from body
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err, "in reading body")
			return
		}
		fmt.Printf("%s\n", b)
		return
	}
	url, err := resp.Location()
	if err != nil {
		fmt.Println(err, "in getting location from response")
		return
	}
	urlstring = url.String()
	fmt.Println("Location is", urlstring)

	return
}

// TODO: design a test plan
func main() {
	var num int = 5
	var r int
	var key string

	// Random seed
	rand.Seed(time.Now().Unix())

	// Test suite
	fmt.Println("========================================")
	fmt.Println("Store an image")
	fmt.Println("========================================")
	imageUrlString := storeImage()
	if imageUrlString == "" {
		fmt.Println("Store an image failed")
		return
	} else {
		fmt.Println("Store an image " + imageUrlString)
	}

	fmt.Println("========================================")
	fmt.Printf("Store %d items of the image\n", num)
	fmt.Println("========================================")
	for i := 1; i <= num; i++ {
		r, key = storeItem(imageUrlString)
		if r != 0 {
			fmt.Printf("Store item %d failed\n", i)
			return
		} else {
			fmt.Printf("Store item %d in key %s\n", i, key)
		}
	}
	fmt.Println("========================================")
	fmt.Println("Query all items")
	fmt.Println("========================================")
	queryAll()

	fmt.Println("========================================")
	fmt.Println("Query the item")
	fmt.Println("========================================")
	queryItem()

	fmt.Println("========================================")
	fmt.Println("Delete the last item")
	fmt.Println("========================================")
	if deleteItem(key) != 0 {
		fmt.Println("Failed to delete item key", key)
		return
	} else {
		fmt.Println("Delete item key", key)
	}
	fmt.Println("========================================")
	fmt.Println("Delete all items")
	fmt.Println("========================================")
	if deleteAll() != 0 {
		fmt.Println("Delete failed")
		return
	} else {
		fmt.Println("Delete all")
	}
}
<|endoftext|>


<commit_before>package test

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strings"

	"github.com/bitrise-io/bitrise/models"
	"github.com/bitrise-io/go-utils/colorstring"
	"github.com/bitrise-io/go-utils/fileutil"
	"github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-xcode/utility"
	"github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters"
)

// FileInfo ...
type FileInfo struct {
	FileName string `json:"filename"`
	FileSize int    `json:"filesize"`
}

// UploadURL ...
type UploadURL struct {
	FileName string `json:"filename"`
	URL      string `json:"upload_url"`
}

// UploadRequest ...
type UploadRequest struct {
	Name   string                    `json:"name"`
	Step   models.TestResultStepInfo `json:"step_info"`
	Assets []FileInfo                `json:"assets"`
	FileInfo
}

// UploadResponse ...
type UploadResponse struct {
	ID     string      `json:"id"`
	Assets []UploadURL `json:"assets"`
	UploadURL
}

// Result ...
type Result struct {
	Name       string
	XMLContent []byte
	ImagePaths []string
	StepInfo   models.TestResultStepInfo
}

// Results ...
type Results []Result

func httpCall(apiToken, method, url string, input io.Reader, output interface{}) error {
	if apiToken != "" {
		url = url + "/" + apiToken
	}
	req, err := http.NewRequest(method, url, input)
	if err != nil {
		return err
	}

	b, err := httputil.DumpRequest(req, true)
	if err != nil {
		return err
	}
	fmt.Println(string(b))

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}

	b, err = httputil.DumpResponse(resp, true)
	if err != nil {
		return err
	}
	log.Debugf(string(b))

	defer func() {
		if err := resp.Body.Close(); err != nil {
			fmt.Printf("Failed to close body, error: %s\n", err)
		}
	}()

	if resp.StatusCode < 200 || 299 < resp.StatusCode {
		bodyData, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("unsuccessful response code: %d and failed to read body, error: %s", resp.StatusCode, err)
		}
		return fmt.Errorf("unsuccessful response code: %d\nbody:\n%s", resp.StatusCode, bodyData)
	}

	if output != nil {
		return json.NewDecoder(resp.Body).Decode(&output)
	}
	return nil
}

func findImages(testDir string) (imageFilePaths []string) {
	for _, ext := range []string{".jpg", ".jpeg", ".png"} {
		if paths, err := filepath.Glob(filepath.Join(testDir, "*"+ext)); err == nil {
			imageFilePaths = append(imageFilePaths, paths...)
		}
		if paths, err := filepath.Glob(filepath.Join(testDir, "*"+strings.ToUpper(ext))); err == nil {
			imageFilePaths = append(imageFilePaths, paths...)
		}
	}
	return
}

// ParseTestResults ...
func ParseTestResults(testsRootDir string) (results Results, err error) {
	// read dirs in base tests dir
	// <root_tests_dir>

	testDirs, err := ioutil.ReadDir(testsRootDir)
	if err != nil {
		return nil, err
	}

	// find test results in each dir, skip if invalid test dir
	for _, testDir := range testDirs {
		// <root_tests_dir>/<test_dir>
		testDirPath := filepath.Join(testsRootDir, testDir.Name())

		if !testDir.IsDir() {
			log.Debugf(colorstring.Yellowf("%s is not a directory", testDirPath))
			continue
		}

		// read unique test phase dirs
		testPhaseDirs, err := ioutil.ReadDir(testDirPath)
		if err != nil {
			return nil, err
		}

		// find step-info in dir, continue if no step-info.json as this file is only required if step has exported artifacts also
		// <root_tests_dir>/<test_dir>/step-info.json
		var stepInfo *models.TestResultStepInfo
		stepInfoFileContent, err := fileutil.ReadBytesFromFile(filepath.Join(testDirPath, "step-info.json"))
		if err != nil {
			log.Debugf(colorstring.Yellowf("Failed to read step-info.json file in dir: %s, error: %s", testDirPath, err))
			continue
		}

		if err := json.Unmarshal(stepInfoFileContent, &stepInfo); err != nil {
			continue
		}

		for _, testPhaseDir := range testPhaseDirs {
			if !testPhaseDir.IsDir() {
				continue
			}

			// <root_tests_dir>/<test_dir>/<unique_dir>
			testPhaseDirPath := filepath.Join(testDirPath, testPhaseDir.Name())
			// read one level of file set only <root_tests_dir>/<test_dir>/<unique_dir>/files_to_get
			testFiles, err := filepath.Glob(filepath.Join(utility.EscapeGlobPath(testPhaseDirPath), "*"))
			if err != nil {
				return nil, err
			}

			// get the converter that can manage test type contained in the dir
			for _, converter := range converters.List() {

				// skip if couldn't find converter for content type
				if converter.Detect(testFiles) {
					// test-info.json file is required
					testInfoFileContent, err := fileutil.ReadBytesFromFile(filepath.Join(testPhaseDirPath, "test-info.json"))
					if err != nil {
						return nil, err
					}

					var testInfo struct {
						Name string `json:"test-name"`
					}
					if err := json.Unmarshal(testInfoFileContent, &testInfo); err != nil {
						return nil, err
					}

					junitXML, err := converter.XML()
					if err != nil {
						return nil, err
					}
					xmlData, err := xml.MarshalIndent(junitXML, "", " ")
					if err != nil {
						return nil, err
					}
					xmlData = append([]byte(`<?xml version="1.0" encoding="UTF-8"?>`+"\n"), xmlData...)

					// so here I will have image paths, xml data, and step info per test dir in a bundle info
					results = append(results, Result{
						Name:       testInfo.Name,
						XMLContent: xmlData,
						ImagePaths: findImages(testPhaseDirPath),
						StepInfo:   *stepInfo,
					})
				}
			}
		}
	}
	return results, nil
}

// Upload ...
func (results Results) Upload(apiToken, endpointBaseURL, appSlug, buildSlug string) error {
	for _, result := range results {
		uploadReq := UploadRequest{
			FileInfo: FileInfo{
				FileName: "test_result.xml",
				FileSize: len(result.XMLContent),
			},
			Name: result.Name,
			Step: result.StepInfo,
		}
		for _, asset := range result.ImagePaths {
			fi, err := os.Stat(asset)
			if err != nil {
				return err
			}
			uploadReq.Assets = append(uploadReq.Assets, FileInfo{
				FileName: filepath.Base(asset),
				FileSize: int(fi.Size()),
			})
		}

		uploadRequestBodyData, err := json.Marshal(uploadReq)
		if err != nil {
			return err
		}

		var (
			uploadResponse   UploadResponse
			uploadRequestURL = fmt.Sprintf("%s/apps/%s/builds/%s/test_reports", endpointBaseURL, appSlug, buildSlug)
		)
		if err := httpCall(apiToken, http.MethodPost, uploadRequestURL, bytes.NewReader(uploadRequestBodyData), &uploadResponse); err != nil {
			return err
		}

		if err := httpCall("", http.MethodPut, uploadResponse.URL, bytes.NewReader(result.XMLContent), nil); err != nil {
			return err
		}

		for _, upload := range uploadResponse.Assets {
			for _, file := range result.ImagePaths {
				if filepath.Base(file) == upload.FileName {
					fi, err := os.Open(file)
					if err != nil {
						return err
					}
					if err := httpCall("", http.MethodPut, upload.URL, fi, nil); err != nil {
						return err
					}
					break
				}
			}
		}

		var uploadPatchURL = fmt.Sprintf("%s/apps/%s/builds/%s/test_reports/%s", endpointBaseURL, appSlug, buildSlug, uploadResponse.ID)
		if err := httpCall(apiToken, http.MethodPatch, uploadPatchURL, strings.NewReader(`{"uploaded":true}`), nil); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>remove logs (#82)<commit_after>package test

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strings"

	"github.com/bitrise-io/bitrise/models"
	"github.com/bitrise-io/go-utils/colorstring"
	"github.com/bitrise-io/go-utils/fileutil"
	"github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-xcode/utility"
	"github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters"
)

// FileInfo ...
type FileInfo struct {
	FileName string `json:"filename"`
	FileSize int    `json:"filesize"`
}

// UploadURL ...
type UploadURL struct {
	FileName string `json:"filename"`
	URL      string `json:"upload_url"`
}

// UploadRequest ...
type UploadRequest struct {
	Name   string                    `json:"name"`
	Step   models.TestResultStepInfo `json:"step_info"`
	Assets []FileInfo                `json:"assets"`
	FileInfo
}

// UploadResponse ...
type UploadResponse struct {
	ID     string      `json:"id"`
	Assets []UploadURL `json:"assets"`
	UploadURL
}

// Result ...
type Result struct {
	Name       string
	XMLContent []byte
	ImagePaths []string
	StepInfo   models.TestResultStepInfo
}

// Results ...
type Results []Result

func httpCall(apiToken, method, url string, input io.Reader, output interface{}) error {
	if apiToken != "" {
		url = url + "/" + apiToken
	}
	req, err := http.NewRequest(method, url, input)
	if err != nil {
		return err
	}

	b, err := httputil.DumpRequest(req, true)
	if err != nil {
		return err
	}
	log.Debugf(string(b))

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}

	b, err = httputil.DumpResponse(resp, true)
	if err != nil {
		return err
	}
	log.Debugf(string(b))

	defer func() {
		if err := resp.Body.Close(); err != nil {
			fmt.Printf("Failed to close body, error: %s\n", err)
		}
	}()

	if resp.StatusCode < 200 || 299 < resp.StatusCode {
		bodyData, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("unsuccessful response code: %d and failed to read body, error: %s", resp.StatusCode, err)
		}
		return fmt.Errorf("unsuccessful response code: %d\nbody:\n%s", resp.StatusCode, bodyData)
	}

	if output != nil {
		return json.NewDecoder(resp.Body).Decode(&output)
	}
	return nil
}

func findImages(testDir string) (imageFilePaths []string) {
	for _, ext := range []string{".jpg", ".jpeg", ".png"} {
		if paths, err := filepath.Glob(filepath.Join(testDir, "*"+ext)); err == nil {
			imageFilePaths = append(imageFilePaths, paths...)
		}
		if paths, err := filepath.Glob(filepath.Join(testDir, "*"+strings.ToUpper(ext))); err == nil {
			imageFilePaths = append(imageFilePaths, paths...)
		}
	}
	return
}

// ParseTestResults ...
func ParseTestResults(testsRootDir string) (results Results, err error) {
	// read dirs in base tests dir
	// <root_tests_dir>

	testDirs, err := ioutil.ReadDir(testsRootDir)
	if err != nil {
		return nil, err
	}

	// find test results in each dir, skip if invalid test dir
	for _, testDir := range testDirs {
		// <root_tests_dir>/<test_dir>
		testDirPath := filepath.Join(testsRootDir, testDir.Name())

		if !testDir.IsDir() {
			log.Debugf(colorstring.Yellowf("%s is not a directory", testDirPath))
			continue
		}

		// read unique test phase dirs
		testPhaseDirs, err := ioutil.ReadDir(testDirPath)
		if err != nil {
			return nil, err
		}

		// find step-info in dir, continue if no step-info.json as this file is only required if step has exported artifacts also
		// <root_tests_dir>/<test_dir>/step-info.json
		var stepInfo *models.TestResultStepInfo
		stepInfoFileContent, err := fileutil.ReadBytesFromFile(filepath.Join(testDirPath, "step-info.json"))
		if err != nil {
			log.Debugf(colorstring.Yellowf("Failed to read step-info.json file in dir: %s, error: %s", testDirPath, err))
			continue
		}

		if err := json.Unmarshal(stepInfoFileContent, &stepInfo); err != nil {
			continue
		}

		for _, testPhaseDir := range testPhaseDirs {
			if !testPhaseDir.IsDir() {
				continue
			}

			// <root_tests_dir>/<test_dir>/<unique_dir>
			testPhaseDirPath := filepath.Join(testDirPath, testPhaseDir.Name())
			// read one level of file set only <root_tests_dir>/<test_dir>/<unique_dir>/files_to_get
			testFiles, err := filepath.Glob(filepath.Join(utility.EscapeGlobPath(testPhaseDirPath), "*"))
			if err != nil {
				return nil, err
			}

			// get the converter that can manage test type contained in the dir
			for _, converter := range converters.List() {

				// skip if couldn't find converter for content type
				if converter.Detect(testFiles) {
					// test-info.json file is required
					testInfoFileContent, err := fileutil.ReadBytesFromFile(filepath.Join(testPhaseDirPath, "test-info.json"))
					if err != nil {
						return nil, err
					}

					var testInfo struct {
						Name string `json:"test-name"`
					}
					if err := json.Unmarshal(testInfoFileContent, &testInfo); err != nil {
						return nil, err
					}

					junitXML, err := converter.XML()
					if err != nil {
						return nil, err
					}
					xmlData, err := xml.MarshalIndent(junitXML, "", " ")
					if err != nil {
						return nil, err
					}
					xmlData = append([]byte(`<?xml version="1.0" encoding="UTF-8"?>`+"\n"), xmlData...)

					// so here I will have image paths, xml data, and step info per test dir in a bundle info
					results = append(results, Result{
						Name:       testInfo.Name,
						XMLContent: xmlData,
						ImagePaths: findImages(testPhaseDirPath),
						StepInfo:   *stepInfo,
					})
				}
			}
		}
	}
	return results, nil
}

// Upload ...
func (results Results) Upload(apiToken, endpointBaseURL, appSlug, buildSlug string) error {
	for _, result := range results {
		uploadReq := UploadRequest{
			FileInfo: FileInfo{
				FileName: "test_result.xml",
				FileSize: len(result.XMLContent),
			},
			Name: result.Name,
			Step: result.StepInfo,
		}
		for _, asset := range result.ImagePaths {
			fi, err := os.Stat(asset)
			if err != nil {
				return err
			}
			uploadReq.Assets = append(uploadReq.Assets, FileInfo{
				FileName: filepath.Base(asset),
				FileSize: int(fi.Size()),
			})
		}

		uploadRequestBodyData, err := json.Marshal(uploadReq)
		if err != nil {
			return err
		}

		var (
			uploadResponse   UploadResponse
			uploadRequestURL = fmt.Sprintf("%s/apps/%s/builds/%s/test_reports", endpointBaseURL, appSlug, buildSlug)
		)
		if err := httpCall(apiToken, http.MethodPost, uploadRequestURL, bytes.NewReader(uploadRequestBodyData), &uploadResponse); err != nil {
			return err
		}

		if err := httpCall("", http.MethodPut, uploadResponse.URL, bytes.NewReader(result.XMLContent), nil); err != nil {
			return err
		}

		for _, upload := range uploadResponse.Assets {
			for _, file := range result.ImagePaths {
				if filepath.Base(file) == upload.FileName {
					fi, err := os.Open(file)
					if err != nil {
						return err
					}
					if err := httpCall("", http.MethodPut, upload.URL, fi, nil); err != nil {
						return err
					}
					break
				}
			}
		}

		var uploadPatchURL = fmt.Sprintf("%s/apps/%s/builds/%s/test_reports/%s", endpointBaseURL, appSlug, buildSlug, uploadResponse.ID)
		if err := httpCall(apiToken, http.MethodPatch, uploadPatchURL, strings.NewReader(`{"uploaded":true}`), nil); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package timeutils

import "time"

//Constants
var stdDaysInMonth = [13]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

const (
	februaryLeapYearLength = 29
)

//Now a simple wrapper of time.Time
type Now struct {
	time.Time
}

//New return a new instance of Now
func New(n time.Time) *Now {
	return &Now{n}
}

//Tomorrow return a time instance for tomorrows date at the same time
func (t *Now) Tomorrow() time.Time {
	return t.AddDate(0, 0, 1)
}

//TomorrowAtTime return a time instance for tomorrow's date at a given time of day
func (t *Now) TomorrowAtTime(w time.Time) time.Time {
	tn := t.Tomorrow()
	return time.Date(tn.Year(), tn.Month(), tn.Day(), w.Hour(), w.Minute(), w.Second(), w.Nanosecond(), w.Location())
}

//TomorrowDayOfWeek return the day of the week of tomorrow
func (t *Now) TomorrowDayOfWeek() time.Weekday {
	return t.Tomorrow().Weekday()
}

//Yesterday return a time instance for yesterday's date at the same time
func (t *Now) Yesterday() time.Time {
	//return t.Add(-time.Duration(24) * time.Hour)
	return t.AddDate(0, 0, -1)
}

//YesterdayAtTime return a time instance for yesterday's date at a given time of day
func (t *Now) YesterdayAtTime(w time.Time) time.Time {
	tn := t.Yesterday()
	return time.Date(tn.Year(), tn.Month(), tn.Day(), w.Hour(), w.Minute(), w.Second(), w.Nanosecond(), w.Location())
}

//YesterdayDayOfWeek return the day of week of yesterday
func (t *Now) YesterdayDayOfWeek() time.Weekday {
	return t.Yesterday().Weekday()
}

//DayOfWeekAfterNDays return the day of week after a specified number of days from the given time instance
func (t *Now) DayOfWeekAfterNDays(n int) time.Weekday {
	return t.Add(time.Duration(24*n) * time.Hour).Weekday()
}

//IsLeap return true if the Year in t is a leap year
func (t *Now) IsLeap() bool {
	return (t.Year()%400 == 0 || (t.Year()%100 != 0 && t.Year()%4 == 0))
}

//DaysInMonth return the number of days in the month which t is in
func (t *Now) DaysInMonth() int {
	if t.Month() == time.February && t.IsLeap() {
		return februaryLeapYearLength
	}
	return stdDaysInMonth[t.Month()]
}

//AddDays add a number of days at Now
func (t *Now) AddDays(n int) time.Time {
	//return t.Add(time.Duration(24*n) * time.Hour)
	return t.AddDate(0, 0, n)
}

//Since return a time instance representing the time a given seconds since the instance time
func (t *Now) Since(seconds int64) time.Time {
	return t.Add(time.Duration(seconds) * time.Second)
}

//Ago return a time instance representing the time a given number of seconds ago
func (t *Now) Ago(seconds int64) time.Time {
	return t.Add(-time.Duration(seconds) * time.Second)
}

//NextMonth return the next month (time.Month)
func (t *Now) NextMonth() time.Month {
	return t.AddDate(0, 1, 0).Month()
}

//PreviousMonth return the next month (time.Month)
func (t *Now) PreviousMonth() time.Month {
	return t.AddDate(0, -1, 0).Month()
}

//NewTimeAfterInterval return a new time instance obtained adding "length" seconds to the original time instance excluding
//an interval of time
func (t *Now) NewTimeAfterInterval(istart time.Time, iend time.Time, length int64) time.Time {
	td := iend.Sub(istart)
	return t.Add(td + (time.Duration(length) * time.Second))
}

//BeginningOfDay return a time instance for the beginning of the day
func (t *Now) BeginningOfDay() time.Time {
	d := time.Duration(-t.Hour()) * time.Hour
	return t.Truncate(time.Hour).Add(d)
}

//EndOfDay return a time instance for the end of the day
func (t *Now) EndOfDay() time.Time {
	return t.BeginningOfDay().Add(24*time.Hour - time.Nanosecond)
}

//SecondsToEndOfDay return the number of seconds to the end of the day
func (t *Now) SecondsToEndOfDay() int32 {
	dt := t.EndOfDay().Add(-time.Nanosecond).Sub(t.Time)
	return int32(time.Duration(dt) / time.Second)
}

//Between check the given time instance if between to time instances
func (t *Now) Between(start time.Time, end time.Time) bool {
	return t.Before(end) && t.After(start)
}
<commit_msg>Renamed Now in Timeutils. Added Easter()<commit_after>package timeutils

import "time"

//Constants
var stdDaysInMonth = [13]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

const (
	februaryLeapYearLength = 29
)

//Timeutils a simple wrapper of time.Time
type Timeutils struct {
	time.Time
}

//New return a new instance of Timeutils
func New(n time.Time) *Timeutils {
	return &Timeutils{n}
}

//Tomorrow return a time instance for tomorrows date at the same time
func (t *Timeutils) Tomorrow() time.Time {
	return t.AddDate(0, 0, 1)
}

//TomorrowAtTime return a time instance for tomorrow's date at a given time of day
func (t *Timeutils) TomorrowAtTime(w time.Time) time.Time {
	tn := t.Tomorrow()
	return time.Date(tn.Year(), tn.Month(), tn.Day(), w.Hour(), w.Minute(), w.Second(), w.Nanosecond(), w.Location())
}

//TomorrowDayOfWeek return the day of the week of tomorrow
func (t *Timeutils) TomorrowDayOfWeek() time.Weekday {
	return t.Tomorrow().Weekday()
}

//Yesterday return a time instance for yesterday's date at the same time
func (t *Timeutils) Yesterday() time.Time {
	//return t.Add(-time.Duration(24) * time.Hour)
	return t.AddDate(0, 0, -1)
}

//YesterdayAtTime return a time instance for yesterday's date at a given time of day
func (t *Timeutils) YesterdayAtTime(w time.Time) time.Time {
	tn := t.Yesterday()
	return time.Date(tn.Year(), tn.Month(), tn.Day(), w.Hour(), w.Minute(), w.Second(), w.Nanosecond(), w.Location())
}

//YesterdayDayOfWeek return the day of week of yesterday
func (t *Timeutils) YesterdayDayOfWeek() time.Weekday {
	return t.Yesterday().Weekday()
}

//DayOfWeekAfterNDays return the day of week after a specified number of days from the given time instance
func (t *Timeutils) DayOfWeekAfterNDays(n int) time.Weekday {
	return t.Add(time.Duration(24*n) * time.Hour).Weekday()
}

//IsLeap return true if the Year in t is a leap year
func (t *Timeutils) IsLeap() bool {
	return (t.Year()%400 == 0 || (t.Year()%100 != 0 && t.Year()%4 == 0))
}

//DaysInMonth return the number of days in the month which t is in
func (t *Timeutils) DaysInMonth() int {
	if t.Month() == time.February && t.IsLeap() {
		return februaryLeapYearLength
	}
	return stdDaysInMonth[t.Month()]
}

//AddDays add a number of days at Timeutils
func (t *Timeutils) AddDays(n int) time.Time {
	//return t.Add(time.Duration(24*n) * time.Hour)
	return t.AddDate(0, 0, n)
}

//Since return a time instance representing the time a given seconds since the instance time
func (t *Timeutils) Since(seconds int64) time.Time {
	return t.Add(time.Duration(seconds) * time.Second)
}

//Ago return a time instance representing the time a given number of seconds ago
func (t *Timeutils) Ago(seconds int64) time.Time {
	return t.Add(-time.Duration(seconds) * time.Second)
}

//NextMonth return the next month (time.Month)
func (t *Timeutils) NextMonth() time.Month {
	return t.AddDate(0, 1, 0).Month()
}

//PreviousMonth return the next month (time.Month)
func (t *Timeutils) PreviousMonth() time.Month {
	return t.AddDate(0, -1, 0).Month()
}

//NewTimeAfterInterval return a new time instance obtained adding "length" seconds to the original time instance excluding
//an interval of time
func (t *Timeutils) NewTimeAfterInterval(istart time.Time, iend time.Time, length int64) time.Time {
	td := iend.Sub(istart)
	return t.Add(td + (time.Duration(length) * time.Second))
}

//BeginningOfDay return a time instance for the beginning of the day
func (t *Timeutils) BeginningOfDay() time.Time {
	d := time.Duration(-t.Hour()) * time.Hour
	return t.Truncate(time.Hour).Add(d)
}

//EndOfDay return a time instance for the end of the day
func (t *Timeutils) EndOfDay() time.Time {
	return t.BeginningOfDay().Add(24*time.Hour - time.Nanosecond)
}

//SecondsToEndOfDay return the number of seconds to the end of the day
func (t *Timeutils) SecondsToEndOfDay() int32 {
	dt := t.EndOfDay().Add(-time.Nanosecond).Sub(t.Time)
	return int32(time.Duration(dt) / time.Second)
}

//Between check the given time instance if between to time instances
func (t *Timeutils) Between(start time.Time, end time.Time) bool {
	return t.Before(end) && t.After(start)
}

func mod(a, n int) int {
	r := a % n
	if r < 0 {
		return r + n
	}
	return r
}

//Easter the Easter day for the year of t
func (t *Timeutils) Easter() time.Time {
	y := t.Year()
	c := y / 100
	n := mod(y, 19)
	i := mod(c-c/4-(c-(c-17)/25)/3+19*n+15, 30)
	i -= (i / 28) * (1 - (i/28)*(29/(i+1))*((21-n)/11))
	l := i - mod(y+y/4+i+2-c+c/4, 7)
	m := 3 + (l+40)/44
	d := l + 28 - 31*(m/4)
	return time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC)
}
<|endoftext|>


<commit_before>// openssl genrsa -out localhost.key 2048
// openssl req -new -x509 -key localhost.key -out localhost.cert -days 3650 -subj /CN=localhost
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

// Create a handler function that calls an upgrade to websocket session using our upgrader parameters
func handler(w http.ResponseWriter, r *http.Request) {
	// TODO encode a msg to: gzip, deflate, sdch.
	w.Header().Set("Content-Type", "text/plain")
	fmt.Fprintf(w, "Method: %s\n", r.Method)
	fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
	fmt.Fprintf(w, "Host: %s\n", r.Host)
	fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr)
	fmt.Fprintf(w, "RequestURI: %q\n", r.RequestURI)
	fmt.Fprintf(w, "URL: %#v\n", r.URL)
	fmt.Fprintf(w, "Body.ContentLength: %d (-1 means unknown)\n", r.ContentLength)
	fmt.Fprintf(w, "Close: %v (relevant for HTTP/1 only)\n", r.Close)
	fmt.Fprintf(w, "TLS: %#v\n", r.TLS)
	fmt.Fprintf(w, "\nHeaders:\n")
	r.Header.Write(w)

	io.WriteString(w, "boby: tls")
}

func main() {
	http.HandleFunc("/", handler)
	log.Printf("Listening for SECURE websocket connections on port 8000.")
	log.Fatal(http.ListenAndServeTLS(":8000", "localhost.cert", "localhost.key", nil))
}

/*
url = https://localhost:8000
*/

/* Chrome 49.0
Method: GET
Protocol: HTTP/2.0
Host: localhost:8000
RemoteAddr: [::1]:52439
RequestURI: "/"
URL: &url.URL{Scheme:"", Opaque:"", User:(*url.Userinfo)(nil), Host:"", Path:"/", RawPath:"", RawQuery:"", Fragment:""}
Body.ContentLength: 0 (-1 means unknown)
Close: false (relevant for HTTP/1 only)
TLS: &tls.ConnectionState{Version:0x303, HandshakeComplete:true, DidResume:false, CipherSuite:0xc02f, NegotiatedProtocol:"h2", NegotiatedProtocolIsMutual:true, ServerName:"localhost", PeerCertificates:[]*x509.Certificate(nil), VerifiedChains:[][]*x509.Certificate(nil), SignedCertificateTimestamps:[][]uint8(nil), OCSPResponse:[]uint8(nil), TLSUnique:[]uint8{0xc7, 0xda, 0x29, 0xa2, 0x4d, 0xad, 0x8, 0x84, 0x9e, 0x36, 0x24, 0x1e}}

Headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
boby: tls
*/

/* Safari 9.1
Method: GET
Protocol: HTTP/1.1
Host: localhost:8000
RemoteAddr: [::1]:52523
RequestURI: "/"
URL: &url.URL{Scheme:"", Opaque:"", User:(*url.Userinfo)(nil), Host:"", Path:"/", RawPath:"", RawQuery:"", Fragment:""}
Body.ContentLength: 0 (-1 means unknown)
Close: false (relevant for HTTP/1 only)
TLS: &tls.ConnectionState{Version:0x303, HandshakeComplete:true, DidResume:false, CipherSuite:0xc013, NegotiatedProtocol:"", NegotiatedProtocolIsMutual:true, ServerName:"localhost", PeerCertificates:[]*x509.Certificate(nil), VerifiedChains:[][]*x509.Certificate(nil), SignedCertificateTimestamps:[][]uint8(nil), OCSPResponse:[]uint8(nil), TLSUnique:[]uint8{0x52, 0xa3, 0xfe, 0x14, 0x85, 0xd5, 0xfe, 0x4d, 0xf5, 0xc, 0xd1, 0x7b}}

Headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Cache-Control: max-age=0
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/537.86.5
boby: tls
*/
<commit_msg>Update https.go<commit_after>// openssl genrsa -out localhost.key 2048
// openssl req -new -x509 -key localhost.key -out localhost.cert -days 3650 -subj /CN=localhost
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

// Create a handler function that calls an upgrade to websocket session using our upgrader parameters
func handler(w http.ResponseWriter, r *http.Request) {
	// TODO encode to: gzip, deflate, sdch
	// TODO Let's Encrypt https://habrahabr.ru/post/270273/
	w.Header().Set("Content-Type", "text/plain")
	fmt.Fprintf(w, "Method: %s\n", r.Method)
	fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
	fmt.Fprintf(w, "Host: %s\n", r.Host)
	fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr)
	fmt.Fprintf(w, "RequestURI: %q\n", r.RequestURI)
	fmt.Fprintf(w, "URL: %#v\n", r.URL)
	fmt.Fprintf(w, "Body.ContentLength: %d (-1 means unknown)\n", r.ContentLength)
	fmt.Fprintf(w, "Close: %v (relevant for HTTP/1 only)\n", r.Close)
	fmt.Fprintf(w, "TLS: %#v\n", r.TLS)
	fmt.Fprintf(w, "\nHeaders:\n")
	r.Header.Write(w)

	io.WriteString(w, "boby: tls")
}

func main() {
	http.HandleFunc("/", handler)
	log.Printf("Listening for SECURE websocket connections on port 8000.")
	log.Fatal(http.ListenAndServeTLS(":8000", "localhost.cert", "localhost.key", nil))
}

/*
url = https://localhost:8000
*/

/* Chrome 49.0
Method: GET
Protocol: HTTP/2.0
Host: localhost:8000
RemoteAddr: [::1]:52439
RequestURI: "/"
URL: &url.URL{Scheme:"", Opaque:"", User:(*url.Userinfo)(nil), Host:"", Path:"/", RawPath:"", RawQuery:"", Fragment:""}
Body.ContentLength: 0 (-1 means unknown)
Close: false (relevant for HTTP/1 only)
TLS: &tls.ConnectionState{Version:0x303, HandshakeComplete:true, DidResume:false, CipherSuite:0xc02f, NegotiatedProtocol:"h2", NegotiatedProtocolIsMutual:true, ServerName:"localhost", PeerCertificates:[]*x509.Certificate(nil), VerifiedChains:[][]*x509.Certificate(nil), SignedCertificateTimestamps:[][]uint8(nil), OCSPResponse:[]uint8(nil), TLSUnique:[]uint8{0xc7, 0xda, 0x29, 0xa2, 0x4d, 0xad, 0x8, 0x84, 0x9e, 0x36, 0x24, 0x1e}}

Headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
boby: tls
*/

/* Safari 9.1
Method: GET
Protocol: HTTP/1.1
Host: localhost:8000
RemoteAddr: [::1]:52523
RequestURI: "/"
URL: &url.URL{Scheme:"", Opaque:"", User:(*url.Userinfo)(nil), Host:"", Path:"/", RawPath:"", RawQuery:"", Fragment:""}
Body.ContentLength: 0 (-1 means unknown)
Close: false (relevant for HTTP/1 only)
TLS: &tls.ConnectionState{Version:0x303, HandshakeComplete:true, DidResume:false, CipherSuite:0xc013, NegotiatedProtocol:"", NegotiatedProtocolIsMutual:true, ServerName:"localhost", PeerCertificates:[]*x509.Certificate(nil), VerifiedChains:[][]*x509.Certificate(nil), SignedCertificateTimestamps:[][]uint8(nil), OCSPResponse:[]uint8(nil), TLSUnique:[]uint8{0x52, 0xa3, 0xfe, 0x14, 0x85, 0xd5, 0xfe, 0x4d, 0xf5, 0xc, 0xd1, 0x7b}}

Headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Cache-Control: max-age=0
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/537.86.5
boby: tls
*/
<|endoftext|>


<commit_before>/*
Package password implements a simple JSON web token based authentication
system.

Background

The package revolves around the `password.Authenticator` interface. This
interface implements only two methods: one for storing passwords, and one for
retrieving them. This lets you use any backend to store your users, whether
that be an in-memory store, Redis, Postgres, or something else altogether.

Usage

The functions defined in this library are designed to make it as easy as
possible to create and authenticate users. They are all designed to be used
with HTTP handlers:

	// Grab the username and password from the request, and create a new user
	// in the user store with those values
	http.HandleFunc("/signup", func(w http.ResponseWriter, r *http.Request) {
		username := r.FormValue("Username")
		password := r.FormValue("Password")
		id, _ := password.New(username, password, UserStore)
		w.Write([]byte("New user: "+id))
	})
	...
	// Sign in using a username and password. This will respond with a JSON web
	// token if the user authenticates successfully
	http.HandleFunc("/signin", func(w http.ResponseWriter, r *http.Request) {
		username := r.FormValue("Username")
		password := r.FormValue("Password")
		password.Authenticate(username, password, w, UserStore)
	})
	...
	// Respond with the user's username. If they don't have a valid JSON web
	// token, then this request will fail, saying the client is unauthorized
	http.Handle("/whoami", password.Protected(
		func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			username := ctx.Value("id")
			fmt.Fprintf(w, "Your username: %s\n", username)
	}))

For a reference implementation of the `password.Authenticator` interface, see
the example in the GitHub repository.
*/
package password

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"net/http"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/net/context"
)

var (
	// ErrInvalidSigningMethod is the error returned when a token's signature
	// does match the signature used to sign the token header.
	ErrInvalidSigningMethod = errors.New("Invalid signing method")
	// ErrTokenInvalid means the signature didn't match.
	ErrTokenInvalid = errors.New("Token isn't valid")

	signingKey = genRandBytes()
)

// Authenticator is an interface for storing and retrieving hashed passwords
type Authenticator interface {
	Store(id string, hashedPassword string) (string, error)
	Retrieve(id string) (string, error)
}

// New hashes and salts a given plaintext password using the bcrypt algorithm,
// and stores it. The returned string is the generated key used to identify
// that id/secret combination. It is typically the primary used to retrieve
// that entry in the database.
func New(username string, password string, a Authenticator) (string, error) {
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", err // couldn't run bcrypt
	}

	id, err := a.Store(username, string(hashedPassword))
	if err != nil {
		return "", err // couldn't store pwd in db
	}

	return id, nil
}

// Compare compares the stored hashed password with the password provided by
// the user. If they match, it returns a JSON web token.
func Compare(id string, password string, a Authenticator) (string, error) {
	hashedPassword, err := a.Retrieve(id)
	if err != nil {
		return "", err // failed to retrieve password
	}

	err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
	if err != nil {
		return "", err // passwords didn't match
	}

	return genToken(id)
}

// Authenticate runs `Compare` against an authenticator interface, and responds
// with a JSON web token in the body of the request.
func Authenticate(id string, password string, w http.ResponseWriter, a Authenticator) {
	tokStr, err := Compare(id, password, a)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	json.NewEncoder(w).Encode(map[string]string{"token": tokStr})
}

// Protected is middleware that checks to see if the incoming request has a
// valid JSON web token. If it does, it executes the next `http.HandlerFunc`,
// and passes it a `context.Context` containing a way to identify the current
// user.
type Protected func(ctx context.Context, w http.ResponseWriter, r *http.Request)

func (fn Protected) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tok, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
		_, ok := token.Method.(*jwt.SigningMethodHMAC)
		if ok == false {
			return nil, ErrInvalidSigningMethod
		}
		return signingKey, nil
	})
	if err != nil {
		// might wanna use switch statement
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if tok.Valid != true {
		http.Error(w, ErrTokenInvalid.Error(), http.StatusUnauthorized)
	}

	id := tok.Claims["sub"]
	ctx := context.WithValue(context.Background(), "id", id)

	fn(ctx, w, r)
}

// SetSigningKey allows you to override the default HMAC signing key with one
// of your own. Every time this package is imported, a signing key is set
// randomly. That means that in between restarts, a new key is set, so you'd
// no longer be able to verify JSON web tokens created with that key. In order
// to reuse the signing key, you must set it yourself. Just call this function
// before creating any tokens, and you'll be good to go.
func SetSigningKey(key []byte) {
	signingKey = key
}

func genToken(id string) (string, error) {
	jwt := jwt.New(jwt.SigningMethodHS256)
	expTime := time.Now().Add(time.Hour * 72).Unix()

	jwt.Claims["sub"] = id
	jwt.Claims["exp"] = expTime
	jwt.Claims["iat"] = time.Now().Unix()

	tokStr, err := jwt.SignedString(signingKey)
	if err != nil {
		return "", err // failed to sign token
	}

	return tokStr, nil
}

func genRandBytes() []byte {
	// Use 32 bytes (256 bits) to satisfy the requirement for the HMAC key
	// length.
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		// If this errors, it means that something is wrong the system's
		// CSPRNG, which indicates a critical operating system failure. Panic
		// and crash here
		panic(err)
	}
	return []byte(base64.URLEncoding.EncodeToString(b))
}
<commit_msg>Fix doc formatting again<commit_after>/*
Package password implements a simple JSON web token based authentication
system.

Background

The package revolves around the password.Authenticator interface. This
interface implements only two methods: one for storing passwords, and one for
retrieving them. This lets you use any backend to store your users, whether
that be an in-memory store, Redis, Postgres, or something else altogether.

Usage

The functions defined in this library are designed to make it as easy as
possible to create and authenticate users. They are all designed to be used
with HTTP handlers:

	// Grab the username and password from the request, and create a new user
	// in the user store with those values
	http.HandleFunc("/signup", func(w http.ResponseWriter, r *http.Request) {
		username := r.FormValue("Username")
		password := r.FormValue("Password")
		id, _ := password.New(username, password, UserStore)
		w.Write([]byte("New user: "+id))
	})
	...
	// Sign in using a username and password. This will respond with a JSON web
	// token if the user authenticates successfully
	http.HandleFunc("/signin", func(w http.ResponseWriter, r *http.Request) {
		username := r.FormValue("Username")
		password := r.FormValue("Password")
		password.Authenticate(username, password, w, UserStore)
	})
	...
	// Respond with the user's username. If they don't have a valid JSON web
	// token, then this request will fail, saying the client is unauthorized
	http.Handle("/whoami", password.Protected(
		func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			username := ctx.Value("id")
			fmt.Fprintf(w, "Your username: %s\n", username)
	}))

In this example, "UserStore" would satisfy the password.Authenticator
interface. For a reference implementation of this interface, see the example
in the GitHub repository.
*/
package password

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"net/http"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/net/context"
)

var (
	// ErrInvalidSigningMethod is the error returned when a token's signature
	// does match the signature used to sign the token header.
	ErrInvalidSigningMethod = errors.New("Invalid signing method")
	// ErrTokenInvalid means the signature didn't match.
	ErrTokenInvalid = errors.New("Token isn't valid")

	signingKey = genRandBytes()
)

// Authenticator is an interface for storing and retrieving hashed passwords
type Authenticator interface {
	Store(id string, hashedPassword string) (string, error)
	Retrieve(id string) (string, error)
}

// New hashes and salts a given plaintext password using the bcrypt algorithm,
// and stores it. The returned string is the generated key used to identify
// that id/secret combination. It is typically the primary used to retrieve
// that entry in the database.
func New(username string, password string, a Authenticator) (string, error) {
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", err // couldn't run bcrypt
	}

	id, err := a.Store(username, string(hashedPassword))
	if err != nil {
		return "", err // couldn't store pwd in db
	}

	return id, nil
}

// Compare compares the stored hashed password with the password provided by
// the user. If they match, it returns a JSON web token.
func Compare(id string, password string, a Authenticator) (string, error) {
	hashedPassword, err := a.Retrieve(id)
	if err != nil {
		return "", err // failed to retrieve password
	}

	err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
	if err != nil {
		return "", err // passwords didn't match
	}

	return genToken(id)
}

// Authenticate runs `Compare` against an authenticator interface, and responds
// with a JSON web token in the body of the request.
func Authenticate(id string, password string, w http.ResponseWriter, a Authenticator) {
	tokStr, err := Compare(id, password, a)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	json.NewEncoder(w).Encode(map[string]string{"token": tokStr})
}

// Protected is middleware that checks to see if the incoming request has a
// valid JSON web token. If it does, it executes the next `http.HandlerFunc`,
// and passes it a `context.Context` containing a way to identify the current
// user.
type Protected func(ctx context.Context, w http.ResponseWriter, r *http.Request)

func (fn Protected) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tok, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
		_, ok := token.Method.(*jwt.SigningMethodHMAC)
		if ok == false {
			return nil, ErrInvalidSigningMethod
		}
		return signingKey, nil
	})
	if err != nil {
		// might wanna use switch statement
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if tok.Valid != true {
		http.Error(w, ErrTokenInvalid.Error(), http.StatusUnauthorized)
	}

	id := tok.Claims["sub"]
	ctx := context.WithValue(context.Background(), "id", id)

	fn(ctx, w, r)
}

// SetSigningKey allows you to override the default HMAC signing key with one
// of your own. Every time this package is imported, a signing key is set
// randomly. That means that in between restarts, a new key is set, so you'd
// no longer be able to verify JSON web tokens created with that key. In order
// to reuse the signing key, you must set it yourself. Just call this function
// before creating any tokens, and you'll be good to go.
func SetSigningKey(key []byte) {
	signingKey = key
}

func genToken(id string) (string, error) {
	jwt := jwt.New(jwt.SigningMethodHS256)
	expTime := time.Now().Add(time.Hour * 72).Unix()

	jwt.Claims["sub"] = id
	jwt.Claims["exp"] = expTime
	jwt.Claims["iat"] = time.Now().Unix()

	tokStr, err := jwt.SignedString(signingKey)
	if err != nil {
		return "", err // failed to sign token
	}

	return tokStr, nil
}

func genRandBytes() []byte {
	// Use 32 bytes (256 bits) to satisfy the requirement for the HMAC key
	// length.
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		// If this errors, it means that something is wrong the system's
		// CSPRNG, which indicates a critical operating system failure. Panic
		// and crash here
		panic(err)
	}
	return []byte(base64.URLEncoding.EncodeToString(b))
}
<|endoftext|>


<commit_before>package model

type IProductRepository interface {
	Read(id string) *Product
	ListByType(tpeid string) []Product
}

type IProductTypeRepository interface {
	Create(*ProductType) string
	Update(*ProductType) string
	Read(id string) *ProductType
	ListByArrived() []ProductType
	ListByLove() []ProductType
}

type ProductTypeMgt struct {
	Repo IProductTypeRepository
	ProductRepo IProductRepository
}

func (me *ProductTypeMgt) Read(typeid string) *ProductType {
	return me.Repo.Read(typeid)
}

func (me *ProductTypeMgt) ListNewArrivedProductTypes() []ProductType {
	return me.Repo.ListByArrived()
}

func (me *ProductTypeMgt) ListMostLovedProductTypes(fromtime int) []ProductType {
	return me.Repo.ListByLove()
}

func (me *ProductTypeMgt) ReadProduct(productid string) *Product {
	return me.ProductRepo.Read(productid)
}

func (me *ProductTypeMgt) ListProductByType(typeid string) []Product {
	return me.ProductRepo.ListByType(typeid)
}
<commit_msg>add love and view<commit_after>package model

type IProductRepository interface {
	Read(id string) *Product
	ListByType(tpeid string) []Product
}

type IProductTypeRepository interface {
//	Create(*ProductType) string
	Update(*ProductType)
	Read(id string) *ProductType
	ListByArrived() []ProductType
	ListByLove() []ProductType
}

type ProductTypeMgt struct {
	Repo IProductTypeRepository
	ProductRepo IProductRepository
}

func (me *ProductTypeMgt) Love(typeid string) {
	producttype := me.Read(typeid)
	if producttype == nil {
		panic "not found product type " + typeid
	}
	producttype.NumberOfLove = producttype.NumberOfLove + 1
	me.Update(producttype)
}

func (me *ProductTypeMgt) View(typeid string) {
	producttype := me.Read(typeid)
	if producttype == nil {
		panic "not found product type " + typeid
	}
	producttype.NumberOfView = producttype.NumberOfView + 1
	me.Update(producttype)
}

func (me *ProductTypeMgt) Read(typeid string) *ProductType {
	return me.Repo.Read(typeid)
}

func (me *ProductTypeMgt) ListNewArrivedProductTypes() []ProductType {
	return me.Repo.ListByArrived()
}

func (me *ProductTypeMgt) ListMostLovedProductTypes(fromtime int) []ProductType {
	return me.Repo.ListByLove()
}

func (me *ProductTypeMgt) ReadProduct(productid string) *Product {
	return me.ProductRepo.Read(productid)
}

func (me *ProductTypeMgt) ListProductByType(typeid string) []Product {
	return me.ProductRepo.ListByType(typeid)
}
<|endoftext|>


<commit_before>package pdf

import (
	"bufio"
	"fmt"
	"os"
	"github.com/mawicks/goPDF/containers" )

// TestFile is a simple file implementing the File interface for use in unit tests.
type testFile struct {
	nextObjectNumber     uint32
	nextGenerationNumber uint16
}

// Constructor for testFile object
func NewTestFile(obj uint32, gen uint16) File {
	return &testFile{obj, gen}
}

// Public methods

// Implements Close() in File interface
func (f *testFile) Close() {}

// Implements AddObjectAt() in File interface
func (f *testFile) AddObjectAt(ObjectNumber, Object) {}

// Implements AddObject() in File interface
func (f *testFile) AddObject(object Object) (reference *Indirect) {
	reference = NewIndirect(f)
	reference.Finalize(object)
	return reference
}

// Implements DeleteObject() in File interface
func (f *testFile) DeleteObject(on ObjectNumber) {}

// Implements ReserveObjectNumber() in File interface
func (f *testFile) ReserveObjectNumber(o Object) ObjectNumber {
	result := ObjectNumber{f.nextObjectNumber, f.nextGenerationNumber}
	f.nextObjectNumber += 1
	f.nextGenerationNumber += 1
	return result
}

func (f *testFile) SetCatalog(i *Indirect) {
}

func (f *testFile) SetInfo(i *Indirect) {
}

// xrefEntry type
type xrefEntry struct {
	byteOffset uint64
	generation uint16
	inUse      bool

	// "dirty" is true when the in-memory version of the object doesn't match
	// the "file" copy.
	dirty bool
}

// Write xrefEntry to output stream using Writer.
func (entry *xrefEntry) Serialize(w Writer) {
	fmt.Fprintf(w,
		"%010d %05d %c \n",
		entry.byteOffset,
		entry.generation,
		func(inuse bool) (result rune) {
			if inuse {
				result = 'n'
			} else {
				result = 'f'
			}
			return result
		}(entry.inUse))
}

type file struct {
	xref              containers.Array
	trailerDictionary *Dictionary
	catalogIndirect   *Indirect
	file              *os.File

	// "writer" is a wrapper around "file".
	// Note: Do not use "file" as a writer.  Use "writer" instead.
	// "file" must be used for low-level operations such as Seek(),
	// flush "writer" before using "file".
	writer *bufio.Writer
}

// Constructor for File object
func NewFile(filename string) File {
	var result *file
	f, error := os.Create(filename)
	if error != nil {
		panic("Failed to create file")
	} else {
		result = new(file)
		result.file = f
		result.writer = bufio.NewWriter(f)
		result.xref = containers.NewDynamicArray(1024)
		result.trailerDictionary = NewDictionary()

		result.writePdfHeader()
		result.createInitialXref()
		result.writer.Flush()
	}

	return result
}

// Public methods
func (f *file) SetCatalog(catalog *Indirect) {
	f.catalogIndirect = catalog
}

func (f *file) SetInfo(i *Indirect) {
	f.trailerDictionary.Add("Info", i)
}

func (f *file) release() {
	f.xref.SetSize(0)
	f.catalogIndirect = nil
	f.trailerDictionary = nil
	f.file = nil
}

// Implements Close() in File interface
func (f *file) Close() {
	f.trailerDictionary.Add("Size", NewIntNumeric(int(f.xref.Size())))

	// The catalog appearing in the trailer must be indirect
	// object.  Create an indirect object pointed at the catalog,
	// add it to the trailer dictionary, and write out the trailer dictionary.
	if f.catalogIndirect == nil {
		panic("No document catalog has been specified.  Use File.SetCatalog() to set one.")
	}
	f.trailerDictionary.Add("Root", f.catalogIndirect)

	xrefPosition := f.Tell()
	f.writeXref()

	f.writeTrailer(xrefPosition)
	f.writer.Flush()
	f.file.Close()

	f.release()
}

func (f *file) Seek(position int64, whence int) (int64, error) {
	f.writer.Flush()
	return f.file.Seek(position, whence)
}

func (f *file) Tell() int64 {
	position, _ := f.Seek(0, 1)
	return position
}

// Implements AddObjectAt() in File interface
func (f *file) AddObjectAt(object ObjectNumber, o Object) {
	entry := (*f.xref.At(uint(object.number))).(*xrefEntry)
	if entry.byteOffset != 0 {
		panic("An object has already been written with this number")
	}
	if entry.generation != object.generation {
		panic("Generation number mismatch")
	}

	entry.byteOffset = uint64(f.Tell())

	fmt.Fprintf(f.writer, "%d %d obj\n", object.number, object.generation)
	o.Serialize(f.writer, f)
	fmt.Fprintf(f.writer, "\nendobj\n")
}

// Implements AddObject() in File interface
func (f *file) AddObject(object Object) (reference *Indirect) {
	reference = NewIndirect(f)
	reference.Finalize(object)
	return reference
}

// Implements DeleteObject() in File interface
func (f *file) DeleteObject(object ObjectNumber) {
	entry := (*f.xref.At(uint(object.number))).(*xrefEntry)
	if object.generation != entry.generation {
		panic("Generation number mismatch")
	}

	if entry.generation < 65535 {
		// Increment the generation count for the next use
		// and link into free list.
		entry.generation += 1
		entry.byteOffset = (*f.xref.At(0)).(*xrefEntry).byteOffset
		(*f.xref.At(0)).(*xrefEntry).byteOffset = uint64(object.number)
	} else {
		// Don't link into free list.  Just set byte offset to 0
		entry.byteOffset = 0
	}

	entry.inUse = false
	entry.dirty = true
}

// Implements ReserveObjectNumber() in File interface
func (f *file) ReserveObjectNumber(o Object) ObjectNumber {
	var nextUnused uint
	var generation uint16

	// Find an unused node if possible.  Begin searching at
	// index=1 because first record begins free list and is always
	// marked as free.
	for nextUnused = 1; nextUnused < f.xref.Size() &&
		(*f.xref.At(nextUnused)).(*xrefEntry).generation < 65535 &&
		(*f.xref.At(nextUnused)).(*xrefEntry).inUse; nextUnused++ {
		// Empty loop
	}

	if nextUnused >= f.xref.Size() {
		// Create a new xref entry
		f.xref.PushBack(&xrefEntry{0, 0, true, true})
	} else {
		entry := (*f.xref.At(nextUnused)).(*xrefEntry)
		// Adjust link in head of free list
		(*f.xref.At(0)).(*xrefEntry).byteOffset = entry.byteOffset
		generation = entry.generation
		entry.inUse = true
	}
	result := ObjectNumber{uint32(nextUnused), generation}
	return result
}

func (f *file) parseExistingFile() {
	panic("Not implemented")
}

func (f *file) createInitialXref() {
	f.xref.PushBack(&xrefEntry{0, 65535, false, true})
}

func (f *file) writePdfHeader() {
	f.writer.WriteString("%PDF-1.4\n")
}

func nextSegment(xref containers.Array, start uint) (nextStart, length uint) {
	var i uint
	// Skip "clean" entries.
	for i = start; i < xref.Size() && !(*xref.At(i)).(*xrefEntry).dirty; i++ {
	}

	nextStart = i
	for i = nextStart; i < xref.Size() && (*xref.At(i)).(*xrefEntry).dirty; i++ {
		length += 1
	}

	return nextStart, length
}

func (f *file) writeXref() {
	f.writer.WriteString("xref\n")

	for s, l := nextSegment(f.xref, 0); s < f.xref.Size(); s, l = nextSegment(f.xref, s+l) {
		fmt.Fprintf(f.writer, "%d %d\n", s, l)
		for i := s; i < s+l; i++ {
			entry := (*f.xref.At(uint(i))).(*xrefEntry)
			if entry.byteOffset == 0 && entry.inUse {
				panic(fmt.Sprintf("Object %d reserved but never added or finalized", i))
			}
			entry.Serialize(f.writer)
		}
	}
}

func (f *file) writeTrailer(xrefPosition int64) {
	f.writer.WriteString("trailer\n")
	f.trailerDictionary.Serialize(f.writer, f)
	f.writer.WriteString("\nstartxref\n")
	fmt.Fprintf(f.writer, "%d\n", xrefPosition)
	f.writer.WriteString("%%EOF\n")
}
<commit_msg>Add code to read determine xref location in pre-existing files.<commit_after>package pdf

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"github.com/mawicks/goPDF/containers"
	"github.com/mawicks/goPDF/readers" )

// TestFile is a simple file implementing the File interface for use in unit tests.
type testFile struct {
	nextObjectNumber     uint32
	nextGenerationNumber uint16
}

// Constructor for testFile object
func NewTestFile(obj uint32, gen uint16) File {
	return &testFile{obj, gen}
}

// Public methods

// Implements Close() in File interface
func (f *testFile) Close() {}

// Implements AddObjectAt() in File interface
func (f *testFile) AddObjectAt(ObjectNumber, Object) {}

// Implements AddObject() in File interface
func (f *testFile) AddObject(object Object) (reference *Indirect) {
	reference = NewIndirect(f)
	reference.Finalize(object)
	return reference
}

// Implements DeleteObject() in File interface
func (f *testFile) DeleteObject(on ObjectNumber) {}

// Implements ReserveObjectNumber() in File interface
func (f *testFile) ReserveObjectNumber(o Object) ObjectNumber {
	result := ObjectNumber{f.nextObjectNumber, f.nextGenerationNumber}
	f.nextObjectNumber += 1
	f.nextGenerationNumber += 1
	return result
}

func (f *testFile) SetCatalog(i *Indirect) {
}

func (f *testFile) SetInfo(i *Indirect) {
}

// xrefEntry type
type xrefEntry struct {
	byteOffset uint64
	generation uint16
	inUse      bool

	// "dirty" is true when the in-memory version of the object doesn't match
	// the "file" copy.
	dirty bool
}

// Write xrefEntry to output stream using Writer.
func (entry *xrefEntry) Serialize(w Writer) {
	fmt.Fprintf(w,
		"%010d %05d %c \n",
		entry.byteOffset,
		entry.generation,
		func(inuse bool) (result rune) {
			if inuse {
				result = 'n'
			} else {
				result = 'f'
			}
			return result
		}(entry.inUse))
}

type file struct {
	file *os.File
	originalSize int64
	mode int
	xrefLocation [2]int64
	xref containers.Array
	trailerDictionary *Dictionary
	catalogIndirect *Indirect

	// "writer" is a wrapper around "file".
	// Note: Do not use "file" as a writer.  Use "writer" instead.
	// "file" must be used for low-level operations such as Seek(),
	// flush "writer" before using "file".
	writer *bufio.Writer
}

// Public methods

// Constructor for File object
func NewFile(filename string) File {
	var result *file

	success := false
	modes := [...]int {os.O_RDWR|os.O_CREATE, os.O_RDONLY}
	var f *os.File
	var err error
	var mode int
	for _,m := range modes {
		f, err = os.OpenFile(filename, m, 0777)
		if (err == nil) {
			mode = m
			success = true
			break;
		}
	}
	if !success {
		panic("Failed to open or create file")

	} else {
		result = new(file)
		result.file = f
		result.mode = mode
		result.originalSize,_ = f.Seek(0,os.SEEK_END)
		result.xrefLocation = getXrefLocation(f)
		result.writer = bufio.NewWriter(f)
		result.xref = containers.NewDynamicArray(1024)
		result.trailerDictionary = NewDictionary()

		result.writePdfHeader()
		result.createInitialXref()
		result.writer.Flush()
	}

	return result
}

func getXrefLocation(f *os.File) (result [2]int64) {
	end,_ := f.Seek(0,os.SEEK_END)
	regexp,_ := regexp.Compile (`\s*FOE%%\s*(\d+)(\s*ferxtrats)`)
	reader := bufio.NewReader(readers.NewReverseReader(f))
	indexes := regexp.FindReaderSubmatchIndex(reader)

	if (indexes != nil) {
		s1,s2 := indexes[2],indexes[3]
		fmt.Printf ("xrefloc=%d,%d\n", end-int64(s2),end-int64(s1))
		result = [2]int64{end-int64(s2),end-int64(s1)}
	}
	return result

}

func (f *file) SetCatalog(catalog *Indirect) {
	f.catalogIndirect = catalog
}

func (f *file) SetInfo(i *Indirect) {
	f.trailerDictionary.Add("Info", i)
}

func (f *file) release() {
	f.xref.SetSize(0)
	f.catalogIndirect = nil
	f.trailerDictionary = nil
	f.file = nil
}

// Implements Close() in File interface
func (f *file) Close() {
	f.trailerDictionary.Add("Size", NewIntNumeric(int(f.xref.Size())))

	// The catalog appearing in the trailer must be indirect
	// object.  Create an indirect object pointed at the catalog,
	// add it to the trailer dictionary, and write out the trailer dictionary.
	if f.catalogIndirect == nil {
		panic("No document catalog has been specified.  Use File.SetCatalog() to set one.")
	}
	f.trailerDictionary.Add("Root", f.catalogIndirect)

	xrefPosition := f.Tell()
	f.writeXref()

	f.writeTrailer(xrefPosition)
	f.writer.Flush()
	f.file.Close()

	f.release()
}

func (f *file) Seek(position int64, whence int) (int64, error) {
	f.writer.Flush()
	return f.file.Seek(position, whence)
}

func (f *file) Tell() int64 {
	position, _ := f.Seek(0, os.SEEK_CUR)
	return position
}

// Implements AddObjectAt() in File interface
func (f *file) AddObjectAt(object ObjectNumber, o Object) {
	entry := (*f.xref.At(uint(object.number))).(*xrefEntry)
	if entry.byteOffset != 0 {
		panic("An object has already been written with this number")
	}
	if entry.generation != object.generation {
		panic("Generation number mismatch")
	}

	entry.byteOffset = uint64(f.Tell())

	fmt.Fprintf(f.writer, "%d %d obj\n", object.number, object.generation)
	o.Serialize(f.writer, f)
	fmt.Fprintf(f.writer, "\nendobj\n")
}

// Implements AddObject() in File interface
func (f *file) AddObject(object Object) (reference *Indirect) {
	reference = NewIndirect(f)
	reference.Finalize(object)
	return reference
}

// Implements DeleteObject() in File interface
func (f *file) DeleteObject(object ObjectNumber) {
	entry := (*f.xref.At(uint(object.number))).(*xrefEntry)
	if object.generation != entry.generation {
		panic("Generation number mismatch")
	}

	if entry.generation < 65535 {
		// Increment the generation count for the next use
		// and link into free list.
		entry.generation += 1
		entry.byteOffset = (*f.xref.At(0)).(*xrefEntry).byteOffset
		(*f.xref.At(0)).(*xrefEntry).byteOffset = uint64(object.number)
	} else {
		// Don't link into free list.  Just set byte offset to 0
		entry.byteOffset = 0
	}

	entry.inUse = false
	entry.dirty = true
}

// Implements ReserveObjectNumber() in File interface
func (f *file) ReserveObjectNumber(o Object) ObjectNumber {
	var nextUnused uint
	var generation uint16

	// Find an unused node if possible.  Begin searching at
	// index=1 because first record begins free list and is always
	// marked as free.
	for nextUnused = 1; nextUnused < f.xref.Size() &&
		(*f.xref.At(nextUnused)).(*xrefEntry).generation < 65535 &&
		(*f.xref.At(nextUnused)).(*xrefEntry).inUse; nextUnused++ {
		// Empty loop
	}

	if nextUnused >= f.xref.Size() {
		// Create a new xref entry
		f.xref.PushBack(&xrefEntry{0, 0, true, true})
	} else {
		entry := (*f.xref.At(nextUnused)).(*xrefEntry)
		// Adjust link in head of free list
		(*f.xref.At(0)).(*xrefEntry).byteOffset = entry.byteOffset
		generation = entry.generation
		entry.inUse = true
	}
	result := ObjectNumber{uint32(nextUnused), generation}
	return result
}

func (f *file) parseExistingFile() {
	panic("Not implemented")
}

func (f *file) createInitialXref() {
	f.xref.PushBack(&xrefEntry{0, 65535, false, true})
}

func (f *file) writePdfHeader() {
	_,err := f.writer.WriteString("%PDF-1.4\n")
	if (err != nil) {
		panic("Unable to write PDF header")
	}
}

func nextSegment(xref containers.Array, start uint) (nextStart, length uint) {
	var i uint
	// Skip "clean" entries.
	for i = start; i < xref.Size() && !(*xref.At(i)).(*xrefEntry).dirty; i++ {
	}

	nextStart = i
	for i = nextStart; i < xref.Size() && (*xref.At(i)).(*xrefEntry).dirty; i++ {
		length += 1
	}

	return nextStart, length
}

func (f *file) writeXref() {
	f.writer.WriteString("xref\n")

	for s, l := nextSegment(f.xref, 0); s < f.xref.Size(); s, l = nextSegment(f.xref, s+l) {
		fmt.Fprintf(f.writer, "%d %d\n", s, l)
		for i := s; i < s+l; i++ {
			entry := (*f.xref.At(uint(i))).(*xrefEntry)
			if entry.byteOffset == 0 && entry.inUse {
				panic(fmt.Sprintf("Object %d reserved but never added or finalized", i))
			}
			entry.Serialize(f.writer)
		}
	}
}

func (f *file) writeTrailer(xrefPosition int64) {
	f.writer.WriteString("trailer\n")
	f.trailerDictionary.Serialize(f.writer, f)
	f.writer.WriteString("\nstartxref\n")
	fmt.Fprintf(f.writer, "%d\n", xrefPosition)
	f.writer.WriteString("%%EOF\n")
}
<|endoftext|>


<commit_before>package server

import (
	"golang.org/x/net/context"
)

type serverKey struct{}

func wait(ctx context.Context) bool {
	if ctx == nil {
		return false
	}
	wait, _ := ctx.Value("wait").(bool)
	return wait
}

func FromContext(ctx context.Context) (Server, bool) {
	c, ok := ctx.Value(serverKey{}).(Server)
	return c, ok
}

func NewContext(ctx context.Context, s Server) context.Context {
	return context.WithValue(ctx, serverKey{}, s)
}
<commit_msg>be pedantic<commit_after>package server

import (
	"golang.org/x/net/context"
)

type serverKey struct{}

func wait(ctx context.Context) bool {
	if ctx == nil {
		return false
	}
	wait, ok := ctx.Value("wait").(bool)
	if !ok {
		return false
	}
	return wait
}

func FromContext(ctx context.Context) (Server, bool) {
	c, ok := ctx.Value(serverKey{}).(Server)
	return c, ok
}

func NewContext(ctx context.Context, s Server) context.Context {
	return context.WithValue(ctx, serverKey{}, s)
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/jingweno/jqplay/jq"
	"github.com/unrolled/render"
)

type JQHandler struct {
	r *render.Render
	c *Config
}

func (h *JQHandler) handleIndex(rw http.ResponseWriter, r *http.Request) {
	h.r.HTML(rw, 200, "index", h.c)
}

func (h *JQHandler) handleJq(rw http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		h.r.JSON(rw, 500, nil)
		return
	}

	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}
	defer r.Body.Close()

	var jq *jq.JQ
	err = json.Unmarshal(b, &jq)
	if err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}

	if err := jq.Validate(); err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}

	log.Println(jq)

	re, err := jq.Eval()
	if err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}

	h.r.JSON(rw, 200, map[string]string{"result": re})
}
<commit_msg>Remove logging<commit_after>package server

import (
	"encoding/json"
	"io/ioutil"
	"net/http"

	"github.com/jingweno/jqplay/jq"
	"github.com/unrolled/render"
)

type JQHandler struct {
	r *render.Render
	c *Config
}

func (h *JQHandler) handleIndex(rw http.ResponseWriter, r *http.Request) {
	h.r.HTML(rw, 200, "index", h.c)
}

func (h *JQHandler) handleJq(rw http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		h.r.JSON(rw, 500, nil)
		return
	}

	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}
	defer r.Body.Close()

	var jq *jq.JQ
	err = json.Unmarshal(b, &jq)
	if err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}

	if err := jq.Validate(); err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}

	re, err := jq.Eval()
	if err != nil {
		h.r.JSON(rw, 422, map[string]string{"message": err.Error()})
		return
	}

	h.r.JSON(rw, 200, map[string]string{"result": re})
}
<|endoftext|>