<commit_before>package assert

import (
	"fmt"
	"reflect"
	"runtime"
	"strings"
	"time"
)

// TestingT is an interface wrapper around *testing.T
type TestingT interface {
	Errorf(format string, args ...interface{})
}

// Comparison a custom function that returns true on success and false on failure
type Comparison func() (success bool)

/*
	Helper functions
*/

// ObjectsAreEqual determines if two objects are considered equal.
//
// This function does no assertion of any kind.
func ObjectsAreEqual(expected, actual interface{}) bool {

	if reflect.DeepEqual(expected, actual) {
		return true
	}

	if reflect.ValueOf(expected) == reflect.ValueOf(actual) {
		return true
	}

	// Last ditch effort
	if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) {
		return true
	}

	return false

}

/* CallerInfo is necessary because the assert functions use the testing object
internally, causing it to print the file:line of the assert method, rather than where
the problem actually occured in calling code.*/

// CallerInfo returns a string containing the file and line number of the assert call
// that failed.
func CallerInfo() string {

	file := ""
	line := 0
	ok := false

	for i := 0; ; i++ {
		_, file, line, ok = runtime.Caller(i)
		if !ok {
			return ""
		}
		parts := strings.Split(file, "/")
		dir := parts[len(parts)-2]
		file = parts[len(parts)-1]
		if (dir != "assert" && dir != "mock") || file == "mock_test.go" {
			break
		}
	}

	return fmt.Sprintf("%s:%d", file, line)
}

// getWhitespaceString returns a string that is long enough to overwrite the default
// output from the go testing framework.
func getWhitespaceString() string {

	_, file, line, ok := runtime.Caller(1)
	if !ok {
		return ""
	}
	parts := strings.Split(file, "/")
	file = parts[len(parts)-1]

	return strings.Repeat(" ", len(fmt.Sprintf("%s:%d:      ", file, line)))

}

func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
	if len(msgAndArgs) == 0 || msgAndArgs == nil {
		return ""
	}
	if len(msgAndArgs) == 1 {
		return msgAndArgs[0].(string)
	}
	if len(msgAndArgs) > 1 {
		return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
	}
	return ""
}

// Fail reports a failure through
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)

	if len(message) > 0 {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r\tMessages:\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage, message)
	} else {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage)
	}

	return false
}

// Implements asserts that an object is implemented by the specified interface.
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	interfaceType := reflect.TypeOf(interfaceObject).Elem()

	if !reflect.TypeOf(object).Implements(interfaceType) {
		return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
	}

	return true

}

// IsType asserts that the specified objects are of the same type.
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
		return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
	}

	return true
}

// Equal asserts that two objects are equal.
//
//    assert.Equal(t, 123, 123, "123 and 123 should be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(expected, actual) {
		return Fail(t, fmt.Sprintf("Not equal: %#v != %#v", expected, actual), msgAndArgs...)
	}

	return true

}

// Exactly asserts that two objects are equal is value and type.
//
//    assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	aType := reflect.TypeOf(expected)
	bType := reflect.TypeOf(actual)

	if aType != bType {
		return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
	}

	return Equal(t, expected, actual, msgAndArgs...)

}

// NotNil asserts that the specified object is not nil.
//
//    assert.NotNil(t, err, "err should be something")
//
// Returns whether the assertion was successful (true) or not (false).
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	var success bool = true

	if object == nil {
		success = false
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			success = false
		}
	}

	if !success {
		Fail(t, "Expected not to be nil.", msgAndArgs...)
	}

	return success
}

// Nil asserts that the specified object is nil.
//
//    assert.Nil(t, err, "err should be nothing")
//
// Returns whether the assertion was successful (true) or not (false).
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	if object == nil {
		return true
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			return true
		}
	}

	return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
}

// isEmpty gets whether the specified object is considered empty or not.
func isEmpty(object interface{}) bool {

	if object == nil {
		return true
	} else if object == "" {
		return true
	} else if object == 0 {
		return true
	} else if object == false {
		return true
	}

	objValue := reflect.ValueOf(object)
	switch objValue.Kind() {
	case reflect.Map:
		fallthrough
	case reflect.Slice:
		{
			return (objValue.Len() == 0)
		}
	}

	return false

}

// Empty asserts that the specified object is empty.  I.e. nil, "", false, 0 or a
// slice with len == 0.
//
// assert.Empty(t, obj)
//
// Returns whether the assertion was successful (true) or not (false).
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// Empty asserts that the specified object is NOT empty.  I.e. not nil, "", false, 0 or a
// slice with len == 0.
//
// if assert.NotEmpty(t, obj) {
//   assert.Equal(t, "two", obj[1])
// }
//
// Returns whether the assertion was successful (true) or not (false).
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := !isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// True asserts that the specified value is true.
//
//    assert.True(t, myBool, "myBool should be true")
//
// Returns whether the assertion was successful (true) or not (false).
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != true {
		return Fail(t, "Should be true", msgAndArgs...)
	}

	return true

}

// False asserts that the specified value is true.
//
//    assert.False(t, myBool, "myBool should be false")
//
// Returns whether the assertion was successful (true) or not (false).
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != false {
		return Fail(t, "Should be false", msgAndArgs...)
	}

	return true

}

// NotEqual asserts that the specified values are NOT equal.
//
//    assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	if ObjectsAreEqual(expected, actual) {
		return Fail(t, "Should not be equal", msgAndArgs...)
	}

	return true

}

// Contains asserts that the specified string contains the specified substring.
//
//    assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
//
// Returns whether the assertion was successful (true) or not (false).
func Contains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if !strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// NotContains asserts that the specified string does NOT contain the specified substring.
//
//    assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
//
// Returns whether the assertion was successful (true) or not (false).
func NotContains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// Uses a Comparison to assert a complex condition.
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
	result := comp()
	if !result {
		Fail(t, "Condition failed!", msgAndArgs...)
	}
	return result
}

// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
// methods, and represents a simple func that takes no arguments, and returns nothing.
type PanicTestFunc func()

// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
func didPanic(f PanicTestFunc) (bool, interface{}) {

	var didPanic bool = false
	var message interface{}
	func() {

		defer func() {
			if message = recover(); message != nil {
				didPanic = true
			}
		}()

		// call the target function
		f()

	}()

	return didPanic, message

}

// Panics asserts that the code inside the specified PanicTestFunc panics.
//
//   assert.Panics(t, func(){
//     GoCrazy()
//   }, "Calling GoCrazy() should panic")
//
// Returns whether the assertion was successful (true) or not (false).
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
//
//   assert.NotPanics(t, func(){
//     RemainCalm()
//   }, "Calling RemainCalm() should NOT panic")
//
// Returns whether the assertion was successful (true) or not (false).
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// WithinDuration asserts that the two times are within duration delta of each other.
//
//   assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
//
// Returns whether the assertion was successful (true) or not (false).
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {

	dt := expected.Sub(actual)
	if dt < -delta || dt > delta {
		return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, dt, delta), msgAndArgs...)
	}

	return true
}

/*
	Errors
*/

// NoError asserts that a function returned no error (i.e. `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.NoError(t, err) {
//	   assert.Equal(t, actualObj, expectedObj)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func NoError(t TestingT, theError error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return Nil(t, theError, "No error is expected but got %v %s", theError, message)

}

// Error asserts that a function returned an error (i.e. not `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.Error(t, err, "An error was expected") {
//	   assert.Equal(t, err, expectedError)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func Error(t TestingT, theError error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return NotNil(t, theError, "An error is expected but got nil. %s", message)

}
<commit_msg>Rename the error argument from theError to err in Error asserts.<commit_after>package assert

import (
	"fmt"
	"reflect"
	"runtime"
	"strings"
	"time"
)

// TestingT is an interface wrapper around *testing.T
type TestingT interface {
	Errorf(format string, args ...interface{})
}

// Comparison a custom function that returns true on success and false on failure
type Comparison func() (success bool)

/*
	Helper functions
*/

// ObjectsAreEqual determines if two objects are considered equal.
//
// This function does no assertion of any kind.
func ObjectsAreEqual(expected, actual interface{}) bool {

	if reflect.DeepEqual(expected, actual) {
		return true
	}

	if reflect.ValueOf(expected) == reflect.ValueOf(actual) {
		return true
	}

	// Last ditch effort
	if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) {
		return true
	}

	return false

}

/* CallerInfo is necessary because the assert functions use the testing object
internally, causing it to print the file:line of the assert method, rather than where
the problem actually occured in calling code.*/

// CallerInfo returns a string containing the file and line number of the assert call
// that failed.
func CallerInfo() string {

	file := ""
	line := 0
	ok := false

	for i := 0; ; i++ {
		_, file, line, ok = runtime.Caller(i)
		if !ok {
			return ""
		}
		parts := strings.Split(file, "/")
		dir := parts[len(parts)-2]
		file = parts[len(parts)-1]
		if (dir != "assert" && dir != "mock") || file == "mock_test.go" {
			break
		}
	}

	return fmt.Sprintf("%s:%d", file, line)
}

// getWhitespaceString returns a string that is long enough to overwrite the default
// output from the go testing framework.
func getWhitespaceString() string {

	_, file, line, ok := runtime.Caller(1)
	if !ok {
		return ""
	}
	parts := strings.Split(file, "/")
	file = parts[len(parts)-1]

	return strings.Repeat(" ", len(fmt.Sprintf("%s:%d:      ", file, line)))

}

func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
	if len(msgAndArgs) == 0 || msgAndArgs == nil {
		return ""
	}
	if len(msgAndArgs) == 1 {
		return msgAndArgs[0].(string)
	}
	if len(msgAndArgs) > 1 {
		return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
	}
	return ""
}

// Fail reports a failure through
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)

	if len(message) > 0 {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r\tMessages:\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage, message)
	} else {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage)
	}

	return false
}

// Implements asserts that an object is implemented by the specified interface.
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	interfaceType := reflect.TypeOf(interfaceObject).Elem()

	if !reflect.TypeOf(object).Implements(interfaceType) {
		return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
	}

	return true

}

// IsType asserts that the specified objects are of the same type.
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
		return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
	}

	return true
}

// Equal asserts that two objects are equal.
//
//    assert.Equal(t, 123, 123, "123 and 123 should be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(expected, actual) {
		return Fail(t, fmt.Sprintf("Not equal: %#v != %#v", expected, actual), msgAndArgs...)
	}

	return true

}

// Exactly asserts that two objects are equal is value and type.
//
//    assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	aType := reflect.TypeOf(expected)
	bType := reflect.TypeOf(actual)

	if aType != bType {
		return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
	}

	return Equal(t, expected, actual, msgAndArgs...)

}

// NotNil asserts that the specified object is not nil.
//
//    assert.NotNil(t, err, "err should be something")
//
// Returns whether the assertion was successful (true) or not (false).
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	var success bool = true

	if object == nil {
		success = false
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			success = false
		}
	}

	if !success {
		Fail(t, "Expected not to be nil.", msgAndArgs...)
	}

	return success
}

// Nil asserts that the specified object is nil.
//
//    assert.Nil(t, err, "err should be nothing")
//
// Returns whether the assertion was successful (true) or not (false).
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	if object == nil {
		return true
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			return true
		}
	}

	return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
}

// isEmpty gets whether the specified object is considered empty or not.
func isEmpty(object interface{}) bool {

	if object == nil {
		return true
	} else if object == "" {
		return true
	} else if object == 0 {
		return true
	} else if object == false {
		return true
	}

	objValue := reflect.ValueOf(object)
	switch objValue.Kind() {
	case reflect.Map:
		fallthrough
	case reflect.Slice:
		{
			return (objValue.Len() == 0)
		}
	}

	return false

}

// Empty asserts that the specified object is empty.  I.e. nil, "", false, 0 or a
// slice with len == 0.
//
// assert.Empty(t, obj)
//
// Returns whether the assertion was successful (true) or not (false).
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// Empty asserts that the specified object is NOT empty.  I.e. not nil, "", false, 0 or a
// slice with len == 0.
//
// if assert.NotEmpty(t, obj) {
//   assert.Equal(t, "two", obj[1])
// }
//
// Returns whether the assertion was successful (true) or not (false).
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := !isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// True asserts that the specified value is true.
//
//    assert.True(t, myBool, "myBool should be true")
//
// Returns whether the assertion was successful (true) or not (false).
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != true {
		return Fail(t, "Should be true", msgAndArgs...)
	}

	return true

}

// False asserts that the specified value is true.
//
//    assert.False(t, myBool, "myBool should be false")
//
// Returns whether the assertion was successful (true) or not (false).
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != false {
		return Fail(t, "Should be false", msgAndArgs...)
	}

	return true

}

// NotEqual asserts that the specified values are NOT equal.
//
//    assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	if ObjectsAreEqual(expected, actual) {
		return Fail(t, "Should not be equal", msgAndArgs...)
	}

	return true

}

// Contains asserts that the specified string contains the specified substring.
//
//    assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
//
// Returns whether the assertion was successful (true) or not (false).
func Contains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if !strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// NotContains asserts that the specified string does NOT contain the specified substring.
//
//    assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
//
// Returns whether the assertion was successful (true) or not (false).
func NotContains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// Uses a Comparison to assert a complex condition.
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
	result := comp()
	if !result {
		Fail(t, "Condition failed!", msgAndArgs...)
	}
	return result
}

// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
// methods, and represents a simple func that takes no arguments, and returns nothing.
type PanicTestFunc func()

// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
func didPanic(f PanicTestFunc) (bool, interface{}) {

	var didPanic bool = false
	var message interface{}
	func() {

		defer func() {
			if message = recover(); message != nil {
				didPanic = true
			}
		}()

		// call the target function
		f()

	}()

	return didPanic, message

}

// Panics asserts that the code inside the specified PanicTestFunc panics.
//
//   assert.Panics(t, func(){
//     GoCrazy()
//   }, "Calling GoCrazy() should panic")
//
// Returns whether the assertion was successful (true) or not (false).
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
//
//   assert.NotPanics(t, func(){
//     RemainCalm()
//   }, "Calling RemainCalm() should NOT panic")
//
// Returns whether the assertion was successful (true) or not (false).
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// WithinDuration asserts that the two times are within duration delta of each other.
//
//   assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
//
// Returns whether the assertion was successful (true) or not (false).
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {

	dt := expected.Sub(actual)
	if dt < -delta || dt > delta {
		return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, dt, delta), msgAndArgs...)
	}

	return true
}

/*
	Errors
*/

// NoError asserts that a function returned no error (i.e. `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.NoError(t, err) {
//	   assert.Equal(t, actualObj, expectedObj)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return Nil(t, err, "No error is expected but got %v %s", err, message)

}

// Error asserts that a function returned an error (i.e. not `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.Error(t, err, "An error was expected") {
//	   assert.Equal(t, err, expectedError)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return NotNil(t, err, "An error is expected but got nil. %s", message)

}
<|endoftext|>


<commit_before>// Copyright 2014 tsuru 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 oauth

import (
	goauth2 "code.google.com/p/goauth2/oauth"
	"encoding/json"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/auth"
	"github.com/tsuru/tsuru/auth/native"
	tsuruErrors "github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/log"
	"net/http"
	"strconv"
)

var (
	ErrMissingCodeError       = &tsuruErrors.ValidationError{Message: "You must provide code to login"}
	ErrMissingCodeRedirectUrl = &tsuruErrors.ValidationError{Message: "You must provide the used redirect url to login"}
	ErrEmptyAccessToken       = &tsuruErrors.NotAuthorizedError{Message: "Couldn't convert code to access token."}
	ErrEmptyUserEmail         = &tsuruErrors.NotAuthorizedError{Message: "Couldn't parse user email."}
)

type OAuthParser interface {
	Parse(infoResponse *http.Response) (string, error)
}

type OAuthScheme struct {
	BaseConfig   goauth2.Config
	InfoUrl      string
	CallbackPort int
	Parser       OAuthParser
}

type DBTokenCache struct {
	scheme *OAuthScheme
}

func (c *DBTokenCache) Token() (*goauth2.Token, error) {
	return nil, nil
}

func (c *DBTokenCache) PutToken(t *goauth2.Token) error {
	if t.AccessToken == "" {
		return ErrEmptyAccessToken
	}
	var email string
	if t.Extra == nil || t.Extra["email"] == "" {
		conf, err := c.scheme.loadConfig()
		if err != nil {
			return err
		}
		transport := &goauth2.Transport{Config: &conf}
		transport.Token = t
		client := transport.Client()
		response, err := client.Get(c.scheme.InfoUrl)
		if err != nil {
			return err
		}
		email, err = c.scheme.Parser.Parse(response)
		if email == "" {
			return ErrEmptyUserEmail
		}
		_, err = auth.GetUserByEmail(email)
		if err != nil {
			if err != auth.ErrUserNotFound {
				return err
			}
			registrationEnabled, _ := config.GetBool("auth:user-registration")
			if !registrationEnabled {
				return err
			}
			user := auth.User{Email: email}
			err := user.Create()
			if err != nil {
				return err
			}
			err = user.CreateOnGandalf()
			if err != nil {
				return err
			}
		}
		t.Extra = make(map[string]string)
		t.Extra["email"] = email
	}
	return makeToken(t).save()
}

func init() {
	auth.RegisterScheme("oauth", &OAuthScheme{})
}

// This method loads basic config and returns a copy of the
// config object.
func (s *OAuthScheme) loadConfig() (goauth2.Config, error) {
	if s.BaseConfig.ClientId != "" {
		return s.BaseConfig, nil
	}
	if s.Parser == nil {
		s.Parser = s
	}
	var emptyConfig goauth2.Config
	clientId, err := config.GetString("auth:oauth:client-id")
	if err != nil {
		return emptyConfig, err
	}
	clientSecret, err := config.GetString("auth:oauth:client-secret")
	if err != nil {
		return emptyConfig, err
	}
	scope, err := config.GetString("auth:oauth:scope")
	if err != nil {
		return emptyConfig, err
	}
	authURL, err := config.GetString("auth:oauth:auth-url")
	if err != nil {
		return emptyConfig, err
	}
	tokenURL, err := config.GetString("auth:oauth:token-url")
	if err != nil {
		return emptyConfig, err
	}
	infoURL, err := config.GetString("auth:oauth:info-url")
	if err != nil {
		return emptyConfig, err
	}
	callbackPort, err := config.GetInt("auth:oauth:callback-port")
	if err != nil {
		log.Debugf("auth:oauth:callback-port not found using random port: %s", err)
	}
	s.InfoUrl = infoURL
	s.CallbackPort = callbackPort
	s.BaseConfig = goauth2.Config{
		ClientId:     clientId,
		ClientSecret: clientSecret,
		Scope:        scope,
		AuthURL:      authURL,
		TokenURL:     tokenURL,
		TokenCache:   &DBTokenCache{s},
	}
	return s.BaseConfig, nil
}

func (s *OAuthScheme) Login(params map[string]string) (auth.Token, error) {
	config, err := s.loadConfig()
	if err != nil {
		return nil, err
	}
	code, ok := params["code"]
	if !ok {
		return nil, ErrMissingCodeError
	}
	redirectUrl, ok := params["redirectUrl"]
	if !ok {
		return nil, ErrMissingCodeRedirectUrl
	}
	config.RedirectURL = redirectUrl
	transport := &goauth2.Transport{Config: &config}
	oauthToken, err := transport.Exchange(code)
	if err != nil {
		return nil, err
	}
	return makeToken(oauthToken), nil
}

func (s *OAuthScheme) AppLogin(appName string) (auth.Token, error) {
	nativeScheme := native.NativeScheme{}
	return nativeScheme.AppLogin(appName)
}

func (s *OAuthScheme) Logout(token string) error {
	return deleteToken(token)
}

func (s *OAuthScheme) Auth(header string) (auth.Token, error) {
	token, err := getToken(header)
	if err != nil {
		nativeScheme := native.NativeScheme{}
		token, nativeErr := nativeScheme.Auth(header)
		if nativeErr == nil && token.IsAppToken() {
			return token, nil
		}
		return nil, err
	}
	config, err := s.loadConfig()
	if err != nil {
		return nil, err
	}
	transport := goauth2.Transport{Config: &config}
	transport.Token = &token.Token
	client := transport.Client()
	_, err = client.Get(s.InfoUrl)
	if err != nil {
		return nil, err
	}
	return makeToken(transport.Token), nil
}

func (s *OAuthScheme) Name() string {
	return "oauth"
}

func (s *OAuthScheme) Info() (auth.SchemeInfo, error) {
	config, err := s.loadConfig()
	if err != nil {
		return nil, err
	}
	config.RedirectURL = "__redirect_url__"
	return auth.SchemeInfo{"authorizeUrl": config.AuthCodeURL(""), "port": strconv.Itoa(s.CallbackPort)}, nil
}

func (s *OAuthScheme) Parse(infoResponse *http.Response) (string, error) {
	user := struct {
		Email string `json:"email"`
	}{}
	err := json.NewDecoder(infoResponse.Body).Decode(&user)
	if err != nil {
		return user.Email, err
	}
	return user.Email, nil
}

func (s *OAuthScheme) Create(user *auth.User) (*auth.User, error) {
	err := user.Create()
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (s *OAuthScheme) Remove(token auth.Token) error {
	u, err := token.User()
	if err != nil {
		return err
	}
	err = deleteAllTokens(u.Email)
	if err != nil {
		return err
	}
	return u.Delete()
}
<commit_msg>auth/oauth: tries to create user on gandalf on login<commit_after>// Copyright 2014 tsuru 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 oauth

import (
	goauth2 "code.google.com/p/goauth2/oauth"
	"encoding/json"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/auth"
	"github.com/tsuru/tsuru/auth/native"
	tsuruErrors "github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/log"
	"net/http"
	"strconv"
)

var (
	ErrMissingCodeError       = &tsuruErrors.ValidationError{Message: "You must provide code to login"}
	ErrMissingCodeRedirectUrl = &tsuruErrors.ValidationError{Message: "You must provide the used redirect url to login"}
	ErrEmptyAccessToken       = &tsuruErrors.NotAuthorizedError{Message: "Couldn't convert code to access token."}
	ErrEmptyUserEmail         = &tsuruErrors.NotAuthorizedError{Message: "Couldn't parse user email."}
)

type OAuthParser interface {
	Parse(infoResponse *http.Response) (string, error)
}

type OAuthScheme struct {
	BaseConfig   goauth2.Config
	InfoUrl      string
	CallbackPort int
	Parser       OAuthParser
}

type DBTokenCache struct {
	scheme *OAuthScheme
}

func (c *DBTokenCache) Token() (*goauth2.Token, error) {
	return nil, nil
}

func (c *DBTokenCache) PutToken(t *goauth2.Token) error {
	if t.AccessToken == "" {
		return ErrEmptyAccessToken
	}
	var email string
	if t.Extra == nil || t.Extra["email"] == "" {
		conf, err := c.scheme.loadConfig()
		if err != nil {
			return err
		}
		transport := &goauth2.Transport{Config: &conf}
		transport.Token = t
		client := transport.Client()
		response, err := client.Get(c.scheme.InfoUrl)
		if err != nil {
			return err
		}
		email, err = c.scheme.Parser.Parse(response)
		if email == "" {
			return ErrEmptyUserEmail
		}
		user, err := auth.GetUserByEmail(email)
		if err != nil {
			if err != auth.ErrUserNotFound {
				return err
			}
			registrationEnabled, _ := config.GetBool("auth:user-registration")
			if !registrationEnabled {
				return err
			}
			user = &auth.User{Email: email}
			err := user.Create()
			if err != nil {
				return err
			}
		}
		err = user.CreateOnGandalf()
		if err != nil {
			log.Errorf("Ignored error trying to create user on gandalf: %s", err.Error())
		}
		t.Extra = make(map[string]string)
		t.Extra["email"] = email
	}
	return makeToken(t).save()
}

func init() {
	auth.RegisterScheme("oauth", &OAuthScheme{})
}

// This method loads basic config and returns a copy of the
// config object.
func (s *OAuthScheme) loadConfig() (goauth2.Config, error) {
	if s.BaseConfig.ClientId != "" {
		return s.BaseConfig, nil
	}
	if s.Parser == nil {
		s.Parser = s
	}
	var emptyConfig goauth2.Config
	clientId, err := config.GetString("auth:oauth:client-id")
	if err != nil {
		return emptyConfig, err
	}
	clientSecret, err := config.GetString("auth:oauth:client-secret")
	if err != nil {
		return emptyConfig, err
	}
	scope, err := config.GetString("auth:oauth:scope")
	if err != nil {
		return emptyConfig, err
	}
	authURL, err := config.GetString("auth:oauth:auth-url")
	if err != nil {
		return emptyConfig, err
	}
	tokenURL, err := config.GetString("auth:oauth:token-url")
	if err != nil {
		return emptyConfig, err
	}
	infoURL, err := config.GetString("auth:oauth:info-url")
	if err != nil {
		return emptyConfig, err
	}
	callbackPort, err := config.GetInt("auth:oauth:callback-port")
	if err != nil {
		log.Debugf("auth:oauth:callback-port not found using random port: %s", err)
	}
	s.InfoUrl = infoURL
	s.CallbackPort = callbackPort
	s.BaseConfig = goauth2.Config{
		ClientId:     clientId,
		ClientSecret: clientSecret,
		Scope:        scope,
		AuthURL:      authURL,
		TokenURL:     tokenURL,
		TokenCache:   &DBTokenCache{s},
	}
	return s.BaseConfig, nil
}

func (s *OAuthScheme) Login(params map[string]string) (auth.Token, error) {
	config, err := s.loadConfig()
	if err != nil {
		return nil, err
	}
	code, ok := params["code"]
	if !ok {
		return nil, ErrMissingCodeError
	}
	redirectUrl, ok := params["redirectUrl"]
	if !ok {
		return nil, ErrMissingCodeRedirectUrl
	}
	config.RedirectURL = redirectUrl
	transport := &goauth2.Transport{Config: &config}
	oauthToken, err := transport.Exchange(code)
	if err != nil {
		return nil, err
	}
	return makeToken(oauthToken), nil
}

func (s *OAuthScheme) AppLogin(appName string) (auth.Token, error) {
	nativeScheme := native.NativeScheme{}
	return nativeScheme.AppLogin(appName)
}

func (s *OAuthScheme) Logout(token string) error {
	return deleteToken(token)
}

func (s *OAuthScheme) Auth(header string) (auth.Token, error) {
	token, err := getToken(header)
	if err != nil {
		nativeScheme := native.NativeScheme{}
		token, nativeErr := nativeScheme.Auth(header)
		if nativeErr == nil && token.IsAppToken() {
			return token, nil
		}
		return nil, err
	}
	config, err := s.loadConfig()
	if err != nil {
		return nil, err
	}
	transport := goauth2.Transport{Config: &config}
	transport.Token = &token.Token
	client := transport.Client()
	_, err = client.Get(s.InfoUrl)
	if err != nil {
		return nil, err
	}
	return makeToken(transport.Token), nil
}

func (s *OAuthScheme) Name() string {
	return "oauth"
}

func (s *OAuthScheme) Info() (auth.SchemeInfo, error) {
	config, err := s.loadConfig()
	if err != nil {
		return nil, err
	}
	config.RedirectURL = "__redirect_url__"
	return auth.SchemeInfo{"authorizeUrl": config.AuthCodeURL(""), "port": strconv.Itoa(s.CallbackPort)}, nil
}

func (s *OAuthScheme) Parse(infoResponse *http.Response) (string, error) {
	user := struct {
		Email string `json:"email"`
	}{}
	err := json.NewDecoder(infoResponse.Body).Decode(&user)
	if err != nil {
		return user.Email, err
	}
	return user.Email, nil
}

func (s *OAuthScheme) Create(user *auth.User) (*auth.User, error) {
	err := user.Create()
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (s *OAuthScheme) Remove(token auth.Token) error {
	u, err := token.User()
	if err != nil {
		return err
	}
	err = deleteAllTokens(u.Email)
	if err != nil {
		return err
	}
	return u.Delete()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/codegangsta/cli"
	"github.com/coreos/go-semver/semver"
	"github.com/fatih/color"
	De "github.com/visionmedia/go-debug"
)

var debug = De.Debug("{{.ProjectName}}:main")

func main() {
	app := cli.NewApp()
	app.Name = "{{.ProjectName}}"
	app.Version = version()
	app.Action = run
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "example, e",
			EnvVar: "{{.PROJECTNAME}}_EXAMPLE",
			Usage:  "Example string flag",
		},
	}
	app.Run(os.Args)
}

func run(context *cli.Context) {
	example := getOpts(context)

	sigTerm := make(chan os.Signal)
	signal.Notify(sigTerm, syscall.SIGTERM)

	sigTermReceived := false

	go func() {
		<-sigTerm
		fmt.Println("SIGTERM received, waiting to exit")
		sigTermReceived = true
	}()

	for {
		if sigTermReceived {
			fmt.Println("I'll be back.")
			os.Exit(0)
		}

		debug("{{.ProjectName}}.loop: %v", example)
		time.Sleep(1 * time.Second)
	}
}

func getOpts(context *cli.Context) string {
	example := context.String("example")

	if example == "" {
		cli.ShowAppHelp(context)

		if example == "" {
			color.Red("  Missing required flag --example or {{.PROJECTNAME}}_EXAMPLE")
		}
		os.Exit(1)
	}

	return example
}

func version() string {
	version, err := semver.NewVersion(VERSION)
	if err != nil {
		errorMessage := fmt.Sprintf("Error with version number: %v", VERSION)
		log.Panicln(errorMessage, err.Error())
	}
	return version.String()
}
<commit_msg>Fix the templates<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/urfave/cli"
	"github.com/coreos/go-semver/semver"
	"github.com/fatih/color"
	De "github.com/visionmedia/go-debug"
)

var debug = De.Debug("{{.ProjectName}}:main")

func main() {
	app := cli.NewApp()
	app.Name = "{{.ProjectName}}"
	app.Version = version()
	app.Action = run
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "example, e",
			EnvVar: "{{.PROJECTNAME}}_EXAMPLE",
			Usage:  "Example string flag",
		},
	}
	app.Run(os.Args)
}

func run(context *cli.Context) {
	example := getOpts(context)

	sigTerm := make(chan os.Signal)
	signal.Notify(sigTerm, syscall.SIGTERM)

	sigTermReceived := false

	go func() {
		<-sigTerm
		fmt.Println("SIGTERM received, waiting to exit")
		sigTermReceived = true
	}()

	for {
		if sigTermReceived {
			fmt.Println("I'll be back.")
			os.Exit(0)
		}

		debug("{{.ProjectName}}.loop: %v", example)
		time.Sleep(1 * time.Second)
	}
}

func getOpts(context *cli.Context) string {
	example := context.String("example")

	if example == "" {
		cli.ShowAppHelp(context)

		if example == "" {
			color.Red("  Missing required flag --example or {{.PROJECTNAME}}_EXAMPLE")
		}
		os.Exit(1)
	}

	return example
}

func version() string {
	version, err := semver.NewVersion(VERSION)
	if err != nil {
		errorMessage := fmt.Sprintf("Error with version number: %v", VERSION)
		log.Panicln(errorMessage, err.Error())
	}
	return version.String()
}
<|endoftext|>


<commit_before>// Copyright 2014 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 dataflow provides data flow analyses that can be performed on a
// previously constructed control flow graph, including a reaching definitions
// analysis and a live variables analysis for local variables.
package dataflow

// This file contains functions common to all data flow analyses, as well as
// one exported function.

import (
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/loader"
	"code.google.com/p/go.tools/go/types"
)

// ReferencedVars returns the sets of local variables that are defined or used
// within the given list of statements (based on syntax).
func ReferencedVars(stmts []ast.Stmt, info *loader.PackageInfo) (def, use map[*types.Var]struct{}) {
	def = make(map[*types.Var]struct{})
	use = make(map[*types.Var]struct{})

	for _, stmt := range stmts {
		for _, d := range defs(stmt, info) {
			def[d] = struct{}{}
		}
		for _, u := range uses(stmt, info) {
			use[u] = struct{}{}
		}
	}
	return def, use
}

// defs extracts any local variables whose values are assigned in the given statement.
func defs(stmt ast.Stmt, info *loader.PackageInfo) []*types.Var {
	idnts := make(map[*ast.Ident]struct{})

	switch stmt := stmt.(type) {
	case *ast.DeclStmt: // vars (1+) in decl; zero values
		ast.Inspect(stmt, func(n ast.Node) bool {
			if v, ok := n.(*ast.ValueSpec); ok {
				idnts = union(idnts, idents(v))
			}
			return true
		})
	case *ast.IncDecStmt: // i++, i--
		idnts = idents(stmt.X)
	case *ast.AssignStmt: // :=, =, &=, etc. except x[i] (IndexExpr)
		for _, x := range stmt.Lhs {
			indExp := false
			ast.Inspect(x, func(n ast.Node) bool {
				if _, ok := n.(*ast.IndexExpr); ok {
					indExp = true
					return false
				}
				return true
			})
			if !indExp {
				idnts = union(idnts, idents(x))
			}
		}
	case *ast.RangeStmt: // only [ x, y ] on Lhs
		idnts = union(idents(stmt.Key), idents(stmt.Value))
	case *ast.TypeSwitchStmt:
		// The assigned variable does not have a types.Var
		// associated in this stmt; rather, the uses of that
		// variable in the case clauses have several different
		// types.Vars associated with them, according to type
		var vars []*types.Var
		ast.Inspect(stmt.Body, func(n ast.Node) bool {
			switch cc := n.(type) {
			case *ast.CaseClause:
				v := info.TypeCaseVar(cc)
				if v != nil {
					vars = append(vars, v)
				}
				return false
			default:
				return true
			}
		})
		return vars
	}

	var vars []*types.Var
	// should all map to types.Var's, if not we don't want anyway
	for i, _ := range idnts {
		if v, ok := info.ObjectOf(i).(*types.Var); ok {
			vars = append(vars, v)
		}
	}
	return vars
}

// uses extracts local variables whose values are used in the given statement.
func uses(stmt ast.Stmt, info *loader.PackageInfo) []*types.Var {
	idnts := make(map[*ast.Ident]struct{})

	ast.Inspect(stmt, func(n ast.Node) bool {
		switch stmt := stmt.(type) {
		case *ast.AssignStmt: // mostly rhs of =, :=, &=, etc.
			// some LHS are uses, e.g. x[i]
			for _, x := range stmt.Lhs {
				indExp := false
				ast.Inspect(stmt, func(n ast.Node) bool {
					if _, ok := n.(*ast.IndexExpr); ok {
						indExp = true
						return false
					}
					return true
				})
				if indExp || // x[i] is a uses of x and i
					(stmt.Tok != token.ASSIGN &&
						stmt.Tok != token.DEFINE) { // e.g. +=, ^=, etc.
					idnts = union(idnts, idents(x))
				}
			}
			// all RHS are uses
			for _, s := range stmt.Rhs {
				idnts = union(idnts, idents(s))
			}
		case *ast.BlockStmt: // no uses, skip - should not appear in cfg
		case *ast.BranchStmt: // no uses, skip
		case *ast.CaseClause: // no uses, skip
		case *ast.CommClause: // no uses, skip
		case *ast.DeclStmt: // no uses, skip
		case *ast.DeferStmt:
			idnts = idents(stmt.Call)
		case *ast.ForStmt:
			idnts = idents(stmt.Cond)
		case *ast.IfStmt:
			idnts = idents(stmt.Cond)
		case *ast.LabeledStmt: // no uses, skip
		case *ast.RangeStmt: // list in _, _ = range [ list ]
			idnts = idents(stmt.X)
		case *ast.SelectStmt: // no uses, skip
		case *ast.SwitchStmt:
			idnts = idents(stmt.Tag)
		case *ast.TypeSwitchStmt: // no uses, skip
		case ast.Stmt: // everything else is all uses
			idnts = idents(stmt)
		}
		return true
	})

	var vars []*types.Var

	// should all map to types.Var's, if not we don't want anyway
	for i, _ := range idnts {
		if v, ok := info.ObjectOf(i).(*types.Var); ok {
			vars = append(vars, v)
		}
	}

	return vars
}

// idents returns the set of all identifiers in given node.
func idents(node ast.Node) map[*ast.Ident]struct{} {
	idents := make(map[*ast.Ident]struct{})
	if node == nil {
		return idents
	}
	ast.Inspect(node, func(n ast.Node) bool {
		switch n := n.(type) {
		case *ast.Ident:
			idents[n] = struct{}{}
		}
		return true
	})
	return idents
}

func union(one, two map[*ast.Ident]struct{}) map[*ast.Ident]struct{} {
	for o, _ := range one {
		two[o] = struct{}{}
	}
	return two
}
<commit_msg>TypeCaseVar removed from go/loader<commit_after>// Copyright 2014 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 dataflow provides data flow analyses that can be performed on a
// previously constructed control flow graph, including a reaching definitions
// analysis and a live variables analysis for local variables.
package dataflow

// This file contains functions common to all data flow analyses, as well as
// one exported function.

import (
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/loader"
	"code.google.com/p/go.tools/go/types"
)

// ReferencedVars returns the sets of local variables that are defined or used
// within the given list of statements (based on syntax).
func ReferencedVars(stmts []ast.Stmt, info *loader.PackageInfo) (def, use map[*types.Var]struct{}) {
	def = make(map[*types.Var]struct{})
	use = make(map[*types.Var]struct{})

	for _, stmt := range stmts {
		for _, d := range defs(stmt, info) {
			def[d] = struct{}{}
		}
		for _, u := range uses(stmt, info) {
			use[u] = struct{}{}
		}
	}
	return def, use
}

// defs extracts any local variables whose values are assigned in the given statement.
func defs(stmt ast.Stmt, info *loader.PackageInfo) []*types.Var {
	idnts := make(map[*ast.Ident]struct{})

	switch stmt := stmt.(type) {
	case *ast.DeclStmt: // vars (1+) in decl; zero values
		ast.Inspect(stmt, func(n ast.Node) bool {
			if v, ok := n.(*ast.ValueSpec); ok {
				idnts = union(idnts, idents(v))
			}
			return true
		})
	case *ast.IncDecStmt: // i++, i--
		idnts = idents(stmt.X)
	case *ast.AssignStmt: // :=, =, &=, etc. except x[i] (IndexExpr)
		for _, x := range stmt.Lhs {
			indExp := false
			ast.Inspect(x, func(n ast.Node) bool {
				if _, ok := n.(*ast.IndexExpr); ok {
					indExp = true
					return false
				}
				return true
			})
			if !indExp {
				idnts = union(idnts, idents(x))
			}
		}
	case *ast.RangeStmt: // only [ x, y ] on Lhs
		idnts = union(idents(stmt.Key), idents(stmt.Value))
	case *ast.TypeSwitchStmt:
		// The assigned variable does not have a types.Var
		// associated in this stmt; rather, the uses of that
		// variable in the case clauses have several different
		// types.Vars associated with them, according to type
		var vars []*types.Var
		ast.Inspect(stmt.Body, func(n ast.Node) bool {
			switch cc := n.(type) {
			case *ast.CaseClause:
				v := typeCaseVar(info, cc)
				if v != nil {
					vars = append(vars, v)
				}
				return false
			default:
				return true
			}
		})
		return vars
	}

	var vars []*types.Var
	// should all map to types.Var's, if not we don't want anyway
	for i, _ := range idnts {
		if v, ok := info.ObjectOf(i).(*types.Var); ok {
			vars = append(vars, v)
		}
	}
	return vars
}

// typeCaseVar returns the implicit variable associated with a case clause in a
// type switch statement.
func typeCaseVar(info *loader.PackageInfo, cc *ast.CaseClause) *types.Var {
	// Removed from go/loader
	if v := info.Implicits[cc]; v != nil {
		return v.(*types.Var)
	}
	return nil
}

// uses extracts local variables whose values are used in the given statement.
func uses(stmt ast.Stmt, info *loader.PackageInfo) []*types.Var {
	idnts := make(map[*ast.Ident]struct{})

	ast.Inspect(stmt, func(n ast.Node) bool {
		switch stmt := stmt.(type) {
		case *ast.AssignStmt: // mostly rhs of =, :=, &=, etc.
			// some LHS are uses, e.g. x[i]
			for _, x := range stmt.Lhs {
				indExp := false
				ast.Inspect(stmt, func(n ast.Node) bool {
					if _, ok := n.(*ast.IndexExpr); ok {
						indExp = true
						return false
					}
					return true
				})
				if indExp || // x[i] is a uses of x and i
					(stmt.Tok != token.ASSIGN &&
						stmt.Tok != token.DEFINE) { // e.g. +=, ^=, etc.
					idnts = union(idnts, idents(x))
				}
			}
			// all RHS are uses
			for _, s := range stmt.Rhs {
				idnts = union(idnts, idents(s))
			}
		case *ast.BlockStmt: // no uses, skip - should not appear in cfg
		case *ast.BranchStmt: // no uses, skip
		case *ast.CaseClause: // no uses, skip
		case *ast.CommClause: // no uses, skip
		case *ast.DeclStmt: // no uses, skip
		case *ast.DeferStmt:
			idnts = idents(stmt.Call)
		case *ast.ForStmt:
			idnts = idents(stmt.Cond)
		case *ast.IfStmt:
			idnts = idents(stmt.Cond)
		case *ast.LabeledStmt: // no uses, skip
		case *ast.RangeStmt: // list in _, _ = range [ list ]
			idnts = idents(stmt.X)
		case *ast.SelectStmt: // no uses, skip
		case *ast.SwitchStmt:
			idnts = idents(stmt.Tag)
		case *ast.TypeSwitchStmt: // no uses, skip
		case ast.Stmt: // everything else is all uses
			idnts = idents(stmt)
		}
		return true
	})

	var vars []*types.Var

	// should all map to types.Var's, if not we don't want anyway
	for i, _ := range idnts {
		if v, ok := info.ObjectOf(i).(*types.Var); ok {
			vars = append(vars, v)
		}
	}

	return vars
}

// idents returns the set of all identifiers in given node.
func idents(node ast.Node) map[*ast.Ident]struct{} {
	idents := make(map[*ast.Ident]struct{})
	if node == nil {
		return idents
	}
	ast.Inspect(node, func(n ast.Node) bool {
		switch n := n.(type) {
		case *ast.Ident:
			idents[n] = struct{}{}
		}
		return true
	})
	return idents
}

func union(one, two map[*ast.Ident]struct{}) map[*ast.Ident]struct{} {
	for o, _ := range one {
		two[o] = struct{}{}
	}
	return two
}
<|endoftext|>


<commit_before>package routes

import (
	_ "context"
	"errors"
	"github.com/gillesdemey/npm-registry/mocks"
	"github.com/jarcoal/httpmock"
	_ "github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/suite"
	"io/ioutil"
	"net/http"
	_ "net/http/httptest"
	"strings"
	"testing"
)

type TarballStorageSuite struct {
	suite.Suite
	storage mocks.MockedStorage
}

func (s *TarballStorageSuite) SetupSuite() {
	httpmock.Activate()

	httpmock.RegisterResponder(
		"GET", "https://registry.npmjs.org/foo/-/foo-0.1.0.tgz",
		httpmock.NewBytesResponder(http.StatusOK, []byte("")),
	)

	packageNotFoundResponder, _ := httpmock.NewJsonResponder(
		http.StatusNotFound,
		`{"error":"package could not be found."}`,
	)
	httpmock.RegisterResponder(
		"GET", "https://registry.npmjs.org/foo/-/foo-0.0.0.tgz",
		packageNotFoundResponder,
	)

	httpmock.RegisterResponder(
		"GET", "https://registry.npmjs.org/fail/-/fail-0.1.0.tgz",
		httpmock.ConnectionFailure,
	)
}

func (s *TarballStorageSuite) TestTryUpstreamTarballFound() {
	_, err := tryUpstreamTarball("foo", "foo-0.1.0.tgz")
	s.Nil(err)
}

func (s *TarballStorageSuite) TestTryUpstreamTarballNotFound() {
	_, err := tryUpstreamTarball("foo", "foo-0.0.0.tgz")
	s.EqualError(err, "no such package available")
}

func (s *TarballStorageSuite) TestTryUpstreamTarballConnectionFailure() {
	_, err := tryUpstreamTarball("fail", "fail-0.1.0.tgz")
	s.NotNil(err)
}

func (s *TarballStorageSuite) TestTryStorageTarball() {
	storage := new(mocks.MockedStorage)
	storage.On("RetrieveTarball", "foo", "foo-0.1.0.tgz", ioutil.Discard).
		Return(nil)

	err := tryStorageTarball(storage, "foo", "foo-0.1.0.tgz", ioutil.Discard)
	s.Nil(err)
}

func (s *TarballStorageSuite) TestTryStorageTarballFailure() {
	storage := new(mocks.MockedStorage)
	storage.On("RetrieveTarball", "foo", "foo-0.1.0.tgz", ioutil.Discard).
		Return(errors.New("something happened"))

	err := tryStorageTarball(storage, "foo", "foo-0.1.0.tgz", ioutil.Discard)
	s.NotNil(err)
}

func (s *TarballStorageSuite) TestUpdateTarballStorage() {
	storage := new(mocks.MockedStorage)
	storage.On("StoreTarball", "foo/foo-0.1.0.tgz", strings.NewReader("")).
		Return(nil)

	err := updateTarballStorage(storage, "foo/foo-0.1.0.tgz", strings.NewReader(""))
	s.Nil(err)
}

// func (s *TarballStorageSuite) TestGetTarball() {
// 	req, _ := http.NewRequest("GET", "foo/-/foo-0.1.0.tgz", nil)
// 	req.Header.Add("Authorization", "Bearer abc123")
//
// 	rec := httptest.NewRecorder()
//
// 	ctx := req.Context()
// 	storage := new(mocks.MockedStorage)
//
// 	storage.On("RetrieveUsernameFromToken", "abc123").Return("foo", nil)
// 	storage.On("RetrieveTarball", "foo", "foo-0.1.0.tgz", mock.Anything).
// 		Return(nil)
// 	storage.On("StoreTarball", "foo/foo-0.1.0.tgz", strings.NewReader("")).
// 		Return(nil)
//
// 	ctx = context.WithValue(ctx, "storage", storage)
//
// 	GetTarball(rec, req.WithContext(ctx), func(w http.ResponseWriter, req *http.Request) {
// 		s.Equal(rec.Code, http.StatusOK)
// 	})
// }

func (s *TarballStorageSuite) TearDownSuite() {
	httpmock.DeactivateAndReset()
}

func TestTarballStorageSuite(t *testing.T) {
	suite.Run(t, new(TarballStorageSuite))
}
<commit_msg>Adds test for GetTarball<commit_after>package routes

import (
	"context"
	"errors"
	"github.com/gillesdemey/npm-registry/mocks"
	"github.com/jarcoal/httpmock"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/suite"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	_ "fmt"
)

type TarballStorageSuite struct {
	suite.Suite
	storage mocks.MockedStorage
}

func (s *TarballStorageSuite) SetupSuite() {
	httpmock.Activate()

	httpmock.RegisterResponder(
		"GET", "https://registry.npmjs.org/foo/-/foo-0.1.0.tgz",
		httpmock.NewBytesResponder(http.StatusOK, []byte("")),
	)

	packageNotFoundResponder, _ := httpmock.NewJsonResponder(
		http.StatusNotFound,
		`{"error":"package could not be found."}`,
	)
	httpmock.RegisterResponder(
		"GET", "https://registry.npmjs.org/foo/-/foo-0.0.0.tgz",
		packageNotFoundResponder,
	)

	httpmock.RegisterResponder(
		"GET", "https://registry.npmjs.org/fail/-/fail-0.1.0.tgz",
		httpmock.ConnectionFailure,
	)
}

func (s *TarballStorageSuite) TestTryUpstreamTarballFound() {
	_, err := tryUpstreamTarball("foo", "foo-0.1.0.tgz")
	s.Nil(err)
}

func (s *TarballStorageSuite) TestTryUpstreamTarballNotFound() {
	_, err := tryUpstreamTarball("foo", "foo-0.0.0.tgz")
	s.EqualError(err, "no such package available")
}

func (s *TarballStorageSuite) TestTryUpstreamTarballConnectionFailure() {
	_, err := tryUpstreamTarball("fail", "fail-0.1.0.tgz")
	s.NotNil(err)
}

func (s *TarballStorageSuite) TestTryStorageTarball() {
	storage := new(mocks.MockedStorage)
	storage.On("RetrieveTarball", "foo", "foo-0.1.0.tgz", ioutil.Discard).
		Return(nil)

	err := tryStorageTarball(storage, "foo", "foo-0.1.0.tgz", ioutil.Discard)
	s.Nil(err)
}

func (s *TarballStorageSuite) TestTryStorageTarballFailure() {
	storage := new(mocks.MockedStorage)
	storage.On("RetrieveTarball", "foo", "foo-0.1.0.tgz", ioutil.Discard).
		Return(errors.New("something happened"))

	err := tryStorageTarball(storage, "foo", "foo-0.1.0.tgz", ioutil.Discard)
	s.NotNil(err)
}

func (s *TarballStorageSuite) TestUpdateTarballStorage() {
	storage := new(mocks.MockedStorage)
	storage.On("StoreTarball", "foo-0.1.0.tgz", mock.Anything).
		Return(nil)

	err := updateTarballStorage(storage, "foo-0.1.0.tgz", strings.NewReader(""))
	s.Nil(err)
}

func (s *TarballStorageSuite) TestGetTarball() {
	httpmock.RegisterNoResponder(httpmock.InitialTransport.RoundTrip)

	req, _ := http.NewRequest("GET", "/foo/-/foo-0.1.0.tgz", nil)
	q := req.URL.Query()
	q.Set(":pkg", "foo")
	q.Set(":filename", "foo-0.1.0.tgz")
	req.URL.RawQuery = q.Encode()

	req.Header.Add("Authorization", "Bearer abc123")

	rec := httptest.NewRecorder()

	ctx := req.Context()
	storage := new(mocks.MockedStorage)

	// storage.On("RetrieveUsernameFromToken", "abc123").Return("foo", nil)
	storage.On("RetrieveTarball", "foo", "foo-0.1.0.tgz", mock.Anything).
		Return(nil)
	storage.On("StoreTarball", "foo-0.1.0.tgz", mock.Anything).
		Return(nil)

	ctx = context.WithValue(ctx, "storage", storage)

	GetTarball(rec, req.WithContext(ctx), func(w http.ResponseWriter, req *http.Request) {
		s.Equal(rec.Code, http.StatusOK)
	})
}

func (s *TarballStorageSuite) TearDownSuite() {
	httpmock.DeactivateAndReset()
}

func TestTarballStorageSuite(t *testing.T) {
	suite.Run(t, new(TarballStorageSuite))
}
<|endoftext|>


<commit_before>package misc_tests

import (
	"encoding/json"
	"github.com/json-iterator/go"
	"github.com/stretchr/testify/require"
	"io"
	"testing"
)

func Test_nil_non_empty_interface(t *testing.T) {
	type TestObject struct {
		Field []io.Closer
	}
	should := require.New(t)
	obj := TestObject{}
	b := []byte(`{"Field":["AAA"]}`)
	should.NotNil(json.Unmarshal(b, &obj))
	should.NotNil(jsoniter.Unmarshal(b, &obj))
}

func Test_nil_out_null_interface(t *testing.T) {
	type TestData struct {
		Field interface{} `json:"field"`
	}
	should := require.New(t)

	var boolVar bool
	obj := TestData{
		Field: &boolVar,
	}

	data1 := []byte(`{"field": true}`)

	err := jsoniter.Unmarshal(data1, &obj)
	should.NoError(err)
	should.Equal(true, *(obj.Field.(*bool)))

	data2 := []byte(`{"field": null}`)

	err = jsoniter.Unmarshal(data2, &obj)
	should.NoError(err)
	should.Nil(obj.Field)

	// Checking stdlib behavior matches.
	obj2 := TestData{
		Field: &boolVar,
	}

	err = json.Unmarshal(data1, &obj2)
	should.NoError(err)
	should.Equal(true, *(obj2.Field.(*bool)))

	err = json.Unmarshal(data2, &obj2)
	should.NoError(err)
	should.Equal(nil, obj2.Field)
}

func Test_overwrite_interface_ptr_value_with_nil(t *testing.T) {
	type Wrapper struct {
		Payload interface{} `json:"payload,omitempty"`
	}
	type Payload struct {
		Value int `json:"val,omitempty"`
	}

	should := require.New(t)

	payload := &Payload{}
	wrapper := &Wrapper{
		Payload: &payload,
	}

	err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)

	err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal((*Payload)(nil), payload)

	payload = &Payload{}
	wrapper = &Wrapper{
		Payload: &payload,
	}

	err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.Equal(nil, err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)

	err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal((*Payload)(nil), payload)
}

func Test_overwrite_interface_value_with_nil(t *testing.T) {
	type Wrapper struct {
		Payload interface{} `json:"payload,omitempty"`
	}
	type Payload struct {
		Value int `json:"val,omitempty"`
	}

	should := require.New(t)

	payload := &Payload{}
	wrapper := &Wrapper{
		Payload: payload,
	}

	err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)

	err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Equal(nil, wrapper.Payload)
	should.Equal(42, payload.Value)

	payload = &Payload{}
	wrapper = &Wrapper{
		Payload: payload,
	}

	err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.Equal(nil, err)
	should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)

	err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.Equal(nil, err)
	should.Equal(nil, wrapper.Payload)
	should.Equal(42, payload.Value)
}

func Test_unmarshal_into_nil(t *testing.T) {
	type Payload struct {
		Value int `json:"val,omitempty"`
	}
	type Wrapper struct {
		Payload interface{} `json:"payload,omitempty"`
	}

	should := require.New(t)

	var payload *Payload
	wrapper := &Wrapper{
		Payload: payload,
	}

	err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.NotNil(wrapper.Payload)
	should.Nil(payload)

	err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Nil(wrapper.Payload)
	should.Nil(payload)

	payload = nil
	wrapper = &Wrapper{
		Payload: payload,
	}

	err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.NotNil(wrapper.Payload)
	should.Nil(payload)

	err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Nil(wrapper.Payload)
	should.Nil(payload)
}
<commit_msg>remove redundant dereferencing expressions<commit_after>package misc_tests

import (
	"encoding/json"
	"github.com/json-iterator/go"
	"github.com/stretchr/testify/require"
	"io"
	"testing"
)

func Test_nil_non_empty_interface(t *testing.T) {
	type TestObject struct {
		Field []io.Closer
	}
	should := require.New(t)
	obj := TestObject{}
	b := []byte(`{"Field":["AAA"]}`)
	should.NotNil(json.Unmarshal(b, &obj))
	should.NotNil(jsoniter.Unmarshal(b, &obj))
}

func Test_nil_out_null_interface(t *testing.T) {
	type TestData struct {
		Field interface{} `json:"field"`
	}
	should := require.New(t)

	var boolVar bool
	obj := TestData{
		Field: &boolVar,
	}

	data1 := []byte(`{"field": true}`)

	err := jsoniter.Unmarshal(data1, &obj)
	should.NoError(err)
	should.Equal(true, *(obj.Field.(*bool)))

	data2 := []byte(`{"field": null}`)

	err = jsoniter.Unmarshal(data2, &obj)
	should.NoError(err)
	should.Nil(obj.Field)

	// Checking stdlib behavior matches.
	obj2 := TestData{
		Field: &boolVar,
	}

	err = json.Unmarshal(data1, &obj2)
	should.NoError(err)
	should.Equal(true, *(obj2.Field.(*bool)))

	err = json.Unmarshal(data2, &obj2)
	should.NoError(err)
	should.Equal(nil, obj2.Field)
}

func Test_overwrite_interface_ptr_value_with_nil(t *testing.T) {
	type Wrapper struct {
		Payload interface{} `json:"payload,omitempty"`
	}
	type Payload struct {
		Value int `json:"val,omitempty"`
	}

	should := require.New(t)

	payload := &Payload{}
	wrapper := &Wrapper{
		Payload: &payload,
	}

	err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)

	err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal((*Payload)(nil), payload)

	payload = &Payload{}
	wrapper = &Wrapper{
		Payload: &payload,
	}

	err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.Equal(nil, err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)

	err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Equal(&payload, wrapper.Payload)
	should.Equal((*Payload)(nil), payload)
}

func Test_overwrite_interface_value_with_nil(t *testing.T) {
	type Wrapper struct {
		Payload interface{} `json:"payload,omitempty"`
	}
	type Payload struct {
		Value int `json:"val,omitempty"`
	}

	should := require.New(t)

	payload := &Payload{}
	wrapper := &Wrapper{
		Payload: payload,
	}

	err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.Equal(42, wrapper.Payload.(*Payload).Value)

	err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Equal(nil, wrapper.Payload)
	should.Equal(42, payload.Value)

	payload = &Payload{}
	wrapper = &Wrapper{
		Payload: payload,
	}

	err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.Equal(nil, err)
	should.Equal(42, wrapper.Payload.(*Payload).Value)

	err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.Equal(nil, err)
	should.Equal(nil, wrapper.Payload)
	should.Equal(42, payload.Value)
}

func Test_unmarshal_into_nil(t *testing.T) {
	type Payload struct {
		Value int `json:"val,omitempty"`
	}
	type Wrapper struct {
		Payload interface{} `json:"payload,omitempty"`
	}

	should := require.New(t)

	var payload *Payload
	wrapper := &Wrapper{
		Payload: payload,
	}

	err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.NotNil(wrapper.Payload)
	should.Nil(payload)

	err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Nil(wrapper.Payload)
	should.Nil(payload)

	payload = nil
	wrapper = &Wrapper{
		Payload: payload,
	}

	err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
	should.NoError(err)
	should.NotNil(wrapper.Payload)
	should.Nil(payload)

	err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
	should.NoError(err)
	should.Nil(wrapper.Payload)
	should.Nil(payload)
}
<|endoftext|>


<commit_before>package sofa

import (
	"encoding/json"
)

// DocumentList is the CouchDB reprentation of a list of Documents where each document
// is contained within a Row along with some metadata. Depending on the view & the request
// paramaters used the documents may or may not be included in the row.
type DocumentList struct {
	TotalRows float64 `json:"total_rows"`
	Offset    float64 `json:"offset"`
	Rows      []Row   `json:"rows"`
}

// Size returns the number of documents currently stored in this DocumentList.
func (dl *DocumentList) Size() int {
	// TODO: Possibly should just return `int(dl.TotalRows)`
	return len(dl.Rows)
}

// RawDocuments returns the Document from each Row of this DocumentList as a json.RawMessage
// which can then be Unmarshalled into the correct type.
func (dl *DocumentList) RawDocuments() []json.RawMessage {
	var docs []json.RawMessage

	for _, row := range dl.Rows {
		if row.HasDocument() {
			docs = append(docs, row.Document)
		} else {
			docs = append(docs, nil)
		}
	}

	return docs
}

// MapDocuments returns a list containing the document from each row in this DocumentList
// Unmarshalled into a map[string]interface{}.
func (dl *DocumentList) MapDocuments() ([]map[string]interface{}, error) {
	var docs []map[string]interface{}

	for _, row := range dl.Rows {
		if row.HasDocument() {
			var rowDoc map[string]interface{}

			err := json.Unmarshal(row.Document, &rowDoc)
			if err != nil {
				return nil, err
			}

			docs = append(docs, rowDoc)
		}
	}

	return docs, nil
}

// UnmarshalDocuments is a convenience function which unmarshalls just the list of Documents from
// this. Due to a Marshal/Unmarhal cycle this method may be slow. Sometimes slow is fine though.
func (dl *DocumentList) UnmarshalDocuments(docs interface{}) error {
	rawDocs := dl.RawDocuments()

	jsonAllDocs, err := json.Marshal(rawDocs)
	if err != nil {
		return err
	}

	return json.Unmarshal(jsonAllDocs, docs)
}

// Row represents a row in a CouchDB DocumentList. These are mainly returned by views but
// may also be sent to the server as part of the bulk documents API.
type Row struct {
	ID       string          `json:"id,omitempty"`
	Key      interface{}     `json:"key,omitempty"`
	Value    interface{}     `json:"value,omitempty"`
	Document json.RawMessage `json:"doc,omitempty"`
}

// HasDocument checks the current Row for the presence of the Document attached to it.
func (r Row) HasDocument() bool {
	if r.Document == nil {
		return false
	}
	return true
}
<commit_msg>Simplify return to solve lint issue<commit_after>package sofa

import (
	"encoding/json"
)

// DocumentList is the CouchDB reprentation of a list of Documents where each document
// is contained within a Row along with some metadata. Depending on the view & the request
// paramaters used the documents may or may not be included in the row.
type DocumentList struct {
	TotalRows float64 `json:"total_rows"`
	Offset    float64 `json:"offset"`
	Rows      []Row   `json:"rows"`
}

// Size returns the number of documents currently stored in this DocumentList.
func (dl *DocumentList) Size() int {
	// TODO: Possibly should just return `int(dl.TotalRows)`
	return len(dl.Rows)
}

// RawDocuments returns the Document from each Row of this DocumentList as a json.RawMessage
// which can then be Unmarshalled into the correct type.
func (dl *DocumentList) RawDocuments() []json.RawMessage {
	var docs []json.RawMessage

	for _, row := range dl.Rows {
		if row.HasDocument() {
			docs = append(docs, row.Document)
		} else {
			docs = append(docs, nil)
		}
	}

	return docs
}

// MapDocuments returns a list containing the document from each row in this DocumentList
// Unmarshalled into a map[string]interface{}.
func (dl *DocumentList) MapDocuments() ([]map[string]interface{}, error) {
	var docs []map[string]interface{}

	for _, row := range dl.Rows {
		if row.HasDocument() {
			var rowDoc map[string]interface{}

			err := json.Unmarshal(row.Document, &rowDoc)
			if err != nil {
				return nil, err
			}

			docs = append(docs, rowDoc)
		}
	}

	return docs, nil
}

// UnmarshalDocuments is a convenience function which unmarshalls just the list of Documents from
// this. Due to a Marshal/Unmarhal cycle this method may be slow. Sometimes slow is fine though.
func (dl *DocumentList) UnmarshalDocuments(docs interface{}) error {
	rawDocs := dl.RawDocuments()

	jsonAllDocs, err := json.Marshal(rawDocs)
	if err != nil {
		return err
	}

	return json.Unmarshal(jsonAllDocs, docs)
}

// Row represents a row in a CouchDB DocumentList. These are mainly returned by views but
// may also be sent to the server as part of the bulk documents API.
type Row struct {
	ID       string          `json:"id,omitempty"`
	Key      interface{}     `json:"key,omitempty"`
	Value    interface{}     `json:"value,omitempty"`
	Document json.RawMessage `json:"doc,omitempty"`
}

// HasDocument checks the current Row for the presence of the Document attached to it.
func (r Row) HasDocument() bool {
	return r.Document != nil
}
<|endoftext|>


<commit_before>package httpfs

import (
	"io"
	"net/http"
	"os"

	"github.com/CloudyKit/jet"
)

type httpFileSystemLoader struct {
	fs http.FileSystem
}

// NewLoader returns an initialized loader serving the passed http.FileSystem.
func NewLoader(fs http.FileSystem) jet.Loader {
	return &httpFileSystemLoader{fs: fs}
}

// Open opens the file via the internal http.FileSystem. It is the callers duty to close the file.
func (l *httpFileSystemLoader) Open(name string) (io.ReadCloser, error) {
	return l.fs.Open(name)
}

// Exists checks if the template name exists by walking the list of template paths
// returns string with the full path of the template and bool true if the template file was found
func (l *httpFileSystemLoader) Exists(name string) (string, bool) {
	if l.fs == nil {
		return "", false
	}
	if f, err := l.Open(name); err == nil {
		f.Close()
		return name, true
	}
	return "", false
}
<commit_msg>Fix `httpFileSystemLoader.Open` to not crash on nil<commit_after>package httpfs

import (
	"io"
	"net/http"
	"os"

	"github.com/CloudyKit/jet"
)

type httpFileSystemLoader struct {
	fs http.FileSystem
}

// NewLoader returns an initialized loader serving the passed http.FileSystem.
func NewLoader(fs http.FileSystem) jet.Loader {
	return &httpFileSystemLoader{fs: fs}
}

// Open opens the file via the internal http.FileSystem. It is the callers duty to close the file.
func (l *httpFileSystemLoader) Open(name string) (io.ReadCloser, error) {
	if l.fs == nil {
		return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist}
	}
	return l.fs.Open(name)
}

// Exists checks if the template name exists by walking the list of template paths
// returns string with the full path of the template and bool true if the template file was found
func (l *httpFileSystemLoader) Exists(name string) (string, bool) {
	if l.fs == nil {
		return "", false
	}
	if f, err := l.Open(name); err == nil {
		f.Close()
		return name, true
	}
	return "", false
}
<|endoftext|>


<commit_before>package drivers

import (
	"log"
	"strings"

	"github.com/mijia/modelq/drivers/mysql"
	"github.com/mijia/modelq/gmq"
)

type MysqlDriver struct{}

func (m MysqlDriver) LoadDatabaseSchema(dsnString, schema, tableNames string) (DbSchema, error) {
	log.Printf("[MySQL Driver] Start to load tables schema from db, %s, tables=%s", schema, tableNames)
	db, err := gmq.Open("mysql", m.useInformationSchema(dsnString, schema))
	if err != nil {
		return nil, err
	}
	defer db.Close()

	if err = db.Ping(); err != nil {
		return nil, err
	}

	dbSchema := make(DbSchema)
	if err = m.queryColumns(db, schema, tableNames, dbSchema); err != nil {
		return nil, err
	}
	log.Printf("[MySQL Driver] Loaded schema data of %d tables from db[%s]", len(dbSchema), schema)
	return dbSchema, nil
}

func (m MysqlDriver) dataType(colDataType string) string {
	kFieldTypes := map[string]string{
		"bigint":    "int64",
		"int":       "int",
		"tinyint":   "int",
		"smallint":  "int",
		"char":      "string",
		"varchar":   "string",
		"blob":      "[]byte",
		"date":      "time.Time",
		"datetime":  "time.Time",
		"timestamp": "time.Time",
		"decimal":   "float64",
		"bit":       "uint64",
	}
	if fieldType, ok := kFieldTypes[strings.ToLower(colDataType)]; !ok {
		return "string"
	} else {
		return fieldType
	}
}

func (m MysqlDriver) queryColumns(db *gmq.Db, dbName string, tables string, dbSchema DbSchema) error {
	objs := mysql.ColumnsObjs
	filter := objs.FilterTableSchema("=", dbName)
	if len(tables) > 0 {
		tableVs := strings.Split(tables, ",")
		filter = filter.And(objs.FilterTableName("IN", tableVs[0], tableVs[1:]...))
	}

	query := objs.Select().Where(filter).OrderBy("TableName", "OrdinalPosition")
	return query.Iterate(db, func(col mysql.Columns) bool {
		if _, ok := dbSchema[col.TableName]; !ok {
			dbSchema[col.TableName] = make(TableSchema, 0, 5)
		}
		sCol := Column{
			Schema:       col.TableSchema,
			TableName:    col.TableName,
			ColumnName:   col.ColumnName,
			DefaultValue: col.ColumnDefault,
			DataType:     m.dataType(col.DataType),
			ColumnType:   col.ColumnType,
			ColumnKey:    col.ColumnKey,
			Extra:        col.Extra,
			Comment:      col.ColumnComment,
		}
		dbSchema[col.TableName] = append(dbSchema[col.TableName], sCol)
		return true
	})
}

func (m MysqlDriver) useInformationSchema(dsn string, schema string) string {
	return strings.Replace(dsn, "/"+schema, "/information_schema", 1)
}
<commit_msg>Add missing MySQL type<commit_after>package drivers

import (
	"log"
	"strings"

	"github.com/mijia/modelq/drivers/mysql"
	"github.com/mijia/modelq/gmq"
)

type MysqlDriver struct{}

func (m MysqlDriver) LoadDatabaseSchema(dsnString, schema, tableNames string) (DbSchema, error) {
	log.Printf("[MySQL Driver] Start to load tables schema from db, %s, tables=%s", schema, tableNames)
	db, err := gmq.Open("mysql", m.useInformationSchema(dsnString, schema))
	if err != nil {
		return nil, err
	}
	defer db.Close()

	if err = db.Ping(); err != nil {
		return nil, err
	}

	dbSchema := make(DbSchema)
	if err = m.queryColumns(db, schema, tableNames, dbSchema); err != nil {
		return nil, err
	}
	log.Printf("[MySQL Driver] Loaded schema data of %d tables from db[%s]", len(dbSchema), schema)
	return dbSchema, nil
}

func (m MysqlDriver) dataType(colDataType string) string {
	kFieldTypes := map[string]string{
		"bigint":    "int64",
		"int":       "int",
		"tinyint":   "int",
		"smallint":  "int",
		"char":      "string",
		"varchar":   "string",
		"blob":      "[]byte",
		"date":      "time.Time",
		"datetime":  "time.Time",
		"timestamp": "time.Time",
		"decimal":   "float64",
		"double":    "float64",
		"bit":       "uint64",
	}
	if fieldType, ok := kFieldTypes[strings.ToLower(colDataType)]; !ok {
		return "string"
	} else {
		return fieldType
	}
}

func (m MysqlDriver) queryColumns(db *gmq.Db, dbName string, tables string, dbSchema DbSchema) error {
	objs := mysql.ColumnsObjs
	filter := objs.FilterTableSchema("=", dbName)
	if len(tables) > 0 {
		tableVs := strings.Split(tables, ",")
		filter = filter.And(objs.FilterTableName("IN", tableVs[0], tableVs[1:]...))
	}

	query := objs.Select().Where(filter).OrderBy("TableName", "OrdinalPosition")
	return query.Iterate(db, func(col mysql.Columns) bool {
		if _, ok := dbSchema[col.TableName]; !ok {
			dbSchema[col.TableName] = make(TableSchema, 0, 5)
		}
		sCol := Column{
			Schema:       col.TableSchema,
			TableName:    col.TableName,
			ColumnName:   col.ColumnName,
			DefaultValue: col.ColumnDefault,
			DataType:     m.dataType(col.DataType),
			ColumnType:   col.ColumnType,
			ColumnKey:    col.ColumnKey,
			Extra:        col.Extra,
			Comment:      col.ColumnComment,
		}
		dbSchema[col.TableName] = append(dbSchema[col.TableName], sCol)
		return true
	})
}

func (m MysqlDriver) useInformationSchema(dsn string, schema string) string {
	return strings.Replace(dsn, "/"+schema, "/information_schema", 1)
}
<|endoftext|>


<commit_before>package drone

import (
	"errors"
	"fmt"
	"io"
)

type CommitService struct {
	*Client
}

// GET /api/repos/{host}/{owner}/{name}/branch/{branch}/commit/{commit}
func (s *CommitService) Get(host, owner, name, branch, sha string) (*Commit, error) {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/%s", owner, name, sha)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/branches/%s/commits/%s", host, owner, name, branch, sha)
	}
	var commit = Commit{}
	var err = s.run("GET", path, nil, &commit)
	return &commit, err
}

// GET /api/repos/{host}/{owner}/{name}/branches/{branch}/commits/{commit}/console
func (s *CommitService) GetOutput(host, owner, name, branch, sha, build_number string) (io.ReadCloser, error) {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/logs/%s/1", owner, name, build_number)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/branches/%s/commits/%s/console", host, owner, name, branch, sha)
	}
	resp, err := s.do("GET", path)
	if err != nil {
		return nil, nil
	}
	return resp.Body, nil
}

// POST /api/repos/{host}/{owner}/{name}/branches/{branch}/commits/{commit}?action=rebuild
func (s *CommitService) Rebuild(host, owner, name, branch, sha string) error {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/builds/%s", owner, name, sha)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/branches/%s/commits/%s?action=rebuild", host, owner, name, branch, sha)
	}
	return s.run("POST", path, nil, nil)
}

// GET /api/repos/{host}/{owner}/{name}/commits
func (s *CommitService) List(host, owner, name string) ([]*Commit, error) {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/builds", owner, name)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/commits", host, owner, name)
	}
	var list []*Commit
	var err = s.run("GET", path, nil, &list)
	return list, err
}

// GET /api/repos/{host}/{owner}/{name}/branch/{branch}
func (s *CommitService) ListBranch(host, owner, name, branch string) ([]*Commit, error) {
	if s.isServer04 {
		return nil, errors.New("No list branch function in Drone 0.4")
	}
	var path = fmt.Sprintf("/api/repos/%s/%s/%s/commits", host, owner, name)
	var list []*Commit
	var err = s.run("GET", path, nil, &list)
	return list, err
}
<commit_msg>Also add build_number to drone rebuild command<commit_after>package drone

import (
	"errors"
	"fmt"
	"io"
)

type CommitService struct {
	*Client
}

// GET /api/repos/{host}/{owner}/{name}/branch/{branch}/commit/{commit}
func (s *CommitService) Get(host, owner, name, branch, sha string) (*Commit, error) {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/%s", owner, name, sha)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/branches/%s/commits/%s", host, owner, name, branch, sha)
	}
	var commit = Commit{}
	var err = s.run("GET", path, nil, &commit)
	return &commit, err
}

// GET /api/repos/{host}/{owner}/{name}/branches/{branch}/commits/{commit}/console
func (s *CommitService) GetOutput(host, owner, name, branch, sha, build_number string) (io.ReadCloser, error) {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/logs/%s/1", owner, name, build_number)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/branches/%s/commits/%s/console", host, owner, name, branch, sha)
	}
	resp, err := s.do("GET", path)
	if err != nil {
		return nil, nil
	}
	return resp.Body, nil
}

// POST /api/repos/{host}/{owner}/{name}/branches/{branch}/commits/{commit}?action=rebuild
// POST /api/repos/{owner}/{name}/builds/{build_number}
func (s *CommitService) Rebuild(host, owner, name, branch, sha, build_number string) error {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/builds/%s", owner, name, build_number)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/branches/%s/commits/%s?action=rebuild", host, owner, name, branch, sha)
	}
	return s.run("POST", path, nil, nil)
}

// GET /api/repos/{host}/{owner}/{name}/commits
func (s *CommitService) List(host, owner, name string) ([]*Commit, error) {
	var path string
	if s.isServer04 {
		path = fmt.Sprintf("/api/repos/%s/%s/builds", owner, name)
	} else {
		path = fmt.Sprintf("/api/repos/%s/%s/%s/commits", host, owner, name)
	}
	var list []*Commit
	var err = s.run("GET", path, nil, &list)
	return list, err
}

// GET /api/repos/{host}/{owner}/{name}/branch/{branch}
func (s *CommitService) ListBranch(host, owner, name, branch string) ([]*Commit, error) {
	if s.isServer04 {
		return nil, errors.New("No list branch function in Drone 0.4")
	}
	var path = fmt.Sprintf("/api/repos/%s/%s/%s/commits", host, owner, name)
	var list []*Commit
	var err = s.run("GET", path, nil, &list)
	return list, err
}
<|endoftext|>


<commit_before>package http

import (
	"github.com/astaxie/beego/orm"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"
)

type Nqm_node struct {
	Id         int
	Nid        string
	Pid        string
	Pname      string
	Pname_abbr string
	Cid        string
	Cname      string
	Cname_abbr string
	Iid        int
	Iname      string
	Status     int
	Note       string
	Addtime    int
}

func getNQMNodes(rw http.ResponseWriter, req *http.Request) {
	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	items := []interface{}{}
	o := orm.NewOrm()
	o.Using("gz_nqm")
	var NQMNodes []*Nqm_node
	_, err := o.Raw("SELECT nid, pname, cname, status, note FROM gz_nqm.nqm_node ORDER BY nid ASC").QueryRows(&NQMNodes)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, node := range NQMNodes {
			idc := map[string]string{
				"idc":      node.Nid,
				"status":   strconv.Itoa(node.Status),
				"province": node.Pname,
				"city":     node.Cname,
				"note":     node.Note,
			}
			items = append(items, idc)
		}
	}
	result["items"] = items
	nodes["result"] = result
	nodes["count"] = len(items)
	setResponse(rw, nodes)
}

func getLatestTimestamp(tableName string, result map[string]interface{}) int64 {
	timestamp := int64(0)
	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT mtime FROM `gz_nqm`.`" + tableName + "` ORDER BY mtime DESC LIMIT 1"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		mtime, err := strconv.Atoi(rows[0]["mtime"].(string))
		if err == nil {
			timestamp = int64(mtime)
		}
	}
	return timestamp
}

func getNearestTimestamp(tableName string, bound int64, result map[string]interface{}) int64 {
	timestamp := int64(0)
	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT mtime FROM gz_nqm." + tableName
	sqlcmd += " WHERE mtime <= ? ORDER BY mtime DESC LIMIT 1"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd, bound).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		mtime, err := strconv.Atoi(rows[0]["mtime"].(string))
		if err == nil {
			timestamp = int64(mtime)
		}
	}
	return timestamp
}

func getSum(slice []float64) float64 {
	sum := float64(0)
	for _, number := range slice {
		sum += number
	}
	return sum
}

func getPacketLossAndAveragePingTime(tableName string, timestamp int64, result map[string]interface{}) map[string]interface{} {
	idc := map[string]interface{}{}
	if timestamp == int64(0) {
		return idc
	}
	sends := []float64{}
	receives := []float64{}
	averages := []float64{}

	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT send, receive, avg FROM `gz_nqm`.`" + tableName + "` WHERE mtime = ?"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd, strconv.Itoa(int(timestamp))).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		for _, row := range rows {
			send, err := strconv.ParseFloat(row["send"].(string), 64)
			if err != nil {
				setError(err.Error(), result)
			} else {
				sends = append(sends, send)
			}
			receive, err := strconv.ParseFloat(row["receive"].(string), 64)
			if err != nil {
				setError(err.Error(), result)
			} else {
				receives = append(receives, receive)
			}
			avg, err := strconv.ParseFloat(row["avg"].(string), 64)
			if err != nil {
				setError(err.Error(), result)
			} else {
				averages = append(averages, avg)
			}
		}
	}
	divider := float64(len(sends))
	if divider > 0 {
		packetLossRate := 1 - (getSum(receives) / getSum(sends))
		averagePingTimeMilliseconds := getSum(averages) / divider
		idc = map[string]interface{}{
			"packetLossRate":              packetLossRate,
			"averagePingTimeMilliseconds": averagePingTimeMilliseconds,
			"time": time.Unix(timestamp, 0).Format("2006-01-02 15:04"),
		}
	}
	return idc
}

func getNQMPacketLoss(rw http.ResponseWriter, req *http.Request) {
	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	items := []interface{}{}

	tablesMap := map[string]interface{}{}
	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT table_name FROM information_schema.tables WHERE table_name LIKE 'nqm_log_prober_%'"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		for _, row := range rows {
			tablesMap[row["table_name"].(string)] = ""
		}
	}

	nids := []string{}
	pidMap := map[string]interface{}{}
	var NQMNodes []*Nqm_node
	_, err = o.Raw("SELECT nid, pid, status FROM gz_nqm.nqm_node ORDER BY nid ASC").QueryRows(&NQMNodes)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, node := range NQMNodes {
			if node.Status > 0 {
				nids = append(nids, node.Nid)
				pidMap[node.Nid] = node.Pid
			}
		}
	}
	idcNames := []string{}
	for _, nid := range nids {
		if _, ok := tablesMap["nqm_log_prober_"+strings.Replace(nid, "-", "_", -1)]; ok {
			idcNames = append(idcNames, nid)
		}
	}
	sort.Strings(idcNames)
	for _, idcName := range idcNames {
		tableName := "nqm_log_" + strings.Replace(idcName, "-", "_", -1)
		timestamp := getLatestTimestamp(tableName, result)
		if timestamp > 0 {
			idc := getPacketLossAndAveragePingTime(tableName, timestamp, result)
			idc["nodeName"] = idcName
			idc["pid"] = pidMap[idcName]
			items = append(items, idc)
		}
	}
	result["items"] = items
	nodes["result"] = result
	nodes["count"] = len(items)
	rw.Header().Set("Access-Control-Allow-Origin", "*")
	setResponse(rw, nodes)
}

func getJaguar(rw http.ResponseWriter, req *http.Request) {
	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	items := []interface{}{}
	timestamp := int64(0)
	loc, err := time.LoadLocation("Asia/Taipei")
	if err != nil {
		loc = time.Local
	}
	timeFormat := "2006-01-02 15:04"
	timeInput := req.URL.Query().Get("time")
	date, err := time.ParseInLocation(timeFormat, timeInput, loc)
	if err == nil {
		timestamp = date.Unix()
	}
	nodeMap := map[string]map[string]string{}
	nodeNames := []string{}
	o := orm.NewOrm()
	o.Using("gz_nqm")
	var NQMNodes []*Nqm_node
	_, err = o.Raw("SELECT nid, pname, cname, iname FROM gz_nqm.nqm_node ORDER BY nid ASC").QueryRows(&NQMNodes)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, node := range NQMNodes {
			nodeName := node.Nid
			node := map[string]string{
				"node":     nodeName,
				"province": node.Pname,
				"city":     node.Cname,
				"isp":      node.Iname,
			}
			nodeMap[nodeName] = node
			nodeNames = append(nodeNames, nodeName)
		}
	}
	sqlcmd := "SELECT nid, ip, note FROM gz_nqm.nqm_dev WHERE nid IN ('"
	sqlcmd += strings.Join(nodeNames, "','") + "')"
	var rows []orm.Params
	_, err = o.Raw(sqlcmd).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, row := range rows {
			nodeName := row["nid"].(string)
			nodeMap[nodeName]["ip"] = row["ip"].(string)
			nodeMap[nodeName]["idc"] = row["note"].(string)
		}
	}
	for _, nodeName := range nodeNames {
		node := nodeMap[nodeName]
		item := map[string]interface{}{
			"node":     node["node"],
			"province": node["province"],
			"city":     node["city"],
			"isp":      node["isp"],
			"ip":       node["ip"],
			"idc":      node["idc"],
			"loss":     nil,
			"ping.ms":  nil,
			"time":     nil,
		}
		tableName := "nqm_log_" + strings.Replace(nodeName, "-", "_", -1)
		timestampLatest := getLatestTimestamp(tableName, result)
		if timestampLatest > 0 {
			timestampNearest := timestampLatest
			if timestamp > 0 {
				timestampNearest = getNearestTimestamp(tableName, timestamp, result)
			}
			resp := getPacketLossAndAveragePingTime(tableName, timestampNearest, result)
			if _, ok := resp["packetLossRate"]; ok {
				item["loss"] = resp["packetLossRate"]
				item["ping.ms"] = resp["averagePingTimeMilliseconds"]
				item["time"] = resp["time"]
			}
		}
		items = append(items, item)
	}
	result["items"] = items
	nodes["result"] = result
	nodes["count"] = len(items)
	rw.Header().Set("Access-Control-Allow-Origin", "*")
	setResponse(rw, nodes)
}

func configNQMRoutes() {
	http.HandleFunc("/api/nqm/nodes", getNQMNodes)
	http.HandleFunc("/api/nqm/loss", getNQMPacketLoss)
	http.HandleFunc("/api/nqm/jaguar", getJaguar)
}
<commit_msg>[OWL-1236][query] refine func getNQMNodes()<commit_after>package http

import (
	"github.com/astaxie/beego/orm"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"
)

type Nqm_node struct {
	Id         int
	Nid        string
	Pid        string
	Pname      string
	Pname_abbr string
	Cid        string
	Cname      string
	Cname_abbr string
	Iid        int
	Iname      string
	Status     int
	Note       string
	Addtime    int
}

func getNQMNodes(rw http.ResponseWriter, req *http.Request) {
	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	items := []interface{}{}
	o := orm.NewOrm()
	o.Using("gz_nqm")
	var NQMNodes []*Nqm_node
	_, err := o.Raw("SELECT nid, pname, cname, status, note FROM `gz_nqm`.`nqm_node` ORDER BY nid ASC").QueryRows(&NQMNodes)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, node := range NQMNodes {
			idc := map[string]string{
				"idc":      node.Nid,
				"status":   strconv.Itoa(node.Status),
				"province": node.Pname,
				"city":     node.Cname,
				"note":     node.Note,
			}
			items = append(items, idc)
		}
	}
	result["items"] = items
	nodes["result"] = result
	nodes["count"] = len(items)
	setResponse(rw, nodes)
}

func getLatestTimestamp(tableName string, result map[string]interface{}) int64 {
	timestamp := int64(0)
	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT mtime FROM `gz_nqm`.`" + tableName + "` ORDER BY mtime DESC LIMIT 1"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		mtime, err := strconv.Atoi(rows[0]["mtime"].(string))
		if err == nil {
			timestamp = int64(mtime)
		}
	}
	return timestamp
}

func getNearestTimestamp(tableName string, bound int64, result map[string]interface{}) int64 {
	timestamp := int64(0)
	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT mtime FROM gz_nqm." + tableName
	sqlcmd += " WHERE mtime <= ? ORDER BY mtime DESC LIMIT 1"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd, bound).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		mtime, err := strconv.Atoi(rows[0]["mtime"].(string))
		if err == nil {
			timestamp = int64(mtime)
		}
	}
	return timestamp
}

func getSum(slice []float64) float64 {
	sum := float64(0)
	for _, number := range slice {
		sum += number
	}
	return sum
}

func getPacketLossAndAveragePingTime(tableName string, timestamp int64, result map[string]interface{}) map[string]interface{} {
	idc := map[string]interface{}{}
	if timestamp == int64(0) {
		return idc
	}
	sends := []float64{}
	receives := []float64{}
	averages := []float64{}

	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT send, receive, avg FROM `gz_nqm`.`" + tableName + "` WHERE mtime = ?"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd, strconv.Itoa(int(timestamp))).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		for _, row := range rows {
			send, err := strconv.ParseFloat(row["send"].(string), 64)
			if err != nil {
				setError(err.Error(), result)
			} else {
				sends = append(sends, send)
			}
			receive, err := strconv.ParseFloat(row["receive"].(string), 64)
			if err != nil {
				setError(err.Error(), result)
			} else {
				receives = append(receives, receive)
			}
			avg, err := strconv.ParseFloat(row["avg"].(string), 64)
			if err != nil {
				setError(err.Error(), result)
			} else {
				averages = append(averages, avg)
			}
		}
	}
	divider := float64(len(sends))
	if divider > 0 {
		packetLossRate := 1 - (getSum(receives) / getSum(sends))
		averagePingTimeMilliseconds := getSum(averages) / divider
		idc = map[string]interface{}{
			"packetLossRate":              packetLossRate,
			"averagePingTimeMilliseconds": averagePingTimeMilliseconds,
			"time": time.Unix(timestamp, 0).Format("2006-01-02 15:04"),
		}
	}
	return idc
}

func getNQMPacketLoss(rw http.ResponseWriter, req *http.Request) {
	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	items := []interface{}{}

	tablesMap := map[string]interface{}{}
	o := orm.NewOrm()
	o.Using("gz_nqm")
	sqlcmd := "SELECT table_name FROM information_schema.tables WHERE table_name LIKE 'nqm_log_prober_%'"
	var rows []orm.Params
	num, err := o.Raw(sqlcmd).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else if num > 0 {
		for _, row := range rows {
			tablesMap[row["table_name"].(string)] = ""
		}
	}

	nids := []string{}
	pidMap := map[string]interface{}{}
	var NQMNodes []*Nqm_node
	_, err = o.Raw("SELECT nid, pid, status FROM gz_nqm.nqm_node ORDER BY nid ASC").QueryRows(&NQMNodes)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, node := range NQMNodes {
			if node.Status > 0 {
				nids = append(nids, node.Nid)
				pidMap[node.Nid] = node.Pid
			}
		}
	}
	idcNames := []string{}
	for _, nid := range nids {
		if _, ok := tablesMap["nqm_log_prober_"+strings.Replace(nid, "-", "_", -1)]; ok {
			idcNames = append(idcNames, nid)
		}
	}
	sort.Strings(idcNames)
	for _, idcName := range idcNames {
		tableName := "nqm_log_" + strings.Replace(idcName, "-", "_", -1)
		timestamp := getLatestTimestamp(tableName, result)
		if timestamp > 0 {
			idc := getPacketLossAndAveragePingTime(tableName, timestamp, result)
			idc["nodeName"] = idcName
			idc["pid"] = pidMap[idcName]
			items = append(items, idc)
		}
	}
	result["items"] = items
	nodes["result"] = result
	nodes["count"] = len(items)
	rw.Header().Set("Access-Control-Allow-Origin", "*")
	setResponse(rw, nodes)
}

func getJaguar(rw http.ResponseWriter, req *http.Request) {
	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	items := []interface{}{}
	timestamp := int64(0)
	loc, err := time.LoadLocation("Asia/Taipei")
	if err != nil {
		loc = time.Local
	}
	timeFormat := "2006-01-02 15:04"
	timeInput := req.URL.Query().Get("time")
	date, err := time.ParseInLocation(timeFormat, timeInput, loc)
	if err == nil {
		timestamp = date.Unix()
	}
	nodeMap := map[string]map[string]string{}
	nodeNames := []string{}
	o := orm.NewOrm()
	o.Using("gz_nqm")
	var NQMNodes []*Nqm_node
	_, err = o.Raw("SELECT nid, pname, cname, iname FROM gz_nqm.nqm_node ORDER BY nid ASC").QueryRows(&NQMNodes)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, node := range NQMNodes {
			nodeName := node.Nid
			node := map[string]string{
				"node":     nodeName,
				"province": node.Pname,
				"city":     node.Cname,
				"isp":      node.Iname,
			}
			nodeMap[nodeName] = node
			nodeNames = append(nodeNames, nodeName)
		}
	}
	sqlcmd := "SELECT nid, ip, note FROM gz_nqm.nqm_dev WHERE nid IN ('"
	sqlcmd += strings.Join(nodeNames, "','") + "')"
	var rows []orm.Params
	_, err = o.Raw(sqlcmd).Values(&rows)
	if err != nil {
		setError(err.Error(), result)
	} else {
		for _, row := range rows {
			nodeName := row["nid"].(string)
			nodeMap[nodeName]["ip"] = row["ip"].(string)
			nodeMap[nodeName]["idc"] = row["note"].(string)
		}
	}
	for _, nodeName := range nodeNames {
		node := nodeMap[nodeName]
		item := map[string]interface{}{
			"node":     node["node"],
			"province": node["province"],
			"city":     node["city"],
			"isp":      node["isp"],
			"ip":       node["ip"],
			"idc":      node["idc"],
			"loss":     nil,
			"ping.ms":  nil,
			"time":     nil,
		}
		tableName := "nqm_log_" + strings.Replace(nodeName, "-", "_", -1)
		timestampLatest := getLatestTimestamp(tableName, result)
		if timestampLatest > 0 {
			timestampNearest := timestampLatest
			if timestamp > 0 {
				timestampNearest = getNearestTimestamp(tableName, timestamp, result)
			}
			resp := getPacketLossAndAveragePingTime(tableName, timestampNearest, result)
			if _, ok := resp["packetLossRate"]; ok {
				item["loss"] = resp["packetLossRate"]
				item["ping.ms"] = resp["averagePingTimeMilliseconds"]
				item["time"] = resp["time"]
			}
		}
		items = append(items, item)
	}
	result["items"] = items
	nodes["result"] = result
	nodes["count"] = len(items)
	rw.Header().Set("Access-Control-Allow-Origin", "*")
	setResponse(rw, nodes)
}

func configNQMRoutes() {
	http.HandleFunc("/api/nqm/nodes", getNQMNodes)
	http.HandleFunc("/api/nqm/loss", getNQMPacketLoss)
	http.HandleFunc("/api/nqm/jaguar", getJaguar)
}
<|endoftext|>