<commit_before>package main

import (
	"fmt"
	"time"

	"koding/db/mongodb"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

func init() {
	registerAnalytic(numberOfTwoWeekEngagedUsers)
}

func numberOfTwoWeekEngagedUsers() (string, int) {
	var identifier string = "number_of_two_week_engaged_users"
	var year, month, _ = time.Now().Date()
	var startDateOfMonth = time.Date(year, month, 1, 0, 0, 0, 0, currentTimeLocation)

	// 14 isn't always the middle of the month, but it's easier to assume for now
	var middleOfMonth = time.Date(year, month, 14, 0, 0, 0, 0, currentTimeLocation)

	var iterQuery = func(c *mgo.Collection) *mgo.Query {
		var query = c.Find(bson.M{
			"createdAt": bson.M{"$gte": startDateOfMonth, "$lte": middleOfMonth},
		})

		return query
	}

	var possibleEngagedUsers = map[string]bool{}

	var iter = mongodb.Iter("jSessionHistories", iterQuery)
	var result map[string]interface{}

	for iter.Next(&result) {
		var username = result["username"].(string)
		possibleEngagedUsers[username] = true
	}

	var err = mongodb.IterClose(iter)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("count of possibleEngagedUsers", len(possibleEngagedUsers))

	var possibleEngagedUsernames = []string{}
	for username, _ := range possibleEngagedUsers {
		possibleEngagedUsernames = append(possibleEngagedUsernames, username)
	}

	//----------------------------------------------------------
	// Second Query
	//----------------------------------------------------------

	var secondIterQuery = func(c *mgo.Collection) *mgo.Query {
		var query = c.Find(bson.M{
			"username":  bson.M{"$in": possibleEngagedUsernames},
			"createdAt": bson.M{"$gt": middleOfMonth},
		})

		return query
	}

	var engagedUsers = map[string]bool{}

	var secondIter = mongodb.Iter("jSessionHistories", secondIterQuery)
	var secondResult map[string]interface{}

	for secondIter.Next(&secondResult) {
		var username = result["username"].(string)
		engagedUsers[username] = true
	}

	err = mongodb.IterClose(iter)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("count of engagedUsers", len(engagedUsers))

	var engagedUsernames = []string{}
	for username, _ := range engagedUsers {
		engagedUsernames = append(engagedUsernames, username)
	}

	var engagedUsernamesLength = len(engagedUsernames)

	return identifier, engagedUsernamesLength
}
<commit_msg>graphitefeeder: use 15 instead of 14, more closer to middle<commit_after>package main

import (
	"fmt"
	"time"

	"koding/db/mongodb"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

func init() {
	registerAnalytic(numberOfTwoWeekEngagedUsers)
}

func numberOfTwoWeekEngagedUsers() (string, int) {
	var identifier string = "number_of_two_week_engaged_users"
	var year, month, _ = time.Now().Date()
	var startDateOfMonth = time.Date(year, month, 1, 0, 0, 0, 0, currentTimeLocation)

	// 14 isn't always the middle of the month, but it's easier to assume for now
	var middleOfMonth = time.Date(year, month, 15, 0, 0, 0, 0, currentTimeLocation)

	var iterQuery = func(c *mgo.Collection) *mgo.Query {
		var query = c.Find(bson.M{
			"createdAt": bson.M{"$gte": startDateOfMonth, "$lte": middleOfMonth},
		})

		return query
	}

	var possibleEngagedUsers = map[string]bool{}

	var iter = mongodb.Iter("jSessionHistories", iterQuery)
	var result map[string]interface{}

	for iter.Next(&result) {
		var username = result["username"].(string)
		possibleEngagedUsers[username] = true
	}

	var err = mongodb.IterClose(iter)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("count of possibleEngagedUsers", len(possibleEngagedUsers))

	var possibleEngagedUsernames = []string{}
	for username, _ := range possibleEngagedUsers {
		possibleEngagedUsernames = append(possibleEngagedUsernames, username)
	}

	//----------------------------------------------------------
	// Second Query
	//----------------------------------------------------------

	var secondIterQuery = func(c *mgo.Collection) *mgo.Query {
		var query = c.Find(bson.M{
			"username":  bson.M{"$in": possibleEngagedUsernames},
			"createdAt": bson.M{"$gt": middleOfMonth},
		})

		return query
	}

	var engagedUsers = map[string]bool{}

	var secondIter = mongodb.Iter("jSessionHistories", secondIterQuery)
	var secondResult map[string]interface{}

	for secondIter.Next(&secondResult) {
		var username = result["username"].(string)
		engagedUsers[username] = true
	}

	err = mongodb.IterClose(iter)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("count of engagedUsers", len(engagedUsers))

	var engagedUsernames = []string{}
	for username, _ := range engagedUsers {
		engagedUsernames = append(engagedUsernames, username)
	}

	var engagedUsernamesLength = len(engagedUsernames)

	return identifier, engagedUsernamesLength
}
<|endoftext|>


<commit_before>package paypal

import (
	"errors"
	"socialapi/workers/payment/paymenterrors"
	"socialapi/workers/payment/paymentmodels"
	"socialapi/workers/payment/stripe"
	"strings"

	"github.com/koding/paypal"
)

func SubscribeWithPlan(token, accId, planTitle, planInterval string) error {
	plan, err := stripe.FindPlanByTitleAndInterval(planTitle, planInterval)
	if err != nil {
		return err
	}

	return _subscribe(token, accId, plan)
}

func Subscribe(token, accId string) error {
	plan, err := FindPlanFromToken(token)
	if err != nil {
		return err
	}

	return _subscribe(token, accId, plan)
}

func _subscribe(token, accId string, plan *paymentmodels.Plan) error {
	customer, err := FindCustomerByOldId(accId)
	if err != nil && err != paymenterrors.ErrCustomerNotFound {
		return err
	}

	var subscription *paymentmodels.Subscription
	if customer != nil {
		subscription, err = customer.FindActiveSubscription()
		if err != nil {
			return err
		}
	}

	status, err := checkStatus(customer, err, plan)
	if err != nil {
		return err
	}

	switch status {
	case AlreadySubscribedToPlan:
		err = paymenterrors.ErrCustomerAlreadySubscribedToPlan
	case NewSubscription:
		err = handleNewSubscription(token, accId, plan)
	case DowngradeToFreePlan:
		err = handleCancelation(customer, subscription)
	case Downgrade:
		err = handleDowngrade(customer, plan, subscription)
	case Upgrade:
		err = handleUpgrade(token, customer, plan)
	default:
		// user should never come here
	}

	return err
}

func handleNewSubscription(token, accId string, plan *paymentmodels.Plan) error {
	customer, err := CreateCustomer(accId)
	if err != nil {
		return err
	}

	return CreateSubscription(token, plan, customer)
}

func handleCancelation(customer *paymentmodels.Customer, subscription *paymentmodels.Subscription) error {
	client, err := Client()
	if err != nil {
		return err
	}

	response, err := client.ManageRecurringPaymentsProfileStatus(
		customer.ProviderCustomerId, paypal.Cancel,
	)
	err = handlePaypalErr(response, err)
	if err != nil {
		return err
	}

	return subscription.Cancel()
}

func handleDowngrade(customer *paymentmodels.Customer, plan *paymentmodels.Plan, subscription *paymentmodels.Subscription) error {
	params := map[string]string{
		"AMT": normalizeAmount(plan.AmountInCents),
		"L_PAYMENTREQUEST_0_NAME0": goodName(plan),
	}

	client, err := Client()
	if err != nil {
		return err
	}

	resp, err := client.UpdateRecurringPaymentsProfile(customer.ProviderCustomerId, params)
	err = handlePaypalErr(resp, err)
	if err != nil {
		return err
	}

	return subscription.UpdatePlan(plan.Id, plan.AmountInCents)
}

func handleUpgrade(token string, customer *paymentmodels.Customer, plan *paymentmodels.Plan) error {
	return errors.New("upgrades are disabled for paypal")
}

func parsePlanInfo(str string) (string, string) {
	split := strings.Split(str, "-")
	planTitle, planInterval := split[0], split[1]

	return planTitle, planInterval
}
<commit_msg>payments: don't use _ in func names<commit_after>package paypal

import (
	"errors"
	"socialapi/workers/payment/paymenterrors"
	"socialapi/workers/payment/paymentmodels"
	"socialapi/workers/payment/stripe"
	"strings"

	"github.com/koding/paypal"
)

func SubscribeWithPlan(token, accId, planTitle, planInterval string) error {
	plan, err := stripe.FindPlanByTitleAndInterval(planTitle, planInterval)
	if err != nil {
		return err
	}

	return subscribe(token, accId, plan)
}

func Subscribe(token, accId string) error {
	plan, err := FindPlanFromToken(token)
	if err != nil {
		return err
	}

	return subscribe(token, accId, plan)
}

func subscribe(token, accId string, plan *paymentmodels.Plan) error {
	customer, err := FindCustomerByOldId(accId)
	if err != nil && err != paymenterrors.ErrCustomerNotFound {
		return err
	}

	var subscription *paymentmodels.Subscription
	if customer != nil {
		subscription, err = customer.FindActiveSubscription()
		if err != nil {
			return err
		}
	}

	status, err := checkStatus(customer, err, plan)
	if err != nil {
		return err
	}

	switch status {
	case AlreadySubscribedToPlan:
		err = paymenterrors.ErrCustomerAlreadySubscribedToPlan
	case NewSubscription:
		err = handleNewSubscription(token, accId, plan)
	case DowngradeToFreePlan:
		err = handleCancelation(customer, subscription)
	case Downgrade:
		err = handleDowngrade(customer, plan, subscription)
	case Upgrade:
		err = handleUpgrade(token, customer, plan)
	default:
		// user should never come here
	}

	return err
}

func handleNewSubscription(token, accId string, plan *paymentmodels.Plan) error {
	customer, err := CreateCustomer(accId)
	if err != nil {
		return err
	}

	return CreateSubscription(token, plan, customer)
}

func handleCancelation(customer *paymentmodels.Customer, subscription *paymentmodels.Subscription) error {
	client, err := Client()
	if err != nil {
		return err
	}

	response, err := client.ManageRecurringPaymentsProfileStatus(
		customer.ProviderCustomerId, paypal.Cancel,
	)
	err = handlePaypalErr(response, err)
	if err != nil {
		return err
	}

	return subscription.Cancel()
}

func handleDowngrade(customer *paymentmodels.Customer, plan *paymentmodels.Plan, subscription *paymentmodels.Subscription) error {
	params := map[string]string{
		"AMT": normalizeAmount(plan.AmountInCents),
		"L_PAYMENTREQUEST_0_NAME0": goodName(plan),
	}

	client, err := Client()
	if err != nil {
		return err
	}

	resp, err := client.UpdateRecurringPaymentsProfile(customer.ProviderCustomerId, params)
	err = handlePaypalErr(resp, err)
	if err != nil {
		return err
	}

	return subscription.UpdatePlan(plan.Id, plan.AmountInCents)
}

func handleUpgrade(token string, customer *paymentmodels.Customer, plan *paymentmodels.Plan) error {
	return errors.New("upgrades are disabled for paypal")
}

func parsePlanInfo(str string) (string, string) {
	split := strings.Split(str, "-")
	planTitle, planInterval := split[0], split[1]

	return planTitle, planInterval
}
<|endoftext|>


<commit_before>// Copyright 2011 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 build gathers information about Go packages.
//
// Go Path
//
// The Go path is a list of directory trees containing Go source code.
// It is consulted to resolve imports that cannot be found in the standard
// Go tree.  The default path is the value of the GOPATH environment
// variable, interpreted as a path list appropriate to the operating system
// (on Unix, the variable is a colon-separated string;
// on Windows, a semicolon-separated string;
// on Plan 9, a list).
//
// Each directory listed in the Go path must have a prescribed structure:
//
// The src/ directory holds source code.  The path below 'src' determines
// the import path or executable name.
//
// The pkg/ directory holds installed package objects.
// As in the Go tree, each target operating system and
// architecture pair has its own subdirectory of pkg
// (pkg/GOOS_GOARCH).
//
// If DIR is a directory listed in the Go path, a package with
// source in DIR/src/foo/bar can be imported as "foo/bar" and
// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
//
// The bin/ directory holds compiled commands.
// Each command is named for its source directory, but only
// using the final element, not the entire path.  That is, the
// command with source in DIR/src/foo/quux is installed into
// DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
// so that you can add DIR/bin to your PATH to get at the
// installed commands.
//
// Here's an example directory layout:
//
//	GOPATH=/home/user/gocode
//
//	/home/user/gocode/
//	    src/
//	        foo/
//	            bar/               (go code in package bar)
//	                x.go
//	            quux/              (go code in package main)
//	                y.go
//	    bin/
//	        quux                   (installed command)
//	    pkg/
//	        linux_amd64/
//	            foo/
//	                bar.a          (installed package object)
//
// Build Constraints
//
// A build constraint is a line comment beginning with the directive +build
// that lists the conditions under which a file should be included in the package.
// Constraints may appear in any kind of source file (not just Go), but
// they must be appear near the top of the file, preceded
// only by blank lines and other line comments.
//
// A build constraint is evaluated as the OR of space-separated options;
// each option evaluates as the AND of its comma-separated terms;
// and each term is an alphanumeric word or, preceded by !, its negation.
// That is, the build constraint:
//
//	// +build linux,386 darwin,!cgo
//
// corresponds to the boolean formula:
//
//	(linux AND 386) OR (darwin AND (NOT cgo))
//
// During a particular build, the following words are satisfied:
//
//	- the target operating system, as spelled by runtime.GOOS
//	- the target architecture, as spelled by runtime.GOARCH
//	- "cgo", if ctxt.CgoEnabled is true
//	- any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,
// matches *_GOOS, *_GOARCH, or *_GOOS_GOARCH for any known operating
// system and architecture values, then the file is considered to have an implicit
// build constraint requiring those terms.
//
// To keep a file from being considered for the build:
//
//	// +build ignore
//
// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
//
// To build a file only when using cgo, and only on Linux and OS X:
//
//	// +build linux,cgo darwin,cgo
//
// Such a file is usually paired with another file implementing the
// default functionality for other systems, which in this case would
// carry the constraint:
//
//	// +build !linux !darwin !cgo
//
// Naming a file dns_windows.go will cause it to be included only when
// building the package for Windows; similarly, math_386.s will be included
// only when building the package for 32-bit x86.
//
package build
<commit_msg>go/build: fix boolean negation<commit_after>// Copyright 2011 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 build gathers information about Go packages.
//
// Go Path
//
// The Go path is a list of directory trees containing Go source code.
// It is consulted to resolve imports that cannot be found in the standard
// Go tree.  The default path is the value of the GOPATH environment
// variable, interpreted as a path list appropriate to the operating system
// (on Unix, the variable is a colon-separated string;
// on Windows, a semicolon-separated string;
// on Plan 9, a list).
//
// Each directory listed in the Go path must have a prescribed structure:
//
// The src/ directory holds source code.  The path below 'src' determines
// the import path or executable name.
//
// The pkg/ directory holds installed package objects.
// As in the Go tree, each target operating system and
// architecture pair has its own subdirectory of pkg
// (pkg/GOOS_GOARCH).
//
// If DIR is a directory listed in the Go path, a package with
// source in DIR/src/foo/bar can be imported as "foo/bar" and
// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
//
// The bin/ directory holds compiled commands.
// Each command is named for its source directory, but only
// using the final element, not the entire path.  That is, the
// command with source in DIR/src/foo/quux is installed into
// DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
// so that you can add DIR/bin to your PATH to get at the
// installed commands.
//
// Here's an example directory layout:
//
//	GOPATH=/home/user/gocode
//
//	/home/user/gocode/
//	    src/
//	        foo/
//	            bar/               (go code in package bar)
//	                x.go
//	            quux/              (go code in package main)
//	                y.go
//	    bin/
//	        quux                   (installed command)
//	    pkg/
//	        linux_amd64/
//	            foo/
//	                bar.a          (installed package object)
//
// Build Constraints
//
// A build constraint is a line comment beginning with the directive +build
// that lists the conditions under which a file should be included in the package.
// Constraints may appear in any kind of source file (not just Go), but
// they must be appear near the top of the file, preceded
// only by blank lines and other line comments.
//
// A build constraint is evaluated as the OR of space-separated options;
// each option evaluates as the AND of its comma-separated terms;
// and each term is an alphanumeric word or, preceded by !, its negation.
// That is, the build constraint:
//
//	// +build linux,386 darwin,!cgo
//
// corresponds to the boolean formula:
//
//	(linux AND 386) OR (darwin AND (NOT cgo))
//
// During a particular build, the following words are satisfied:
//
//	- the target operating system, as spelled by runtime.GOOS
//	- the target architecture, as spelled by runtime.GOARCH
//	- "cgo", if ctxt.CgoEnabled is true
//	- any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,
// matches *_GOOS, *_GOARCH, or *_GOOS_GOARCH for any known operating
// system and architecture values, then the file is considered to have an implicit
// build constraint requiring those terms.
//
// To keep a file from being considered for the build:
//
//	// +build ignore
//
// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
//
// To build a file only when using cgo, and only on Linux and OS X:
//
//	// +build linux,cgo darwin,cgo
//
// Such a file is usually paired with another file implementing the
// default functionality for other systems, which in this case would
// carry the constraint:
//
//	// +build !linux,!darwin !cgo
//
// Naming a file dns_windows.go will cause it to be included only when
// building the package for Windows; similarly, math_386.s will be included
// only when building the package for 32-bit x86.
//
package build
<|endoftext|>


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

package http_test

import (
	"fmt"
	. "http"
	"http/httptest"
	"io/ioutil"
	"os"
	"testing"
)

const (
	testFile       = "testdata/file"
	testFileLength = 11
)

var ServeFileRangeTests = []struct {
	start, end int
	r          string
	code       int
}{
	{0, testFileLength, "", StatusOK},
	{0, 5, "0-4", StatusPartialContent},
	{2, testFileLength, "2-", StatusPartialContent},
	{testFileLength - 5, testFileLength, "-5", StatusPartialContent},
	{3, 8, "3-7", StatusPartialContent},
	{0, 0, "20-", StatusRequestedRangeNotSatisfiable},
}

func TestServeFile(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()

	var err os.Error

	file, err := ioutil.ReadFile(testFile)
	if err != nil {
		t.Fatal("reading file:", err)
	}

	// set up the Request (re-used for all tests)
	var req Request
	req.Header = make(Header)
	if req.URL, err = ParseURL(ts.URL); err != nil {
		t.Fatal("ParseURL:", err)
	}
	req.Method = "GET"

	// straight GET
	_, body := getBody(t, req)
	if !equal(body, file) {
		t.Fatalf("body mismatch: got %q, want %q", body, file)
	}

	// Range tests
	for _, rt := range ServeFileRangeTests {
		req.Header.Set("Range", "bytes="+rt.r)
		if rt.r == "" {
			req.Header["Range"] = nil
		}
		r, body := getBody(t, req)
		if r.StatusCode != rt.code {
			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
		}
		if rt.code == StatusRequestedRangeNotSatisfiable {
			continue
		}
		h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
		if rt.r == "" {
			h = ""
		}
		cr := r.Header.Get("Content-Range")
		if cr != h {
			t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
		}
		if !equal(body, file[rt.start:rt.end]) {
			t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
		}
	}
}

type testFileSystem struct {
	open func(name string) (File, os.Error)
}

func (fs *testFileSystem) Open(name string) (File, os.Error) {
	return fs.open(name)
}

func TestFileServerCleans(t *testing.T) {
	ch := make(chan string, 1)
	fs := FileServer(&testFileSystem{func(name string) (File, os.Error) {
		ch <- name
		return nil, os.ENOENT
	}})
	tests := []struct {
		reqPath, openArg string
	}{
		{"/foo.txt", "/foo.txt"},
		{"//foo.txt", "/foo.txt"},
		{"/../foo.txt", "/foo.txt"},
	}
	req, _ := NewRequest("GET", "http://example.com", nil)
	for n, test := range tests {
		rec := httptest.NewRecorder()
		req.URL.Path = test.reqPath
		fs.ServeHTTP(rec, req)
		if got := <-ch; got != test.openArg {
			t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
		}
	}
}

func TestDirJoin(t *testing.T) {
	wfi, err := os.Stat("/etc/hosts")
	if err != nil {
		t.Logf("skipping test; no /etc/hosts file")
		return
	}
	test := func(d Dir, name string) {
		f, err := d.Open(name)
		if err != nil {
			t.Fatalf("open of %s: %v", name, err)
		}
		defer f.Close()
		gfi, err := f.Stat()
		if err != nil {
			t.Fatalf("stat of %s: %v", err)
		}
		if gfi.Ino != wfi.Ino {
			t.Errorf("%s got different inode")
		}
	}
	test(Dir("/etc/"), "/hosts")
	test(Dir("/etc/"), "hosts")
	test(Dir("/etc/"), "../../../../hosts")
	test(Dir("/etc"), "/hosts")
	test(Dir("/etc"), "hosts")
	test(Dir("/etc"), "../../../../hosts")

	// Not really directories, but since we use this trick in
	// ServeFile, test it:
	test(Dir("/etc/hosts"), "")
	test(Dir("/etc/hosts"), "/")
	test(Dir("/etc/hosts"), "../")
}

func TestServeFileContentType(t *testing.T) {
	const ctype = "icecream/chocolate"
	override := false
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		if override {
			w.Header().Set("Content-Type", ctype)
		}
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	get := func(want string) {
		resp, err := Get(ts.URL)
		if err != nil {
			t.Fatal(err)
		}
		if h := resp.Header.Get("Content-Type"); h != want {
			t.Errorf("Content-Type mismatch: got %d, want %d", h, want)
		}
	}
	get("text/plain; charset=utf-8")
	override = true
	get(ctype)
}

func TestServeFileMimeType(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/style.css")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	want := "text/css"
	if h := resp.Header.Get("Content-Type"); h != want {
		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
	}
}

func TestServeFileWithContentEncoding(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		w.Header().Set("Content-Encoding", "foo")
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	if g, e := resp.ContentLength, int64(-1); g != e {
		t.Errorf("Content-Length mismatch: got %q, want %q", g, e)
	}
}

func getBody(t *testing.T, req Request) (*Response, []byte) {
	r, err := DefaultClient.Do(&req)
	if err != nil {
		t.Fatal(req.URL.String(), "send:", err)
	}
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		t.Fatal("reading Body:", err)
	}
	return r, b
}

func equal(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<commit_msg>fix build from e904b6784768 breakage<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http_test

import (
	"fmt"
	. "http"
	"http/httptest"
	"io/ioutil"
	"os"
	"testing"
)

const (
	testFile       = "testdata/file"
	testFileLength = 11
)

var ServeFileRangeTests = []struct {
	start, end int
	r          string
	code       int
}{
	{0, testFileLength, "", StatusOK},
	{0, 5, "0-4", StatusPartialContent},
	{2, testFileLength, "2-", StatusPartialContent},
	{testFileLength - 5, testFileLength, "-5", StatusPartialContent},
	{3, 8, "3-7", StatusPartialContent},
	{0, 0, "20-", StatusRequestedRangeNotSatisfiable},
}

func TestServeFile(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()

	var err os.Error

	file, err := ioutil.ReadFile(testFile)
	if err != nil {
		t.Fatal("reading file:", err)
	}

	// set up the Request (re-used for all tests)
	var req Request
	req.Header = make(Header)
	if req.URL, err = ParseURL(ts.URL); err != nil {
		t.Fatal("ParseURL:", err)
	}
	req.Method = "GET"

	// straight GET
	_, body := getBody(t, req)
	if !equal(body, file) {
		t.Fatalf("body mismatch: got %q, want %q", body, file)
	}

	// Range tests
	for _, rt := range ServeFileRangeTests {
		req.Header.Set("Range", "bytes="+rt.r)
		if rt.r == "" {
			req.Header["Range"] = nil
		}
		r, body := getBody(t, req)
		if r.StatusCode != rt.code {
			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
		}
		if rt.code == StatusRequestedRangeNotSatisfiable {
			continue
		}
		h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
		if rt.r == "" {
			h = ""
		}
		cr := r.Header.Get("Content-Range")
		if cr != h {
			t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
		}
		if !equal(body, file[rt.start:rt.end]) {
			t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
		}
	}
}

type testFileSystem struct {
	open func(name string) (File, os.Error)
}

func (fs *testFileSystem) Open(name string) (File, os.Error) {
	return fs.open(name)
}

func TestFileServerCleans(t *testing.T) {
	ch := make(chan string, 1)
	fs := FileServer(&testFileSystem{func(name string) (File, os.Error) {
		ch <- name
		return nil, os.ENOENT
	}})
	tests := []struct {
		reqPath, openArg string
	}{
		{"/foo.txt", "/foo.txt"},
		{"//foo.txt", "/foo.txt"},
		{"/../foo.txt", "/foo.txt"},
	}
	req, _ := NewRequest("GET", "http://example.com", nil)
	for n, test := range tests {
		rec := httptest.NewRecorder()
		req.URL.Path = test.reqPath
		fs.ServeHTTP(rec, req)
		if got := <-ch; got != test.openArg {
			t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
		}
	}
}

func TestDirJoin(t *testing.T) {
	wfi, err := os.Stat("/etc/hosts")
	if err != nil {
		t.Logf("skipping test; no /etc/hosts file")
		return
	}
	test := func(d Dir, name string) {
		f, err := d.Open(name)
		if err != nil {
			t.Fatalf("open of %s: %v", name, err)
		}
		defer f.Close()
		gfi, err := f.Stat()
		if err != nil {
			t.Fatalf("stat of %s: %v", err)
		}
		if gfi.Ino != wfi.Ino {
			t.Errorf("%s got different inode")
		}
	}
	test(Dir("/etc/"), "/hosts")
	test(Dir("/etc/"), "hosts")
	test(Dir("/etc/"), "../../../../hosts")
	test(Dir("/etc"), "/hosts")
	test(Dir("/etc"), "hosts")
	test(Dir("/etc"), "../../../../hosts")

	// Not really directories, but since we use this trick in
	// ServeFile, test it:
	test(Dir("/etc/hosts"), "")
	test(Dir("/etc/hosts"), "/")
	test(Dir("/etc/hosts"), "../")
}

func TestServeFileContentType(t *testing.T) {
	const ctype = "icecream/chocolate"
	override := false
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		if override {
			w.Header().Set("Content-Type", ctype)
		}
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	get := func(want string) {
		resp, err := Get(ts.URL)
		if err != nil {
			t.Fatal(err)
		}
		if h := resp.Header.Get("Content-Type"); h != want {
			t.Errorf("Content-Type mismatch: got %d, want %d", h, want)
		}
	}
	get("text/plain; charset=utf-8")
	override = true
	get(ctype)
}

func TestServeFileMimeType(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/style.css")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	want := "text/css; charset=utf-8"
	if h := resp.Header.Get("Content-Type"); h != want {
		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
	}
}

func TestServeFileWithContentEncoding(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		w.Header().Set("Content-Encoding", "foo")
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	if g, e := resp.ContentLength, int64(-1); g != e {
		t.Errorf("Content-Length mismatch: got %q, want %q", g, e)
	}
}

func getBody(t *testing.T, req Request) (*Response, []byte) {
	r, err := DefaultClient.Do(&req)
	if err != nil {
		t.Fatal(req.URL.String(), "send:", err)
	}
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		t.Fatal("reading Body:", err)
	}
	return r, b
}

func equal(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>/*
Given an array of integers, find if the array contains any duplicates.

Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

Example 1:

Input: [1,2,3,1]
Output: true
Example 2:

Input: [1,2,3,4]
Output: false
Example 3:

Input: [1,1,1,3,3,4,3,2,4,2]
Output: true
*/

package main

import (
	"fmt"
	"sort"
	"math/rand"
	"time"
)

func main()  {
	// tests := [][]int{{}, {1},{1,2,3,1}, {1,2,3,4}, {1,1,1,3,3,4,3,2,4,2}}

	// for _, test := range tests {
	// 	fmt.Println(test, containsDuplicate2(test))
	// }

	bigArray := []int{}
	for i := 0; i < 1000000; i++ {
		bigArray = append(bigArray, rand.Intn(1000))
	}

	fmt.Println("Running sort-based function..")
	start1 := time.Now()
	fmt.Println(containsDuplicate1(bigArray))
	end1 := time.Now()
	fmt.Println("Elapsed time(ms):", end1.Sub(start1))

	fmt.Println("\nRunning map-based function..")
	start2 := time.Now()
	fmt.Println(containsDuplicate2(bigArray))
	end2 := time.Now()
	fmt.Println("Elapsed time(ms):", end2.Sub(start2))
}

func containsDuplicate1(nums []int) bool {
	sort.Ints(nums)
	for i := 0; i <= len(nums)-2; i++ {
		if nums[i] == nums[i+1] {
			return true
		}
	}

	return false
}

func containsDuplicate2(nums []int) bool {
	m := map[int]int{}

	for _, i := range nums {
		_, exists := m[i]
		if exists {
			return true
		} else {
			m[i] = 1
		}
	}

	return false
}
<commit_msg>Add commentary<commit_after>/*
Given an array of integers, find if the array contains any duplicates.

Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

Example 1:

Input: [1,2,3,1]
Output: true
Example 2:

Input: [1,2,3,4]
Output: false
Example 3:

Input: [1,1,1,3,3,4,3,2,4,2]
Output: true
*/

package main

import (
	"fmt"
	"sort"
	"math/rand"
	"time"
)

func main()  {
	// tests := [][]int{{}, {1},{1,2,3,1}, {1,2,3,4}, {1,1,1,3,3,4,3,2,4,2}}

	// for _, test := range tests {
	// 	fmt.Println(test, containsDuplicate2(test))
	// }

	// test function performances against large input
	bigArray := []int{}
	for i := 0; i < 1000000; i++ {
		bigArray = append(bigArray, rand.Intn(1000))
	}

	fmt.Println("Running sort-based function..")
	start1 := time.Now()
	fmt.Println(containsDuplicate1(bigArray))
	end1 := time.Now()
	fmt.Println("Elapsed time(ms):", end1.Sub(start1))

	fmt.Println("\nRunning map-based function..")
	start2 := time.Now()
	fmt.Println(containsDuplicate2(bigArray))
	end2 := time.Now()
	fmt.Println("Elapsed time(ms):", end2.Sub(start2))
}

// sort-based approach (space efficient)
func containsDuplicate1(nums []int) bool {
	// sort input
	sort.Ints(nums)

	// check for consequent duplicate elements
	for i := 0; i <= len(nums)-2; i++ {
		if nums[i] == nums[i+1] {
			return true
		}
	}

	return false
}

// map-based approach (runtime efficient)
func containsDuplicate2(nums []int) bool {
	// declare map to store element counts
	m := map[int]int{}

	// per element in input
	for _, i := range nums {
		// check if in map already, if yes: duplicate
		_, exists := m[i]
		if exists {
			return true
		} else {
			// if not in map, insert
			m[i] = 1
		}
	}

	return false
}
<|endoftext|>


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

package http_test

import (
	"fmt"
	. "http"
	"http/httptest"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

const (
	testFile       = "testdata/file"
	testFileLength = 11
)

var ServeFileRangeTests = []struct {
	start, end int
	r          string
	code       int
}{
	{0, testFileLength, "", StatusOK},
	{0, 5, "0-4", StatusPartialContent},
	{2, testFileLength, "2-", StatusPartialContent},
	{testFileLength - 5, testFileLength, "-5", StatusPartialContent},
	{3, 8, "3-7", StatusPartialContent},
	{0, 0, "20-", StatusRequestedRangeNotSatisfiable},
}

func TestServeFile(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()

	var err os.Error

	file, err := ioutil.ReadFile(testFile)
	if err != nil {
		t.Fatal("reading file:", err)
	}

	// set up the Request (re-used for all tests)
	var req Request
	req.Header = make(Header)
	if req.URL, err = ParseURL(ts.URL); err != nil {
		t.Fatal("ParseURL:", err)
	}
	req.Method = "GET"

	// straight GET
	_, body := getBody(t, req)
	if !equal(body, file) {
		t.Fatalf("body mismatch: got %q, want %q", body, file)
	}

	// Range tests
	for _, rt := range ServeFileRangeTests {
		req.Header.Set("Range", "bytes="+rt.r)
		if rt.r == "" {
			req.Header["Range"] = nil
		}
		r, body := getBody(t, req)
		if r.StatusCode != rt.code {
			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
		}
		if rt.code == StatusRequestedRangeNotSatisfiable {
			continue
		}
		h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
		if rt.r == "" {
			h = ""
		}
		cr := r.Header.Get("Content-Range")
		if cr != h {
			t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
		}
		if !equal(body, file[rt.start:rt.end]) {
			t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
		}
	}
}

type testFileSystem struct {
	open func(name string) (File, os.Error)
}

func (fs *testFileSystem) Open(name string) (File, os.Error) {
	return fs.open(name)
}

func TestFileServerCleans(t *testing.T) {
	ch := make(chan string, 1)
	fs := FileServer(&testFileSystem{func(name string) (File, os.Error) {
		ch <- name
		return nil, os.ENOENT
	}})
	tests := []struct {
		reqPath, openArg string
	}{
		{"/foo.txt", "/foo.txt"},
		{"//foo.txt", "/foo.txt"},
		{"/../foo.txt", "/foo.txt"},
	}
	req, _ := NewRequest("GET", "http://example.com", nil)
	for n, test := range tests {
		rec := httptest.NewRecorder()
		req.URL.Path = test.reqPath
		fs.ServeHTTP(rec, req)
		if got := <-ch; got != test.openArg {
			t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
		}
	}
}

func TestFileServerImplicitLeadingSlash(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "")
	if err != nil {
		t.Fatalf("TempDir: %v", err)
	}
	defer os.RemoveAll(tempDir)
	if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
		t.Fatalf("WriteFile: %v", err)
	}
	ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir))))
	defer ts.Close()
	get := func(suffix string) string {
		res, err := Get(ts.URL + suffix)
		if err != nil {
			t.Fatalf("Get %s: %v", suffix, err)
		}
		b, err := ioutil.ReadAll(res.Body)
		if err != nil {
			t.Fatalf("ReadAll %s: %v", suffix, err)
		}
		return string(b)
	}
	if s := get("/bar/"); !strings.Contains(s, ">foo.txt<") {
		t.Logf("expected a directory listing with foo.txt, got %q", s)
	}
	if s := get("/bar/foo.txt"); s != "Hello world" {
		t.Logf("expected %q, got %q", "Hello world", s)
	}
}

func TestDirJoin(t *testing.T) {
	wfi, err := os.Stat("/etc/hosts")
	if err != nil {
		t.Logf("skipping test; no /etc/hosts file")
		return
	}
	test := func(d Dir, name string) {
		f, err := d.Open(name)
		if err != nil {
			t.Fatalf("open of %s: %v", name, err)
		}
		defer f.Close()
		gfi, err := f.Stat()
		if err != nil {
			t.Fatalf("stat of %s: %v", err)
		}
		if gfi.Ino != wfi.Ino {
			t.Errorf("%s got different inode")
		}
	}
	test(Dir("/etc/"), "/hosts")
	test(Dir("/etc/"), "hosts")
	test(Dir("/etc/"), "../../../../hosts")
	test(Dir("/etc"), "/hosts")
	test(Dir("/etc"), "hosts")
	test(Dir("/etc"), "../../../../hosts")

	// Not really directories, but since we use this trick in
	// ServeFile, test it:
	test(Dir("/etc/hosts"), "")
	test(Dir("/etc/hosts"), "/")
	test(Dir("/etc/hosts"), "../")
}

func TestServeFileContentType(t *testing.T) {
	const ctype = "icecream/chocolate"
	override := false
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		if override {
			w.Header().Set("Content-Type", ctype)
		}
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	get := func(want string) {
		resp, err := Get(ts.URL)
		if err != nil {
			t.Fatal(err)
		}
		if h := resp.Header.Get("Content-Type"); h != want {
			t.Errorf("Content-Type mismatch: got %d, want %d", h, want)
		}
	}
	get("text/plain; charset=utf-8")
	override = true
	get(ctype)
}

func TestServeFileMimeType(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/style.css")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	want := "text/css; charset=utf-8"
	if h := resp.Header.Get("Content-Type"); h != want {
		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
	}
}

func TestServeFileWithContentEncoding(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		w.Header().Set("Content-Encoding", "foo")
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	if g, e := resp.ContentLength, int64(-1); g != e {
		t.Errorf("Content-Length mismatch: got %q, want %q", g, e)
	}
}

func getBody(t *testing.T, req Request) (*Response, []byte) {
	r, err := DefaultClient.Do(&req)
	if err != nil {
		t.Fatal(req.URL.String(), "send:", err)
	}
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		t.Fatal("reading Body:", err)
	}
	return r, b
}

func equal(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<commit_msg>pkg/http: fix a couple of error messages<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http_test

import (
	"fmt"
	. "http"
	"http/httptest"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

const (
	testFile       = "testdata/file"
	testFileLength = 11
)

var ServeFileRangeTests = []struct {
	start, end int
	r          string
	code       int
}{
	{0, testFileLength, "", StatusOK},
	{0, 5, "0-4", StatusPartialContent},
	{2, testFileLength, "2-", StatusPartialContent},
	{testFileLength - 5, testFileLength, "-5", StatusPartialContent},
	{3, 8, "3-7", StatusPartialContent},
	{0, 0, "20-", StatusRequestedRangeNotSatisfiable},
}

func TestServeFile(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()

	var err os.Error

	file, err := ioutil.ReadFile(testFile)
	if err != nil {
		t.Fatal("reading file:", err)
	}

	// set up the Request (re-used for all tests)
	var req Request
	req.Header = make(Header)
	if req.URL, err = ParseURL(ts.URL); err != nil {
		t.Fatal("ParseURL:", err)
	}
	req.Method = "GET"

	// straight GET
	_, body := getBody(t, req)
	if !equal(body, file) {
		t.Fatalf("body mismatch: got %q, want %q", body, file)
	}

	// Range tests
	for _, rt := range ServeFileRangeTests {
		req.Header.Set("Range", "bytes="+rt.r)
		if rt.r == "" {
			req.Header["Range"] = nil
		}
		r, body := getBody(t, req)
		if r.StatusCode != rt.code {
			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
		}
		if rt.code == StatusRequestedRangeNotSatisfiable {
			continue
		}
		h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
		if rt.r == "" {
			h = ""
		}
		cr := r.Header.Get("Content-Range")
		if cr != h {
			t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
		}
		if !equal(body, file[rt.start:rt.end]) {
			t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
		}
	}
}

type testFileSystem struct {
	open func(name string) (File, os.Error)
}

func (fs *testFileSystem) Open(name string) (File, os.Error) {
	return fs.open(name)
}

func TestFileServerCleans(t *testing.T) {
	ch := make(chan string, 1)
	fs := FileServer(&testFileSystem{func(name string) (File, os.Error) {
		ch <- name
		return nil, os.ENOENT
	}})
	tests := []struct {
		reqPath, openArg string
	}{
		{"/foo.txt", "/foo.txt"},
		{"//foo.txt", "/foo.txt"},
		{"/../foo.txt", "/foo.txt"},
	}
	req, _ := NewRequest("GET", "http://example.com", nil)
	for n, test := range tests {
		rec := httptest.NewRecorder()
		req.URL.Path = test.reqPath
		fs.ServeHTTP(rec, req)
		if got := <-ch; got != test.openArg {
			t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
		}
	}
}

func TestFileServerImplicitLeadingSlash(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "")
	if err != nil {
		t.Fatalf("TempDir: %v", err)
	}
	defer os.RemoveAll(tempDir)
	if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
		t.Fatalf("WriteFile: %v", err)
	}
	ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir))))
	defer ts.Close()
	get := func(suffix string) string {
		res, err := Get(ts.URL + suffix)
		if err != nil {
			t.Fatalf("Get %s: %v", suffix, err)
		}
		b, err := ioutil.ReadAll(res.Body)
		if err != nil {
			t.Fatalf("ReadAll %s: %v", suffix, err)
		}
		return string(b)
	}
	if s := get("/bar/"); !strings.Contains(s, ">foo.txt<") {
		t.Logf("expected a directory listing with foo.txt, got %q", s)
	}
	if s := get("/bar/foo.txt"); s != "Hello world" {
		t.Logf("expected %q, got %q", "Hello world", s)
	}
}

func TestDirJoin(t *testing.T) {
	wfi, err := os.Stat("/etc/hosts")
	if err != nil {
		t.Logf("skipping test; no /etc/hosts file")
		return
	}
	test := func(d Dir, name string) {
		f, err := d.Open(name)
		if err != nil {
			t.Fatalf("open of %s: %v", name, err)
		}
		defer f.Close()
		gfi, err := f.Stat()
		if err != nil {
			t.Fatalf("stat of %s: %v", name, err)
		}
		if gfi.Ino != wfi.Ino {
			t.Errorf("%s got different inode", name)
		}
	}
	test(Dir("/etc/"), "/hosts")
	test(Dir("/etc/"), "hosts")
	test(Dir("/etc/"), "../../../../hosts")
	test(Dir("/etc"), "/hosts")
	test(Dir("/etc"), "hosts")
	test(Dir("/etc"), "../../../../hosts")

	// Not really directories, but since we use this trick in
	// ServeFile, test it:
	test(Dir("/etc/hosts"), "")
	test(Dir("/etc/hosts"), "/")
	test(Dir("/etc/hosts"), "../")
}

func TestServeFileContentType(t *testing.T) {
	const ctype = "icecream/chocolate"
	override := false
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		if override {
			w.Header().Set("Content-Type", ctype)
		}
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	get := func(want string) {
		resp, err := Get(ts.URL)
		if err != nil {
			t.Fatal(err)
		}
		if h := resp.Header.Get("Content-Type"); h != want {
			t.Errorf("Content-Type mismatch: got %d, want %d", h, want)
		}
	}
	get("text/plain; charset=utf-8")
	override = true
	get(ctype)
}

func TestServeFileMimeType(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		ServeFile(w, r, "testdata/style.css")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	want := "text/css; charset=utf-8"
	if h := resp.Header.Get("Content-Type"); h != want {
		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
	}
}

func TestServeFileWithContentEncoding(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		w.Header().Set("Content-Encoding", "foo")
		ServeFile(w, r, "testdata/file")
	}))
	defer ts.Close()
	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	if g, e := resp.ContentLength, int64(-1); g != e {
		t.Errorf("Content-Length mismatch: got %q, want %q", g, e)
	}
}

func getBody(t *testing.T, req Request) (*Response, []byte) {
	r, err := DefaultClient.Do(&req)
	if err != nil {
		t.Fatal(req.URL.String(), "send:", err)
	}
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		t.Fatal("reading Body:", err)
	}
	return r, b
}

func equal(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<|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 net

import (
	"net";
	"os";
	"regexp";
	"testing";
)

type DialErrorTest struct {
	Net string;
	Laddr string;
	Raddr string;
	Pattern string;
}

var dialErrorTests = []DialErrorTest {
	DialErrorTest{
		"datakit", "", "mh/astro/r70",
		"dial datakit mh/astro/r70: unknown network datakit",
	},
	DialErrorTest{
		"tcp", "", "127.0.0.1:☺",
		"dial tcp 127.0.0.1:☺: unknown port tcp/☺",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.google.com.:80",
		"dial tcp no-such-name.google.com.:80: lookup no-such-name.google.com.: no such host",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.no-such-top-level-domain.:80",
		"dial tcp no-such-name.no-such-top-level-domain.:80: lookup no-such-name.no-such-top-level-domain.: no such host",
	},
	DialErrorTest{
		"tcp", "", "no-such-name:80",
		"dial tcp no-such-name:80: lookup no-such-name.google.com.: no such host",
	},
	DialErrorTest{
		"tcp", "", "mh/astro/r70:http",
		"dial tcp mh/astro/r70:http: lookup mh/astro/r70: invalid domain name",
	},
	DialErrorTest{
		"unix", "", "/etc/file-not-found",
		"dial unix /etc/file-not-found: no such file or directory",
	},
	DialErrorTest{
		"unix", "", "/etc/",
		"dial unix /etc/: (permission denied|socket operation on non-socket)",
	},
}

func TestDialError(t *testing.T) {
	for i, tt := range dialErrorTests {
		c, e := net.Dial(tt.Net, tt.Laddr, tt.Raddr);
		if c != nil {
			c.Close();
		}
		if e == nil {
			t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern);
			continue;
		}
		s := e.String();
		match, err := regexp.Match(tt.Pattern, s);
		if !match {
			t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern);
		}
	}
}
<commit_msg>Remove assumption about google.com being the default search domain.<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 net

import (
	"net";
	"os";
	"regexp";
	"testing";
)

type DialErrorTest struct {
	Net string;
	Laddr string;
	Raddr string;
	Pattern string;
}

var dialErrorTests = []DialErrorTest {
	DialErrorTest{
		"datakit", "", "mh/astro/r70",
		"dial datakit mh/astro/r70: unknown network datakit",
	},
	DialErrorTest{
		"tcp", "", "127.0.0.1:☺",
		"dial tcp 127.0.0.1:☺: unknown port tcp/☺",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.google.com.:80",
		"dial tcp no-such-name.google.com.:80: lookup no-such-name.google.com.: no such host",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.no-such-top-level-domain.:80",
		"dial tcp no-such-name.no-such-top-level-domain.:80: lookup no-such-name.no-such-top-level-domain.: no such host",
	},
	DialErrorTest{
		"tcp", "", "no-such-name:80",
		`dial tcp no-such-name:80: lookup no-such-name\..*\.: no such host`,
	},
	DialErrorTest{
		"tcp", "", "mh/astro/r70:http",
		"dial tcp mh/astro/r70:http: lookup mh/astro/r70: invalid domain name",
	},
	DialErrorTest{
		"unix", "", "/etc/file-not-found",
		"dial unix /etc/file-not-found: no such file or directory",
	},
	DialErrorTest{
		"unix", "", "/etc/",
		"dial unix /etc/: (permission denied|socket operation on non-socket)",
	},
}

func TestDialError(t *testing.T) {
	for i, tt := range dialErrorTests {
		c, e := net.Dial(tt.Net, tt.Laddr, tt.Raddr);
		if c != nil {
			c.Close();
		}
		if e == nil {
			t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern);
			continue;
		}
		s := e.String();
		match, err := regexp.Match(tt.Pattern, s);
		if !match {
			t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern);
		}
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/flynn/flynn/host/types"
	"github.com/flynn/flynn/pkg/cluster"
	"github.com/flynn/go-docopt"
)

func init() {
	Register("inspect", runInspect, `
usage: flynn-host inspect [options] ID

Get low-level information about a job.

options:
  --omit-env         don't include the job environment, which may be sensitive
  --redact-env ENVS  don't print the specified comma-separated env values
`)
}

func runInspect(args *docopt.Args, client *cluster.Client) error {
	jobID := args.String["ID"]
	hostID, err := cluster.ExtractHostID(jobID)
	if err != nil {
		return err
	}
	hostClient, err := client.Host(hostID)
	if err != nil {
		return fmt.Errorf("could not connect to host %s: %s", hostID, err)
	}
	job, err := hostClient.GetJob(jobID)
	if err != nil {
		return fmt.Errorf("no such job")
	}

	printJobDesc(job, os.Stdout, !args.Bool["--omit-env"], strings.Split(args.String["--redact-env"], ","))
	return nil
}

func displayTime(ts time.Time) string {
	if ts.IsZero() {
		return ""
	}
	return ts.String()
}

func printJobDesc(job *host.ActiveJob, out io.Writer, env bool, redactEnv []string) {
	w := tabwriter.NewWriter(out, 1, 2, 2, ' ', 0)
	defer w.Flush()

	var exitStatus string
	if job.ExitStatus != nil {
		exitStatus = strconv.Itoa(*job.ExitStatus)
	}
	var jobError string
	if job.Error != nil {
		jobError = *job.Error
	}

	listRec(w, "ID", job.Job.ID)
	listRec(w, "Args", strings.Join(job.Job.Config.Args, " "))
	listRec(w, "Status", job.Status)
	listRec(w, "CreatedAt", job.CreatedAt)
	listRec(w, "StartedAt", job.StartedAt)
	listRec(w, "EndedAt", displayTime(job.EndedAt))
	listRec(w, "ExitStatus", exitStatus)
	listRec(w, "Error", jobError)
	listRec(w, "IP Address", job.InternalIP)
	listRec(w, "ImageArtifact", job.Job.ImageArtifact.URI)
	for i, artifact := range job.Job.FileArtifacts {
		listRec(w, fmt.Sprintf("FileArtifact[%d]", i), artifact.URI)
	}
	for k, v := range job.Job.Metadata {
		listRec(w, k, v)
	}
	if env {
		for k, v := range job.Job.Config.Env {
			for _, s := range redactEnv {
				if s == k {
					v = "XXXREDACTEDXXX"
					break
				}
			}
			listRec(w, fmt.Sprintf("ENV[%s]", k), v)
		}
	}
}

func listRec(w io.Writer, a ...interface{}) {
	for i, x := range a {
		fmt.Fprint(w, x)
		if i+1 < len(a) {
			w.Write([]byte{'\t'})
		} else {
			w.Write([]byte{'\n'})
		}
	}
}
<commit_msg>host/cli: Add volume information to inspect<commit_after>package cli

import (
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/flynn/flynn/host/types"
	"github.com/flynn/flynn/pkg/cluster"
	"github.com/flynn/go-docopt"
)

func init() {
	Register("inspect", runInspect, `
usage: flynn-host inspect [options] ID

Get low-level information about a job.

options:
  --omit-env         don't include the job environment, which may be sensitive
  --redact-env ENVS  don't print the specified comma-separated env values
`)
}

func runInspect(args *docopt.Args, client *cluster.Client) error {
	jobID := args.String["ID"]
	hostID, err := cluster.ExtractHostID(jobID)
	if err != nil {
		return err
	}
	hostClient, err := client.Host(hostID)
	if err != nil {
		return fmt.Errorf("could not connect to host %s: %s", hostID, err)
	}
	job, err := hostClient.GetJob(jobID)
	if err != nil {
		return fmt.Errorf("no such job")
	}

	printJobDesc(job, os.Stdout, !args.Bool["--omit-env"], strings.Split(args.String["--redact-env"], ","))
	return nil
}

func displayTime(ts time.Time) string {
	if ts.IsZero() {
		return ""
	}
	return ts.String()
}

func printJobDesc(job *host.ActiveJob, out io.Writer, env bool, redactEnv []string) {
	w := tabwriter.NewWriter(out, 1, 2, 2, ' ', 0)
	defer w.Flush()

	var exitStatus string
	if job.ExitStatus != nil {
		exitStatus = strconv.Itoa(*job.ExitStatus)
	}
	var jobError string
	if job.Error != nil {
		jobError = *job.Error
	}

	listRec(w, "ID", job.Job.ID)
	listRec(w, "Args", strings.Join(job.Job.Config.Args, " "))
	listRec(w, "Status", job.Status)
	listRec(w, "CreatedAt", job.CreatedAt)
	listRec(w, "StartedAt", job.StartedAt)
	listRec(w, "EndedAt", displayTime(job.EndedAt))
	listRec(w, "ExitStatus", exitStatus)
	listRec(w, "Error", jobError)
	listRec(w, "IP Address", job.InternalIP)
	listRec(w, "ImageArtifact", job.Job.ImageArtifact.URI)
	for i, artifact := range job.Job.FileArtifacts {
		listRec(w, fmt.Sprintf("FileArtifact[%d]", i), artifact.URI)
	}
	for _, vb := range job.Job.Config.Volumes {
		listRec(w, fmt.Sprintf("Volume[%s]", vb.Target), vb.VolumeID)
	}
	for k, v := range job.Job.Metadata {
		listRec(w, k, v)
	}
	if env {
		for k, v := range job.Job.Config.Env {
			for _, s := range redactEnv {
				if s == k {
					v = "XXXREDACTEDXXX"
					break
				}
			}
			listRec(w, fmt.Sprintf("ENV[%s]", k), v)
		}
	}
}

func listRec(w io.Writer, a ...interface{}) {
	for i, x := range a {
		fmt.Fprint(w, x)
		if i+1 < len(a) {
			w.Write([]byte{'\t'})
		} else {
			w.Write([]byte{'\n'})
		}
	}
}
<|endoftext|>


<commit_before>// +build darwin

package host

import (
	"bytes"
	"encoding/binary"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
	"unsafe"

	common "github.com/shirou/gopsutil/common"
)

func HostInfo() (*HostInfoStat, error) {
	ret := &HostInfoStat{
		OS:             runtime.GOOS,
		PlatformFamily: "darwin",
	}

	hostname, err := os.Hostname()
	if err != nil {
		return ret, err
	}
	ret.Hostname = hostname

	platform, family, version, err := GetPlatformInformation()
	if err == nil {
		ret.Platform = platform
		ret.PlatformFamily = family
		ret.PlatformVersion = version
	}
	system, role, err := GetVirtualization()
	if err == nil {
		ret.VirtualizationSystem = system
		ret.VirtualizationRole = role
	}

	values, err := common.DoSysctrl("kern.boottime")
	if err == nil {
		// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
		v := strings.Replace(values[2], ",", "", 1)
		t, err := strconv.ParseUint(v, 10, 64)
		if err != nil {
			return ret, err
		}
		ret.Uptime = t
	}

	return ret, nil
}

func BootTime() (int64, error) {
	values, err := common.DoSysctrl("kern.boottime")
	if err != nil {
		return 0, err
	}
	// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
	v := strings.Replace(values[2], ",", "", 1)

	boottime, err := strconv.ParseInt(v, 10, 64)
	if err != nil {
		return 0, err
	}

	return boottime, nil
}

func Users() ([]UserStat, error) {
	utmpfile := "/var/run/utmpx"
	var ret []UserStat

	file, err := os.Open(utmpfile)
	if err != nil {
		return ret, err
	}

	buf, err := ioutil.ReadAll(file)
	if err != nil {
		return ret, err
	}

	u := Utmpx{}
	entrySize := int(unsafe.Sizeof(u))
	count := len(buf) / entrySize

	for i := 0; i < count; i++ {
		b := buf[i*entrySize : i*entrySize+entrySize]

		var u Utmpx
		br := bytes.NewReader(b)
		err := binary.Read(br, binary.LittleEndian, &u)
		if err != nil {
			continue
		}
		if u.Line[0] == 0 { // skip if terminal is empty
			continue
		}
		user := UserStat{
			User:     common.IntToString(u.User[:]),
			Terminal: common.IntToString(u.Line[:]),
			Host:     common.IntToString(u.Host[:]),
			Started:  int(u.Tv.Sec),
		}
		ret = append(ret, user)
	}

	return ret, nil

}

func GetPlatformInformation() (string, string, string, error) {
	platform := ""
	family := ""
	version := ""

	out, err := exec.Command("uname", "-s").Output()
	if err == nil {
		platform = strings.ToLower(strings.TrimSpace(string(out)))
	}

	out, err = exec.Command("uname", "-r").Output()
	if err == nil {
		version = strings.ToLower(strings.TrimSpace(string(out)))
	}

	return platform, family, version, nil
}

func GetVirtualization() (string, string, error) {
	system := ""
	role := ""

	return system, role, nil
}
<commit_msg>host: skip if utmp.Type is not USERPROCESS (defined in utmpx.h)<commit_after>// +build darwin

package host

import (
	"bytes"
	"encoding/binary"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
	"unsafe"

	common "github.com/shirou/gopsutil/common"
)

func HostInfo() (*HostInfoStat, error) {
	ret := &HostInfoStat{
		OS:             runtime.GOOS,
		PlatformFamily: "darwin",
	}

	hostname, err := os.Hostname()
	if err != nil {
		return ret, err
	}
	ret.Hostname = hostname

	platform, family, version, err := GetPlatformInformation()
	if err == nil {
		ret.Platform = platform
		ret.PlatformFamily = family
		ret.PlatformVersion = version
	}
	system, role, err := GetVirtualization()
	if err == nil {
		ret.VirtualizationSystem = system
		ret.VirtualizationRole = role
	}

	values, err := common.DoSysctrl("kern.boottime")
	if err == nil {
		// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
		v := strings.Replace(values[2], ",", "", 1)
		t, err := strconv.ParseUint(v, 10, 64)
		if err != nil {
			return ret, err
		}
		ret.Uptime = t
	}

	return ret, nil
}

func BootTime() (int64, error) {
	values, err := common.DoSysctrl("kern.boottime")
	if err != nil {
		return 0, err
	}
	// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
	v := strings.Replace(values[2], ",", "", 1)

	boottime, err := strconv.ParseInt(v, 10, 64)
	if err != nil {
		return 0, err
	}

	return boottime, nil
}

func Users() ([]UserStat, error) {
	utmpfile := "/var/run/utmpx"
	var ret []UserStat

	file, err := os.Open(utmpfile)
	if err != nil {
		return ret, err
	}

	buf, err := ioutil.ReadAll(file)
	if err != nil {
		return ret, err
	}

	u := Utmpx{}
	entrySize := int(unsafe.Sizeof(u))
	count := len(buf) / entrySize

	for i := 0; i < count; i++ {
		b := buf[i*entrySize : i*entrySize+entrySize]

		var u Utmpx
		br := bytes.NewReader(b)
		err := binary.Read(br, binary.LittleEndian, &u)
		if err != nil {
			continue
		}
		if u.Type != 7 { // skip if not USERPROCESS
			continue
		}
		user := UserStat{
			User:     common.IntToString(u.User[:]),
			Terminal: common.IntToString(u.Line[:]),
			Host:     common.IntToString(u.Host[:]),
			Started:  int(u.Tv.Sec),
		}
		ret = append(ret, user)
	}

	return ret, nil

}

func GetPlatformInformation() (string, string, string, error) {
	platform := ""
	family := ""
	version := ""

	out, err := exec.Command("uname", "-s").Output()
	if err == nil {
		platform = strings.ToLower(strings.TrimSpace(string(out)))
	}

	out, err = exec.Command("uname", "-r").Output()
	if err == nil {
		version = strings.ToLower(strings.TrimSpace(string(out)))
	}

	return platform, family, version, nil
}

func GetVirtualization() (string, string, error) {
	system := ""
	role := ""

	return system, role, nil
}
<|endoftext|>


<commit_before>/*
package kosaraju

import (
	"fmt"
	"testing"

	"github.com/gyuho/goraph/graph/gs"
)

func TestSCC(t *testing.T) {
	g15 := gs.FromJSON("../../../files/testgraph.json", "testgraph.015")
	gr15 := gs.FromJSONT("../../../files/testgraph.json", "testgraph.015")
	rs := SCC(g15, gr15)
	fmt.Println(rs)
	// [[B E A] [D C] [G F] [H]]

	if len(rs) != 4 {
		t.Errorf("expected 4 but %v", rs)
	}
	//
	//
	// TODO
	// g16 := gs.FromJSON("../../../files/testgraph.json", "testgraph.016")
	// gr16 := gs.FromJSONT("../../../files/testgraph.json", "testgraph.016")
	// fmt.Println(SCC(g16, gr16))
	// [[B F G A] [D H C] [I] [E J]]
}
*/

/*
=== RUN TestSCC
SIGQUIT: quit
PC=0x42233e

goroutine 25 [running]:
runtime.mallocgc(0x20, 0x513f40, 0xc200000000)
	/usr/local/go/src/pkg/runtime/malloc.goc:156 +0x32e fp=0xc20808dc98 sp=0xc20808dc30
runtime.new(0x513f40, 0x0)
	/usr/local/go/src/pkg/runtime/malloc.goc:826 +0x3b fp=0xc20808dcb8 sp=0xc20808dc98
github.com/gyuho/goraph/algorithm/scc/kosaraju.DFSandSCC(0xc208001970, 0xc20801a370, 0x0, 0x0, 0x0)
	/home/travis/gopath/src/github.com/gyuho/goraph/algorithm/scc/kosaraju/dfs.go:97 +0x41 fp=0xc20808dd00 sp=0xc20808dcb8
github.com/gyuho/goraph/algorithm/scc/kosaraju.SCC(0xc208001970, 0xc208089d70, 0x0, 0x0, 0x0)
	/home/travis/gopath/src/github.com/gyuho/goraph/algorithm/scc/kosaraju/kosaraju.go:20 +0x24f fp=0xc20808dec8 sp=0xc20808dd00
github.com/gyuho/goraph/algorithm/scc/kosaraju.TestSCC(0xc208048240)
	/home/travis/gopath/src/github.com/gyuho/goraph/algorithm/scc/kosaraju/kosaraju_test.go:13 +0xa4 fp=0xc20808df68 sp=0xc20808dec8
testing.tRunner(0xc208048240, 0x65d7b8)
	/usr/local/go/src/pkg/testing/testing.go:422 +0x8b fp=0xc20808df98 sp=0xc20808df68
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445 fp=0xc20808dfa0 sp=0xc20808df98
created by testing.RunTests
	/usr/local/go/src/pkg/testing/testing.go:504 +0x8db

goroutine 16 [chan receive, 9 minutes]:
testing.RunTests(0x5cc860, 0x65d740, 0x6, 0x6, 0x1)
	/usr/local/go/src/pkg/testing/testing.go:505 +0x923
testing.Main(0x5cc860, 0x65d740, 0x6, 0x6, 0x665fc0, 0x0, 0x0, 0x665fc0, 0x0, 0x0)
	/usr/local/go/src/pkg/testing/testing.go:435 +0x84
main.main()
	github.com/gyuho/goraph/algorithm/scc/kosaraju/_test/_testmain.go:57 +0x9c

goroutine 19 [finalizer wait, 10 minutes]:
runtime.park(0x4130d0, 0x662a58, 0x661589)
	/usr/local/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x662a58, 0x661589)
	/usr/local/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
	/usr/local/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445

rax     0xc2080724c0
rbx     0x3
rcx     0xc2080724e0
rdx     0xc2080724e0
rdi     0x7f6a990bd000
rsi     0xc2080724c0
rbp     0x7f6a990c3100
rsp     0xc20808dc30
r8      0xc20808db98
r9      0x25
r10     0x0
r11     0x246
r12     0x411890
r13     0xc2080400f0
r14     0x0
r15     0xc2080003f0
rip     0x42233e
rflags  0x206
cs      0x33
fs      0x0
gs      0x0
*/
<commit_msg>Fix this file to the point that "go get" on gyuho/gorpah works.<commit_after>package kosaraju

func main() {}

/*
import (
	"fmt"
	"testing"

	"github.com/gyuho/goraph/graph/gs"
)

func TestSCC(t *testing.T) {
	g15 := gs.FromJSON("../../../files/testgraph.json", "testgraph.015")
	gr15 := gs.FromJSONT("../../../files/testgraph.json", "testgraph.015")
	rs := SCC(g15, gr15)
	fmt.Println(rs)
	// [[B E A] [D C] [G F] [H]]

	if len(rs) != 4 {
		t.Errorf("expected 4 but %v", rs)
	}
	//
	//
	// TODO
	// g16 := gs.FromJSON("../../../files/testgraph.json", "testgraph.016")
	// gr16 := gs.FromJSONT("../../../files/testgraph.json", "testgraph.016")
	// fmt.Println(SCC(g16, gr16))
	// [[B F G A] [D H C] [I] [E J]]
}
*/

/*
=== RUN TestSCC
SIGQUIT: quit
PC=0x42233e

goroutine 25 [running]:
runtime.mallocgc(0x20, 0x513f40, 0xc200000000)
	/usr/local/go/src/pkg/runtime/malloc.goc:156 +0x32e fp=0xc20808dc98 sp=0xc20808dc30
runtime.new(0x513f40, 0x0)
	/usr/local/go/src/pkg/runtime/malloc.goc:826 +0x3b fp=0xc20808dcb8 sp=0xc20808dc98
github.com/gyuho/goraph/algorithm/scc/kosaraju.DFSandSCC(0xc208001970, 0xc20801a370, 0x0, 0x0, 0x0)
	/home/travis/gopath/src/github.com/gyuho/goraph/algorithm/scc/kosaraju/dfs.go:97 +0x41 fp=0xc20808dd00 sp=0xc20808dcb8
github.com/gyuho/goraph/algorithm/scc/kosaraju.SCC(0xc208001970, 0xc208089d70, 0x0, 0x0, 0x0)
	/home/travis/gopath/src/github.com/gyuho/goraph/algorithm/scc/kosaraju/kosaraju.go:20 +0x24f fp=0xc20808dec8 sp=0xc20808dd00
github.com/gyuho/goraph/algorithm/scc/kosaraju.TestSCC(0xc208048240)
	/home/travis/gopath/src/github.com/gyuho/goraph/algorithm/scc/kosaraju/kosaraju_test.go:13 +0xa4 fp=0xc20808df68 sp=0xc20808dec8
testing.tRunner(0xc208048240, 0x65d7b8)
	/usr/local/go/src/pkg/testing/testing.go:422 +0x8b fp=0xc20808df98 sp=0xc20808df68
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445 fp=0xc20808dfa0 sp=0xc20808df98
created by testing.RunTests
	/usr/local/go/src/pkg/testing/testing.go:504 +0x8db

goroutine 16 [chan receive, 9 minutes]:
testing.RunTests(0x5cc860, 0x65d740, 0x6, 0x6, 0x1)
	/usr/local/go/src/pkg/testing/testing.go:505 +0x923
testing.Main(0x5cc860, 0x65d740, 0x6, 0x6, 0x665fc0, 0x0, 0x0, 0x665fc0, 0x0, 0x0)
	/usr/local/go/src/pkg/testing/testing.go:435 +0x84
main.main()
	github.com/gyuho/goraph/algorithm/scc/kosaraju/_test/_testmain.go:57 +0x9c

goroutine 19 [finalizer wait, 10 minutes]:
runtime.park(0x4130d0, 0x662a58, 0x661589)
	/usr/local/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x662a58, 0x661589)
	/usr/local/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
	/usr/local/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445

rax     0xc2080724c0
rbx     0x3
rcx     0xc2080724e0
rdx     0xc2080724e0
rdi     0x7f6a990bd000
rsi     0xc2080724c0
rbp     0x7f6a990c3100
rsp     0xc20808dc30
r8      0xc20808db98
r9      0x25
r10     0x0
r11     0x246
r12     0x411890
r13     0xc2080400f0
r14     0x0
r15     0xc2080003f0
rip     0x42233e
rflags  0x206
cs      0x33
fs      0x0
gs      0x0
*/
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/portworx/torpedo/scheduler"
)

// testDriverFunc runs a specific external storage test case.  It takes
// in a scheduler driver and an external volume provider (string) as
// arguments.
type testDriverFunc func(scheduler.Driver, string) error

const (
	// Use the inline volume specification so that we can test
	// volume options being dynamically parsed and used inline.
	volName = "size=10G,name=torpedo_fiovol"
)

// Create dynamic volumes.  Make sure that a task can use the dynamic volume
// in th einline format as size=x,repl=x,compress=x,name=foo.
func testDynamicVolume(
	d scheduler.Driver,
	volumeDriver string,
) error {
	// If it exists, remove it.
	d.RemoveVolume(volName)

	t := scheduler.Task{
		Name: "testDynamicVolume",
		Img:  "gourao/fio",
		Tag:  "latest",
		Cmd: []string{
			"fio",
			"--blocksize=64k",
			"--directory=/mnt/",
			"--ioengine=libaio",
			"--readwrite=write",
			"--size=5G",
			"--name=test",
			"--verify=meta",
			"--do_verify=1",
			"--verify_pattern=0xDeadBeef",
			"--direct=1",
			"--gtod_reduce=1",
			"--iodepth=1",
			"--randrepeat=1",
		},
		Vol: scheduler.Volume{
			Driver: volumeDriver,
			Name:   volName,
			Path:   "/mnt/",
			Size:   10240,
		},
	}

	if ctx, err := d.Create(t); err != nil {
		return err
	} else {
		defer func() {
			d.Destroy(ctx)
			d.RemoveVolume(volName)
		}()

		// Run the task and wait for completion.  This task will exit and
		// must not be re-started by the scheduler.
		if err = d.Run(ctx); err != nil {
			return err
		}

		if ctx.Status != 0 {
			return fmt.Errorf("Exit status %v\nStdout: %v\nStderr: %v\n",
				ctx.Status,
				ctx.Stdout,
				ctx.Stderr,
			)
		}
	}

	// Verify that the volume properties are honored.
	if v, err := d.InspectVolume(volName); err != nil {
		return err
	} else {
		// TODO: inspect size.
		/*
			if v.Size != 10240 {
				return fmt.Errorf(
					"Dynamic volume creation failed, size was not honored (size = %v).",
					v.Size,
				)
			}
		*/
		if v.Driver != volumeDriver {
			return fmt.Errorf(
				"Dynamic volume creation failed, incorrect volume driver (driver = %v).",
				v.Driver,
			)
		}
	}
	return nil
}

// Verify that the volume driver can deal with an uneven number of mounts
// and unmounts and allow the volume to get mounted on another node.
func testRemoteForceMount(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Volume Driver Plugin is down, unavailable - and the client container should
// not be impacted.
func testDriverDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Volume driver plugin is down and the client container gets terminated.
// There is a lost unmount call in this case, but the container should i
// be able to come up on another system and use the volume.
func testDriverDownContainerDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// A container is using a volume on node X.  Node X is now powered off.
func testNodePowerOff(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Storage plugin is down.  Scheduler tries to create a container using the
// provider’s volume.
func testPluginDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// A container is running on node X.  Node X loses network access and is
// partitioned away.  Node Y that is in the cluster can use the volume for
// another container.
func testNetworkDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// A container is running on node X.  Node X can only see a subset of the
// storage cluster.  That is, it can see the entire DC/OS cluster, but just the
// storage cluster gets a network partition. Node Y that is in the cluster
// can use the volume for another container.
func testNetworkPartition(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Docker daemon crashes and live restore is disabled.
func testDockerDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Docker daemon crashes and live restore is enabled.
func testDockerDownLiveRestore(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

func run(d scheduler.Driver, vd string) error {
	if err := d.Init(); err != nil {
		return err
	}

	// Add new test functions here.
	testFuncs := map[string]testDriverFunc{
		"testDynamicVolume":           testDynamicVolume,
		"testRemoteForceMount":        testRemoteForceMount,
		"testDriverDown":              testDriverDown,
		"testDriverDownContainerDown": testDriverDownContainerDown,
		"testNodePowerOff":            testNodePowerOff,
		"testPluginDown":              testPluginDown,
		"testNetworkDown":             testNetworkDown,
		"testNetworkPartition":        testNetworkPartition,
		"testDockerDown":              testDockerDown,
		"testDockerDownLiveRestore":   testDockerDownLiveRestore,
	}

	for n, f := range testFuncs {
		// TODO: Delete test volumes before test, in case there was
		// previous state from a failed run.
		log.Printf("Executing test %v\n", n)
		if err := f(d, vd); err != nil {
			log.Printf("\tTest %v Failed with Error: %v.\n", n, err)
			return err
		}
		log.Printf("\tTest %v Passed.\n", n)
	}

	return nil
}

func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage: %v <scheduler> <volume driver>\n", os.Args[0])
		os.Exit(-1)
	}

	if d, err := scheduler.Get(os.Args[1]); err != nil {
		log.Fatalf("Cannot find driver %v\n", os.Args[1])
		os.Exit(-1)
	} else {
		if run(d, os.Args[2]) != nil {
			os.Exit(-1)
		}
	}

	log.Printf("All tests have passed with this driver: %v and this scheduler: %v\n",
		os.Args[2],
		os.Args[1],
	)
}
<commit_msg>torpedo scheduler driver structures being put into place<commit_after>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/portworx/torpedo/scheduler"
)

// testDriverFunc runs a specific external storage test case.  It takes
// in a scheduler driver and an external volume provider (string) as
// arguments.
type testDriverFunc func(scheduler.Driver, string) error

const (
	// Use the inline volume specification so that we can test
	// volume options being dynamically parsed and used inline.
	volName = "size=10G,name=torpedo_fiovol"
)

// Create dynamic volumes.  Make sure that a task can use the dynamic volume
// in th einline format as size=x,repl=x,compress=x,name=foo.
func testDynamicVolume(
	d scheduler.Driver,
	volumeDriver string,
) error {
	// If it exists, remove it.
	d.RemoveVolume(volName)

	t := scheduler.Task{
		Name: "testDynamicVolume",
		Img:  "gourao/fio",
		Tag:  "latest",
		Cmd: []string{
			"fio",
			"--blocksize=64k",
			"--directory=/mnt/",
			"--ioengine=libaio",
			"--readwrite=write",
			"--size=5G",
			"--name=test",
			"--verify=meta",
			"--do_verify=1",
			"--verify_pattern=0xDeadBeef",
			"--direct=1",
			"--gtod_reduce=1",
			"--iodepth=1",
			"--randrepeat=1",
		},
		Vol: scheduler.Volume{
			Driver: volumeDriver,
			Name:   volName,
			Path:   "/mnt/",
			Size:   10240,
		},
	}

	if ctx, err := d.Create(t); err != nil {
		return err
	} else {
		defer func() {
			d.Destroy(ctx)
			d.RemoveVolume(volName)
		}()

		// Run the task and wait for completion.  This task will exit and
		// must not be re-started by the scheduler.
		if err = d.Run(ctx); err != nil {
			return err
		}

		if ctx.Status != 0 {
			return fmt.Errorf("Exit status %v\nStdout: %v\nStderr: %v\n",
				ctx.Status,
				ctx.Stdout,
				ctx.Stderr,
			)
		}
	}

	// Verify that the volume properties are honored.
	if v, err := d.InspectVolume(volName); err != nil {
		return err
	} else {
		// TODO: inspect size.
		/*
			if v.Size != 10240 {
				return fmt.Errorf(
					"Dynamic volume creation failed, size was not honored (size = %v).",
					v.Size,
				)
			}
		*/
		if v.Driver != volumeDriver {
			return fmt.Errorf(
				"Dynamic volume creation failed, incorrect volume driver (driver = %v).",
				v.Driver,
			)
		}
	}
	return nil
}

// Verify that the volume driver can deal with an uneven number of mounts
// and unmounts and allow the volume to get mounted on another node.
func testRemoteForceMount(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Volume Driver Plugin is down, unavailable - and the client container should
// not be impacted.
func testDriverDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Volume driver plugin is down and the client container gets terminated.
// There is a lost unmount call in this case, but the container should i
// be able to come up on another system and use the volume.
func testDriverDownContainerDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// A container is using a volume on node X.  Node X is now powered off.
func testNodePowerOff(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Storage plugin is down.  Scheduler tries to create a container using the
// provider’s volume.
func testPluginDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// A container is running on node X.  Node X loses network access and is
// partitioned away.  Node Y that is in the cluster can use the volume for
// another container.
func testNetworkDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// A container is running on node X.  Node X can only see a subset of the
// storage cluster.  That is, it can see the entire DC/OS cluster, but just the
// storage cluster gets a network partition. Node Y that is in the cluster
// can use the volume for another container.
func testNetworkPartition(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Docker daemon crashes and live restore is disabled.
func testDockerDown(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

// Docker daemon crashes and live restore is enabled.
func testDockerDownLiveRestore(
	d scheduler.Driver,
	volumeDriver string,
) error {
	return nil
}

func run(d scheduler.Driver, vd string) error {
	if err := d.Init(); err != nil {
		return err
	}

	// Add new test functions here.
	testFuncs := map[string]testDriverFunc{
		"testDynamicVolume":           testDynamicVolume,
		"testRemoteForceMount":        testRemoteForceMount,
		"testDriverDown":              testDriverDown,
		"testDriverDownContainerDown": testDriverDownContainerDown,
		"testNodePowerOff":            testNodePowerOff,
		"testPluginDown":              testPluginDown,
		"testNetworkDown":             testNetworkDown,
		"testNetworkPartition":        testNetworkPartition,
		"testDockerDown":              testDockerDown,
		"testDockerDownLiveRestore":   testDockerDownLiveRestore,
	}

	for n, f := range testFuncs {
		log.Printf("Executing test %v\n", n)
		if err := f(d, vd); err != nil {
			log.Printf("\tTest %v Failed with Error: %v.\n", n, err)
			return err
		}
		log.Printf("\tTest %v Passed.\n", n)
	}

	return nil
}

func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage: %v <scheduler> <volume driver>\n", os.Args[0])
		os.Exit(-1)
	}

	if d, err := scheduler.Get(os.Args[1]); err != nil {
		log.Fatalf("Cannot find driver %v\n", os.Args[1])
		os.Exit(-1)
	} else {
		if run(d, os.Args[2]) != nil {
			os.Exit(-1)
		}
	}

	log.Printf("All tests have passed with this driver: %v and this scheduler: %v\n",
		os.Args[2],
		os.Args[1],
	)
}
<|endoftext|>


<commit_before>package collectors

import (
	"fmt"
	"strings"
	"time"

	"github.com/StackExchange/scollector/opentsdb"
	"github.com/StackExchange/slog"
)

const (
	ifAlias              = ".1.3.6.1.2.1.31.1.1.1.18"
	ifDescr              = ".1.3.6.1.2.1.2.2.1.2"
	ifHCInBroadcastPkts  = ".1.3.6.1.2.1.31.1.1.1.9"
	ifHCInMulticastPkts  = ".1.3.6.1.2.1.31.1.1.1.8"
	ifHCInUcastPkts      = ".1.3.6.1.2.1.31.1.1.1.7"
	ifHCOutBroadcastPkts = ".1.3.6.1.2.1.31.1.1.1.13"
	ifHCOutMulticastPkts = ".1.3.6.1.2.1.31.1.1.1.12"
	ifHCOutOctets        = ".1.3.6.1.2.1.31.1.1.1.10"
	ifHCOutUcastPkts     = ".1.3.6.1.2.1.31.1.1.1.11"
	ifHCinOctets         = ".1.3.6.1.2.1.31.1.1.1.6"
	ifInDiscards         = ".1.3.6.1.2.1.2.2.1.13"
	ifInErrors           = ".1.3.6.1.2.1.2.2.1.14"
	ifOutDiscards        = ".1.3.6.1.2.1.2.2.1.19"
	ifOutErrors          = ".1.3.6.1.2.1.2.2.1.20"
)

// SNMPIfaces registers a SNMP Interfaces collector for the given community and host.
func SNMPIfaces(community, host string) {
	collectors = append(collectors, &IntervalCollector{
		F: func() opentsdb.MultiDataPoint {
			return c_snmp_ifaces(community, host)
		},
		Interval: time.Minute * 5,
		name:     fmt.Sprintf("snmp-ifaces-%s", host),
	})
}

func switch_bond(metric, iname string) string {
	if strings.Contains(iname, "port-channel") {
		return "os.net.bond" + strings.TrimPrefix(metric, "os.net")
	}
	return metric
}

func c_snmp_ifaces(community, host string) opentsdb.MultiDataPoint {
	n, err := snmp_subtree(host, community, ifDescr)
	if err != nil {
		slog.Errorln("snmp ifaces:", err)
		return nil
	}
	a, err := snmp_subtree(host, community, ifAlias)
	if err != nil {
		slog.Errorln("snmp ifaces:", err)
		return nil
	}
	names := make(map[interface{}]string, len(n))
	aliases := make(map[interface{}]string, len(a))
	for k, v := range n {
		names[k] = fmt.Sprint(v)
	}
	for k, v := range a {
		aliases[k] = fmt.Sprint(v)
		if aliases[k] == "" {
			aliases[k] = "NA"
		}
	}
	var md opentsdb.MultiDataPoint
	add := func(oid, metric, dir string) error {
		m, err := snmp_subtree(host, community, oid)
		if err != nil {
			return err
		}
		for k, v := range m {
			Add(&md, switch_bond(metric, names[k]), v, opentsdb.TagSet{
				"host":      host,
				"direction": dir,
				"iface":     fmt.Sprint(k),
				"iname":     names[k],
				"alias":     aliases[k],
			})
		}
		return nil
	}
	oids := []snmpAdd{
		{ifHCInBroadcastPkts, osNetBroadcast, "in"},
		{ifHCInMulticastPkts, osNetMulticast, "in"},
		{ifHCInUcastPkts, osNetUnicast, "in"},
		{ifHCOutBroadcastPkts, osNetBroadcast, "out"},
		{ifHCOutMulticastPkts, osNetMulticast, "out"},
		{ifHCOutOctets, osNetBytes, "out"},
		{ifHCOutUcastPkts, osNetUnicast, "out"},
		{ifHCinOctets, osNetBytes, "in"},
		{ifInDiscards, osNetDropped, "in"},
		{ifInErrors, osNetErrors, "in"},
		{ifOutDiscards, osNetDropped, "out"},
		{ifOutErrors, osNetErrors, "out"},
	}
	for _, o := range oids {
		if err := add(o.oid, o.metric, o.dir); err != nil {
			slog.Errorln("snmp ifaces:", err)
			return nil
		}
	}
	return md
}

type snmpAdd struct {
	oid    string
	metric string
	dir    string
}
<commit_msg>cmd/scollector: Merge branch 'master' of github.com:StackExchange/scollector<commit_after>package collectors

import (
	"fmt"
	"strings"
	"time"

	"github.com/StackExchange/scollector/opentsdb"
	"github.com/StackExchange/slog"
)

const (
	ifAlias              = ".1.3.6.1.2.1.31.1.1.1.18"
	ifDescr              = ".1.3.6.1.2.1.2.2.1.2"
	ifHCInBroadcastPkts  = ".1.3.6.1.2.1.31.1.1.1.9"
	ifHCInMulticastPkts  = ".1.3.6.1.2.1.31.1.1.1.8"
	ifHCInUcastPkts      = ".1.3.6.1.2.1.31.1.1.1.7"
	ifHCOutBroadcastPkts = ".1.3.6.1.2.1.31.1.1.1.13"
	ifHCOutMulticastPkts = ".1.3.6.1.2.1.31.1.1.1.12"
	ifHCOutOctets        = ".1.3.6.1.2.1.31.1.1.1.10"
	ifHCOutUcastPkts     = ".1.3.6.1.2.1.31.1.1.1.11"
	ifHCinOctets         = ".1.3.6.1.2.1.31.1.1.1.6"
	ifInDiscards         = ".1.3.6.1.2.1.2.2.1.13"
	ifInErrors           = ".1.3.6.1.2.1.2.2.1.14"
	ifOutDiscards        = ".1.3.6.1.2.1.2.2.1.19"
	ifOutErrors          = ".1.3.6.1.2.1.2.2.1.20"
)

// SNMPIfaces registers a SNMP Interfaces collector for the given community and host.
func SNMPIfaces(community, host string) {
	collectors = append(collectors, &IntervalCollector{
		F: func() opentsdb.MultiDataPoint {
			return c_snmp_ifaces(community, host)
		},
		Interval: time.Minute * 5,
		name:     fmt.Sprintf("snmp-ifaces-%s", host),
	})
}

func switch_bond(metric, iname string) string {
	if strings.Contains(iname, "port-channel") {
		return "os.net.bond" + strings.TrimPrefix(metric, "os.net")
	}
	return metric
}

func c_snmp_ifaces(community, host string) opentsdb.MultiDataPoint {
	n, err := snmp_subtree(host, community, ifDescr)
	if err != nil {
		slog.Errorln("snmp ifaces:", err)
		return nil
	}
	a, err := snmp_subtree(host, community, ifAlias)
	if err != nil {
		slog.Errorln("snmp ifaces:", err)
		return nil
	}
	names := make(map[interface{}]string, len(n))
	aliases := make(map[interface{}]string, len(a))
	for k, v := range n {
		names[k] = fmt.Sprintf("%s", v)
	}
	for k, v := range a {
		// In case clean would come up empty, prevent the point from being removed
		// by setting our own empty case.
		aliases[k], _ = opentsdb.Clean(fmt.Sprintf("%s", v))
		if aliases[k] == "" {
			aliases[k] = "NA"
		}
	}
	var md opentsdb.MultiDataPoint
	add := func(oid, metric, dir string) error {
		m, err := snmp_subtree(host, community, oid)
		if err != nil {
			return err
		}
		for k, v := range m {
			Add(&md, switch_bond(metric, names[k]), v, opentsdb.TagSet{
				"host":      host,
				"direction": dir,
				"iface":     fmt.Sprintf("%s", k),
				"iname":     names[k],
				"alias":     aliases[k],
			})
		}
		return nil
	}
	oids := []snmpAdd{
		{ifHCInBroadcastPkts, osNetBroadcast, "in"},
		{ifHCInMulticastPkts, osNetMulticast, "in"},
		{ifHCInUcastPkts, osNetUnicast, "in"},
		{ifHCOutBroadcastPkts, osNetBroadcast, "out"},
		{ifHCOutMulticastPkts, osNetMulticast, "out"},
		{ifHCOutOctets, osNetBytes, "out"},
		{ifHCOutUcastPkts, osNetUnicast, "out"},
		{ifHCinOctets, osNetBytes, "in"},
		{ifInDiscards, osNetDropped, "in"},
		{ifInErrors, osNetErrors, "in"},
		{ifOutDiscards, osNetDropped, "out"},
		{ifOutErrors, osNetErrors, "out"},
	}
	for _, o := range oids {
		if err := add(o.oid, o.metric, o.dir); err != nil {
			slog.Errorln("snmp ifaces:", err)
			return nil
		}
	}
	return md
}

type snmpAdd struct {
	oid    string
	metric string
	dir    string
}
<|endoftext|>


<commit_before>package kong

import (
	"fmt"
	"net/http"

	"github.com/dghubble/sling"
	"github.com/hashicorp/terraform/helper/schema"
)

// Plugin : Kong Service/API plugin request object structure
type Plugin struct {
	ID            string                 `json:"id,omitempty"`
	Name          string                 `json:"name,omitempty"`
	Configuration map[string]interface{} `json:"config,omitempty"`
	API           string                 `json:"-"`
	Service       string                 `json:"-"`
	Route         string                 `json:"-"`
	Consumer      string                 `json:"consumer_id,omitempty"`
}

func resourceKongPlugin() *schema.Resource {
	return &schema.Resource{
		Create: resourceKongPluginCreate,
		Read:   resourceKongPluginRead,
		Update: resourceKongPluginUpdate,
		Delete: resourceKongPluginDelete,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"consumer": {
				Type:        schema.TypeString,
				Optional:    true,
				Default:     nil,
				Description: "The id of the consumer to scope this plugin to.",
			},

			"name": {
				Type:        schema.TypeString,
				Optional:    true,
				Default:     nil,
				Description: "The name of the plugin to use.",
			},

			"config": {
				Type:     schema.TypeMap,
				Optional: true,
				Elem:     schema.TypeString,
				Default:  nil,
			},

			"api": {
				Type:          schema.TypeString,
				Optional:      true,
				Deprecated:    "Use service or route instead.",
				Default:       nil,
				ConflictsWith: []string{"service", "route"},
			},

			"service": {
				Type:          schema.TypeString,
				Optional:      true,
				Default:       nil,
				ConflictsWith: []string{"api", "route"},
			},

			"route": {
				Type:          schema.TypeString,
				Optional:      true,
				Default:       nil,
				ConflictsWith: []string{"api", "service"},
			},
		},
	}
}

func resourceKongPluginCreate(d *schema.ResourceData, meta interface{}) error {
	sling := meta.(*sling.Sling)

	plugin := getPluginFromResourceData(d)

	createdPlugin := getPluginFromResourceData(d)

	request := sling.New().BodyJSON(plugin)
	if plugin.API != "" {
		request = request.Path("apis/").Path(plugin.API + "/")
	} else if plugin.Service != "" {
		request = request.Path("services/").Path(plugin.Service + "/")
	} else if plugin.Route != "" {
		request = request.Path("routes/").Path(plugin.Route + "/")
	}

	response, error := request.Post("plugins/").ReceiveSuccess(createdPlugin)
	if error != nil {
		return fmt.Errorf("error while creating plugin: " + error.Error())
	}

	if response.StatusCode == http.StatusConflict {
		return fmt.Errorf("409 Conflict - use terraform import to manage this plugin.")
	} else if response.StatusCode != http.StatusCreated {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	createdPlugin.Configuration = plugin.Configuration

	setPluginToResourceData(d, createdPlugin)

	return nil
}

func resourceKongPluginRead(d *schema.ResourceData, meta interface{}) error {
	sling := meta.(*sling.Sling)

	plugin := getPluginFromResourceData(d)

	configuration := make(map[string]interface{})
	for key, value := range plugin.Configuration {
		configuration[key] = value
	}

	response, error := sling.New().Path("plugins/").Get(plugin.ID).ReceiveSuccess(plugin)
	if error != nil {
		return fmt.Errorf("error while updating plugin: " + error.Error())
	}

	if response.StatusCode == http.StatusNotFound {
		d.SetId("")
		return nil
	} else if response.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	plugin.Configuration = configuration

	setPluginToResourceData(d, plugin)

	return nil
}

func resourceKongPluginUpdate(d *schema.ResourceData, meta interface{}) error {
	sling := meta.(*sling.Sling)

	plugin := getPluginFromResourceData(d)

	updatedPlugin := getPluginFromResourceData(d)

	response, error := sling.New().BodyJSON(plugin).Path("plugins/").Patch(plugin.ID).ReceiveSuccess(updatedPlugin)
	if error != nil {
		return fmt.Errorf("error while updating plugin: " + error.Error())
	}

	if response.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	updatedPlugin.Configuration = plugin.Configuration

	setPluginToResourceData(d, updatedPlugin)

	return nil
}

func resourceKongPluginDelete(d *schema.ResourceData, meta interface{}) error {
	sling := meta.(*sling.Sling)

	plugin := getPluginFromResourceData(d)

	response, error := sling.New().Path("plugins/").Delete(plugin.ID).ReceiveSuccess(nil)
	if error != nil {
		return fmt.Errorf("error while deleting plugin: " + error.Error())
	}

	if response.StatusCode != http.StatusNoContent {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	return nil
}

func getPluginFromResourceData(d *schema.ResourceData) *Plugin {
	plugin := &Plugin{
		ID:            d.Id(),
		Name:          d.Get("name").(string),
		Configuration: d.Get("config").(map[string]interface{}),
		API:           d.Get("api").(string),
		Service:       d.Get("service").(string),
		Route:         d.Get("route").(string),
		Consumer:      d.Get("consumer").(string),
	}

	return plugin
}

func setPluginToResourceData(d *schema.ResourceData, plugin *Plugin) {
	d.SetId(plugin.ID)
	d.Set("name", plugin.Name)
	d.Set("config", plugin.Configuration)
	d.Set("api", plugin.API)
	d.Set("service", plugin.Service)
	d.Set("route", plugin.Route)
	d.Set("consumer", plugin.Consumer)
}
<commit_msg>terraform 0.11.14 plugin compatibility changes<commit_after>package kong

import (
	"encoding/json"
	"fmt"
	"github.com/dghubble/sling"
	"github.com/hashicorp/terraform/helper/schema"
	"net/http"
	"net/url"
	"strings"
)

// Plugin : Kong Service/API plugin request object structure
type Plugin struct {
	ID            string                 `json:"id,omitempty"`
	Name          string                 `json:"name,omitempty"`
	Configuration map[string]interface{} `json:"config,omitempty"`
	API           string                 `json:"-"`
	Service       string                 `json:"-"`
	Route         string                 `json:"-"`
	Consumer      string                 `json:"consumer_id,omitempty"`
}

func resourceKongPlugin() *schema.Resource {
	return &schema.Resource{
		Create: resourceKongPluginCreate,
		Read:   resourceKongPluginRead,
		Update: resourceKongPluginUpdate,
		Delete: resourceKongPluginDelete,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"consumer": {
				Type:        schema.TypeString,
				Optional:    true,
				Default:     nil,
				Description: "The id of the consumer to scope this plugin to.",
			},

			"name": {
				Type:        schema.TypeString,
				Optional:    true,
				Default:     nil,
				Description: "The name of the plugin to use.",
			},

			"config": {
				Type:     schema.TypeMap,
				Optional: true,
				Elem:     schema.TypeString,
				Default:  nil,
				ConflictsWith: []string{ "config_json" },
			},

			"config_json": {
				Type: schema.TypeString,
				Optional: true,
				Default: nil,
				ConflictsWith: []string{ "config" },
			},

			"api": {
				Type:          schema.TypeString,
				Optional:      true,
				Deprecated:    "Use service or route instead.",
				Default:       nil,
				ConflictsWith: []string{"service", "route"},
			},

			"service": {
				Type:          schema.TypeString,
				Optional:      true,
				Default:       nil,
				ConflictsWith: []string{"api", "route"},
			},

			"route": {
				Type:          schema.TypeString,
				Optional:      true,
				Default:       nil,
				ConflictsWith: []string{"api", "service"},
			},
		},
	}
}

func resourceKongPluginCreate(d *schema.ResourceData, meta interface{}) error {
	request := buildModifyRequest(d, meta)
	p := &Plugin{}

	if api, ok := d.GetOk("api"); ok {
		request = request.Path("apis/").Path(api.(string) + "/")
	} else if service, ok := d.GetOk("service"); ok {
		request = request.Path("services/").Path(service.(string) + "/")
	} else if route, ok := d.GetOk("route"); ok {
		request = request.Path("routes/").Path(route.(string) + "/")
	}

	response, err := request.Post("plugins/").ReceiveSuccess(p)
	if err != nil {
		return fmt.Errorf("error while creating plugin: " + err.Error())
	}

	if response.StatusCode == http.StatusConflict {
		return fmt.Errorf("409 Conflict - use terraform import to manage this plugin.")
	} else if response.StatusCode != http.StatusCreated {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	return setPluginToResourceData(d, p)
}

func resourceKongPluginRead(d *schema.ResourceData, meta interface{}) error {
	sling := meta.(*sling.Sling)

	p := &Plugin{}

	response, err := sling.New().Path("plugins/").Get(d.Id()).ReceiveSuccess(p)
	if err != nil {
		return fmt.Errorf("error while updating plugin: " + err.Error())
	}

	if response.StatusCode == http.StatusNotFound {
		d.SetId("")
		return nil
	} else if response.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	return setPluginToResourceData(d, p)
}

func resourceKongPluginUpdate(d *schema.ResourceData, meta interface{}) error {
	request := buildModifyRequest(d, meta)

	p := &Plugin{}

	response, err := request.Path("plugins/").Patch(d.Id()).ReceiveSuccess(p)
	if err != nil {
		return fmt.Errorf("error while updating plugin: " + err.Error())
	}

	if response.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	return setPluginToResourceData(d, p)
}

func resourceKongPluginDelete(d *schema.ResourceData, meta interface{}) error {
	sling := meta.(*sling.Sling)

	response, error := sling.New().Path("plugins/").Delete(d.Id()).ReceiveSuccess(nil)
	if error != nil {
		return fmt.Errorf("error while deleting plugin: " + error.Error())
	}

	if response.StatusCode != http.StatusNoContent {
		return fmt.Errorf("unexpected status code received: " + response.Status)
	}

	return nil
}

func buildModifyRequest(d *schema.ResourceData, meta interface{}) *sling.Sling {
	request := meta.(*sling.Sling).New()

	plugin := &Plugin{
		ID:            d.Id(),
		Name:          d.Get("name").(string),
		API:           d.Get("api").(string),
		Service:       d.Get("service").(string),
		Route:         d.Get("route").(string),
		Consumer:      d.Get("consumer").(string),
	}

	if c, ok := d.GetOk("config"); ok {
		form := url.Values{
			"name": {plugin.Name},
		}

		conf := c.(map[string]interface{})
		for k, v := range conf {
			form.Add("config." + k, v.(string))
		}

		body := strings.NewReader(form.Encode())

		request = request.Body(body).Set("Content-Type", "application/x-www-form-urlencoded")
	} else if c, ok := d.GetOk("config_json"); ok {
		config := make(map[string]interface{})
		err := json.Unmarshal([]byte(c.(string)), &config)
		if err != nil {
			// ...
		}

		plugin.Configuration = config

		request = request.BodyJSON(plugin)
	}

	return request
}

func setPluginToResourceData(d *schema.ResourceData, plugin *Plugin) error {
	d.SetId(plugin.ID)

	_ = d.Set("name", plugin.Name)

	// There are differences in the way service/route IDs are returned from Kong after creation and update between
	// version before and after 1.0.0. We are risking some drift here. This will be handled in later versions.
	if api, ok := d.GetOk("api"); ok {
		plugin.API = api.(string)
	} else if service, ok := d.GetOk("service"); ok {
		plugin.Service = service.(string)
	} else if route, ok := d.GetOk("route"); ok {
		plugin.Route = route.(string)
	}

	_ = d.Set("api", plugin.API)
	_ = d.Set("service", plugin.Service)
	_ = d.Set("route", plugin.Route)
	_ = d.Set("consumer", plugin.Consumer)

	return nil
}<|endoftext|>