<commit_before>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/montanaflynn/stats"
)

// global command line parameters
var runs *int
var cpus0 *string
var cpus1 *string
var threads *string
var hermitcore *bool

func main() {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 = flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 = flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	hermitcore = flag.Bool("hermitcore", false, "Use if you are executing hermitcore binaries")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	defer wg.Done()

	var runtime []float64

	for i := 1; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == 2 {
			// no
			*measurement += "# "
		} else {
			runtime = append(runtime, elapsed.Seconds())
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == 2 {
			// ignore error, stats returns NaN
			mean, _ := stats.Mean(runtime)
			stddev, _ := stats.StandardDeviation(runtime)
			vari, _ := stats.Variance(runtime)

			fmt.Printf("%v \t %9.2fs avg. runtime \t %1.6f std. dev. \t %1.6f variance \t %v runs\n", cmd.Args, mean, stddev, vari, i)
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	var cmd0 *exec.Cmd
	var cmd1 *exec.Cmd

	env := os.Environ()
	if *hermitcore {
		cmd0 = exec.Command("taskset", "-c", *cpus0, "/bin/sh", "-c", cPair[0])
		cmd1 = exec.Command("taskset", "-c", *cpus1, "/bin/sh", "-c", cPair[1])
		cmd0.Env = append(env, "HERMIT_CPUS="+*threads, "HERMIT_MEM=4G", "HERMIT_ISLE=uhyve")
		cmd1.Env = append(env, "HERMIT_CPUS="+*threads, "HERMIT_MEM=4G", "HERMIT_ISLE=uhyve")
	} else {
		cmd0 = exec.Command("/bin/sh", "-c", cPair[0])
		cmd1 = exec.Command("/bin/sh", "-c", cPair[1])
		cmd0.Env = append(env, "GOMP_CPU_AFFINITY="+*cpus0, "OMP_NUM_THREADS="+*threads)
		cmd1.Env = append(env, "GOMP_CPU_AFFINITY="+*cpus1, "OMP_NUM_THREADS="+*threads)
	}

	outfile0, err := os.Create(fmt.Sprintf("%v-0.log", id))
	if err != nil {
		return fmt.Errorf("Error while creating file: %v", err)
	}
	defer outfile0.Close()
	outfile1, err := os.Create(fmt.Sprintf("%v-1.log", id))
	if err != nil {
		return fmt.Errorf("Error while creating file: %v", err)
	}
	defer outfile1.Close()

	cmd0.Stdout = outfile0
	cmd1.Stdout = outfile1

	var measurements [2]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, 2)

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(2)

	go runCmdMinTimes(cmd0, *runs, &wg, &measurements[0], done, errs)
	go runCmdMinTimes(cmd1, *runs, &wg, &measurements[1], done, errs)

	wg.Wait()

	if len(errs) != 0 {
		return <-errs
	}

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}
<commit_msg>Cleanup.<commit_after>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/montanaflynn/stats"
)

// global command line parameters
var runs *int
var cpus [2]string
var threads *string
var hermitcore *bool

func main() {
	commandFile := parseArgs()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	defer wg.Done()

	var runtime []float64

	for i := 1; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == 2 {
			// no
			*measurement += "# "
		} else {
			runtime = append(runtime, elapsed.Seconds())
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == len(cpus) {
			// ignore error, stats returns NaN
			mean, _ := stats.Mean(runtime)
			stddev, _ := stats.StandardDeviation(runtime)
			vari, _ := stats.Variance(runtime)

			fmt.Printf("%v \t %9.2fs avg. runtime \t %1.6f std. dev. \t %1.6f variance \t %v runs\n", cmd.Args, mean, stddev, vari, i)
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	env := os.Environ()

	var cmds [len(cpus)]*exec.Cmd
	// setup commands
	for i, _ := range cmds {
		if *hermitcore {
			cmds[i] = exec.Command("taskset", "-c", cpus[i], "/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "HERMIT_CPUS="+*threads, "HERMIT_MEM=4G", "HERMIT_ISLE=uhyve")
		} else {
			cmds[i] = exec.Command("/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "GOMP_CPU_AFFINITY="+cpus[i], "OMP_NUM_THREADS="+*threads)
		}

		outfile, err := os.Create(fmt.Sprintf("%v-%v.log", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer outfile.Close()
		cmds[i].Stdout = outfile
	}

	var measurements [len(cmds)]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, len(cmds))

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(len(cmds))

	for i, c := range cmds {
		go runCmdMinTimes(c, *runs, &wg, &measurements[i], done, errs)
	}

	wg.Wait()

	if len(errs) != 0 {
		return <-errs
	}

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}

func parseArgs() *string {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 := flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 := flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	hermitcore = flag.Bool("hermitcore", false, "Use if you are executing hermitcore binaries")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	cpus[0] = *cpus0
	cpus[1] = *cpus1

	return commandFile
}
<|endoftext|>


<commit_before>package vangoh

/*
Set of tests for VanGoH checking against the examples provided on the AWS "Signing
and Authenticating REST Requests" page - http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html
*/

import (
	"crypto"
	_ "crypto/SHA1"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

var awsExampleProvider = &testProvider{
	promptErr:  false,
	identifier: []byte("AKIAIOSFODNN7EXAMPLE"),
	secretKey:  []byte("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"),
}

func TestAwsGet(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsGetFail(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:cWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsPut(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("PUT", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:15:45 +0000")
	req.Header.Set("Content-Type", "image/jpeg")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:MyyxeRY7whkBe+bq8fHCL/2kKUg=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsPutFail(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("PUT", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:15:45 +0000")
	req.Header.Set("Content-Type", "image/jpeg")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:NyyxeRY7whkBe+bq8fHCL/2kKUg=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsUpload(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	vg.IncludeHeader("^X-Amz-.*")

	req, _ := http.NewRequest("PUT", "/static.johnsmith.net/db-backup.dat.gz", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:06:08 +0000")
	req.Header.Set("Content-MD5", "4gJE4saaMU4BqNR0kLY+lw==")
	req.Header.Set("Content-Type", "application/x-download")

	// Custom Headers
	req.Header.Set("X-Amz-Acl", "public-read")
	req.Header.Set("X-Amz-Meta-ReviewedBy", "joe@johnsmith.net")
	req.Header.Add("X-Amz-Meta-ReviewedBy", "jane@johnsmith.net")
	req.Header.Set("X-Amz-Meta-FileChecksum", "0x02661779")
	req.Header.Set("X-Amz-Meta-ChecksumAlgorithm", "crc32")

	req.Header.Set("Content-Disposition", "attachment; filename=database.dat")
	req.Header.Set("Content-Encoding", "gzip")
	req.Header.Set("Content-Length", "5913339")

	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:ilyl83RwaSoYIEdixDQcA4OnAnc=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsUploadFail(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("PUT", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:15:45 +0000")
	req.Header.Set("Content-Type", "image/jpeg")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:NyyxeRY7whkBe+bq8fHCL/2kKUg=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestTimeSkew(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	date, err := time.Parse(time.RFC1123Z, "Tue, 27 Mar 2007 19:36:42 +0000")
	if err != nil {
		t.Error("Date couldn't be parsed")
	}
	skew := time.Now().Sub(date) + (time.Second * 10)
	vg.setMaxTimeSkew(skew)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestTimeSkewFailue(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	vg.setMaxTimeSkew(time.Minute * 15)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestMalformedDate(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	date, err := time.Parse(time.RFC1123Z, "Tue, 27 Mar 2007 19:36:42 +0000")
	if err != nil {
		t.Error("Date couldn't be parsed")
	}
	skew := time.Now().Sub(date) + (time.Second * 10)
	vg.setMaxTimeSkew(skew)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "2007-03-27T19:36:42Z00:00") // RFC 3339 - not supported
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusBadRequest {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}
<commit_msg>Fix capitalization in test<commit_after>package vangoh

/*
Set of tests for VanGoH checking against the examples provided on the AWS "Signing
and Authenticating REST Requests" page - http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html
*/

import (
	"crypto"
	_ "crypto/SHA1"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

var awsExampleProvider = &testProvider{
	promptErr:  false,
	identifier: []byte("AKIAIOSFODNN7EXAMPLE"),
	secretKey:  []byte("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"),
}

func TestAwsGet(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsGetFail(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:cWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsPut(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("PUT", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:15:45 +0000")
	req.Header.Set("Content-Type", "image/jpeg")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:MyyxeRY7whkBe+bq8fHCL/2kKUg=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsPutFail(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("PUT", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:15:45 +0000")
	req.Header.Set("Content-Type", "image/jpeg")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:NyyxeRY7whkBe+bq8fHCL/2kKUg=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsUpload(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	vg.IncludeHeader("^X-Amz-.*")

	req, _ := http.NewRequest("PUT", "/static.johnsmith.net/db-backup.dat.gz", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:06:08 +0000")
	req.Header.Set("Content-MD5", "4gJE4saaMU4BqNR0kLY+lw==")
	req.Header.Set("Content-Type", "application/x-download")

	// Custom Headers
	req.Header.Set("X-Amz-Acl", "public-read")
	req.Header.Set("X-Amz-Meta-ReviewedBy", "joe@johnsmith.net")
	req.Header.Add("X-Amz-Meta-ReviewedBy", "jane@johnsmith.net")
	req.Header.Set("X-Amz-Meta-FileChecksum", "0x02661779")
	req.Header.Set("X-Amz-Meta-ChecksumAlgorithm", "crc32")

	req.Header.Set("Content-Disposition", "attachment; filename=database.dat")
	req.Header.Set("Content-Encoding", "gzip")
	req.Header.Set("Content-Length", "5913339")

	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:ilyl83RwaSoYIEdixDQcA4OnAnc=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestAwsUploadFail(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)

	req, _ := http.NewRequest("PUT", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 21:15:45 +0000")
	req.Header.Set("Content-Type", "image/jpeg")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:NyyxeRY7whkBe+bq8fHCL/2kKUg=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestTimeSkew(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	date, err := time.Parse(time.RFC1123Z, "Tue, 27 Mar 2007 19:36:42 +0000")
	if err != nil {
		t.Error("Date couldn't be parsed")
	}
	skew := time.Now().Sub(date) + (time.Second * 10)
	vg.SetMaxTimeSkew(skew)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestTimeSkewFailue(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	vg.SetMaxTimeSkew(time.Minute * 15)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "Tue, 27 Mar 2007 19:36:42 +0000")
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusForbidden {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}

func TestMalformedDate(t *testing.T) {
	vg := NewSingleProvider(awsExampleProvider)
	vg.SetAlgorithm(crypto.SHA1.New)
	date, err := time.Parse(time.RFC1123Z, "Tue, 27 Mar 2007 19:36:42 +0000")
	if err != nil {
		t.Error("Date couldn't be parsed")
	}
	skew := time.Now().Sub(date) + (time.Second * 10)
	vg.SetMaxTimeSkew(skew)

	req, _ := http.NewRequest("GET", "/johnsmith/photos/puppy.jpg", nil)
	req.Header.Set("Date", "2007-03-27T19:36:42Z00:00") // RFC 3339 - not supported
	req.Header.Set("Authorization", "AWS AKIAIOSFODNN7EXAMPLE:bWq2s1WEIj+Ydj0vQ697zp+IXMU=")
	w := httptest.NewRecorder()

	vg.authenticateRequest(w, req)

	if w.Code != http.StatusBadRequest {
		t.Errorf("Authentication didn't return expected status, instead returned %d,"+
			" with message %q", w.Code, w.Header().Get(errorMessageHeader))
	}
}
<|endoftext|>


<commit_before>package graphql

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"reflect"
	"runtime"
	"sync"

	"github.com/samsarahq/thunder/concurrencylimiter"
	"github.com/samsarahq/thunder/reactive"
)

type pathError struct {
	inner error
	path  []string
}

func nestPathError(key string, err error) error {
	// Don't nest SanitzedError's, as they are intended for human consumption.
	if se, ok := err.(SanitizedError); ok {
		return se
	}

	if pe, ok := err.(*pathError); ok {
		return &pathError{
			inner: pe.inner,
			path:  append(pe.path, key),
		}
	}

	return &pathError{
		inner: err,
		path:  []string{key},
	}
}

func extractPathError(err error) error {
	if pe, ok := err.(*pathError); ok {
		return pe.inner
	}
	return err
}

func (pe *pathError) Error() string {
	var buffer bytes.Buffer
	for i := len(pe.path) - 1; i >= 0; i-- {
		if i < len(pe.path)-1 {
			buffer.WriteString(".")
		}
		buffer.WriteString(pe.path[i])
	}
	buffer.WriteString(": ")
	buffer.WriteString(pe.inner.Error())
	return buffer.String()
}

func isNilArgs(args interface{}) bool {
	m, ok := args.(map[string]interface{})
	return args == nil || (ok && len(m) == 0)
}

// unwrap will return the value associated with a pointer type, or nil if the
// pointer is nil
func unwrap(v interface{}) interface{} {
	i := reflect.ValueOf(v)
	for i.Kind() == reflect.Ptr && !i.IsNil() {
		i = i.Elem()
	}
	if i.Kind() == reflect.Invalid {
		return nil
	}
	return i.Interface()
}

// PrepareQuery checks that the given selectionSet matches the schema typ, and
// parses the args in selectionSet
func PrepareQuery(typ Type, selectionSet *SelectionSet) error {
	switch typ := typ.(type) {
	case *Scalar:
		if selectionSet != nil {
			return NewClientError("scalar field must have no selections")
		}
		return nil
	case *Enum:
		if selectionSet != nil {
			return NewClientError("enum field must have no selections")
		}
		return nil
	case *Object:
		if selectionSet == nil {
			return NewClientError("object field must have selections")
		}
		for _, selection := range selectionSet.Selections {
			if selection.Name == "__typename" {
				if !isNilArgs(selection.Args) {
					return NewClientError(`error parsing args for "__typename": no args expected`)
				}
				if selection.SelectionSet != nil {
					return NewClientError(`scalar field "__typename" must have no selection`)
				}
				continue
			}

			field, ok := typ.Fields[selection.Name]
			if !ok {
				return NewClientError(`unknown field "%s"`, selection.Name)
			}

			// Only parse args once for a given selection.
			if !selection.parsed {
				parsed, err := field.ParseArguments(selection.Args)
				if err != nil {
					return NewClientError(`error parsing args for "%s": %s`, selection.Name, err)
				}
				selection.Args = parsed
				selection.parsed = true
			}

			if err := PrepareQuery(field.Type, selection.SelectionSet); err != nil {
				return err
			}
		}
		for _, fragment := range selectionSet.Fragments {
			if err := PrepareQuery(typ, fragment.SelectionSet); err != nil {
				return err
			}
		}
		return nil

	case *List:
		return PrepareQuery(typ.Type, selectionSet)

	case *NonNull:
		return PrepareQuery(typ.Type, selectionSet)

	default:
		panic("unknown type kind")
	}
}

type panicError struct {
	message string
}

func (p panicError) Error() string {
	return p.message
}

func safeResolve(ctx context.Context, field *Field, source, args interface{}, selectionSet *SelectionSet) (result interface{}, err error) {
	defer func() {
		if panicErr := recover(); panicErr != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			result, err = nil, fmt.Errorf("graphql: panic: %v\n%s", panicErr, buf)
		}
	}()
	return field.Resolve(ctx, source, args, selectionSet)
}

type resolveAndExecuteCacheKey struct {
	field     *Field
	source    interface{}
	selection *Selection
}

func (e *Executor) resolveAndExecute(ctx context.Context, field *Field, source interface{}, selection *Selection) (interface{}, error) {
	if field.Expensive {
		// TODO: Skip goroutine for cached value
		ctx, release := concurrencylimiter.Acquire(ctx)
		return fork(func() (interface{}, error) {
			defer release()

			value := reflect.ValueOf(source)
			// cache the body of resolve and excecute so that if the source doesn't change, we
			// don't need to recompute
			key := resolveAndExecuteCacheKey{field: field, source: source, selection: selection}

			// some types can't be put in a map; for those, use a always different value
			// as source
			if value.IsValid() && !value.Type().Comparable() {
				// TODO: Warn, or somehow prevent using type-system?
				key.source = new(byte)
			}

			// TODO: Consider cacheing resolve and execute independently
			resolvedValue, err := reactive.Cache(ctx, key, func(ctx context.Context) (interface{}, error) {
				value, err := safeResolve(ctx, field, source, selection.Args, selection.SelectionSet)
				if err != nil {
					return nil, err
				}

				// Release concurrency token before recursing into execute. It will attempt to
				// grab another concurrency token.
				release()

				e.mu.Lock()
				value, err = e.execute(ctx, field.Type, value, selection.SelectionSet)
				e.mu.Unlock()

				if err != nil {
					return nil, err
				}
				return await(value)
			})

			return resolvedValue, err
		}), nil
	}

	value, err := safeResolve(ctx, field, source, selection.Args, selection.SelectionSet)
	if err != nil {
		return nil, err
	}
	return e.execute(ctx, field.Type, value, selection.SelectionSet)
}

// executeObject executes an object query
func (e *Executor) executeObject(ctx context.Context, typ *Object, source interface{}, selectionSet *SelectionSet) (interface{}, error) {
	value := reflect.ValueOf(source)
	if value.Kind() == reflect.Ptr && value.IsNil() {
		return nil, nil
	}

	selections := Flatten(selectionSet)

	fields := make(map[string]interface{})

	// for every selection, resolve the value and store it in the output object
	for _, selection := range selections {
		if selection.Name == "__typename" {
			fields[selection.Alias] = typ.Name
			continue
		}

		field := typ.Fields[selection.Name]
		resolved, err := e.resolveAndExecute(ctx, field, source, selection)
		if err != nil {
			return nil, nestPathError(selection.Alias, err)
		}
		fields[selection.Alias] = resolved
	}

	if typ.Key != nil {
		value, err := e.resolveAndExecute(ctx, &Field{Type: &Scalar{Type: "string"}, Resolve: typ.Key}, source, &Selection{})
		if err != nil {
			return nil, nestPathError("__key", err)
		}
		fields["__key"] = value
	}

	return fields, nil
}

var emptyList = []interface{}{}

// executeList executes a set query
func (e *Executor) executeList(ctx context.Context, typ *List, source interface{}, selectionSet *SelectionSet) (interface{}, error) {
	if reflect.ValueOf(source).IsNil() {
		return emptyList, nil
	}

	// iterate over arbitrary slice types using reflect
	slice := reflect.ValueOf(source)
	items := make([]interface{}, slice.Len())

	// resolve every element in the slice
	for i := 0; i < slice.Len(); i++ {
		value := slice.Index(i)
		resolved, err := e.execute(ctx, typ.Type, value.Interface(), selectionSet)
		if err != nil {
			return nil, nestPathError(fmt.Sprint(i), err)
		}
		items[i] = resolved
	}

	return items, nil
}

// execute executes a query by dispatches according to typ
func (e *Executor) execute(ctx context.Context, typ Type, source interface{}, selectionSet *SelectionSet) (interface{}, error) {
	if err := ctx.Err(); err != nil {
		return nil, err
	}
	switch typ := typ.(type) {
	case *Scalar:
		return unwrap(source), nil
	case *Enum:
		val := unwrap(source)
		if mapVal, ok := typ.ReverseMap[val]; ok {
			return mapVal, nil
		}
		return nil, errors.New("enum is not valid")
	case *Object:
		return e.executeObject(ctx, typ, source, selectionSet)
	case *List:
		return e.executeList(ctx, typ, source, selectionSet)
	case *NonNull:
		return e.execute(ctx, typ.Type, source, selectionSet)
	default:
		panic(typ)
	}
}

type Executor struct {
	mu sync.Mutex
}

// Execute executes a query by dispatches according to typ
func (e *Executor) Execute(ctx context.Context, typ Type, source interface{}, query *Query) (interface{}, error) {
	e.mu.Lock()
	value, err := e.execute(ctx, typ, source, query.SelectionSet)
	e.mu.Unlock()

	// Await the promise if things look good so far.
	if err == nil {
		value, err = await(value)
	}

	// Maybe error wrap if we have an error and a name to attach.
	if err != nil && query.Name != "" {
		err = nestPathError(query.Name, err)
	}

	return value, err
}
<commit_msg>graphql: add union execution<commit_after>package graphql

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"reflect"
	"runtime"
	"strings"
	"sync"

	"github.com/samsarahq/thunder/concurrencylimiter"
	"github.com/samsarahq/thunder/reactive"
)

type pathError struct {
	inner error
	path  []string
}

func nestPathError(key string, err error) error {
	// Don't nest SanitzedError's, as they are intended for human consumption.
	if se, ok := err.(SanitizedError); ok {
		return se
	}

	if pe, ok := err.(*pathError); ok {
		return &pathError{
			inner: pe.inner,
			path:  append(pe.path, key),
		}
	}

	return &pathError{
		inner: err,
		path:  []string{key},
	}
}

func extractPathError(err error) error {
	if pe, ok := err.(*pathError); ok {
		return pe.inner
	}
	return err
}

func (pe *pathError) Error() string {
	var buffer bytes.Buffer
	for i := len(pe.path) - 1; i >= 0; i-- {
		if i < len(pe.path)-1 {
			buffer.WriteString(".")
		}
		buffer.WriteString(pe.path[i])
	}
	buffer.WriteString(": ")
	buffer.WriteString(pe.inner.Error())
	return buffer.String()
}

func isNilArgs(args interface{}) bool {
	m, ok := args.(map[string]interface{})
	return args == nil || (ok && len(m) == 0)
}

// unwrap will return the value associated with a pointer type, or nil if the
// pointer is nil
func unwrap(v interface{}) interface{} {
	i := reflect.ValueOf(v)
	for i.Kind() == reflect.Ptr && !i.IsNil() {
		i = i.Elem()
	}
	if i.Kind() == reflect.Invalid {
		return nil
	}
	return i.Interface()
}

// PrepareQuery checks that the given selectionSet matches the schema typ, and
// parses the args in selectionSet
func PrepareQuery(typ Type, selectionSet *SelectionSet) error {
	switch typ := typ.(type) {
	case *Scalar:
		if selectionSet != nil {
			return NewClientError("scalar field must have no selections")
		}
		return nil
	case *Enum:
		if selectionSet != nil {
			return NewClientError("enum field must have no selections")
		}
		return nil
	case *Union:
		if selectionSet == nil {
			return NewClientError("object field must have selections")
		}

		for _, fragment := range selectionSet.Fragments {
			for typString, graphqlTyp := range typ.Types {
				if fragment.On != typString {
					continue
				}
				if err := PrepareQuery(graphqlTyp, fragment.SelectionSet); err != nil {
					return err
				}
			}
		}
		for _, selection := range selectionSet.Selections {
			if selection.Name == "__typename" {
				if !isNilArgs(selection.Args) {
					return NewClientError(`error parsing args for "__typename": no args expected`)
				}
				if selection.SelectionSet != nil {
					return NewClientError(`scalar field "__typename" must have no selection`)
				}
				continue
			}
			return NewClientError(`unknown field "%s"`, selection.Name)
		}
		return nil
	case *Object:
		if selectionSet == nil {
			return NewClientError("object field must have selections")
		}
		for _, selection := range selectionSet.Selections {
			if selection.Name == "__typename" {
				if !isNilArgs(selection.Args) {
					return NewClientError(`error parsing args for "__typename": no args expected`)
				}
				if selection.SelectionSet != nil {
					return NewClientError(`scalar field "__typename" must have no selection`)
				}
				continue
			}

			field, ok := typ.Fields[selection.Name]
			if !ok {
				return NewClientError(`unknown field "%s"`, selection.Name)
			}

			// Only parse args once for a given selection.
			if !selection.parsed {
				parsed, err := field.ParseArguments(selection.Args)
				if err != nil {
					return NewClientError(`error parsing args for "%s": %s`, selection.Name, err)
				}
				selection.Args = parsed
				selection.parsed = true
			}

			if err := PrepareQuery(field.Type, selection.SelectionSet); err != nil {
				return err
			}
		}
		for _, fragment := range selectionSet.Fragments {
			if err := PrepareQuery(typ, fragment.SelectionSet); err != nil {
				return err
			}
		}
		return nil

	case *List:
		return PrepareQuery(typ.Type, selectionSet)

	case *NonNull:
		return PrepareQuery(typ.Type, selectionSet)

	default:
		panic("unknown type kind")
	}
}

type panicError struct {
	message string
}

func (p panicError) Error() string {
	return p.message
}

func safeResolve(ctx context.Context, field *Field, source, args interface{}, selectionSet *SelectionSet) (result interface{}, err error) {
	defer func() {
		if panicErr := recover(); panicErr != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			result, err = nil, fmt.Errorf("graphql: panic: %v\n%s", panicErr, buf)
		}
	}()
	return field.Resolve(ctx, source, args, selectionSet)
}

type resolveAndExecuteCacheKey struct {
	field     *Field
	source    interface{}
	selection *Selection
}

func (e *Executor) resolveAndExecute(ctx context.Context, field *Field, source interface{}, selection *Selection) (interface{}, error) {
	if field.Expensive {
		// TODO: Skip goroutine for cached value
		ctx, release := concurrencylimiter.Acquire(ctx)
		return fork(func() (interface{}, error) {
			defer release()

			value := reflect.ValueOf(source)
			// cache the body of resolve and excecute so that if the source doesn't change, we
			// don't need to recompute
			key := resolveAndExecuteCacheKey{field: field, source: source, selection: selection}

			// some types can't be put in a map; for those, use a always different value
			// as source
			if value.IsValid() && !value.Type().Comparable() {
				// TODO: Warn, or somehow prevent using type-system?
				key.source = new(byte)
			}

			// TODO: Consider cacheing resolve and execute independently
			resolvedValue, err := reactive.Cache(ctx, key, func(ctx context.Context) (interface{}, error) {
				value, err := safeResolve(ctx, field, source, selection.Args, selection.SelectionSet)
				if err != nil {
					return nil, err
				}

				// Release concurrency token before recursing into execute. It will attempt to
				// grab another concurrency token.
				release()

				e.mu.Lock()
				value, err = e.execute(ctx, field.Type, value, selection.SelectionSet)
				e.mu.Unlock()

				if err != nil {
					return nil, err
				}
				return await(value)
			})

			return resolvedValue, err
		}), nil
	}

	value, err := safeResolve(ctx, field, source, selection.Args, selection.SelectionSet)
	if err != nil {
		return nil, err
	}
	return e.execute(ctx, field.Type, value, selection.SelectionSet)
}

func (e *Executor) executeUnion(ctx context.Context, typ *Union, source interface{}, selectionSet *SelectionSet) (interface{}, error) {
	value := reflect.ValueOf(source)
	if value.Kind() == reflect.Ptr && value.IsNil() {
		return nil, nil
	}

	fields := make(map[string]interface{})
	for _, selection := range selectionSet.Selections {
		if selection.Name == "__typename" {
			fields[selection.Alias] = typ.Name
			continue
		}
	}

	// For every inline fragment spread, check if the current concrete type
	// matches and execute that object.
	var possibleTypes []string
	for typString, graphqlTyp := range typ.Types {
		inner := reflect.ValueOf(source)
		if inner.Kind() == reflect.Ptr && inner.Elem().Kind() == reflect.Struct {
			inner = inner.Elem()
		}

		inner = inner.FieldByName(typString)
		if inner.IsNil() {
			continue
		}
		possibleTypes = append(possibleTypes, graphqlTyp.String())

		for _, fragment := range selectionSet.Fragments {
			if fragment.On != typString {
				continue
			}
			resolved, err := e.executeObject(ctx, graphqlTyp, inner.Interface(), fragment.SelectionSet)
			if err != nil {
				return nil, nestPathError(typString, err)
			}

			for k, v := range resolved.(map[string]interface{}) {
				fields[k] = v
			}
		}
	}

	if len(possibleTypes) > 1 {
		return nil, fmt.Errorf("union type field should only return one value, but received: %s", strings.Join(possibleTypes, " "))
	}
	return fields, nil
}

// executeObject executes an object query
func (e *Executor) executeObject(ctx context.Context, typ *Object, source interface{}, selectionSet *SelectionSet) (interface{}, error) {
	value := reflect.ValueOf(source)
	if value.Kind() == reflect.Ptr && value.IsNil() {
		return nil, nil
	}

	selections := Flatten(selectionSet)

	fields := make(map[string]interface{})

	// for every selection, resolve the value and store it in the output object
	for _, selection := range selections {
		if selection.Name == "__typename" {
			fields[selection.Alias] = typ.Name
			continue
		}

		field := typ.Fields[selection.Name]
		resolved, err := e.resolveAndExecute(ctx, field, source, selection)
		if err != nil {
			return nil, nestPathError(selection.Alias, err)
		}
		fields[selection.Alias] = resolved
	}

	if typ.Key != nil {
		value, err := e.resolveAndExecute(ctx, &Field{Type: &Scalar{Type: "string"}, Resolve: typ.Key}, source, &Selection{})
		if err != nil {
			return nil, nestPathError("__key", err)
		}
		fields["__key"] = value
	}

	return fields, nil
}

var emptyList = []interface{}{}

// executeList executes a set query
func (e *Executor) executeList(ctx context.Context, typ *List, source interface{}, selectionSet *SelectionSet) (interface{}, error) {
	if reflect.ValueOf(source).IsNil() {
		return emptyList, nil
	}

	// iterate over arbitrary slice types using reflect
	slice := reflect.ValueOf(source)
	items := make([]interface{}, slice.Len())

	// resolve every element in the slice
	for i := 0; i < slice.Len(); i++ {
		value := slice.Index(i)
		resolved, err := e.execute(ctx, typ.Type, value.Interface(), selectionSet)
		if err != nil {
			return nil, nestPathError(fmt.Sprint(i), err)
		}
		items[i] = resolved
	}

	return items, nil
}

// execute executes a query by dispatches according to typ
func (e *Executor) execute(ctx context.Context, typ Type, source interface{}, selectionSet *SelectionSet) (interface{}, error) {
	if err := ctx.Err(); err != nil {
		return nil, err
	}
	switch typ := typ.(type) {
	case *Scalar:
		return unwrap(source), nil
	case *Enum:
		val := unwrap(source)
		if mapVal, ok := typ.ReverseMap[val]; ok {
			return mapVal, nil
		}
		return nil, errors.New("enum is not valid")
	case *Union:
		return e.executeUnion(ctx, typ, source, selectionSet)
	case *Object:
		return e.executeObject(ctx, typ, source, selectionSet)
	case *List:
		return e.executeList(ctx, typ, source, selectionSet)
	case *NonNull:
		return e.execute(ctx, typ.Type, source, selectionSet)
	default:
		panic(typ)
	}
}

type Executor struct {
	mu sync.Mutex
}

// Execute executes a query by dispatches according to typ
func (e *Executor) Execute(ctx context.Context, typ Type, source interface{}, query *Query) (interface{}, error) {
	e.mu.Lock()
	value, err := e.execute(ctx, typ, source, query.SelectionSet)
	e.mu.Unlock()

	// Await the promise if things look good so far.
	if err == nil {
		value, err = await(value)
	}

	// Maybe error wrap if we have an error and a name to attach.
	if err != nil && query.Name != "" {
		err = nestPathError(query.Name, err)
	}

	return value, err
}
<|endoftext|>


<commit_before>package message

import (
	"fmt"
	"strings"

	"github.com/mongodb/grip/level"
)

// FieldsMsgName is the name of the default "message" field in the
// fields structure.
const FieldsMsgName = "message"

type fieldMessage struct {
	message      string
	fields       Fields
	cachedOutput string
	Base
}

// Fields is a convince type that wraps map[string]interface{} and is
// used for attaching structured metadata to a build request. For
// example:
//
//     message.Fields{"key0", <value>, "key1", <value>}
type Fields map[string]interface{}

// NewFieldsMessage creates a fully configured Composer instance that
// will attach some additional structured data. This constructor
// allows you to include a string message as well as Fields
// object.
func NewFieldsMessage(p level.Priority, message string, f Fields) Composer {
	m := MakeFieldsMessage(message, f)

	_ = m.SetPriority(p)

	return m
}

// NewFields constructs a full configured fields Composer.
func NewFields(p level.Priority, f Fields) Composer {
	m := MakeFields(f)
	_ = m.SetPriority(p)

	return m
}

// MakeFieldsMessage constructs a fields Composer from a message string and
// Fields object, without specifying the priority of the message.
func MakeFieldsMessage(message string, f Fields) Composer {
	return &fieldMessage{message: message, fields: f}
}

// MakeFields creates a composer interface from *just* a Fields instance.
func MakeFields(f Fields) Composer { return &fieldMessage{fields: f} }

func (m *fieldMessage) Loggable() bool { return m.message != "" || len(m.fields) > 0 }
func (m *fieldMessage) String() string {
	if !m.Loggable() {
		return ""
	}

	if m.cachedOutput == "" {
		const tmpl = "%s='%v'"
		out := []string{}
		if m.message != "" {
			out = append(out, fmt.Sprintf(tmpl, FieldsMsgName, m.message))
		}

		for k, v := range m.fields {
			if k == "msg" && v == m.message {
				continue
			}
			if k == "time" {
				continue
			}

			out = append(out, fmt.Sprintf(tmpl, k, v))
		}

		m.cachedOutput = fmt.Sprintf("[%s]", strings.Join(out, " "))
	}

	return m.cachedOutput
}

func (m *fieldMessage) Raw() interface{} {
	_ = m.Collect()

	if _, ok := m.fields[FieldsMsgName]; !ok {
		m.fields[FieldsMsgName] = m.message
	}

	if _, ok := m.fields["metadata"]; !ok {
		m.fields["metadata"] = &m.Base
	}

	return m.fields
}
<commit_msg>avoid empty field message fields<commit_after>package message

import (
	"fmt"
	"strings"

	"github.com/mongodb/grip/level"
)

// FieldsMsgName is the name of the default "message" field in the
// fields structure.
const FieldsMsgName = "message"

type fieldMessage struct {
	message      string
	fields       Fields
	cachedOutput string
	Base
}

// Fields is a convince type that wraps map[string]interface{} and is
// used for attaching structured metadata to a build request. For
// example:
//
//     message.Fields{"key0", <value>, "key1", <value>}
type Fields map[string]interface{}

// NewFieldsMessage creates a fully configured Composer instance that
// will attach some additional structured data. This constructor
// allows you to include a string message as well as Fields
// object.
func NewFieldsMessage(p level.Priority, message string, f Fields) Composer {
	m := MakeFieldsMessage(message, f)

	_ = m.SetPriority(p)

	return m
}

// NewFields constructs a full configured fields Composer.
func NewFields(p level.Priority, f Fields) Composer {
	m := MakeFields(f)
	_ = m.SetPriority(p)

	return m
}

// MakeFieldsMessage constructs a fields Composer from a message string and
// Fields object, without specifying the priority of the message.
func MakeFieldsMessage(message string, f Fields) Composer {
	return &fieldMessage{message: message, fields: f}
}

// MakeFields creates a composer interface from *just* a Fields instance.
func MakeFields(f Fields) Composer { return &fieldMessage{fields: f} }

func (m *fieldMessage) Loggable() bool { return m.message != "" || len(m.fields) > 0 }
func (m *fieldMessage) String() string {
	if !m.Loggable() {
		return ""
	}

	if m.cachedOutput == "" {
		const tmpl = "%s='%v'"
		out := []string{}
		if m.message != "" {
			out = append(out, fmt.Sprintf(tmpl, FieldsMsgName, m.message))
		}

		for k, v := range m.fields {
			if k == "msg" && v == m.message {
				continue
			}
			if k == "time" {
				continue
			}

			out = append(out, fmt.Sprintf(tmpl, k, v))
		}

		m.cachedOutput = fmt.Sprintf("[%s]", strings.Join(out, " "))
	}

	return m.cachedOutput
}

func (m *fieldMessage) Raw() interface{} {
	_ = m.Collect()

	if _, ok := m.fields[FieldsMsgName]; !ok && m.message != "" {
		m.fields[FieldsMsgName] = m.message
	}

	if _, ok := m.fields["metadata"]; !ok {
		m.fields["metadata"] = &m.Base
	}

	return m.fields
}
<|endoftext|>


<commit_before>package gitlab

import "fmt"

// EpicIssuesService handles communication with the epic issue related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epic_issues.html
type EpicIssuesService struct {
	client *Client
}

// ListEpicIssues get a list of epic issues.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/epic_issues.html#list-issues-for-an-epic
func (s *EpicIssuesService) ListEpicIssues(gid interface{}, epic int, opt *ListOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/epics/%d/issues", group, epic)

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var i []*Issue
	resp, err := s.client.Do(req, &i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}

// EpicIssueAssignment contains both the Epic and Issue objects returned from Gitlab w/ the assignment ID
type EpicIssueAssignment struct {
	ID    int    `json:"id"`
	Epic  *Epic  `json:"epic"`
	Issue *Issue `json:"issue"`
}

// AssignEpicIssue assigns an existing issue to an Epic
//
// Gitlab API Docs: https://docs.gitlab.com/ee/api/epic_issues.html#assign-an-issue-to-the-epic
func (s *EpicIssuesService) AssignEpicIssue(gid interface{}, epic int, issue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", pathEscape(group), epic, issue)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var a *EpicIssueAssignment

	resp, err := s.client.Do(req, &a)
	if err != nil {
		return nil, resp, err
	}

	return a, resp, err
}

// RemoveEpicIssue removes an issue from an Epic
//
// Gitlab API Docs: https://docs.gitlab.com/ee/api/epic_issues.html#remove-an-issue-from-the-epic
func (s *EpicIssuesService) RemoveEpicIssue(gid interface{}, epic int, epicIssue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", pathEscape(group), epic, epicIssue)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var a *EpicIssueAssignment

	resp, err := s.client.Do(req, &a)
	if err != nil {
		return nil, resp, err
	}

	return a, resp, err
}

// UpdateEpicIsssueAssignmentOptions describes options to move issues within an epic
type UpdateEpicIsssueAssignmentOptions struct {
	*ListOptions
	MoveBeforeID int `json:"move_before_id"`
	MoveAfterID  int `json:"move_after_id"`
}

// UpdateEpicIssueAssignment moves an issue before or after another issue in an epic issue list
//
// Gitlab API Docs: https://docs.gitlab.com/ee/api/epic_issues.html#update-epic---issue-association
func (s *EpicIssuesService) UpdateEpicIssueAssignment(gid interface{}, epic int, epicIssue int, opt *UpdateEpicIsssueAssignmentOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", pathEscape(group), epic, epicIssue)

	req, err := s.client.NewRequest("PUT", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var i []*Issue

	resp, err := s.client.Do(req, &i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}
<commit_msg>path escape group<commit_after>package gitlab

import "fmt"

// EpicIssuesService handles communication with the epic issue related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epic_issues.html
type EpicIssuesService struct {
	client *Client
}

// ListEpicIssues get a list of epic issues.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/epic_issues.html#list-issues-for-an-epic
func (s *EpicIssuesService) ListEpicIssues(gid interface{}, epic int, opt *ListOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/epics/%d/issues", pathEscape(group), epic)

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var i []*Issue
	resp, err := s.client.Do(req, &i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}

// EpicIssueAssignment contains both the Epic and Issue objects returned from Gitlab w/ the assignment ID
type EpicIssueAssignment struct {
	ID    int    `json:"id"`
	Epic  *Epic  `json:"epic"`
	Issue *Issue `json:"issue"`
}

// AssignEpicIssue assigns an existing issue to an Epic
//
// Gitlab API Docs: https://docs.gitlab.com/ee/api/epic_issues.html#assign-an-issue-to-the-epic
func (s *EpicIssuesService) AssignEpicIssue(gid interface{}, epic int, issue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", pathEscape(group), epic, issue)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var a *EpicIssueAssignment

	resp, err := s.client.Do(req, &a)
	if err != nil {
		return nil, resp, err
	}

	return a, resp, err
}

// RemoveEpicIssue removes an issue from an Epic
//
// Gitlab API Docs: https://docs.gitlab.com/ee/api/epic_issues.html#remove-an-issue-from-the-epic
func (s *EpicIssuesService) RemoveEpicIssue(gid interface{}, epic int, epicIssue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", pathEscape(group), epic, epicIssue)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var a *EpicIssueAssignment

	resp, err := s.client.Do(req, &a)
	if err != nil {
		return nil, resp, err
	}

	return a, resp, err
}

// UpdateEpicIsssueAssignmentOptions describes options to move issues within an epic
type UpdateEpicIsssueAssignmentOptions struct {
	*ListOptions
	MoveBeforeID int `json:"move_before_id"`
	MoveAfterID  int `json:"move_after_id"`
}

// UpdateEpicIssueAssignment moves an issue before or after another issue in an epic issue list
//
// Gitlab API Docs: https://docs.gitlab.com/ee/api/epic_issues.html#update-epic---issue-association
func (s *EpicIssuesService) UpdateEpicIssueAssignment(gid interface{}, epic int, epicIssue int, opt *UpdateEpicIsssueAssignmentOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", pathEscape(group), epic, epicIssue)

	req, err := s.client.NewRequest("PUT", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var i []*Issue

	resp, err := s.client.Do(req, &i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Home Office All rights reserved.

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

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

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

package main

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// VaultResources is a collection of type resource
type VaultResources struct {
	// an array of resource to retrieve
	items []*VaultResource
}

// Set is the implementation for the parser
// secret:test:file=filename.test,fmt=yaml
func (r *VaultResources) Set(value string) error {
	rn := defaultVaultResource()

	// step: split on the ':'
	items := strings.Split(os.ExpandEnv(value), ":")
	if len(items) < 2 {
		return fmt.Errorf("invalid resource, must have at least two sections TYPE:PATH")
	}
	if len(items) > 3 {
		return fmt.Errorf("invalid resource, can only has three sections, TYPE:PATH[:OPTIONS]")
	}
	if items[0] == "" || items[1] == "" {
		return fmt.Errorf("invalid resource, neither type or path can be empty")
	}

	// step: extract the elements
	rn.resource = items[0]
	rn.path = items[1]
	rn.options = make(map[string]string, 0)

	// step: extract any options
	if len(items) > 2 {
		for _, x := range strings.Split(items[2], ",") {
			kp := strings.Split(x, "=")
			if len(kp) != 2 {
				return fmt.Errorf("invalid resource option: %s, must be KEY=VALUE", x)
			}
			if kp[1] == "" {
				return fmt.Errorf("invalid resource option: %s, must have a value", x)
			}
			// step: set the name and value
			name := kp[0]
			value := strings.Replace(kp[1], "|", ",", -1)

			// step: extract the control options from the path resource parameters
			switch name {
			case optionFormat:
				if matched := resourceFormatRegex.MatchString(value); !matched {
					return fmt.Errorf("unsupported output format: %s", value)
				}
				rn.format = value
			case optionUpdate:
				duration, err := time.ParseDuration(value)
				if err != nil {
					return fmt.Errorf("update option: %s is not value, should be a duration format", value)
				}
				rn.update = duration
			case optionRevoke:
				choice, err := strconv.ParseBool(value)
				if err != nil {
					return fmt.Errorf("the revoke option: %s is invalid, should be a boolean", value)
				}
				rn.revoked = choice
			case optionsRevokeDelay:
				duration, err := time.ParseDuration(value)
				if err != nil {
					return fmt.Errorf("the revoke delay option: %s is not value, should be a duration format", value)
				}
				rn.revokeDelay = duration
			case optionRenewal:
				choice, err := strconv.ParseBool(value)
				if err != nil {
					return fmt.Errorf("the renewal option: %s is invalid, should be a boolean", value)
				}
				rn.renewable = choice
			case optionCreate:
				choice, err := strconv.ParseBool(value)
				if err != nil {
					return fmt.Errorf("the create option: %s is invalid, should be a boolean", value)
				}
				if rn.resource != "secret" {
					return fmt.Errorf("the create option is only supported for 'cn=secret' at this time")
				}
				rn.create = choice
			case optionSize:
				size, err := strconv.ParseInt(value, 10, 16)
				if err != nil {
					return fmt.Errorf("the size option: %s is invalid, should be an integer", value)
				}
				rn.size = size
			case optionExec:
				rn.execPath = value
			case optionFilename:
				rn.filename = value
			case optionTemplatePath:
				rn.templateFile = value
			default:
				rn.options[name] = value
			}
		}
	}
	// step: append to the list of resources
	r.items = append(r.items, rn)

	return nil
}

// String returns a string representation of the struct
func (r VaultResources) String() string {
	return ""
}
<commit_msg>- removing the regexs import<commit_after>/*
Copyright 2015 Home Office All rights reserved.

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

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

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

package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"
)

// VaultResources is a collection of type resource
type VaultResources struct {
	// an array of resource to retrieve
	items []*VaultResource
}

// Set is the implementation for the parser
// secret:test:file=filename.test,fmt=yaml
func (r *VaultResources) Set(value string) error {
	rn := defaultVaultResource()

	// step: split on the ':'
	items := strings.Split(os.ExpandEnv(value), ":")
	if len(items) < 2 {
		return fmt.Errorf("invalid resource, must have at least two sections TYPE:PATH")
	}
	if len(items) > 3 {
		return fmt.Errorf("invalid resource, can only has three sections, TYPE:PATH[:OPTIONS]")
	}
	if items[0] == "" || items[1] == "" {
		return fmt.Errorf("invalid resource, neither type or path can be empty")
	}

	// step: extract the elements
	rn.resource = items[0]
	rn.path = items[1]
	rn.options = make(map[string]string, 0)

	// step: extract any options
	if len(items) > 2 {
		for _, x := range strings.Split(items[2], ",") {
			kp := strings.Split(x, "=")
			if len(kp) != 2 {
				return fmt.Errorf("invalid resource option: %s, must be KEY=VALUE", x)
			}
			if kp[1] == "" {
				return fmt.Errorf("invalid resource option: %s, must have a value", x)
			}
			// step: set the name and value
			name := kp[0]
			value := strings.Replace(kp[1], "|", ",", -1)

			// step: extract the control options from the path resource parameters
			switch name {
			case optionFormat:
				if matched := resourceFormatRegex.MatchString(value); !matched {
					return fmt.Errorf("unsupported output format: %s", value)
				}
				rn.format = value
			case optionUpdate:
				duration, err := time.ParseDuration(value)
				if err != nil {
					return fmt.Errorf("update option: %s is not value, should be a duration format", value)
				}
				rn.update = duration
			case optionRevoke:
				choice, err := strconv.ParseBool(value)
				if err != nil {
					return fmt.Errorf("the revoke option: %s is invalid, should be a boolean", value)
				}
				rn.revoked = choice
			case optionsRevokeDelay:
				duration, err := time.ParseDuration(value)
				if err != nil {
					return fmt.Errorf("the revoke delay option: %s is not value, should be a duration format", value)
				}
				rn.revokeDelay = duration
			case optionRenewal:
				choice, err := strconv.ParseBool(value)
				if err != nil {
					return fmt.Errorf("the renewal option: %s is invalid, should be a boolean", value)
				}
				rn.renewable = choice
			case optionCreate:
				choice, err := strconv.ParseBool(value)
				if err != nil {
					return fmt.Errorf("the create option: %s is invalid, should be a boolean", value)
				}
				if rn.resource != "secret" {
					return fmt.Errorf("the create option is only supported for 'cn=secret' at this time")
				}
				rn.create = choice
			case optionSize:
				size, err := strconv.ParseInt(value, 10, 16)
				if err != nil {
					return fmt.Errorf("the size option: %s is invalid, should be an integer", value)
				}
				rn.size = size
			case optionExec:
				rn.execPath = value
			case optionFilename:
				rn.filename = value
			case optionTemplatePath:
				rn.templateFile = value
			default:
				rn.options[name] = value
			}
		}
	}
	// step: append to the list of resources
	r.items = append(r.items, rn)

	return nil
}

// String returns a string representation of the struct
func (r VaultResources) String() string {
	return ""
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/stretchr/testify/assert"
)

func TestInitialMigration(t *testing.T) {
	assert := assert.New(t)

}
<commit_msg>Add migration tests<commit_after>package main

import (
	"github.com/boltdb/bolt"
	"github.com/stretchr/testify/assert"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
	"testing"
)

func testDB(fn string) *bolt.DB {
	// Reset it
	_ = os.Remove(fn)

	db, err := bolt.Open(fn, 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	return db
}

func TestInitialMigration(t *testing.T) {
	assert := assert.New(t)

	db := testDB("test/migration1.db")
	err := InitialMigration(db)
	assert.Nil(err)

	v, err := getVersion(db)
	assert.Nil(err)
	assert.Equal(1, v)
}

func TestBackup(t *testing.T) {
	assert := assert.New(t)
	path := "test/backups/"
	_ = os.RemoveAll(path)

	db := testDB("test/backup.db")

	err := backup(db, 255, path)
	assert.Nil(err)

	files, err := ioutil.ReadDir(path)
	assert.Nil(err)
	assert.Equal(1, len(files))

	assert.True(
		strings.Contains(files[0].Name(), "_"+strconv.Itoa(255)+"-"),
		"Backup file did not contain the version number",
	)
}
<|endoftext|>


<commit_before>package errors

import (
	"encoding/json"
	"fmt"
)

type (
	errorSource struct {
		*errorType
		source error
	}
)

// Error implements error interface.
func (e *errorSource) Error() string {
	return e.source.Error()
}

// NewAsSource returns a new error which is the source.
func NewAsSource(msg string) error {
	return newSource(nil, new(nil, msg, 1), 1)
}

// NewAsSourcef returns a new error which is the source.
func NewAsSourcef(format string, a ...interface{}) error {
	return newSource(nil, new(nil, fmt.Sprintf(format, a...), 1), 1)
}

// WrapBySourceError returns a new error.
// If the error is passed to errors.SourceOf function,
// returns the source.
func WrapBySourceError(inner error, source error) error {
	if inner == nil {
		return nil
	}
	return newSource(inner, source, 1)
}

// WrapBySourceMsg returns a new error.
func WrapBySourceMsg(inner error, msg string) error {
	if inner == nil {
		return nil
	}
	return newSource(inner, new(nil, msg, 1), 1)
}

// WrapBySourceMsgf returns a new error.
func WrapBySourceMsgf(inner error, format string, a ...interface{}) error {
	if inner == nil {
		return nil
	}
	return newSource(inner, new(nil, fmt.Sprintf(format, a...), 1), 1)
}

// SourceOf returns the source error of the err.
func SourceOf(err error) error {
	if e, ok := err.(*errorSource); ok {
		return e.source
	}
	if e, ok := err.(*collection); ok {
		return e.source()
	}
	if e, ok := err.(*errorType); ok {
		if e.inner != nil {
			return SourceOf(e.inner)
		}
		return e
	}
	return err
}

// ExplicitSourceOf returns an error if the error is
// explicitly specified Source by WrapBySourceXxx.
func ExplicitSourceOf(err error) error {
	if e, ok := err.(*errorSource); ok {
		return e.source
	}
	if e, ok := err.(*collection); ok {
		return e.explicitSource()
	}
	if e, ok := err.(*errorType); ok {
		if e.inner != nil {
			return ExplicitSourceOf(e.inner)
		}
		return nil
	}
	return nil
}

// MarshalJSON implements json.Marshaler interface.
func (e *errorSource) MarshalJSON() ([]byte, error) {
	obj := struct {
		Inner    *errMarshal `json:"inner"`
		Callers  *callerInfo `json:"callers"`
		Message  string      `json:"message"`
		IsSource bool        `json:"isSource"`
	}{
		Inner: &errMarshal{
			err:         e.inner,
			callerCount: e.callerCount,
		},
		Callers:  e.info,
		Message:  e.source.Error(),
		IsSource: true,
	}
	return json.Marshal(&obj)
}

func newSource(inner error, source error, skip int) error {
	return &errorSource{
		errorType: new(inner, "", skip+1).(*errorType),
		source:    source,
	}
}
<commit_msg>Add AsSource<commit_after>package errors

import (
	"encoding/json"
	"fmt"
)

type (
	errorSource struct {
		*errorType
		source error
	}
)

// Error implements error interface.
func (e *errorSource) Error() string {
	return e.source.Error()
}

// NewAsSource returns a new error which is the source.
func NewAsSource(msg string) error {
	return newSource(nil, new(nil, msg, 1), 1)
}

// NewAsSourcef returns a new error which is the source.
func NewAsSourcef(format string, a ...interface{}) error {
	return newSource(nil, new(nil, fmt.Sprintf(format, a...), 1), 1)
}

// AsSource returns a new source error.
func AsSource(err error) error {
	return newSource(nil, err, 1)
}

// WrapBySourceError returns a new error.
// If the error is passed to errors.SourceOf function,
// returns the source.
func WrapBySourceError(inner error, source error) error {
	if inner == nil {
		return nil
	}
	return newSource(inner, source, 1)
}

// WrapBySourceMsg returns a new error.
func WrapBySourceMsg(inner error, msg string) error {
	if inner == nil {
		return nil
	}
	return newSource(inner, new(nil, msg, 1), 1)
}

// WrapBySourceMsgf returns a new error.
func WrapBySourceMsgf(inner error, format string, a ...interface{}) error {
	if inner == nil {
		return nil
	}
	return newSource(inner, new(nil, fmt.Sprintf(format, a...), 1), 1)
}

// SourceOf returns the source error of the err.
func SourceOf(err error) error {
	if e, ok := err.(*errorSource); ok {
		return e.source
	}
	if e, ok := err.(*collection); ok {
		return e.source()
	}
	if e, ok := err.(*errorType); ok {
		if e.inner != nil {
			return SourceOf(e.inner)
		}
		return e
	}
	return err
}

// ExplicitSourceOf returns an error if the error is
// explicitly specified Source by WrapBySourceXxx.
func ExplicitSourceOf(err error) error {
	if e, ok := err.(*errorSource); ok {
		return e.source
	}
	if e, ok := err.(*collection); ok {
		return e.explicitSource()
	}
	if e, ok := err.(*errorType); ok {
		if e.inner != nil {
			return ExplicitSourceOf(e.inner)
		}
		return nil
	}
	return nil
}

// MarshalJSON implements json.Marshaler interface.
func (e *errorSource) MarshalJSON() ([]byte, error) {
	obj := struct {
		Inner    *errMarshal `json:"inner"`
		Callers  *callerInfo `json:"callers"`
		Message  string      `json:"message"`
		IsSource bool        `json:"isSource"`
	}{
		Inner: &errMarshal{
			err:         e.inner,
			callerCount: e.callerCount,
		},
		Callers:  e.info,
		Message:  e.source.Error(),
		IsSource: true,
	}
	return json.Marshal(&obj)
}

func newSource(inner error, source error, skip int) error {
	return &errorSource{
		errorType: new(inner, "", skip+1).(*errorType),
		source:    source,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

func main() {
	problemIDFlag := flag.Int("new", 1, "new <problem ID>")
	flag.Parse()
	problemID := *problemIDFlag
	println("ProblemID: " + strconv.Itoa(problemID))
	folder := "p" + strconv.Itoa(problemID)
	err := os.Mkdir(folder, 0771)
	if err != nil {
		log.Fatal("Folder " + folder + " already exists! Remove it to generate problem template.")

	}
	data := strings.Replace(problemTemplate, problemIDString, strconv.Itoa(problemID), -1)
	data = strings.Replace(data, problemDescriptionString, getProblemDescription(problemID), -1)
	file := "p" + strconv.Itoa(problemID) + ".go"
	err = ioutil.WriteFile(folder+"/"+file, []byte(data), 0664)
	panicIfError(err)

	data = strings.Replace(problemTestTemplate, problemIDString, strconv.Itoa(problemID), -1)
	file = "p" + strconv.Itoa(problemID) + "_test.go"
	err = ioutil.WriteFile(folder+"/"+file, []byte(data), 0664)
	panicIfError(err)
}
func panicIfError(err error) {
	if err != nil {
		panic(err)
	}
}

func getProblemDescription(problemID int) string {
	doc, err := goquery.NewDocument("https://projecteuler.net/problem=" + strconv.Itoa(problemID))
	if err != nil {
		log.Fatal(err)
	}
	info := "Project Euler: Problem " + strconv.Itoa(problemID) + "\n\n"
	doc.Find("h2").Each(func(i int, s *goquery.Selection) {
		// class, _ := s.Attr("id")
		// fmt.Println(class, s.Text())
		info += "Title:\n" + s.Text()
	})
	info += "\n\n"
	doc.Find(".info").Each(func(i int, s *goquery.Selection) {
		info += "Info:\n" + s.Text()
	})
	info += "\n\n"
	doc.Find(".problem_content").Each(func(i int, s *goquery.Selection) {
		info += "Description:\n" + s.Text() + "{{end_block}}"
	})

	yuckyStrings := map[string]string{
		"\n\n\n":           "\n\n",
		"\n{{end_block}}":  "",
		"Description:\n\n": "Description:\n",
		"Title:\n":         "Title: ",
		"You are currently using a secure connectionInfo:\n": "",
		"Problem " + strconv.Itoa(problemID):                 ""}

	for k, v := range yuckyStrings {
		for i := 0; i < 5; i++ { // Make sure all get replaced.
			info = strings.Replace(info, k, v, -1)
		}
	}
	return info
}
<commit_msg>Replacements fix<commit_after>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

func main() {
	problemIDFlag := flag.Int("new", 1, "new <problem ID>")
	flag.Parse()
	problemID := *problemIDFlag
	println("ProblemID: " + strconv.Itoa(problemID))
	folder := "p" + strconv.Itoa(problemID)
	err := os.Mkdir(folder, 0771)
	if err != nil {
		log.Fatal("Folder " + folder + " already exists! Remove it to generate problem template.")

	}
	data := strings.Replace(problemTemplate, problemIDString, strconv.Itoa(problemID), -1)
	data = strings.Replace(data, problemDescriptionString, getProblemDescription(problemID), -1)
	file := "p" + strconv.Itoa(problemID) + ".go"
	err = ioutil.WriteFile(folder+"/"+file, []byte(data), 0664)
	panicIfError(err)

	data = strings.Replace(problemTestTemplate, problemIDString, strconv.Itoa(problemID), -1)
	file = "p" + strconv.Itoa(problemID) + "_test.go"
	err = ioutil.WriteFile(folder+"/"+file, []byte(data), 0664)
	panicIfError(err)
}
func panicIfError(err error) {
	if err != nil {
		panic(err)
	}
}

func getProblemDescription(problemID int) string {
	doc, err := goquery.NewDocument("https://projecteuler.net/problem=" + strconv.Itoa(problemID))
	if err != nil {
		log.Fatal(err)
	}
	info := "Project Euler: Problem " + strconv.Itoa(problemID) + "\n\n"
	doc.Find("h2").Each(func(i int, s *goquery.Selection) {
		// class, _ := s.Attr("id")
		// fmt.Println(class, s.Text())
		info += "Title:\n" + s.Text()
	})
	info += "\n\n"
	doc.Find(".info").Each(func(i int, s *goquery.Selection) {
		info += "Info:\n" + s.Text()
	})
	info += "\n\n"
	doc.Find(".problem_content").Each(func(i int, s *goquery.Selection) {
		info += "Description:\n" + s.Text() + "{{end_block}}"
	})

	yuckyStrings := map[string]string{
		"\n\n\n":           "\n\n",
		"\n{{end_block}}":  "",
		"Description:\n\n": "Description:\n",
		"Title:\n":         "Title: ",
		"You are currently using a secure connectionInfo:\n": "",
		"Title:\nProblem " + strconv.Itoa(problemID):         ""}

	for k, v := range yuckyStrings {
		for i := 0; i < 5; i++ { // Make sure all get replaced.
			info = strings.Replace(info, k, v, -1)
		}
	}
	return info
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/andrewslotin/doppelganger/git"
)

type MirrorHandler struct {
	githubRepos      git.RepositoryService
	mirroredRepos    git.MirrorService
	trackRepoService git.TrackingService
}

func NewMirrorHandler(githubRepos git.RepositoryService, mirroredRepos git.MirrorService, trackingService git.TrackingService) *MirrorHandler {
	return &MirrorHandler{
		githubRepos:      githubRepos,
		mirroredRepos:    mirroredRepos,
		trackRepoService: trackingService,
	}
}

func (handler *MirrorHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	startTime := time.Now()

	repoName := req.FormValue("repo")
	if repoName == "" {
		http.Error(w, "Missing source repository name", http.StatusBadRequest)
		return
	}

	switch action := strings.ToLower(req.FormValue("action")); action {
	case "create":
		if err := handler.CreateMirror(w, repoName); err != nil {
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		log.Printf("mirrored %s [%s]", repoName, time.Since(startTime))
		handler.redirectToRepository(w, req, repoName)
	case "update":
		if err := handler.UpdateMirror(w, repoName); err != nil {
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		log.Printf("updated mirror %s [%s]", repoName, time.Since(startTime))
		handler.redirectToRepository(w, req, repoName)
	case "track":
		if handler.trackRepoService == nil {
			http.Error(w, "Tracking changes not supported", http.StatusNotImplemented)
			return
		}

		if err := handler.SetupChangeTracking(w, req, repoName); err != nil {
			http.Error(w, "Internal service error", http.StatusInternalServerError)
			return
		}

		log.Printf("set up push changes hook for %s [%s]", repoName, time.Since(startTime))
		handler.redirectToRepository(w, req, repoName)
	default:
		http.Error(w, fmt.Sprintf("Unsupported action %q", action), http.StatusBadRequest)
	}
}

func (handler *MirrorHandler) CreateMirror(w http.ResponseWriter, repoName string) error {
	switch repo, err := handler.githubRepos.Get(repoName); err {
	case nil:
		return handler.mirroredRepos.Create(repo.FullName, repo.GitURL)
	case git.ErrorNotFound:
		http.Error(w, "Source repository not found", http.StatusNotFound)
		return nil
	default:
		return err
	}
}

func (handler *MirrorHandler) SetupChangeTracking(w http.ResponseWriter, req *http.Request, repoName string) error {
	switch repo, err := handler.mirroredRepos.Get(repoName); err {
	case nil:
		return handler.trackRepoService.Track(repo.FullName, apiHookURL(req).String())
	case git.ErrorNotMirrored:
		http.Error(w, "Repository not mirrored", http.StatusNotFound)
		return nil
	default:
		return err
	}
}

func (handler *MirrorHandler) UpdateMirror(w http.ResponseWriter, repoName string) error {
	switch repo, err := handler.mirroredRepos.Get(repoName); err {
	case nil:
		return handler.mirroredRepos.Update(repo.FullName)
	case git.ErrorNotMirrored:
		http.Error(w, "Source repository not mirrored", http.StatusNotFound)
		return nil
	default:
		return err
	}
}

func (handler *MirrorHandler) redirectToRepository(w http.ResponseWriter, req *http.Request, repoName string) {
	http.Redirect(w, req, fmt.Sprintf("/mirrored?repo=%s", url.QueryEscape(repoName)), http.StatusSeeOther)
}

func apiHookURL(req *http.Request) *url.URL {
	return &url.URL{
		Scheme: req.URL.Scheme,
		Host:   req.URL.Host,
		Path:   "/apihook",
	}
}
<commit_msg>Fix typo<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/andrewslotin/doppelganger/git"
)

type MirrorHandler struct {
	githubRepos      git.RepositoryService
	mirroredRepos    git.MirrorService
	trackRepoService git.TrackingService
}

func NewMirrorHandler(githubRepos git.RepositoryService, mirroredRepos git.MirrorService, trackingService git.TrackingService) *MirrorHandler {
	return &MirrorHandler{
		githubRepos:      githubRepos,
		mirroredRepos:    mirroredRepos,
		trackRepoService: trackingService,
	}
}

func (handler *MirrorHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	startTime := time.Now()

	repoName := req.FormValue("repo")
	if repoName == "" {
		http.Error(w, "Missing source repository name", http.StatusBadRequest)
		return
	}

	switch action := strings.ToLower(req.FormValue("action")); action {
	case "create":
		if err := handler.CreateMirror(w, repoName); err != nil {
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		log.Printf("mirrored %s [%s]", repoName, time.Since(startTime))
		handler.redirectToRepository(w, req, repoName)
	case "update":
		if err := handler.UpdateMirror(w, repoName); err != nil {
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		log.Printf("updated mirror %s [%s]", repoName, time.Since(startTime))
		handler.redirectToRepository(w, req, repoName)
	case "track":
		if handler.trackRepoService == nil {
			http.Error(w, "Tracking changes not supported", http.StatusNotImplemented)
			return
		}

		if err := handler.SetupChangeTracking(w, req, repoName); err != nil {
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		log.Printf("set up push changes hook for %s [%s]", repoName, time.Since(startTime))
		handler.redirectToRepository(w, req, repoName)
	default:
		http.Error(w, fmt.Sprintf("Unsupported action %q", action), http.StatusBadRequest)
	}
}

func (handler *MirrorHandler) CreateMirror(w http.ResponseWriter, repoName string) error {
	switch repo, err := handler.githubRepos.Get(repoName); err {
	case nil:
		return handler.mirroredRepos.Create(repo.FullName, repo.GitURL)
	case git.ErrorNotFound:
		http.Error(w, "Source repository not found", http.StatusNotFound)
		return nil
	default:
		return err
	}
}

func (handler *MirrorHandler) SetupChangeTracking(w http.ResponseWriter, req *http.Request, repoName string) error {
	switch repo, err := handler.mirroredRepos.Get(repoName); err {
	case nil:
		return handler.trackRepoService.Track(repo.FullName, apiHookURL(req).String())
	case git.ErrorNotMirrored:
		http.Error(w, "Repository not mirrored", http.StatusNotFound)
		return nil
	default:
		return err
	}
}

func (handler *MirrorHandler) UpdateMirror(w http.ResponseWriter, repoName string) error {
	switch repo, err := handler.mirroredRepos.Get(repoName); err {
	case nil:
		return handler.mirroredRepos.Update(repo.FullName)
	case git.ErrorNotMirrored:
		http.Error(w, "Source repository not mirrored", http.StatusNotFound)
		return nil
	default:
		return err
	}
}

func (handler *MirrorHandler) redirectToRepository(w http.ResponseWriter, req *http.Request, repoName string) {
	http.Redirect(w, req, fmt.Sprintf("/mirrored?repo=%s", url.QueryEscape(repoName)), http.StatusSeeOther)
}

func apiHookURL(req *http.Request) *url.URL {
	return &url.URL{
		Scheme: req.URL.Scheme,
		Host:   req.URL.Host,
		Path:   "/apihook",
	}
}
<|endoftext|>


<commit_before>package tp

import (
	//	"fmt"
	"testing"
)

func TestTP(t *testing.T) {
	s := []float32{300, 400, 500}
	d := []float32{250, 350, 400, 200}
	c := [][]float32{
		[]float32{3, 1, 7, 4},
		[]float32{2, 6, 5, 9},
		[]float32{8, 3, 3, 2},
	}
	for i := 0; i < 10; i++ {
		//sLen, dLen := len(s), len(d)
		_, _, err := Solve(s, d, c)
		if err != nil {
			t.Error("failed to create state", err)
			//fmt.Println(err)
			//os.Exit(1)
		} else {
			/*fmt.Println("Solution: ")
			for i := 0; i < sLen; i++ {
				for j := 0; j < dLen; j++ {
					f := flow[i][j]
					if f == 0 {
						continue
					}
					fmt.Printf(" (%v,%v),cost=%v,flow=%v\n", i, j, c[i][j], f)
				}
			}
			fmt.Printf("solution cost=%v\n", cost)
			fmt.Println("")*/
		}
	}
}
<commit_msg>fix some wording in tests<commit_after>package tp

import (
	//	"fmt"
	"testing"
)

func TestTP(t *testing.T) {
	s := []float32{300, 400, 500}
	d := []float32{250, 350, 400, 200}
	c := [][]float32{
		[]float32{3, 1, 7, 4},
		[]float32{2, 6, 5, 9},
		[]float32{8, 3, 3, 2},
	}
	for i := 0; i < 10; i++ {
		//sLen, dLen := len(s), len(d)
		_, _, err := Solve(s, d, c)
		if err != nil {
			t.Error("failed to solve givn TP problem:", err)
			//fmt.Println(err)
			//os.Exit(1)
		} else {
			/*fmt.Println("Solution: ")
			for i := 0; i < sLen; i++ {
				for j := 0; j < dLen; j++ {
					f := flow[i][j]
					if f == 0 {
						continue
					}
					fmt.Printf(" (%v,%v),cost=%v,flow=%v\n", i, j, c[i][j], f)
				}
			}
			fmt.Printf("solution cost=%v\n", cost)
			fmt.Println("")*/
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"runtime/trace"
)

const fileName = "trace.out"

var sum int

func main() {
	lgr := log.New(os.Stderr, "", 0)

	f, err := os.Create(fileName)
	if err != nil {
		lgr.Printf("create: %v", err)
	}
	defer deferClose(lgr, f.Close)

	err = trace.Start(f)
	if err != nil {
		lgr.Printf("start: %v", err)
	}
	defer trace.Stop()

	in := make(chan int)

	go result(sum, in)

	generator(in)

}

func result(sum int, ch <-chan int) {
	for out := range ch {
		sum = sum + out
	}
	println(sum)
}

func generator(ch chan<- int) {
	var i int
	for {
		ch <- i
		i++
		if i == 12 {
			return
		}
	}

}

func deferClose(lgr *log.Logger, f func() error) {
	err := f()
	if err != nil {
		lgr.Printf("close: %v", err)
	}
}
<commit_msg>trace: add procesor<commit_after>package main

import (
	"log"
	"os"
	"runtime/trace"
)

const fileName = "trace.out"

var sum int

func main() {
	lgr := log.New(os.Stderr, "", 0)

	f, err := os.Create(fileName)
	if err != nil {
		lgr.Printf("create: %v", err)
	}
	defer deferClose(lgr, f.Close)

	err = trace.Start(f)
	if err != nil {
		lgr.Printf("start: %v", err)
	}
	defer trace.Stop()

	in := make(chan int)

	go procesor(sum, in)

	generator(in)
}

func procesor(sum int, ch <-chan int) {
	for out := range ch {
		sum = sum + out
	}
	println(sum)
}

func generator(ch chan<- int) {
	var i int
	for {
		ch <- i
		i++
		if i == 12 {
			return
		}
	}

}

func deferClose(lgr *log.Logger, f func() error) {
	err := f()
	if err != nil {
		lgr.Printf("close: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	"log"
	"os"
	"os/signal"
	"runtime/trace"
	"sync"
)

const fileName = "trace.out"

func main() {
	lgr := log.New(os.Stderr, "", 0)

	f, err := os.Create(fileName)
	if err != nil {
		lgr.Printf("create: %v", err)
	}
	defer deferClose(lgr, f.Close)

	err = trace.Start(f)
	if err != nil {
		lgr.Printf("start: %v", err)
	}
	defer trace.Stop()

	err = run()
	if err != nil {
		lgr.Printf("run: %v", err)
	}
}

func run() error {
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
	defer stop()

	var wg sync.WaitGroup
	wg.Add(2)

	numbers := make(chan int)

	go procesor(&wg, numbers)

	go generator(ctx, &wg, numbers)

	wg.Wait()

	err := ctx.Err()
	if errors.Is(err, context.Canceled) {
		return nil
	}

	return err
}

func procesor(wg *sync.WaitGroup, numbers <-chan int) {
	defer wg.Done()

	var last int
	for n := range numbers {
		last = n
	}

	println("procesor: ", last)
}

func generator(ctx context.Context, wg *sync.WaitGroup, numbers chan<- int) {
	defer wg.Done()

	var i int

	var done bool
	for !done {
		select {
		case <-ctx.Done():
			done = true
		default:
			i++
			numbers <- i
		}
	}

	close(numbers)
	println("\ngenerator: ", i)
}

func deferClose(lgr *log.Logger, f func() error) {
	err := f()
	if err != nil {
		lgr.Printf("close: %v", err)
	}
}
<commit_msg>trace: clean output<commit_after>package main

import (
	"context"
	"errors"
	"log"
	"os"
	"os/signal"
	"runtime/trace"
	"sync"
)

const fileName = "trace.out"

func main() {
	lgr := log.New(os.Stderr, "", 0)

	f, err := os.Create(fileName)
	if err != nil {
		lgr.Printf("create: %v", err)
	}
	defer deferClose(lgr, f.Close)

	err = trace.Start(f)
	if err != nil {
		lgr.Printf("start: %v", err)
	}
	defer trace.Stop()

	err = run()
	if err != nil {
		lgr.Printf("run: %v", err)
	}
}

func run() error {
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
	defer stop()

	var wg sync.WaitGroup
	wg.Add(2)

	numbers := make(chan int)

	go procesor(&wg, numbers)

	go generator(ctx, &wg, numbers)

	wg.Wait()

	err := ctx.Err()
	if errors.Is(err, context.Canceled) {
		return nil
	}

	return err
}

func procesor(wg *sync.WaitGroup, numbers <-chan int) {
	defer wg.Done()

	var last int
	for n := range numbers {
		last = n
	}

	println("procesor:\t", last)
}

func generator(ctx context.Context, wg *sync.WaitGroup, numbers chan<- int) {
	defer wg.Done()

	var i int

	var done bool
	for !done {
		select {
		case <-ctx.Done():
			done = true
		default:
			i++
			numbers <- i
		}
	}

	close(numbers)
	println("\ngenerator:\t", i)
}

func deferClose(lgr *log.Logger, f func() error) {
	err := f()
	if err != nil {
		lgr.Printf("close: %v", err)
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"html/template"
	"log"
	"net/http"
	"path/filepath"
)

// Catalog describes the set of catalogs that are available.
//
// This is used to separate consuming applications, i.e AtmelStudio70
type Catalog struct {
	Products []string
	template *template.Template
}

// Productslister can return a list of all known products
type Productslister interface {
	Products() []string
}

// NewCatalogHandler creates a new HTTP handler for the catalogs
func NewCatalogHandler(books Productslister, templateFolder string) *Catalog {

	products := books.Products()

	return &Catalog{
		Products: products,
		template: template.Must(template.ParseFiles(filepath.Join(templateFolder, "catalog.gohtml"))),
	}
}

// CatalogHandler handles the
func (c *Catalog) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	log.Printf("[catalog] Serving %d products", len(c.Products))
	if err := c.template.Execute(w, c.Products); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
<commit_msg>Line clean<commit_after>package handlers

import (
	"html/template"
	"log"
	"net/http"
	"path/filepath"
)

// Catalog describes the set of catalogs that are available.
//
// This is used to separate consuming applications, i.e AtmelStudio70
type Catalog struct {
	Products []string
	template *template.Template
}

// Productslister can return a list of all known products
type Productslister interface {
	Products() []string
}

// NewCatalogHandler creates a new HTTP handler for the catalogs
func NewCatalogHandler(books Productslister, templateFolder string) *Catalog {
	return &Catalog{
		Products: books.Products(),
		template: template.Must(template.ParseFiles(filepath.Join(templateFolder, "catalog.gohtml"))),
	}
}

// CatalogHandler handles the
func (c *Catalog) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	log.Printf("[catalog] Serving %d products", len(c.Products))
	if err := c.template.Execute(w, c.Products); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
<|endoftext|>