<commit_before>// Copyright 2018 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 pprof

import (
	"bytes"
	"fmt"
	"internal/profile"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"runtime"
	"runtime/pprof"
	"strings"
	"sync"
	"sync/atomic"
	"testing"
	"time"
)

// TestDescriptions checks that the profile names under runtime/pprof package
// have a key in the description map.
func TestDescriptions(t *testing.T) {
	for _, p := range pprof.Profiles() {
		_, ok := profileDescriptions[p.Name()]
		if ok != true {
			t.Errorf("%s does not exist in profileDescriptions map\n", p.Name())
		}
	}
}

func TestHandlers(t *testing.T) {
	testCases := []struct {
		path               string
		handler            http.HandlerFunc
		statusCode         int
		contentType        string
		contentDisposition string
		resp               []byte
	}{
		{"/debug/pprof/<script>scripty<script>", Index, http.StatusNotFound, "text/plain; charset=utf-8", "", []byte("Unknown profile\n")},
		{"/debug/pprof/heap", Index, http.StatusOK, "application/octet-stream", `attachment; filename="heap"`, nil},
		{"/debug/pprof/heap?debug=1", Index, http.StatusOK, "text/plain; charset=utf-8", "", nil},
		{"/debug/pprof/cmdline", Cmdline, http.StatusOK, "text/plain; charset=utf-8", "", nil},
		{"/debug/pprof/profile?seconds=1", Profile, http.StatusOK, "application/octet-stream", `attachment; filename="profile"`, nil},
		{"/debug/pprof/symbol", Symbol, http.StatusOK, "text/plain; charset=utf-8", "", nil},
		{"/debug/pprof/trace", Trace, http.StatusOK, "application/octet-stream", `attachment; filename="trace"`, nil},
		{"/debug/pprof/mutex", Index, http.StatusOK, "application/octet-stream", `attachment; filename="mutex"`, nil},
		{"/debug/pprof/block?seconds=1", Index, http.StatusOK, "application/octet-stream", `attachment; filename="block-delta"`, nil},
		{"/debug/pprof/", Index, http.StatusOK, "text/html; charset=utf-8", "", []byte("Types of profiles available:")},
	}
	for _, tc := range testCases {
		t.Run(tc.path, func(t *testing.T) {
			req := httptest.NewRequest("GET", "http://example.com"+tc.path, nil)
			w := httptest.NewRecorder()
			tc.handler(w, req)

			resp := w.Result()
			if got, want := resp.StatusCode, tc.statusCode; got != want {
				t.Errorf("status code: got %d; want %d", got, want)
			}

			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				t.Errorf("when reading response body, expected non-nil err; got %v", err)
			}
			if got, want := resp.Header.Get("X-Content-Type-Options"), "nosniff"; got != want {
				t.Errorf("X-Content-Type-Options: got %q; want %q", got, want)
			}
			if got, want := resp.Header.Get("Content-Type"), tc.contentType; got != want {
				t.Errorf("Content-Type: got %q; want %q", got, want)
			}
			if got, want := resp.Header.Get("Content-Disposition"), tc.contentDisposition; got != want {
				t.Errorf("Content-Disposition: got %q; want %q", got, want)
			}

			if resp.StatusCode == http.StatusOK {
				return
			}
			if got, want := resp.Header.Get("X-Go-Pprof"), "1"; got != want {
				t.Errorf("X-Go-Pprof: got %q; want %q", got, want)
			}
			if !bytes.Equal(body, tc.resp) {
				t.Errorf("response: got %q; want %q", body, tc.resp)
			}
		})
	}
}

var Sink uint32

func mutexHog1(mu1, mu2 *sync.Mutex, start time.Time, dt time.Duration) {
	atomic.AddUint32(&Sink, 1)
	for time.Since(start) < dt {
		// When using gccgo the loop of mutex operations is
		// not preemptible. This can cause the loop to block a GC,
		// causing the time limits in TestDeltaContentionz to fail.
		// Since this loop is not very realistic, when using
		// gccgo add preemption points 100 times a second.
		t1 := time.Now()
		for time.Since(start) < dt && time.Since(t1) < 10*time.Millisecond {
			mu1.Lock()
			mu2.Lock()
			mu1.Unlock()
			mu2.Unlock()
		}
		if runtime.Compiler == "gccgo" {
			runtime.Gosched()
		}
	}
}

// mutexHog2 is almost identical to mutexHog but we keep them separate
// in order to distinguish them with function names in the stack trace.
// We make them slightly different, using Sink, because otherwise
// gccgo -c opt will merge them.
func mutexHog2(mu1, mu2 *sync.Mutex, start time.Time, dt time.Duration) {
	atomic.AddUint32(&Sink, 2)
	for time.Since(start) < dt {
		// See comment in mutexHog.
		t1 := time.Now()
		for time.Since(start) < dt && time.Since(t1) < 10*time.Millisecond {
			mu1.Lock()
			mu2.Lock()
			mu1.Unlock()
			mu2.Unlock()
		}
		if runtime.Compiler == "gccgo" {
			runtime.Gosched()
		}
	}
}

// mutexHog starts multiple goroutines that runs the given hogger function for the specified duration.
// The hogger function will be given two mutexes to lock & unlock.
func mutexHog(duration time.Duration, hogger func(mu1, mu2 *sync.Mutex, start time.Time, dt time.Duration)) {
	start := time.Now()
	mu1 := new(sync.Mutex)
	mu2 := new(sync.Mutex)
	var wg sync.WaitGroup
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			hogger(mu1, mu2, start, duration)
		}()
	}
	wg.Wait()
}

func TestDeltaProfile(t *testing.T) {
	rate := runtime.SetMutexProfileFraction(1)
	defer func() {
		runtime.SetMutexProfileFraction(rate)
	}()

	// mutexHog1 will appear in non-delta mutex profile
	// if the mutex profile works.
	mutexHog(20*time.Millisecond, mutexHog1)

	// If mutexHog1 does not appear in the mutex profile,
	// skip this test. Mutex profile is likely not working,
	// so is the delta profile.

	p, err := query("/debug/pprof/mutex")
	if err != nil {
		t.Skipf("mutex profile is unsupported: %v", err)
	}

	if !seen(p, "mutexHog1") {
		t.Skipf("mutex profile is not working: %v", p)
	}

	// causes mutexHog2 call stacks to appear in the mutex profile.
	done := make(chan bool)
	go func() {
		for {
			mutexHog(20*time.Millisecond, mutexHog2)
			select {
			case <-done:
				done <- true
				return
			default:
				time.Sleep(10 * time.Millisecond)
			}
		}
	}()
	defer func() { // cleanup the above goroutine.
		done <- true
		<-done // wait for the goroutine to exit.
	}()

	for _, tc := range []struct {
		endpoint             string
		seconds              int
		mutexHog1, mutexHog2 bool
	}{
		{"/debug/pprof/mutex?seconds=1", 1, false, true},
		{"/debug/pprof/mutex", 0, true, true},
	} {
		t.Run(tc.endpoint, func(t *testing.T) {
			p, err := query(tc.endpoint)
			if err != nil {
				t.Fatalf("failed to query profile: %v", err)
			}
			t.Logf("Profile=%v", p)

			if got := seen(p, "mutexHog1"); got != tc.mutexHog1 {
				t.Errorf("seen(mutexHog1) = %t, want %t", got, tc.mutexHog1)
			}
			if got := seen(p, "mutexHog2"); got != tc.mutexHog2 {
				t.Errorf("seen(mutexHog2) = %t, want %t", got, tc.mutexHog2)
			}

			if tc.seconds > 0 {
				got := time.Duration(p.DurationNanos) * time.Nanosecond
				want := time.Duration(tc.seconds) * time.Second
				if got < want/2 || got > 2*want {
					t.Errorf("got duration = %v; want ~%v", got, want)
				}
			}

		})
	}
}

var srv = httptest.NewServer(nil)

func query(endpoint string) (*profile.Profile, error) {
	url := srv.URL + endpoint
	r, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch %q: %v", url, err)
	}
	if r.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to fetch %q: %v", url, r.Status)
	}

	b, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		return nil, fmt.Errorf("failed to read and parse the result from %q: %v", url, err)
	}
	return profile.Parse(bytes.NewBuffer(b))
}

// seen returns true if the profile includes samples whose stacks include
// the specified function name (fname).
func seen(p *profile.Profile, fname string) bool {
	locIDs := map[*profile.Location]bool{}
	for _, loc := range p.Location {
		for _, l := range loc.Line {
			if strings.Contains(l.Function.Name, fname) {
				locIDs[loc] = true
				break
			}
		}
	}
	for _, sample := range p.Sample {
		for _, loc := range sample.Location {
			if locIDs[loc] {
				return true
			}
		}
	}
	return false
}
<commit_msg>net/http/pprof: make TestDeltaProfile less flaky by retrying<commit_after>// Copyright 2018 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 pprof

import (
	"bytes"
	"fmt"
	"internal/profile"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"runtime"
	"runtime/pprof"
	"strings"
	"sync"
	"sync/atomic"
	"testing"
	"time"
)

// TestDescriptions checks that the profile names under runtime/pprof package
// have a key in the description map.
func TestDescriptions(t *testing.T) {
	for _, p := range pprof.Profiles() {
		_, ok := profileDescriptions[p.Name()]
		if ok != true {
			t.Errorf("%s does not exist in profileDescriptions map\n", p.Name())
		}
	}
}

func TestHandlers(t *testing.T) {
	testCases := []struct {
		path               string
		handler            http.HandlerFunc
		statusCode         int
		contentType        string
		contentDisposition string
		resp               []byte
	}{
		{"/debug/pprof/<script>scripty<script>", Index, http.StatusNotFound, "text/plain; charset=utf-8", "", []byte("Unknown profile\n")},
		{"/debug/pprof/heap", Index, http.StatusOK, "application/octet-stream", `attachment; filename="heap"`, nil},
		{"/debug/pprof/heap?debug=1", Index, http.StatusOK, "text/plain; charset=utf-8", "", nil},
		{"/debug/pprof/cmdline", Cmdline, http.StatusOK, "text/plain; charset=utf-8", "", nil},
		{"/debug/pprof/profile?seconds=1", Profile, http.StatusOK, "application/octet-stream", `attachment; filename="profile"`, nil},
		{"/debug/pprof/symbol", Symbol, http.StatusOK, "text/plain; charset=utf-8", "", nil},
		{"/debug/pprof/trace", Trace, http.StatusOK, "application/octet-stream", `attachment; filename="trace"`, nil},
		{"/debug/pprof/mutex", Index, http.StatusOK, "application/octet-stream", `attachment; filename="mutex"`, nil},
		{"/debug/pprof/block?seconds=1", Index, http.StatusOK, "application/octet-stream", `attachment; filename="block-delta"`, nil},
		{"/debug/pprof/", Index, http.StatusOK, "text/html; charset=utf-8", "", []byte("Types of profiles available:")},
	}
	for _, tc := range testCases {
		t.Run(tc.path, func(t *testing.T) {
			req := httptest.NewRequest("GET", "http://example.com"+tc.path, nil)
			w := httptest.NewRecorder()
			tc.handler(w, req)

			resp := w.Result()
			if got, want := resp.StatusCode, tc.statusCode; got != want {
				t.Errorf("status code: got %d; want %d", got, want)
			}

			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				t.Errorf("when reading response body, expected non-nil err; got %v", err)
			}
			if got, want := resp.Header.Get("X-Content-Type-Options"), "nosniff"; got != want {
				t.Errorf("X-Content-Type-Options: got %q; want %q", got, want)
			}
			if got, want := resp.Header.Get("Content-Type"), tc.contentType; got != want {
				t.Errorf("Content-Type: got %q; want %q", got, want)
			}
			if got, want := resp.Header.Get("Content-Disposition"), tc.contentDisposition; got != want {
				t.Errorf("Content-Disposition: got %q; want %q", got, want)
			}

			if resp.StatusCode == http.StatusOK {
				return
			}
			if got, want := resp.Header.Get("X-Go-Pprof"), "1"; got != want {
				t.Errorf("X-Go-Pprof: got %q; want %q", got, want)
			}
			if !bytes.Equal(body, tc.resp) {
				t.Errorf("response: got %q; want %q", body, tc.resp)
			}
		})
	}
}

var Sink uint32

func mutexHog1(mu1, mu2 *sync.Mutex, start time.Time, dt time.Duration) {
	atomic.AddUint32(&Sink, 1)
	for time.Since(start) < dt {
		// When using gccgo the loop of mutex operations is
		// not preemptible. This can cause the loop to block a GC,
		// causing the time limits in TestDeltaContentionz to fail.
		// Since this loop is not very realistic, when using
		// gccgo add preemption points 100 times a second.
		t1 := time.Now()
		for time.Since(start) < dt && time.Since(t1) < 10*time.Millisecond {
			mu1.Lock()
			mu2.Lock()
			mu1.Unlock()
			mu2.Unlock()
		}
		if runtime.Compiler == "gccgo" {
			runtime.Gosched()
		}
	}
}

// mutexHog2 is almost identical to mutexHog but we keep them separate
// in order to distinguish them with function names in the stack trace.
// We make them slightly different, using Sink, because otherwise
// gccgo -c opt will merge them.
func mutexHog2(mu1, mu2 *sync.Mutex, start time.Time, dt time.Duration) {
	atomic.AddUint32(&Sink, 2)
	for time.Since(start) < dt {
		// See comment in mutexHog.
		t1 := time.Now()
		for time.Since(start) < dt && time.Since(t1) < 10*time.Millisecond {
			mu1.Lock()
			mu2.Lock()
			mu1.Unlock()
			mu2.Unlock()
		}
		if runtime.Compiler == "gccgo" {
			runtime.Gosched()
		}
	}
}

// mutexHog starts multiple goroutines that runs the given hogger function for the specified duration.
// The hogger function will be given two mutexes to lock & unlock.
func mutexHog(duration time.Duration, hogger func(mu1, mu2 *sync.Mutex, start time.Time, dt time.Duration)) {
	start := time.Now()
	mu1 := new(sync.Mutex)
	mu2 := new(sync.Mutex)
	var wg sync.WaitGroup
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			hogger(mu1, mu2, start, duration)
		}()
	}
	wg.Wait()
}

func TestDeltaProfile(t *testing.T) {
	rate := runtime.SetMutexProfileFraction(1)
	defer func() {
		runtime.SetMutexProfileFraction(rate)
	}()

	// mutexHog1 will appear in non-delta mutex profile
	// if the mutex profile works.
	mutexHog(20*time.Millisecond, mutexHog1)

	// If mutexHog1 does not appear in the mutex profile,
	// skip this test. Mutex profile is likely not working,
	// so is the delta profile.

	p, err := query("/debug/pprof/mutex")
	if err != nil {
		t.Skipf("mutex profile is unsupported: %v", err)
	}

	if !seen(p, "mutexHog1") {
		t.Skipf("mutex profile is not working: %v", p)
	}

	// causes mutexHog2 call stacks to appear in the mutex profile.
	done := make(chan bool)
	go func() {
		for {
			mutexHog(20*time.Millisecond, mutexHog2)
			select {
			case <-done:
				done <- true
				return
			default:
				time.Sleep(10 * time.Millisecond)
			}
		}
	}()
	defer func() { // cleanup the above goroutine.
		done <- true
		<-done // wait for the goroutine to exit.
	}()

	for _, d := range []int{1, 4, 16, 32} {
		endpoint := fmt.Sprintf("/debug/pprof/mutex?seconds=%d", d)
		p, err := query(endpoint)
		if err != nil {
			t.Fatalf("failed to query %q: %v", endpoint, err)
		}
		if !seen(p, "mutexHog1") && seen(p, "mutexHog2") && p.DurationNanos > 0 {
			break // pass
		}
		if d == 32 {
			t.Errorf("want mutexHog2 but no mutexHog1 in the profile, and non-zero p.DurationNanos, got %v", p)
		}
	}
	p, err = query("/debug/pprof/mutex")
	if err != nil {
		t.Fatalf("failed to query mutex profile: %v", err)
	}
	if !seen(p, "mutexHog1") || !seen(p, "mutexHog2") {
		t.Errorf("want both mutexHog1 and mutexHog2 in the profile, got %v", p)
	}
}

var srv = httptest.NewServer(nil)

func query(endpoint string) (*profile.Profile, error) {
	url := srv.URL + endpoint
	r, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch %q: %v", url, err)
	}
	if r.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to fetch %q: %v", url, r.Status)
	}

	b, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		return nil, fmt.Errorf("failed to read and parse the result from %q: %v", url, err)
	}
	return profile.Parse(bytes.NewBuffer(b))
}

// seen returns true if the profile includes samples whose stacks include
// the specified function name (fname).
func seen(p *profile.Profile, fname string) bool {
	locIDs := map[*profile.Location]bool{}
	for _, loc := range p.Location {
		for _, l := range loc.Line {
			if strings.Contains(l.Function.Name, fname) {
				locIDs[loc] = true
				break
			}
		}
	}
	for _, sample := range p.Sample {
		for _, loc := range sample.Location {
			if locIDs[loc] {
				return true
			}
		}
	}
	return false
}
<|endoftext|>


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

package ioutil_test

import (
	. "io/ioutil"
	"os"
	"testing"
)

func checkSize(t *testing.T, path string, size int64) {
	dir, err := os.Stat(path)
	if err != nil {
		t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
	}
	if dir.Size != size {
		t.Errorf("Stat %q: size %d want %d", path, dir.Size, size)
	}
}

func TestReadFile(t *testing.T) {
	filename := "rumpelstilzchen"
	contents, err := ReadFile(filename)
	if err == nil {
		t.Fatalf("ReadFile %s: error expected, none found", filename)
	}

	filename = "ioutil_test.go"
	contents, err = ReadFile(filename)
	if err != nil {
		t.Fatalf("ReadFile %s: %v", filename, err)
	}

	checkSize(t, filename, int64(len(contents)))
}

func TestWriteFile(t *testing.T) {
	filename := "_obj/rumpelstilzchen"
	data := "Programming today is a race between software engineers striving to " +
		"build bigger and better idiot-proof programs, and the Universe trying " +
		"to produce bigger and better idiots. So far, the Universe is winning."

	if err := WriteFile(filename, []byte(data), 0644); err != nil {
		t.Fatalf("WriteFile %s: %v", filename, err)
	}

	contents, err := ReadFile(filename)
	if err != nil {
		t.Fatalf("ReadFile %s: %v", filename, err)
	}

	if string(contents) != data {
		t.Fatalf("contents = %q\nexpected = %q", string(contents), data)
	}

	// cleanup
	os.Remove(filename) // ignore error
}

func TestReadDir(t *testing.T) {
	dirname := "rumpelstilzchen"
	_, err := ReadDir(dirname)
	if err == nil {
		t.Fatalf("ReadDir %s: error expected, none found", dirname)
	}

	dirname = "."
	list, err := ReadDir(dirname)
	if err != nil {
		t.Fatalf("ReadDir %s: %v", dirname, err)
	}

	foundTest := false
	foundObj := false
	for _, dir := range list {
		switch {
		case dir.IsRegular() && dir.Name == "ioutil_test.go":
			foundTest = true
		case dir.IsDirectory() && dir.Name == "_obj":
			foundObj = true
		}
	}
	if !foundTest {
		t.Fatalf("ReadDir %s: test file not found", dirname)
	}
	if !foundObj {
		t.Fatalf("ReadDir %s: _obj directory not found", dirname)
	}
}
<commit_msg>io/ioutil: use _test not _obj in test<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ioutil_test

import (
	. "io/ioutil"
	"os"
	"testing"
)

func checkSize(t *testing.T, path string, size int64) {
	dir, err := os.Stat(path)
	if err != nil {
		t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
	}
	if dir.Size != size {
		t.Errorf("Stat %q: size %d want %d", path, dir.Size, size)
	}
}

func TestReadFile(t *testing.T) {
	filename := "rumpelstilzchen"
	contents, err := ReadFile(filename)
	if err == nil {
		t.Fatalf("ReadFile %s: error expected, none found", filename)
	}

	filename = "ioutil_test.go"
	contents, err = ReadFile(filename)
	if err != nil {
		t.Fatalf("ReadFile %s: %v", filename, err)
	}

	checkSize(t, filename, int64(len(contents)))
}

func TestWriteFile(t *testing.T) {
	filename := "_test/rumpelstilzchen"
	data := "Programming today is a race between software engineers striving to " +
		"build bigger and better idiot-proof programs, and the Universe trying " +
		"to produce bigger and better idiots. So far, the Universe is winning."

	if err := WriteFile(filename, []byte(data), 0644); err != nil {
		t.Fatalf("WriteFile %s: %v", filename, err)
	}

	contents, err := ReadFile(filename)
	if err != nil {
		t.Fatalf("ReadFile %s: %v", filename, err)
	}

	if string(contents) != data {
		t.Fatalf("contents = %q\nexpected = %q", string(contents), data)
	}

	// cleanup
	os.Remove(filename) // ignore error
}

func TestReadDir(t *testing.T) {
	dirname := "rumpelstilzchen"
	_, err := ReadDir(dirname)
	if err == nil {
		t.Fatalf("ReadDir %s: error expected, none found", dirname)
	}

	dirname = "."
	list, err := ReadDir(dirname)
	if err != nil {
		t.Fatalf("ReadDir %s: %v", dirname, err)
	}

	foundTest := false
	foundTestDir := false
	for _, dir := range list {
		switch {
		case dir.IsRegular() && dir.Name == "ioutil_test.go":
			foundTest = true
		case dir.IsDirectory() && dir.Name == "_test":
			foundTestDir = true
		}
	}
	if !foundTest {
		t.Fatalf("ReadDir %s: test file not found", dirname)
	}
	if !foundTestDir {
		t.Fatalf("ReadDir %s: _test directory not found", dirname)
	}
}
<|endoftext|>


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

package signal

import (
	"syscall"
	"testing"
)

func TestSignal(t *testing.T) {
	// Send this process a SIGHUP.
	syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0)

	if sig := (<-Incoming).(UnixSignal); sig != 1 {
		t.Error("signal was %v, want %v", sig, 1)
	}
}
<commit_msg>Use t.Errorf for formatted error output.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package signal

import (
	"syscall"
	"testing"
)

func TestSignal(t *testing.T) {
	// Send this process a SIGHUP.
	syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0)

	if sig := (<-Incoming).(UnixSignal); sig != 1 {
		t.Errorf("signal was %v, want %v", sig, 1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

func init() {
	flag.Usage = func() {
		fmt.Printf("Usage of %s:\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Println("The final argument(s) are exec'd and the results stored.")
		fmt.Println("The working directory is expected to be the top level of a git repo")
	}

	config.prefix = flag.String(
		"prefix",
		"",
		"(required): Store run output under this git ref prefix",
	)
	config.propagateErrors = flag.Bool(
		"propagateErrors",
		true,
		"Exit with the same error code as the subcommand",
	)
	config.debug = flag.Bool(
		"debug",
		false,
		"Print verbose debugging",
	)
}

func debug(s interface{}) {
	if *config.debug {
		fmt.Println(s)
	}
}

type Config struct {
	prefix          *string
	propagateErrors *bool
	debug           *bool
}

func (c Config) Valid() bool {
	return !((c.prefix == nil) || (*c.prefix == "") || (len(flag.Args()) == 0))
}

var config Config

func main() {
	flag.Parse()

	if !config.Valid() {
		flag.Usage()
		os.Exit(1)
	}

	treeBeforeBuild := worktree()
	cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
	stdout := bytes.Buffer{}
	stderr := bytes.Buffer{}
	combined := bytes.Buffer{}

	cmd.Stdout = &multiBufferWriter{os.Stdout, &stdout, &combined}
	cmd.Stderr = &multiBufferWriter{os.Stderr, &stderr, &combined}

	run(cmd)

	// Will panic on systems without exit statuses
	waitStatus := cmd.ProcessState.Sys().(syscall.WaitStatus)

	if *config.propagateErrors {
		defer func() {
			os.Exit(waitStatus.ExitStatus())
		}()
	}

	prefix := "refs/" + *config.prefix + "/" + treeBeforeBuild

	updateRef(prefix+"/STDOUT", hashFor(&stdout))
	updateRef(prefix+"/STDERR", hashFor(&stderr))
	updateRef(prefix+"/OUTPUT", hashFor(&combined))
}

func run(cmd *exec.Cmd) {
	die(cmd.Start())
	err := cmd.Wait()
	if err != nil {
		// ExitError indicates process had a non-zero exit code.
		// This is expected behavior for us.
		_, isExitErr := err.(*exec.ExitError)
		if !isExitErr {
			die(err)
		}
	}
}

func hashFor(r io.Reader) string {
	cmd := exec.Command("git", "hash-object", "-w", "--stdin")
	cmd.Stdin = r
	out, err := cmd.Output()
	die(err)
	return strip(string(out))
}

func strip(s string) string {
	return strings.Replace(string(s), "\n", "", -1)
}

func updateRef(ref, sha string) {
	cmd := exec.Command("git", "update-ref", ref, sha)
	out, err := cmd.CombinedOutput()
	debug(string(out))
	die(err)
}

func worktree() string {
	env := os.Environ()
	dir, err := ioutil.TempDir("", "tbd_index")
	die(err)
	env = append(env, "GIT_INDEX_FILE="+dir+"/index")

	output, err := withEnv(env, "git", "add", "-A", ".").CombinedOutput()

	die(err)

	worktree, err := withEnv(env, "git", "write-tree").Output()
	debug(worktree)
	die(err)

	return strip(string(worktree))
}

func withEnv(env []string, target ...string) *exec.Cmd {
	c := exec.Command(target[0], target[1:]...)
	c.Env = env
	return c
}

type multiBufferWriter struct {
	primary  *os.File
	output   *bytes.Buffer
	combined *bytes.Buffer
}

func (db *multiBufferWriter) Write(p []byte) (int, error) {
	n, err := db.primary.Write(p)
	// bytes.Buffer never returns an error and always writes the full length.
	// We can safely discard its result.
	db.output.Write(p[:n])
	db.combined.Write(p[:n])
	return n, err
}

func die(err error) {
	if err == nil {
		return
	}
	fmt.Fprintf(os.Stderr, err.Error()+"\n")
	panic(err)
	os.Exit(1)
}
<commit_msg>Tidy up tbd-run, add todos<commit_after>package main

// TODO: Windows
// TODO: Save worktree
// TODO: Save exit status
// TBD: when/how should I record 'I am about to start building this'

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

func init() {
	flag.Usage = func() {
		fmt.Printf("Usage of %s:\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Println("The final argument(s) are exec'd and the results stored.")
		fmt.Println("The working directory is expected to be the top level of a git repo")
	}

	config.prefix = flag.String(
		"prefix",
		"refs/builds/",
		"(required): Store run output under this git ref prefix",
	)
	config.propagateErrors = flag.Bool(
		"propagateErrors",
		true,
		"Exit with the same error code as the subcommand",
	)
	config.debug = flag.Bool(
		"debug",
		false,
		"Print verbose debugging",
	)
}

func debug(s interface{}) {
	if *config.debug {
		fmt.Println(s)
	}
}

type Config struct {
	prefix          *string
	propagateErrors *bool
	debug           *bool
}

func (c Config) Prefix() string {
	if c.prefix == nil {
		return ""
	} else {
		return *c.prefix
	}
}

func (c Config) Valid() bool {
	return !(c.Prefix() == "" || (len(flag.Args()) == 0))
}

var config Config

func main() {
	flag.Parse()

	if !config.Valid() {
		flag.Usage()
		os.Exit(1)
	}

	treeBeforeBuild := worktree()
	cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
	stdout := bytes.Buffer{}
	stderr := bytes.Buffer{}
	combined := bytes.Buffer{}

	cmd.Stdout = &multiBufferWriter{os.Stdout, &stdout, &combined}
	cmd.Stderr = &multiBufferWriter{os.Stderr, &stderr, &combined}

	run(cmd)

	// Will panic on systems without exit statuses
	waitStatus := cmd.ProcessState.Sys().(syscall.WaitStatus)

	if *config.propagateErrors {
		defer func() {
			os.Exit(waitStatus.ExitStatus())
		}()
	}

	prefix := *config.prefix + treeBeforeBuild

	updateRef(prefix+"/STDOUT", hashFor(&stdout))
	updateRef(prefix+"/STDERR", hashFor(&stderr))
	updateRef(prefix+"/OUTPUT", hashFor(&combined))
}

func run(cmd *exec.Cmd) {
	die(cmd.Start())
	err := cmd.Wait()
	if err != nil {
		// ExitError indicates process had a non-zero exit code.
		// This is expected behavior for us.
		_, isExitErr := err.(*exec.ExitError)
		if !isExitErr {
			die(err)
		}
	}
}

func hashFor(r io.Reader) string {
	cmd := exec.Command("git", "hash-object", "-w", "--stdin")
	cmd.Stdin = r
	out, err := cmd.Output()
	die(err)
	return strip(string(out))
}

func strip(s string) string {
	return strings.Replace(string(s), "\n", "", -1)
}

func updateRef(ref, sha string) {
	cmd := exec.Command("git", "update-ref", ref, sha)
	out, err := cmd.CombinedOutput()
	debug(string(out))
	die(err)
}

func worktree() string {
	env := os.Environ()
	dir, err := ioutil.TempDir("", "tbd_index")
	die(err)
	env = append(env, "GIT_INDEX_FILE="+dir+"/index")

	output, err := withEnv(env, "git", "add", "-A", ".").CombinedOutput()

	die(err)

	worktree, err := withEnv(env, "git", "write-tree").Output()
	debug(worktree)
	die(err)

	return strip(string(worktree))
}

func withEnv(env []string, target ...string) *exec.Cmd {
	c := exec.Command(target[0], target[1:]...)
	c.Env = env
	return c
}

type multiBufferWriter struct {
	primary  *os.File
	output   *bytes.Buffer
	combined *bytes.Buffer
}

func (db *multiBufferWriter) Write(p []byte) (int, error) {
	n, err := db.primary.Write(p)
	// bytes.Buffer never returns an error and always writes the full length.
	// We can safely discard its result.
	db.output.Write(p[:n])
	db.combined.Write(p[:n])
	return n, err
}

func die(err error) {
	if err == nil {
		return
	}
	fmt.Fprintf(os.Stderr, err.Error()+"\n")
	panic(err)
	os.Exit(1)
}
<|endoftext|>


<commit_before>package fit_test

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"sync"
	"testing"
	"time"

	"github.com/tormoder/fit"
)

var (
	update  = flag.Bool("update", false, "update .golden output and table for decode test files if their fingerprint differs")
	fupdate = flag.Bool("fupdate", false, "force regeneration of decode test files table")
)

func init() { flag.Parse() }

var (
	activitySmallMu   sync.Mutex
	activitySmallOnce sync.Once
	activitySmallData []byte
)

func activitySmall() []byte {
	activitySmallMu.Lock()
	defer activitySmallMu.Unlock()
	activitySmallOnce.Do(func() {
		asd, err := ioutil.ReadFile(activitySmallPath)
		if err != nil {
			errDesc := fmt.Sprintf("parseActivitySmallData failed: %v", err)
			panic(errDesc)
		}
		activitySmallData = asd
	})
	return activitySmallData
}

var (
	activitySmallPath      = filepath.Join(tdfolder, "me", "activity-small-fenix2-run.fit")
	activityLargePath      = filepath.Join(tdfolder, "me", "activity-large-fenxi2-multisport.fit")
	activityComponentsPath = filepath.Join(tdfolder, "dcrainmaker", "Edge810-Vector-2013-08-16-15-35-10.fit")
)

const (
	goldenSuffix  = ".golden"
	currentSuffix = ".current"
	gzSuffix      = ".gz"
	tdfolder      = "testdata"
)

func TestDecode(t *testing.T) {
	regenTestTable := struct {
		sync.Mutex
		val bool
	}{}

	t.Run("Group", func(t *testing.T) {
		for i, file := range decodeTestFiles {
			i, file := i, file // Capture range variables.
			t.Run(fmt.Sprintf("%s/%s", file.folder, file.name), func(t *testing.T) {
				t.Parallel()
				fpath := filepath.Join(tdfolder, file.folder, file.name)
				data, err := ioutil.ReadFile(fpath)
				if err != nil {
					t.Fatalf("reading file failed: %v", err)
				}
				fitFile, err := fit.Decode(bytes.NewReader(data), file.dopts.opts()...)
				if !file.wantErr && err != nil {
					t.Fatalf("got error, want none; error is: %v", err)
				}
				if file.wantErr && err == nil {
					t.Fatalf("got no error, want error")
				}
				if file.fingerprint == 0 {
					return
				}
				fp := fitFingerprint(fitFile)
				if fp == file.fingerprint {
					return
				}
				t.Errorf("fit file fingerprint differs: got: %d, want: %d", fp, file.fingerprint)
				if !*update {
					fpath = fpath + currentSuffix
				} else {
					fpath = fpath + goldenSuffix
				}
				if file.compress {
					fpath = fpath + gzSuffix
				}
				err = fitUtterDump(fitFile, fpath, file.compress)
				if err != nil {
					t.Fatalf("error writing output: %v", err)
				}
				if !*update {
					t.Logf("current output written to: %s", fpath)
					t.Logf("use a diff tool to compare (e.g. zdiff if compressed)")
				} else {
					regenTestTable.Lock()
					regenTestTable.val = true
					decodeTestFiles[i].fingerprint = fp
					regenTestTable.Unlock()
					t.Logf("%q has been updated", fpath)
					t.Logf("new fingerprint is: %d, update test case in reader_test.go", fp)
				}
			})
		}
	})

	if regenTestTable.val || *fupdate {
		t.Logf("regenerating table for decode test files...")
		err := regenerateDecodeTestTable()
		if err != nil {
			t.Fatalf("error regenerating table for decode test files: %v", err)
		}
	}
}

func TestDecodeChained(t *testing.T) {
	chainedTestFiles := []struct {
		fpath   string
		dfiles  int
		wantErr bool
		desc    string
	}{
		{
			filepath.Join(tdfolder, "fitsdk", "Activity.fit"),
			1,
			false,
			"single valid fit file",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-settings.fit"),
			2,
			false,
			"two valid chained fit files",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-activity-filecrc.fit"),
			2,
			true,
			"one valid fit file + one fit file with wrong crc",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-settings-corruptheader.fit"),
			1,
			true,
			"one valid fit file + one fit file with corrupt header",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-settings-nodata.fit"),
			2,
			true,
			"one valid fit file + one fit file with ok header but no data",
		},
	}

	for _, ctf := range chainedTestFiles {
		ctf := ctf
		t.Run(ctf.fpath, func(t *testing.T) {
			t.Parallel()
			data, err := ioutil.ReadFile(ctf.fpath)
			if err != nil {
				t.Fatalf("reading file data failed: %v", err)
			}
			fitFiles, err := fit.DecodeChained(bytes.NewReader(data))
			if !ctf.wantErr && err != nil {
				t.Fatalf("got error, want none; error is: %v", err)
			}
			if ctf.wantErr && err == nil {
				t.Fatalf("got no error, want error")
			}
			if len(fitFiles) != ctf.dfiles {
				t.Fatalf("got %d decoded fit file(s), want %d", len(fitFiles), ctf.dfiles)
			}
		})
	}
}

func TestCheckIntegrity(t *testing.T) {
	t.Run("ActivitySmall", func(t *testing.T) {
		err := fit.CheckIntegrity(bytes.NewReader(activitySmall()), false)
		if err != nil {
			t.Errorf("%q: failed: %v", activitySmallPath, err)
		}
	})
	t.Run("ActivitySDK", func(t *testing.T) {
		fpath := filepath.Join(tdfolder, "fitsdk", "Activity.fit")
		data, err := ioutil.ReadFile(fpath)
		if err != nil {
			t.Fatalf("reading %q failed: %v", fpath, err)
		}
		err = fit.CheckIntegrity(bytes.NewReader(data), false)
		if err != nil {
			t.Errorf("%q: failed: %v", fpath, err)
		}
	})
}

func TestDecodeHeader(t *testing.T) {
	wantHeader := fit.Header{
		Size:            0xe,
		ProtocolVersion: 0x10,
		ProfileVersion:  0x457,
		DataSize:        0x1dbdf,
		DataType:        [4]uint8{0x2e, 0x46, 0x49, 0x54},
		CRC:             0x1ec4,
	}
	gotHeader, err := fit.DecodeHeader(bytes.NewReader(activitySmall()))
	if err != nil {
		t.Errorf("%q: failed: %v", activitySmallPath, err)
	}
	if gotHeader != wantHeader {
		t.Errorf("got header:\n%#v\nwant header: %#v", gotHeader, wantHeader)
	}
}

func TestDecodeHeaderAndFileID(t *testing.T) {
	wantHeader := fit.Header{
		Size:            0xe,
		ProtocolVersion: 0x10,
		ProfileVersion:  0x457,
		DataSize:        0x1dbdf,
		DataType:        [4]uint8{0x2e, 0x46, 0x49, 0x54},
		CRC:             0x1ec4,
	}
	tc := time.Unix(1439652761, 0)
	tc = tc.UTC()
	wantFileId := fit.FileIdMsg{
		Type:         0x4,
		Manufacturer: 0x1,
		Product:      0x7af,
		SerialNumber: 0xe762d9cf,
		Number:       0xffff,
		TimeCreated:  tc,
		ProductName:  "",
	}

	gotHeader, gotFileId, err := fit.DecodeHeaderAndFileID(bytes.NewReader(activitySmall()))
	if err != nil {
		t.Errorf("%q: failed: %v", activitySmallPath, err)
	}
	if gotHeader != wantHeader {
		t.Errorf("%q:\ngot header:\n%#v\nwant header:\n%#v", activitySmallPath, gotHeader, wantHeader)
	}
	if gotFileId != wantFileId {
		t.Errorf("%q:\ngot FileIdMsg:\n%v\nwant FileIdMsg:\n%v", activitySmallPath, gotFileId, wantFileId)
	}
}

func BenchmarkDecodeActivity(b *testing.B) {
	files := []struct {
		desc, path string
	}{
		{"Small", activitySmallPath},
		{"Large", activityLargePath},
		{"WithComponents", activityComponentsPath},
	}
	for _, file := range files {
		b.Run(file.desc, func(b *testing.B) {
			data, err := ioutil.ReadFile(file.path)
			if err != nil {
				b.Fatalf("%q: error reading file: %v", file.path, err)
			}
			b.ReportAllocs()
			b.SetBytes(int64(len(data)))
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				_, err := fit.Decode(bytes.NewReader(data))
				if err != nil {
					b.Fatalf("%q: error decoding file: %v", file.path, err)
				}
			}
		})
	}
}

func BenchmarkDecodeActivityLargeParallel(b *testing.B) {
	data, err := ioutil.ReadFile(activityLargePath)
	if err != nil {
		b.Fatal(err)
	}
	b.ReportAllocs()
	b.SetBytes(int64(len(data)))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			_, err := fit.Decode(bytes.NewReader(data))
			if err != nil {
				b.Fatal(err)
			}
		}
	})
}

func BenchmarkDecodeHeader(b *testing.B) {
	data := activitySmall()
	b.ReportAllocs()
	b.SetBytes(int64(len(data)))
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err := fit.DecodeHeader(bytes.NewReader(data))
		if err != nil {
			b.Fatalf("%q: error decoding header: %v", activitySmallPath, err)
		}
	}

}

func BenchmarkDecodeHeaderAndFileID(b *testing.B) {
	data := activitySmall()
	b.ReportAllocs()
	b.SetBytes(int64(len(data)))
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, _, err := fit.DecodeHeaderAndFileID(bytes.NewReader(data))
		if err != nil {
			b.Fatalf("%q: error decoding header/fileid: %v", activitySmallPath, err)
		}
	}
}
<commit_msg>reader_test: generalize decode benchmark with respect to file type<commit_after>package fit_test

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"sync"
	"testing"
	"time"

	"github.com/tormoder/fit"
)

var (
	update  = flag.Bool("update", false, "update .golden output and table for decode test files if their fingerprint differs")
	fupdate = flag.Bool("fupdate", false, "force regeneration of decode test files table")
)

func init() { flag.Parse() }

var (
	activitySmallMu   sync.Mutex
	activitySmallOnce sync.Once
	activitySmallData []byte
)

func activitySmall() []byte {
	activitySmallMu.Lock()
	defer activitySmallMu.Unlock()
	activitySmallOnce.Do(func() {
		asd, err := ioutil.ReadFile(activitySmallPath)
		if err != nil {
			errDesc := fmt.Sprintf("parseActivitySmallData failed: %v", err)
			panic(errDesc)
		}
		activitySmallData = asd
	})
	return activitySmallData
}

var (
	activitySmallPath      = filepath.Join(tdfolder, "me", "activity-small-fenix2-run.fit")
	activityLargePath      = filepath.Join(tdfolder, "me", "activity-large-fenxi2-multisport.fit")
	activityComponentsPath = filepath.Join(tdfolder, "dcrainmaker", "Edge810-Vector-2013-08-16-15-35-10.fit")
)

const (
	goldenSuffix  = ".golden"
	currentSuffix = ".current"
	gzSuffix      = ".gz"
	tdfolder      = "testdata"
)

func TestDecode(t *testing.T) {
	regenTestTable := struct {
		sync.Mutex
		val bool
	}{}

	t.Run("Group", func(t *testing.T) {
		for i, file := range decodeTestFiles {
			i, file := i, file // Capture range variables.
			t.Run(fmt.Sprintf("%s/%s", file.folder, file.name), func(t *testing.T) {
				t.Parallel()
				fpath := filepath.Join(tdfolder, file.folder, file.name)
				data, err := ioutil.ReadFile(fpath)
				if err != nil {
					t.Fatalf("reading file failed: %v", err)
				}
				fitFile, err := fit.Decode(bytes.NewReader(data), file.dopts.opts()...)
				if !file.wantErr && err != nil {
					t.Fatalf("got error, want none; error is: %v", err)
				}
				if file.wantErr && err == nil {
					t.Fatalf("got no error, want error")
				}
				if file.fingerprint == 0 {
					return
				}
				fp := fitFingerprint(fitFile)
				if fp == file.fingerprint {
					return
				}
				t.Errorf("fit file fingerprint differs: got: %d, want: %d", fp, file.fingerprint)
				if !*update {
					fpath = fpath + currentSuffix
				} else {
					fpath = fpath + goldenSuffix
				}
				if file.compress {
					fpath = fpath + gzSuffix
				}
				err = fitUtterDump(fitFile, fpath, file.compress)
				if err != nil {
					t.Fatalf("error writing output: %v", err)
				}
				if !*update {
					t.Logf("current output written to: %s", fpath)
					t.Logf("use a diff tool to compare (e.g. zdiff if compressed)")
				} else {
					regenTestTable.Lock()
					regenTestTable.val = true
					decodeTestFiles[i].fingerprint = fp
					regenTestTable.Unlock()
					t.Logf("%q has been updated", fpath)
					t.Logf("new fingerprint is: %d, update test case in reader_test.go", fp)
				}
			})
		}
	})

	if regenTestTable.val || *fupdate {
		t.Logf("regenerating table for decode test files...")
		err := regenerateDecodeTestTable()
		if err != nil {
			t.Fatalf("error regenerating table for decode test files: %v", err)
		}
	}
}

func TestDecodeChained(t *testing.T) {
	chainedTestFiles := []struct {
		fpath   string
		dfiles  int
		wantErr bool
		desc    string
	}{
		{
			filepath.Join(tdfolder, "fitsdk", "Activity.fit"),
			1,
			false,
			"single valid fit file",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-settings.fit"),
			2,
			false,
			"two valid chained fit files",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-activity-filecrc.fit"),
			2,
			true,
			"one valid fit file + one fit file with wrong crc",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-settings-corruptheader.fit"),
			1,
			true,
			"one valid fit file + one fit file with corrupt header",
		},
		{
			filepath.Join(tdfolder, "chained", "activity-settings-nodata.fit"),
			2,
			true,
			"one valid fit file + one fit file with ok header but no data",
		},
	}

	for _, ctf := range chainedTestFiles {
		ctf := ctf
		t.Run(ctf.fpath, func(t *testing.T) {
			t.Parallel()
			data, err := ioutil.ReadFile(ctf.fpath)
			if err != nil {
				t.Fatalf("reading file data failed: %v", err)
			}
			fitFiles, err := fit.DecodeChained(bytes.NewReader(data))
			if !ctf.wantErr && err != nil {
				t.Fatalf("got error, want none; error is: %v", err)
			}
			if ctf.wantErr && err == nil {
				t.Fatalf("got no error, want error")
			}
			if len(fitFiles) != ctf.dfiles {
				t.Fatalf("got %d decoded fit file(s), want %d", len(fitFiles), ctf.dfiles)
			}
		})
	}
}

func TestCheckIntegrity(t *testing.T) {
	t.Run("ActivitySmall", func(t *testing.T) {
		err := fit.CheckIntegrity(bytes.NewReader(activitySmall()), false)
		if err != nil {
			t.Errorf("%q: failed: %v", activitySmallPath, err)
		}
	})
	t.Run("ActivitySDK", func(t *testing.T) {
		fpath := filepath.Join(tdfolder, "fitsdk", "Activity.fit")
		data, err := ioutil.ReadFile(fpath)
		if err != nil {
			t.Fatalf("reading %q failed: %v", fpath, err)
		}
		err = fit.CheckIntegrity(bytes.NewReader(data), false)
		if err != nil {
			t.Errorf("%q: failed: %v", fpath, err)
		}
	})
}

func TestDecodeHeader(t *testing.T) {
	wantHeader := fit.Header{
		Size:            0xe,
		ProtocolVersion: 0x10,
		ProfileVersion:  0x457,
		DataSize:        0x1dbdf,
		DataType:        [4]uint8{0x2e, 0x46, 0x49, 0x54},
		CRC:             0x1ec4,
	}
	gotHeader, err := fit.DecodeHeader(bytes.NewReader(activitySmall()))
	if err != nil {
		t.Errorf("%q: failed: %v", activitySmallPath, err)
	}
	if gotHeader != wantHeader {
		t.Errorf("got header:\n%#v\nwant header: %#v", gotHeader, wantHeader)
	}
}

func TestDecodeHeaderAndFileID(t *testing.T) {
	wantHeader := fit.Header{
		Size:            0xe,
		ProtocolVersion: 0x10,
		ProfileVersion:  0x457,
		DataSize:        0x1dbdf,
		DataType:        [4]uint8{0x2e, 0x46, 0x49, 0x54},
		CRC:             0x1ec4,
	}
	tc := time.Unix(1439652761, 0)
	tc = tc.UTC()
	wantFileId := fit.FileIdMsg{
		Type:         0x4,
		Manufacturer: 0x1,
		Product:      0x7af,
		SerialNumber: 0xe762d9cf,
		Number:       0xffff,
		TimeCreated:  tc,
		ProductName:  "",
	}

	gotHeader, gotFileId, err := fit.DecodeHeaderAndFileID(bytes.NewReader(activitySmall()))
	if err != nil {
		t.Errorf("%q: failed: %v", activitySmallPath, err)
	}
	if gotHeader != wantHeader {
		t.Errorf("%q:\ngot header:\n%#v\nwant header:\n%#v", activitySmallPath, gotHeader, wantHeader)
	}
	if gotFileId != wantFileId {
		t.Errorf("%q:\ngot FileIdMsg:\n%v\nwant FileIdMsg:\n%v", activitySmallPath, gotFileId, wantFileId)
	}
}

func BenchmarkDecode(b *testing.B) {
	files := []struct {
		desc, path string
	}{
		{"ActivitySmall", activitySmallPath},
		{"ActivityLarge", activityLargePath},
		{"ActivityWithComponents", activityComponentsPath},
	}
	for _, file := range files {
		b.Run(file.desc, func(b *testing.B) {
			data, err := ioutil.ReadFile(file.path)
			if err != nil {
				b.Fatalf("%q: error reading file: %v", file.path, err)
			}
			b.ReportAllocs()
			b.SetBytes(int64(len(data)))
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				_, err := fit.Decode(bytes.NewReader(data))
				if err != nil {
					b.Fatalf("%q: error decoding file: %v", file.path, err)
				}
			}
		})
	}
}

func BenchmarkDecodeActivityLargeParallel(b *testing.B) {
	data, err := ioutil.ReadFile(activityLargePath)
	if err != nil {
		b.Fatal(err)
	}
	b.ReportAllocs()
	b.SetBytes(int64(len(data)))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			_, err := fit.Decode(bytes.NewReader(data))
			if err != nil {
				b.Fatal(err)
			}
		}
	})
}

func BenchmarkDecodeHeader(b *testing.B) {
	data := activitySmall()
	b.ReportAllocs()
	b.SetBytes(int64(len(data)))
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err := fit.DecodeHeader(bytes.NewReader(data))
		if err != nil {
			b.Fatalf("%q: error decoding header: %v", activitySmallPath, err)
		}
	}

}

func BenchmarkDecodeHeaderAndFileID(b *testing.B) {
	data := activitySmall()
	b.ReportAllocs()
	b.SetBytes(int64(len(data)))
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, _, err := fit.DecodeHeaderAndFileID(bytes.NewReader(data))
		if err != nil {
			b.Fatalf("%q: error decoding header/fileid: %v", activitySmallPath, err)
		}
	}
}
<|endoftext|>


<commit_before>// +build linux

package tcplisten

import (
	"fmt"
	"io/ioutil"
	"strconv"
	"strings"
	"syscall"
)

const (
	soReusePort = 0x0F
	tcpFastOpen = 0x17
)

func enableDeferAccept(fd int) error {
	if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_DEFER_ACCEPT, 1); err != nil {
		return fmt.Errorf("cannot enable TCP_DEFER_ACCEPT: %s", err)
	}
	return nil
}

func enableFastOpen(fd int) error {
	if err := syscall.SetsockoptInt(fd, syscall.SOL_TCP, tcpFastOpen, fastOpenQlen); err != nil {
		return fmt.Errorf("cannot enable TCP_FASTOPEN(qlen=%d): %s", fastOpenQlen, err)
	}
	return nil
}

const fastOpenQlen = 16 * 1024

func soMaxConn() (int, error) {
	data, err := ioutil.ReadFile(soMaxConnFilePath)
	if err != nil {
		return -1, err
	}
	s := strings.TrimSpace(string(data))
	n, err := strconv.Atoi(s)
	if err != nil || n <= 0 {
		return -1, fmt.Errorf("cannot parse somaxconn %q read from %s: %s", s, soMaxConnFilePath, err)
	}

	// Linux stores the backlog in a uint16.
	// Truncate number to avoid wrapping.
	// See https://github.com/golang/go/issues/5030 .
	if n > 1<<16-1 {
		n = 1<<16 - 1
	}
	return n, nil
}

const soMaxConnFilePath = "/proc/sys/net/core/somaxconn"
<commit_msg>make travis happy where /proc/sys/net/core/somaxconn may be missing<commit_after>// +build linux

package tcplisten

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"syscall"
)

const (
	soReusePort = 0x0F
	tcpFastOpen = 0x17
)

func enableDeferAccept(fd int) error {
	if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_DEFER_ACCEPT, 1); err != nil {
		return fmt.Errorf("cannot enable TCP_DEFER_ACCEPT: %s", err)
	}
	return nil
}

func enableFastOpen(fd int) error {
	if err := syscall.SetsockoptInt(fd, syscall.SOL_TCP, tcpFastOpen, fastOpenQlen); err != nil {
		return fmt.Errorf("cannot enable TCP_FASTOPEN(qlen=%d): %s", fastOpenQlen, err)
	}
	return nil
}

const fastOpenQlen = 16 * 1024

func soMaxConn() (int, error) {
	data, err := ioutil.ReadFile(soMaxConnFilePath)
	if err != nil {
		// This error may trigger on travis build. Just use SOMAXCONN
		if os.IsNotExist(err) {
			return syscall.SOMAXCONN, nil
		}
		return -1, err
	}
	s := strings.TrimSpace(string(data))
	n, err := strconv.Atoi(s)
	if err != nil || n <= 0 {
		return -1, fmt.Errorf("cannot parse somaxconn %q read from %s: %s", s, soMaxConnFilePath, err)
	}

	// Linux stores the backlog in a uint16.
	// Truncate number to avoid wrapping.
	// See https://github.com/golang/go/issues/5030 .
	if n > 1<<16-1 {
		n = 1<<16 - 1
	}
	return n, nil
}

const soMaxConnFilePath = "/proc/sys/net/core/somaxconn"
<|endoftext|>


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

package k8sTest

import (
	"fmt"
	"path/filepath"
	"sync"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var (
	demoTestName         = "K8sValidatedDemosTest"
	starWarsDemoLinkRoot = "https://raw.githubusercontent.com/cilium/star-wars-demo/master/v1"
)

func getStarWarsResourceLink(file string) string {
	// Cannot use filepath.Join because it removes one of the '/' from
	// https:// and results in a malformed URL.
	return fmt.Sprintf("%s/%s", starWarsDemoLinkRoot, file)
}

var _ = Describe(demoTestName, func() {

	var (
		demoPath         string
		once             sync.Once
		kubectl          *helpers.Kubectl
		logger           *logrus.Entry
		ciliumYAML       string
		microscopeErr    error
		microscopeCancel func() error

		deathStarYAMLLink = getStarWarsResourceLink("02-deathstar.yaml")
		l4PolicyYAMLLink  = getStarWarsResourceLink("policy/l4_policy.yaml")
		xwingYAMLLink     = getStarWarsResourceLink("03-xwing.yaml")
		l7PolicyYAMLLink  = getStarWarsResourceLink("policy/l7_policy.yaml")
	)

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": demoTestName})
		logger.Info("Starting")
		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		//Manifest paths
		demoPath = kubectl.ManifestGet("demo.yaml")

		// TODO (ianvernon) - factor this code out into separate functions as it's
		// boilerplate for most K8s test setup.
		ciliumYAML = kubectl.ManifestGet("cilium_ds.yaml")
		res := kubectl.Apply(ciliumYAML)
		res.ExpectSuccess("unable to apply %s: %s", ciliumYAML, res.CombineOutput())
		status, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 300)
		Expect(status).Should(BeTrue())
		Expect(err).Should(BeNil())
		err = kubectl.WaitKubeDNS()
		Expect(err).Should(BeNil())
	}

	BeforeEach(func() {
		once.Do(initialize)
	})

	AfterFailed(func() {
		kubectl.CiliumReport(helpers.KubeSystemNamespace)
	})

	JustBeforeEach(func() {
		microscopeErr, microscopeCancel = kubectl.MicroscopeStart()
		Expect(microscopeErr).To(BeNil(), "Microscope cannot be started")
	})

	JustAfterEach(func() {
		kubectl.ValidateNoErrorsOnLogs(CurrentGinkgoTestDescription().Duration)
		Expect(microscopeCancel()).To(BeNil(), "cannot stop microscope")
	})

	AfterEach(func() {
		By("Deleting all resources created during test")
		kubectl.Delete(l7PolicyYAMLLink)
		kubectl.Delete(l4PolicyYAMLLink)
		kubectl.Delete(deathStarYAMLLink)
		kubectl.Delete(xwingYAMLLink)

		By("Waiting for all pods to finish terminating")
		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating pods are not deleted after timeout")
	})

	It("Tests Star Wars Demo", func() {

		allianceLabel := "org=alliance"
		empireLabel := "org=empire"
		deathstarServiceName := "deathstar.default.svc.cluster.local"

		exhaustPortPath := filepath.Join(deathstarServiceName, "/v1/exhaust-port")

		By(fmt.Sprintf("Getting Cilium Pod on node %s", helpers.K8s2))
		ciliumPod2, err := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s2)
		Expect(err).Should(BeNil(), "unable to get Cilium pod on node %s", helpers.K8s2)

		// Taint the node instead of adding a nodeselector in the file so that we
		// don't have to customize the YAML for this test.
		By(fmt.Sprintf("Tainting %s so that all pods run on %s", helpers.K8s1, helpers.K8s2))
		res := kubectl.Exec(fmt.Sprintf("kubectl taint nodes %s demo=false:NoSchedule", helpers.K8s1))
		defer func() {
			By(fmt.Sprintf("Removing taint from %s after test finished", helpers.K8s1))
			res := kubectl.Exec(fmt.Sprintf("kubectl taint nodes %s demo:NoSchedule-", helpers.K8s1))
			res.ExpectSuccess("Unable to remove taint from k8s1: %s", res.CombineOutput())
		}()
		res.ExpectSuccess("Unable to apply taint to %s: %s", helpers.K8s1, res.CombineOutput())

		By("Applying deathstar deployment")
		res = kubectl.Apply(deathStarYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", deathStarYAMLLink, res.CombineOutput())

		By("Waiting for deathstar deployment pods to be ready")
		_, err = kubectl.WaitforPods(helpers.DefaultNamespace, fmt.Sprintf("-l %s", empireLabel), 300)
		Expect(err).Should(BeNil(), "Empire pods are not ready after timeout")

		By("Applying policy and waiting for policy revision to increase in Cilium pods")
		res = kubectl.Apply(l4PolicyYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", l4PolicyYAMLLink, res.CombineOutput())

		By("Applying alliance deployment")
		res = kubectl.Apply(xwingYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", xwingYAMLLink, res.CombineOutput())

		By("Waiting for alliance pods to be ready")
		_, err = kubectl.WaitforPods(helpers.DefaultNamespace, fmt.Sprintf("-l %s", allianceLabel), 300)
		Expect(err).Should(BeNil(), "Alliance pods are not ready after timeout")

		By("Getting xwing pod names")
		xwingPods, err := kubectl.GetPodNames(helpers.DefaultNamespace, allianceLabel)
		Expect(err).Should(BeNil())
		Expect(xwingPods[0]).ShouldNot(Equal(""), "unable to get xwing pod names")

		// Test only needs to access one of the pods.
		xwingPod := xwingPods[0]

		By("Making sure all endpoints are in ready state")
		arePodsReady := kubectl.CiliumEndpointWait(ciliumPod2)
		Expect(arePodsReady).To(BeTrue(), "pods running on k8s2 are not ready")

		By("Showing how alliance can execute REST API call to main API endpoint")

		err = kubectl.WaitForKubeDNSEntry(deathstarServiceName)
		Expect(err).To(BeNil(), "DNS entry is not ready after timeout")

		res = kubectl.ExecPodCmd(helpers.DefaultNamespace, xwingPod,
			helpers.CurlWithHTTPCode("http://%s/v1", deathstarServiceName))
		res.ExpectContains("200", "unable to curl %s/v1: %s", deathstarServiceName, res.CombineOutput())

		By(fmt.Sprintf("Importing L7 Policy which restricts access to %s", exhaustPortPath))
		kubectl.Delete(l4PolicyYAMLLink)
		res = kubectl.Apply(l7PolicyYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", l7PolicyYAMLLink, res.CombineOutput())

		By("Waiting for endpoints to be ready after importing policy")
		arePodsReady = kubectl.CiliumEndpointWait(ciliumPod2)
		Expect(arePodsReady).To(BeTrue(), "pods running on k8s2 are not ready")

		By(fmt.Sprintf("Showing how alliance cannot access %s without force header in API request after importing L7 Policy", exhaustPortPath))
		res = kubectl.ExecPodCmd(helpers.DefaultNamespace, xwingPod,
			helpers.CurlWithHTTPCode("-X PUT http://%s", exhaustPortPath))
		res.ExpectContains("403", "able to access %s when policy disallows it; %s", exhaustPortPath, res.CombineOutput())

		By(fmt.Sprintf("Showing how alliance can access %s with force header in API request to attack the deathstar", exhaustPortPath))
		res = kubectl.ExecPodCmd(helpers.DefaultNamespace, xwingPod,
			helpers.CurlWithHTTPCode("-X PUT -H 'X-Has-Force: True' http://%s", exhaustPortPath))
		By("Expecting 503 to be returned when using force header to attack the deathstar")
		res.ExpectContains("503", "unable to access %s when policy allows it; %s", exhaustPortPath, res.CombineOutput())
	})

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

package k8sTest

import (
	"fmt"
	"path/filepath"
	"sync"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var (
	demoTestName         = "K8sValidatedDemosTest"
	starWarsDemoLinkRoot = "https://raw.githubusercontent.com/cilium/star-wars-demo/master/v1"
)

func getStarWarsResourceLink(file string) string {
	// Cannot use filepath.Join because it removes one of the '/' from
	// https:// and results in a malformed URL.
	return fmt.Sprintf("%s/%s", starWarsDemoLinkRoot, file)
}

var _ = Describe(demoTestName, func() {

	var (
		demoPath         string
		once             sync.Once
		kubectl          *helpers.Kubectl
		logger           *logrus.Entry
		ciliumYAML       string
		microscopeErr    error
		microscopeCancel func() error

		deathStarYAMLLink = getStarWarsResourceLink("02-deathstar.yaml")
		l4PolicyYAMLLink  = getStarWarsResourceLink("policy/l4_policy.yaml")
		xwingYAMLLink     = getStarWarsResourceLink("03-xwing.yaml")
		l7PolicyYAMLLink  = getStarWarsResourceLink("policy/l7_policy.yaml")
	)

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": demoTestName})
		logger.Info("Starting")
		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		//Manifest paths
		demoPath = kubectl.ManifestGet("demo.yaml")

		// TODO (ianvernon) - factor this code out into separate functions as it's
		// boilerplate for most K8s test setup.
		ciliumYAML = kubectl.ManifestGet("cilium_ds.yaml")
		res := kubectl.Apply(ciliumYAML)
		res.ExpectSuccess("unable to apply %s: %s", ciliumYAML, res.CombineOutput())
		status, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 300)
		Expect(status).Should(BeTrue())
		Expect(err).Should(BeNil())
		err = kubectl.WaitKubeDNS()
		Expect(err).Should(BeNil())
	}

	BeforeEach(func() {
		once.Do(initialize)
	})

	AfterFailed(func() {
		kubectl.CiliumReport(helpers.KubeSystemNamespace)
	})

	JustBeforeEach(func() {
		microscopeErr, microscopeCancel = kubectl.MicroscopeStart()
		Expect(microscopeErr).To(BeNil(), "Microscope cannot be started")
	})

	JustAfterEach(func() {
		kubectl.ValidateNoErrorsOnLogs(CurrentGinkgoTestDescription().Duration)
		Expect(microscopeCancel()).To(BeNil(), "cannot stop microscope")
	})

	AfterEach(func() {
		By("Deleting all resources created during test")
		kubectl.Delete(l7PolicyYAMLLink)
		kubectl.Delete(l4PolicyYAMLLink)
		kubectl.Delete(deathStarYAMLLink)
		kubectl.Delete(xwingYAMLLink)

		By("Waiting for all pods to finish terminating")
		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating pods are not deleted after timeout")
	})

	It("Tests Star Wars Demo", func() {

		allianceLabel := "org=alliance"
		empireLabel := "org=empire"
		deathstarServiceName := "deathstar.default.svc.cluster.local"

		exhaustPortPath := filepath.Join(deathstarServiceName, "/v1/exhaust-port")

		By(fmt.Sprintf("Getting Cilium Pod on node %s", helpers.K8s2))
		ciliumPod2, err := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s2)
		Expect(err).Should(BeNil(), "unable to get Cilium pod on node %s", helpers.K8s2)

		// Taint the node instead of adding a nodeselector in the file so that we
		// don't have to customize the YAML for this test.
		By(fmt.Sprintf("Tainting %s so that all pods run on %s", helpers.K8s1, helpers.K8s2))
		res := kubectl.Exec(fmt.Sprintf("kubectl taint nodes %s demo=false:NoSchedule", helpers.K8s1))
		defer func() {
			By(fmt.Sprintf("Removing taint from %s after test finished", helpers.K8s1))
			res := kubectl.Exec(fmt.Sprintf("kubectl taint nodes %s demo:NoSchedule-", helpers.K8s1))
			res.ExpectSuccess("Unable to remove taint from k8s1: %s", res.CombineOutput())
		}()
		res.ExpectSuccess("Unable to apply taint to %s: %s", helpers.K8s1, res.CombineOutput())

		By("Applying deathstar deployment")
		res = kubectl.Apply(deathStarYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", deathStarYAMLLink, res.CombineOutput())

		By("Waiting for deathstar deployment pods to be ready")
		_, err = kubectl.WaitforPods(helpers.DefaultNamespace, fmt.Sprintf("-l %s", empireLabel), 300)
		Expect(err).Should(BeNil(), "Empire pods are not ready after timeout")

		By("Applying policy and waiting for policy revision to increase in Cilium pods")
		res = kubectl.Apply(l4PolicyYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", l4PolicyYAMLLink, res.CombineOutput())

		By("Applying alliance deployment")
		res = kubectl.Apply(xwingYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", xwingYAMLLink, res.CombineOutput())

		By("Waiting for alliance pods to be ready")
		_, err = kubectl.WaitforPods(helpers.DefaultNamespace, fmt.Sprintf("-l %s", allianceLabel), 300)
		Expect(err).Should(BeNil(), "Alliance pods are not ready after timeout")

		By("Getting xwing pod names")
		xwingPods, err := kubectl.GetPodNames(helpers.DefaultNamespace, allianceLabel)
		Expect(err).Should(BeNil())
		Expect(xwingPods[0]).ShouldNot(Equal(""), "unable to get xwing pod names")

		// Test only needs to access one of the pods.
		xwingPod := xwingPods[0]

		By("Making sure all endpoints are in ready state")
		arePodsReady := kubectl.CiliumEndpointWait(ciliumPod2)
		Expect(arePodsReady).To(BeTrue(), "pods running on k8s2 are not ready")

		By("Showing how alliance can execute REST API call to main API endpoint")

		err = kubectl.WaitForKubeDNSEntry(deathstarServiceName)
		Expect(err).To(BeNil(), "DNS entry is not ready after timeout")

		res = kubectl.ExecPodCmd(helpers.DefaultNamespace, xwingPod,
			helpers.CurlWithHTTPCode("http://%s/v1", deathstarServiceName))
		res.ExpectContains("200", "unable to curl %s/v1: %s", deathstarServiceName, res.Output())

		By(fmt.Sprintf("Importing L7 Policy which restricts access to %s", exhaustPortPath))
		kubectl.Delete(l4PolicyYAMLLink)
		res = kubectl.Apply(l7PolicyYAMLLink)
		res.ExpectSuccess("unable to apply %s: %s", l7PolicyYAMLLink, res.CombineOutput())

		By("Waiting for endpoints to be ready after importing policy")
		arePodsReady = kubectl.CiliumEndpointWait(ciliumPod2)
		Expect(arePodsReady).To(BeTrue(), "pods running on k8s2 are not ready")

		By(fmt.Sprintf("Showing how alliance cannot access %s without force header in API request after importing L7 Policy", exhaustPortPath))
		res = kubectl.ExecPodCmd(helpers.DefaultNamespace, xwingPod,
			helpers.CurlWithHTTPCode("-X PUT http://%s", exhaustPortPath))
		res.ExpectContains("403", "able to access %s when policy disallows it; %s", exhaustPortPath, res.Output())

		By(fmt.Sprintf("Showing how alliance can access %s with force header in API request to attack the deathstar", exhaustPortPath))
		res = kubectl.ExecPodCmd(helpers.DefaultNamespace, xwingPod,
			helpers.CurlWithHTTPCode("-X PUT -H 'X-Has-Force: True' http://%s", exhaustPortPath))
		By("Expecting 503 to be returned when using force header to attack the deathstar")
		res.ExpectContains("503", "unable to access %s when policy allows it; %s", exhaustPortPath, res.Output())
	})

})
<|endoftext|>


<commit_before><commit_msg>[buildbucket] Treat unspecified task dimension expiration seconds as 0<commit_after><|endoftext|>


<commit_before>// $G $F.go && $L $F.$A && ./$A.out

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

import (
	"fmt"
	"math"
	"strings"
)

type Error interface {
	String() string
}

type ErrorTest struct {
	name	string
	fn	func()
	err	string
}

var (
	i, j, k int = 0, 0, 1
	i8, j8, k8 int8 = 0, 0, 1
	i16, j16, k16 int16 = 0, 0, 1
	i32, j32, k32 int32 = 0, 0, 1
	i64, j64, k64 int64 = 0, 0, 1

	u, v, w uint = 0, 0, 1
	u8, v8, w8 uint8 = 0, 0, 1
	u16, v16, w16 uint16 = 0, 0, 1
	u32, v32, w32 uint32 = 0, 0, 1
	u64, v64, w64 uint64 = 0, 0, 1
	up, vp, wp uintptr = 0, 0, 1

	f, g, h float = 0, 0, 1
	f32, g32, h32 float32 = 0, 0, 1
	f64, g64, h64, inf, negInf, nan float64 = 0, 0, 1, math.Inf(1), math.Inf(-1), math.NaN()

	c, d, e complex = 0+0i, 0+0i, 1+1i
	c64, d64, e64 complex64 = 0+0i, 0+0i, 1+1i
	c128, d128, e128 complex128 = 0+0i, 0+0i, 1+1i
)

var tmp interface{}

// We could assign to _ but the compiler optimizes it too easily.
func use(v interface{}) {
	tmp = v
}

// Verify error/no error for all types.
var errorTests = []ErrorTest{
	// All integer divide by zero should error.
	ErrorTest{ "int 0/0", func() { use(i/j) }, "divide", },
	ErrorTest{ "int8 0/0", func() { use(i8/j8) }, "divide", },
	ErrorTest{ "int16 0/0", func() { use(i16/j16) }, "divide", },
	ErrorTest{ "int32 0/0", func() { use(i32/j32) }, "divide", },
	ErrorTest{ "int64 0/0", func() { use(i64/j64) }, "divide", },

	ErrorTest{ "int 1/0", func() { use(k/j) }, "divide", },
	ErrorTest{ "int8 1/0", func() { use(k8/j8) }, "divide", },
	ErrorTest{ "int16 1/0", func() { use(k16/j16) }, "divide", },
	ErrorTest{ "int32 1/0", func() { use(k32/j32) }, "divide", },
	ErrorTest{ "int64 1/0", func() { use(k64/j64) }, "divide", },

	ErrorTest{ "uint 0/0", func() { use(u/v) }, "divide", },
	ErrorTest{ "uint8 0/0", func() { use(u8/v8) }, "divide", },
	ErrorTest{ "uint16 0/0", func() { use(u16/v16) }, "divide", },
	ErrorTest{ "uint32 0/0", func() { use(u32/v32) }, "divide", },
	ErrorTest{ "uint64 0/0", func() { use(u64/v64) }, "divide", },
	ErrorTest{ "uintptr 0/0", func() { use(up/vp) }, "divide", },

	ErrorTest{ "uint 1/0", func() { use(w/v) }, "divide", },
	ErrorTest{ "uint8 1/0", func() { use(w8/v8) }, "divide", },
	ErrorTest{ "uint16 1/0", func() { use(w16/v16) }, "divide", },
	ErrorTest{ "uint32 1/0", func() { use(w32/v32) }, "divide", },
	ErrorTest{ "uint64 1/0", func() { use(w64/v64) }, "divide", },
	ErrorTest{ "uintptr 1/0", func() { use(wp/vp) }, "divide", },

	// All floating divide by zero should not error.
	ErrorTest{ "float 0/0", func() { use(f/g) }, "", },
	ErrorTest{ "float32 0/0", func() { use(f32/g32) }, "", },
	ErrorTest{ "float64 0/0", func() { use(f64/g64) }, "", },

	ErrorTest{ "float 1/0", func() { use(h/g) }, "", },
	ErrorTest{ "float32 1/0", func() { use(h32/g32) }, "", },
	ErrorTest{ "float64 1/0", func() { use(h64/g64) }, "", },
	ErrorTest{ "float64 inf/0", func() { use(inf/g64) }, "", },
	ErrorTest{ "float64 -inf/0", func() { use(negInf/g64) }, "", },
	ErrorTest{ "float64 nan/0", func() { use(nan/g64) }, "", },

	// All complex divide by zero should not error.
	ErrorTest{ "complex 0/0", func() { use(c/d) }, "", },
	ErrorTest{ "complex64 0/0", func() { use(c64/d64) }, "", },
	ErrorTest{ "complex128 0/0", func() { use(c128/d128) }, "", },

	ErrorTest{ "complex 1/0", func() { use(e/d) }, "", },
	ErrorTest{ "complex64 1/0", func() { use(e64/d64) }, "", },
	ErrorTest{ "complex128 1/0", func() { use(e128/d128) }, "", },
}

func error(fn func()) (error string) {
	defer func() {
		if e := recover(); e != nil {
			error = e.(Error).String()
		}
	}()
	fn()
	return ""
}

type FloatTest struct{
	f, g	float64
	out	float64
}

var floatTests = []FloatTest{
	FloatTest{0, 0, nan},
	FloatTest{nan, 0, nan},
	FloatTest{inf, 0, inf},
	FloatTest{negInf, 0, negInf},
}

func alike(a, b float64) bool {
	switch {
	case math.IsNaN(a) && math.IsNaN(b):
		return true
	case a == b:
		return math.Signbit(a) == math.Signbit(b)
	}
	return false
}

func main() {
	for _, t := range errorTests {
		if t.err != "" && syscall.OS == "nacl" {
			continue
		}
		err := error(t.fn)
		switch {
		case t.err == "" && err == "":
			// fine
		case t.err != "" && err == "":
			fmt.Printf("%s: expected %q; got no error\n", t.name, t.err)
		case t.err == "" && err != "":
			fmt.Printf("%s: expected no error; got %q\n", t.name, err)
		case t.err != "" && err != "":
			if strings.Index(err, t.err) < 0 {
				fmt.Printf("%s: expected %q; got %q\n", t.name, t.err, err)
				continue
			}
		}
	}

	// At this point we know we don't error on the values we're testing
	for _, t := range floatTests {
		x := t.f/t.g
		if !alike(x, t.out) {
			fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x)
		}
	}
}
<commit_msg>test: add missing import for zerodivide<commit_after>// $G $F.go && $L $F.$A && ./$A.out

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

import (
	"fmt"
	"math"
	"strings"
	"syscall"
)

type Error interface {
	String() string
}

type ErrorTest struct {
	name	string
	fn	func()
	err	string
}

var (
	i, j, k int = 0, 0, 1
	i8, j8, k8 int8 = 0, 0, 1
	i16, j16, k16 int16 = 0, 0, 1
	i32, j32, k32 int32 = 0, 0, 1
	i64, j64, k64 int64 = 0, 0, 1

	u, v, w uint = 0, 0, 1
	u8, v8, w8 uint8 = 0, 0, 1
	u16, v16, w16 uint16 = 0, 0, 1
	u32, v32, w32 uint32 = 0, 0, 1
	u64, v64, w64 uint64 = 0, 0, 1
	up, vp, wp uintptr = 0, 0, 1

	f, g, h float = 0, 0, 1
	f32, g32, h32 float32 = 0, 0, 1
	f64, g64, h64, inf, negInf, nan float64 = 0, 0, 1, math.Inf(1), math.Inf(-1), math.NaN()

	c, d, e complex = 0+0i, 0+0i, 1+1i
	c64, d64, e64 complex64 = 0+0i, 0+0i, 1+1i
	c128, d128, e128 complex128 = 0+0i, 0+0i, 1+1i
)

var tmp interface{}

// We could assign to _ but the compiler optimizes it too easily.
func use(v interface{}) {
	tmp = v
}

// Verify error/no error for all types.
var errorTests = []ErrorTest{
	// All integer divide by zero should error.
	ErrorTest{ "int 0/0", func() { use(i/j) }, "divide", },
	ErrorTest{ "int8 0/0", func() { use(i8/j8) }, "divide", },
	ErrorTest{ "int16 0/0", func() { use(i16/j16) }, "divide", },
	ErrorTest{ "int32 0/0", func() { use(i32/j32) }, "divide", },
	ErrorTest{ "int64 0/0", func() { use(i64/j64) }, "divide", },

	ErrorTest{ "int 1/0", func() { use(k/j) }, "divide", },
	ErrorTest{ "int8 1/0", func() { use(k8/j8) }, "divide", },
	ErrorTest{ "int16 1/0", func() { use(k16/j16) }, "divide", },
	ErrorTest{ "int32 1/0", func() { use(k32/j32) }, "divide", },
	ErrorTest{ "int64 1/0", func() { use(k64/j64) }, "divide", },

	ErrorTest{ "uint 0/0", func() { use(u/v) }, "divide", },
	ErrorTest{ "uint8 0/0", func() { use(u8/v8) }, "divide", },
	ErrorTest{ "uint16 0/0", func() { use(u16/v16) }, "divide", },
	ErrorTest{ "uint32 0/0", func() { use(u32/v32) }, "divide", },
	ErrorTest{ "uint64 0/0", func() { use(u64/v64) }, "divide", },
	ErrorTest{ "uintptr 0/0", func() { use(up/vp) }, "divide", },

	ErrorTest{ "uint 1/0", func() { use(w/v) }, "divide", },
	ErrorTest{ "uint8 1/0", func() { use(w8/v8) }, "divide", },
	ErrorTest{ "uint16 1/0", func() { use(w16/v16) }, "divide", },
	ErrorTest{ "uint32 1/0", func() { use(w32/v32) }, "divide", },
	ErrorTest{ "uint64 1/0", func() { use(w64/v64) }, "divide", },
	ErrorTest{ "uintptr 1/0", func() { use(wp/vp) }, "divide", },

	// All floating divide by zero should not error.
	ErrorTest{ "float 0/0", func() { use(f/g) }, "", },
	ErrorTest{ "float32 0/0", func() { use(f32/g32) }, "", },
	ErrorTest{ "float64 0/0", func() { use(f64/g64) }, "", },

	ErrorTest{ "float 1/0", func() { use(h/g) }, "", },
	ErrorTest{ "float32 1/0", func() { use(h32/g32) }, "", },
	ErrorTest{ "float64 1/0", func() { use(h64/g64) }, "", },
	ErrorTest{ "float64 inf/0", func() { use(inf/g64) }, "", },
	ErrorTest{ "float64 -inf/0", func() { use(negInf/g64) }, "", },
	ErrorTest{ "float64 nan/0", func() { use(nan/g64) }, "", },

	// All complex divide by zero should not error.
	ErrorTest{ "complex 0/0", func() { use(c/d) }, "", },
	ErrorTest{ "complex64 0/0", func() { use(c64/d64) }, "", },
	ErrorTest{ "complex128 0/0", func() { use(c128/d128) }, "", },

	ErrorTest{ "complex 1/0", func() { use(e/d) }, "", },
	ErrorTest{ "complex64 1/0", func() { use(e64/d64) }, "", },
	ErrorTest{ "complex128 1/0", func() { use(e128/d128) }, "", },
}

func error(fn func()) (error string) {
	defer func() {
		if e := recover(); e != nil {
			error = e.(Error).String()
		}
	}()
	fn()
	return ""
}

type FloatTest struct{
	f, g	float64
	out	float64
}

var floatTests = []FloatTest{
	FloatTest{0, 0, nan},
	FloatTest{nan, 0, nan},
	FloatTest{inf, 0, inf},
	FloatTest{negInf, 0, negInf},
}

func alike(a, b float64) bool {
	switch {
	case math.IsNaN(a) && math.IsNaN(b):
		return true
	case a == b:
		return math.Signbit(a) == math.Signbit(b)
	}
	return false
}

func main() {
	for _, t := range errorTests {
		if t.err != "" && syscall.OS == "nacl" {
			continue
		}
		err := error(t.fn)
		switch {
		case t.err == "" && err == "":
			// fine
		case t.err != "" && err == "":
			fmt.Printf("%s: expected %q; got no error\n", t.name, t.err)
		case t.err == "" && err != "":
			fmt.Printf("%s: expected no error; got %q\n", t.name, err)
		case t.err != "" && err != "":
			if strings.Index(err, t.err) < 0 {
				fmt.Printf("%s: expected %q; got %q\n", t.name, t.err, err)
				continue
			}
		}
	}

	// At this point we know we don't error on the values we're testing
	for _, t := range floatTests {
		x := t.f/t.g
		if !alike(x, t.out) {
			fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x)
		}
	}
}
<|endoftext|>


<commit_before>package systemd_test

import (
	"fmt"
	"io/ioutil"
	"path/filepath"

	"github.com/coreos/go-systemd/unit"
	"github.com/mistifyio/mistify/acomm"
	systemdp "github.com/mistifyio/mistify/providers/systemd"
)

func (s *systemd) TestCreate() {
	tests := []struct {
		name    string
		options []*unit.UnitOption
		err     string
	}{
		{"", nil, "missing arg: name"},
		{"empty.service", nil, ""},
		{"nonempty.service", []*unit.UnitOption{{"foo", "bar", "baz"}}, ""},
		{"nonempty.service", []*unit.UnitOption{{"foo2", "bar2", "baz2"}}, "unit file already exists"}, // duplicate
	}

	for _, test := range tests {
		args := &systemdp.CreateArgs{Name: test.name, UnitOptions: test.options}
		argsS := fmt.Sprintf("%+v", args)
		req, err := acomm.NewRequest("zfs-create", "unix:///tmp/foobar", "", args, nil, nil)
		s.Require().NoError(err, argsS)

		res, streamURL, err := s.systemd.Create(req)
		s.Nil(streamURL, argsS)
		s.Nil(res, argsS)
		if test.err == "" {
			if !s.NoError(err, argsS) {
				continue
			}
			p, _ := filepath.Abs(filepath.Join(s.dir, filepath.Base(test.name)))
			contents, err := ioutil.ReadFile(p)
			if !s.NoError(err, argsS) {
				continue
			}
			expected, err := ioutil.ReadAll(unit.Serialize(test.options))
			if !s.NoError(err, argsS) {
				continue
			}
			s.Equal(expected, contents, argsS)
		} else {
			s.EqualError(err, test.err, argsS)
		}
	}
}
<commit_msg>Fix copy/paste issue in systemd-create test<commit_after>package systemd_test

import (
	"fmt"
	"io/ioutil"
	"path/filepath"

	"github.com/coreos/go-systemd/unit"
	"github.com/mistifyio/mistify/acomm"
	systemdp "github.com/mistifyio/mistify/providers/systemd"
)

func (s *systemd) TestCreate() {
	tests := []struct {
		name    string
		options []*unit.UnitOption
		err     string
	}{
		{"", nil, "missing arg: name"},
		{"empty.service", nil, ""},
		{"nonempty.service", []*unit.UnitOption{{"foo", "bar", "baz"}}, ""},
		{"nonempty.service", []*unit.UnitOption{{"foo2", "bar2", "baz2"}}, "unit file already exists"}, // duplicate
	}

	for _, test := range tests {
		args := &systemdp.CreateArgs{Name: test.name, UnitOptions: test.options}
		argsS := fmt.Sprintf("%+v", args)
		req, err := acomm.NewRequest("systemd-create", "unix:///tmp/foobar", "", args, nil, nil)
		s.Require().NoError(err, argsS)

		res, streamURL, err := s.systemd.Create(req)
		s.Nil(streamURL, argsS)
		s.Nil(res, argsS)
		if test.err == "" {
			if !s.NoError(err, argsS) {
				continue
			}
			p, _ := filepath.Abs(filepath.Join(s.dir, filepath.Base(test.name)))
			contents, err := ioutil.ReadFile(p)
			if !s.NoError(err, argsS) {
				continue
			}
			expected, err := ioutil.ReadAll(unit.Serialize(test.options))
			if !s.NoError(err, argsS) {
				continue
			}
			s.Equal(expected, contents, argsS)
		} else {
			s.EqualError(err, test.err, argsS)
		}
	}
}
<|endoftext|>


<commit_before>package oauth_test

import (
	"log"
	"testing"

	"github.com/RichardKnop/recall/config"
	"github.com/RichardKnop/recall/database"
	"github.com/RichardKnop/recall/oauth"
	"github.com/gorilla/mux"
	"github.com/jinzhu/gorm"
	"github.com/stretchr/testify/suite"
)

var testDbPath = "/tmp/oauth_testdb.sqlite"

var testFixtures = []string{
	"fixtures/scopes.yml",
	"fixtures/test_clients.yml",
	"fixtures/test_users.yml",
}

// db migrations needed for tests
var testMigrations = []func(*gorm.DB) error{
	oauth.MigrateAll,
}

// OauthTestSuite needs to be exported so the tests run
type OauthTestSuite struct {
	suite.Suite
	cnf     *config.Config
	db      *gorm.DB
	service *oauth.Service
	clients []*oauth.Client
	users   []*oauth.User
	router  *mux.Router
}

// The SetupSuite method will be run by testify once, at the very
// start of the testing suite, before any tests are run.
func (suite *OauthTestSuite) SetupSuite() {

	// Initialise the config
	suite.cnf = config.NewConfig(false, false)

	// Create the test database
	db, err := database.CreateTestDatabase(testDbPath, testMigrations, testFixtures)
	if err != nil {
		log.Fatal(err)
	}
	suite.db = db

	// Fetch test client
	suite.clients = make([]*oauth.Client, 0)
	if err := suite.db.Order("id").Find(&suite.clients).Error; err != nil {
		log.Fatal(err)
	}

	// Fetch test users
	suite.users = make([]*oauth.User, 0)
	if err := suite.db.Order("id").Find(&suite.users).Error; err != nil {
		log.Fatal(err)
	}

	// Initialise the service
	suite.service = oauth.NewService(suite.cnf, suite.db)

	// Register routes
	suite.router = mux.NewRouter()
	oauth.RegisterRoutes(suite.router, suite.service)
}

// The TearDownSuite method will be run by testify once, at the very
// end of the testing suite, after all tests have been run.
func (suite *OauthTestSuite) TearDownSuite() {
	//
}

// The SetupTest method will be run before every test in the suite.
func (suite *OauthTestSuite) SetupTest() {
	//
}

// The TearDownTest method will be run after every test in the suite.
func (suite *OauthTestSuite) TearDownTest() {
	// Scopes are static, populated from fixtures,
	// so there is no need to clear them after running a test
	suite.db.Unscoped().Delete(new(oauth.AuthorizationCode))
	suite.db.Unscoped().Delete(new(oauth.RefreshToken))
	suite.db.Unscoped().Delete(new(oauth.AccessToken))
	suite.db.Unscoped().Not("id", []int64{1, 2}).Delete(new(oauth.User))
	suite.db.Unscoped().Not("id", []int64{1, 2, 3}).Delete(new(oauth.Client))
}

// TestOauthTestSuite ...
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestOauthTestSuite(t *testing.T) {
	suite.Run(t, new(OauthTestSuite))
}
<commit_msg>Oauth suite test small refactor.<commit_after>package oauth_test

import (
	"log"
	"os"
	"testing"

	"github.com/RichardKnop/recall/config"
	"github.com/RichardKnop/recall/database"
	"github.com/RichardKnop/recall/oauth"
	"github.com/gorilla/mux"
	"github.com/jinzhu/gorm"
	"github.com/stretchr/testify/suite"
)

var testDbPath = "/tmp/oauth_testdb.sqlite"

var testFixtures = []string{
	"./oauth/fixtures/scopes.yml",
	"./oauth/fixtures/test_clients.yml",
	"./oauth/fixtures/test_users.yml",
}

// db migrations needed for tests
var testMigrations = []func(*gorm.DB) error{
	oauth.MigrateAll,
}

func init() {
	if err := os.Chdir("../"); err != nil {
		log.Fatal(err)
	}
}

// OauthTestSuite needs to be exported so the tests run
type OauthTestSuite struct {
	suite.Suite
	cnf     *config.Config
	db      *gorm.DB
	service *oauth.Service
	clients []*oauth.Client
	users   []*oauth.User
	router  *mux.Router
}

// The SetupSuite method will be run by testify once, at the very
// start of the testing suite, before any tests are run.
func (suite *OauthTestSuite) SetupSuite() {

	// Initialise the config
	suite.cnf = config.NewConfig(false, false)

	// Create the test database
	db, err := database.CreateTestDatabase(testDbPath, testMigrations, testFixtures)
	if err != nil {
		log.Fatal(err)
	}
	suite.db = db

	// Fetch test client
	suite.clients = make([]*oauth.Client, 0)
	if err := suite.db.Order("id").Find(&suite.clients).Error; err != nil {
		log.Fatal(err)
	}

	// Fetch test users
	suite.users = make([]*oauth.User, 0)
	if err := suite.db.Order("id").Find(&suite.users).Error; err != nil {
		log.Fatal(err)
	}

	// Initialise the service
	suite.service = oauth.NewService(suite.cnf, suite.db)

	// Register routes
	suite.router = mux.NewRouter()
	oauth.RegisterRoutes(suite.router, suite.service)
}

// The TearDownSuite method will be run by testify once, at the very
// end of the testing suite, after all tests have been run.
func (suite *OauthTestSuite) TearDownSuite() {
	//
}

// The SetupTest method will be run before every test in the suite.
func (suite *OauthTestSuite) SetupTest() {
	//
}

// The TearDownTest method will be run after every test in the suite.
func (suite *OauthTestSuite) TearDownTest() {
	// Scopes are static, populated from fixtures,
	// so there is no need to clear them after running a test
	suite.db.Unscoped().Delete(new(oauth.AuthorizationCode))
	suite.db.Unscoped().Delete(new(oauth.RefreshToken))
	suite.db.Unscoped().Delete(new(oauth.AccessToken))
	suite.db.Unscoped().Not("id", []int64{1, 2}).Delete(new(oauth.User))
	suite.db.Unscoped().Not("id", []int64{1, 2, 3}).Delete(new(oauth.Client))
}

// TestOauthTestSuite ...
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestOauthTestSuite(t *testing.T) {
	suite.Run(t, new(OauthTestSuite))
}
<|endoftext|>


<commit_before>package db

import "github.com/pkg/errors"

func (v *SessionList) LoadByConference(tx *Tx, conferenceID, speakerID, date, status string) error {
	// The caller of this method should ensure that query fields are
	// present and that we don't accidentally run an empty query
	stmt := getStmtBuf()
	defer releaseStmtBuf(stmt)

	stmt.WriteString(`SELECT `)
	stmt.WriteString(SessionStdSelectColumns)
	stmt.WriteString(` FROM `)
	stmt.WriteString(SessionTable)
	stmt.WriteString(` WHERE `)

	where := getStmtBuf()
	defer releaseStmtBuf(where)

	var args []interface{}
	if conferenceID != "" {
		where.WriteString(` conference_id = ?`)
		args = append(args, conferenceID)
	}

	if speakerID != "" {
		if where.Len() > 0 {
			where.WriteString(` AND`)
		}
		where.WriteString(` speaker_id = ?`)
		args = append(args, speakerID)
	}

	if date != "" {
		if where.Len() > 0 {
			where.WriteString(` AND`)
		}
		where.WriteString(` DATE(date) = ?`)
		args = append(args, date)
	}

	if status != "" {
		if where.Len() > 0 {
			where.WriteString(` AND`)
		}
		where.WriteString(` status = ?`)
		args = append(args, status)
	}

	where.WriteTo(stmt)

	rows, err := tx.Query(stmt.String(), args...)
	if err != nil {
		return err
	}

	if err := v.FromRows(rows, 0); err != nil {
		return err
	}
	return nil
}

func IsSessionOwner(tx *Tx, sessionID, userID string) error {
	stmt := getStmtBuf()
	defer releaseStmtBuf(stmt)

	stmt.WriteString(`SELECT 1 FROM `)
	stmt.WriteString(SessionTable)
	stmt.WriteString(` WHERE id = ? AND speaker_id = ?`)
	row := tx.QueryRow(stmt.String())
	var r int

	if err := row.Scan(&r); err != nil {
		return errors.Wrap(err, "failed to scan from database")
	}

	if r == 0 {
		return errors.Errorf("user %s is not an owner of session %s", userID, sessionID)
	}
	return nil
}
<commit_msg>Fix SQL used in IsSessionOwner<commit_after>package db

import (
	pdebug "github.com/lestrrat/go-pdebug"
	"github.com/pkg/errors"
)

func (v *SessionList) LoadByConference(tx *Tx, conferenceID, speakerID, date, status string) error {
	// The caller of this method should ensure that query fields are
	// present and that we don't accidentally run an empty query
	stmt := getStmtBuf()
	defer releaseStmtBuf(stmt)

	stmt.WriteString(`SELECT `)
	stmt.WriteString(SessionStdSelectColumns)
	stmt.WriteString(` FROM `)
	stmt.WriteString(SessionTable)
	stmt.WriteString(` WHERE `)

	where := getStmtBuf()
	defer releaseStmtBuf(where)

	var args []interface{}
	if conferenceID != "" {
		where.WriteString(` conference_id = ?`)
		args = append(args, conferenceID)
	}

	if speakerID != "" {
		if where.Len() > 0 {
			where.WriteString(` AND`)
		}
		where.WriteString(` speaker_id = ?`)
		args = append(args, speakerID)
	}

	if date != "" {
		if where.Len() > 0 {
			where.WriteString(` AND`)
		}
		where.WriteString(` DATE(date) = ?`)
		args = append(args, date)
	}

	if status != "" {
		if where.Len() > 0 {
			where.WriteString(` AND`)
		}
		where.WriteString(` status = ?`)
		args = append(args, status)
	}

	where.WriteTo(stmt)

	rows, err := tx.Query(stmt.String(), args...)
	if err != nil {
		return err
	}

	if err := v.FromRows(rows, 0); err != nil {
		return err
	}
	return nil
}

func IsSessionOwner(tx *Tx, sessionID, userID string) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("db.IsSessionOwner %s %s", sessionID, userID).BindError(&err)
		defer g.End()
	}

	stmt := getStmtBuf()
	defer releaseStmtBuf(stmt)

	stmt.WriteString(`SELECT 1 FROM `)
	stmt.WriteString(SessionTable)
	stmt.WriteString(` WHERE eid = ? AND speaker_id = ?`)
	row := tx.QueryRow(stmt.String(), sessionID, userID)
	var r int

	if err := row.Scan(&r); err != nil {
		return errors.Wrap(err, "failed to scan from database")
	}

	if r == 0 {
		return errors.Errorf("user %s is not an owner of session %s", userID, sessionID)
	}
	return nil
}
<|endoftext|>


<commit_before>package client

import (
	"context"
	"time"

	"koding/kites/kloud/klient"
	"koding/klient/fs"
	"koding/klient/machine"
	"koding/klient/machine/index"
	"koding/klient/os"

	"github.com/koding/kite"
)

// KiteBuilder implements Builder interface. It creates Kite clients that use
// kite query string as their source address.
type KiteBuilder struct {
	pool *klient.KlientPool
}

// NewKiteBuilder creates a new KiteBuilder instance.
func NewKiteBuilder(k *kite.Kite) *KiteBuilder {
	return &KiteBuilder{
		pool: klient.NewPool(k),
	}
}

// Ping uses kite network that stores kite's query string to ping the machine.
func (kb *KiteBuilder) Ping(dynAddr DynamicAddrFunc) (machine.Status, machine.Addr, error) {
	addr, err := dynAddr("kite")
	if err != nil {
		return machine.Status{}, machine.Addr{}, err
	}

	if _, err := kb.pool.Get(addr.Value); err != nil {
		return machine.Status{}, machine.Addr{}, err
	}

	return machine.Status{
		State: machine.StateConnected,
		Since: time.Now(),
	}, addr, nil
}

// Build builds new kite client that will connect to machine using provided
// address.
func (kb *KiteBuilder) Build(ctx context.Context, addr machine.Addr) Client {
	if _, err := kb.pool.Get(addr.Value); err != nil {
		return NewDisconnected(ctx)
	}

	return &kiteClient{
		ctx:  ctx,
		addr: addr.Value,
		pool: kb.pool,
	}
}

// kiteClient implements Client interface it uses klient from internal pool.
type kiteClient struct {
	ctx  context.Context
	addr string
	pool *klient.KlientPool
}

// CurrentUser returns remote machine current username.
func (kc *kiteClient) CurrentUser() (string, error) {
	return kc.get().CurrentUser()
}

// SSHAddKeys adds SSH public keys to user's authorized_keys file.
func (kc *kiteClient) SSHAddKeys(username string, keys ...string) error {
	return kc.get().SSHAddKeys(username, keys...)
}

// MountHeadIndex returns the number and the overall size of files in a
// given remote directory.
func (kc *kiteClient) MountHeadIndex(path string) (string, int, int64, error) {
	return kc.get().MountHeadIndex(path)
}

// MountGetIndex returns an index that describes the current state of remote
// directory.
func (kc *kiteClient) MountGetIndex(path string) (*index.Index, error) {
	return kc.get().MountGetIndex(path)
}

// DiskInfo gets basic information about volume pointed by provided path.
func (kc *kiteClient) DiskInfo(path string) (fs.DiskInfo, error) {
	return kc.get().DiskInfo(path)
}

// Exec runs a command on a remote machine.
func (kc *kiteClient) Exec(req *os.ExecRequest) (*os.ExecResponse, error) {
	return kc.get().Exec(req)
}

// Kill terminates previously started command on a remote machine.
func (kc *kiteClient) Kill(req *os.KillRequest) (*os.KillResponse, error) {
	return kc.get().Kill(req)
}

// Context returns client's Context.
func (kc *kiteClient) Context() context.Context {
	return kc.get().Context()
}

// Get gets klient from the pool, if an error occurs, disconnected client will
// be returned.
func (kc *kiteClient) get() Client {
	k, err := kc.pool.Get(kc.addr)
	if err != nil {
		return NewDisconnected(kc.ctx)
	}

	k.SetContext(kc.ctx)
	return k
}
<commit_msg>klient/machine: do not build only disconnected client<commit_after>package client

import (
	"context"
	"time"

	"koding/kites/kloud/klient"
	"koding/klient/fs"
	"koding/klient/machine"
	"koding/klient/machine/index"
	"koding/klient/os"

	"github.com/koding/kite"
)

// KiteBuilder implements Builder interface. It creates Kite clients that use
// kite query string as their source address.
type KiteBuilder struct {
	pool *klient.KlientPool
}

// NewKiteBuilder creates a new KiteBuilder instance.
func NewKiteBuilder(k *kite.Kite) *KiteBuilder {
	return &KiteBuilder{
		pool: klient.NewPool(k),
	}
}

// Ping uses kite network that stores kite's query string to ping the machine.
func (kb *KiteBuilder) Ping(dynAddr DynamicAddrFunc) (machine.Status, machine.Addr, error) {
	addr, err := dynAddr("kite")
	if err != nil {
		return machine.Status{}, machine.Addr{}, err
	}

	if _, err := kb.pool.Get(addr.Value); err != nil {
		return machine.Status{}, machine.Addr{}, err
	}

	return machine.Status{
		State: machine.StateConnected,
		Since: time.Now(),
	}, addr, nil
}

// Build builds new kite client that will connect to machine using provided
// address.
func (kb *KiteBuilder) Build(ctx context.Context, addr machine.Addr) Client {
	return &kiteClient{
		ctx:  ctx,
		addr: addr.Value,
		pool: kb.pool,
	}
}

// kiteClient implements Client interface it uses klient from internal pool.
type kiteClient struct {
	ctx  context.Context
	addr string
	pool *klient.KlientPool
}

// CurrentUser returns remote machine current username.
func (kc *kiteClient) CurrentUser() (string, error) {
	return kc.get().CurrentUser()
}

// SSHAddKeys adds SSH public keys to user's authorized_keys file.
func (kc *kiteClient) SSHAddKeys(username string, keys ...string) error {
	return kc.get().SSHAddKeys(username, keys...)
}

// MountHeadIndex returns the number and the overall size of files in a
// given remote directory.
func (kc *kiteClient) MountHeadIndex(path string) (string, int, int64, error) {
	return kc.get().MountHeadIndex(path)
}

// MountGetIndex returns an index that describes the current state of remote
// directory.
func (kc *kiteClient) MountGetIndex(path string) (*index.Index, error) {
	return kc.get().MountGetIndex(path)
}

// DiskInfo gets basic information about volume pointed by provided path.
func (kc *kiteClient) DiskInfo(path string) (fs.DiskInfo, error) {
	return kc.get().DiskInfo(path)
}

// Exec runs a command on a remote machine.
func (kc *kiteClient) Exec(req *os.ExecRequest) (*os.ExecResponse, error) {
	return kc.get().Exec(req)
}

// Kill terminates previously started command on a remote machine.
func (kc *kiteClient) Kill(req *os.KillRequest) (*os.KillResponse, error) {
	return kc.get().Kill(req)
}

// Context returns client's Context.
func (kc *kiteClient) Context() context.Context {
	return kc.get().Context()
}

// Get gets klient from the pool, if an error occurs, disconnected client will
// be returned.
func (kc *kiteClient) get() Client {
	k, err := kc.pool.Get(kc.addr)
	if err != nil {
		return NewDisconnected(kc.ctx)
	}

	k.SetContext(kc.ctx)
	return k
}
<|endoftext|>