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

package oglemock

import (
	"errors"
	"fmt"
	"math"
	"reflect"
)

// PartialExpecation is a function that should be called exactly once with
// expected arguments or matchers in order to set up an expected method call.
// See Controller.ExpectMethodCall below. It returns an expectation that can be
// further modified (e.g. by calling WillOnce).
//
// If the arguments are of the wrong type, the function reports a fatal error
// and returns nil.
type PartialExpecation func(...interface{}) Expectation

// Controller represents an object that implements the central logic of
// oglemock: recording and verifying expectations, responding to mock method
// calls, and so on.
type Controller interface {
	// ExpectCall expresses an expectation that the method of the given name
	// should be called on the supplied mock object. It returns a function that
	// should be called with the expected arguments, matchers for the arguments,
	// or a mix of both.
	//
	// fileName and lineNumber should indicate the line on which the expectation
	// was made, if known.
	//
	// For example:
	//
	//     mockWriter := [...]
	//     controller.ExpectCall(mockWriter, "Write")(ElementsAre(0x1))
	//         .WillOnce(Return(1, nil))
	//
	// If the mock object doesn't have a method of the supplied name, the
	// function reports a fatal error and returns nil.
	ExpectCall(
		o MockObject,
		methodName string,
		fileName string,
		lineNumber int) PartialExpecation

	// Finish causes the controller to check for any unsatisfied expectations,
	// and report them as errors if they exist.
	//
	// The controller may panic if any of its methods (including this one) are
	// called after Finish is called.
	Finish()

	// HandleMethodCall looks for a registered expectation matching the call of
	// the given method on mock object o, invokes the appropriate action (if
	// any), and returns the values returned by that action (if any).
	//
	// If the action returns nothing, the controller returns zero values. If
	// there is no matching expectation, the controller reports an error and
	// returns zero values.
	//
	// If the mock object doesn't have a method of the supplied name, the
	// arguments are of the wrong type, or the action returns the wrong types,
	// the function reports a fatal error.
	//
	// HandleMethodCall is exported for the sake of mock implementations, and
	// should not be used directly.
	HandleMethodCall(
		o MockObject,
		methodName string,
		fileName string,
		lineNumber int,
		args []interface{}) []interface{}
}

// methodMap represents a map from method name to set of expectations for that
// method.
type methodMap map[string][]*InternalExpectation

// objectMap represents a map from mock object ID to a methodMap for that object.
type objectMap map[uintptr]methodMap

// NewController sets up a fresh controller, without any expectations set, and
// configures the controller to use the supplied error reporter.
func NewController(reporter ErrorReporter) Controller {
	return &controllerImpl{reporter, objectMap{}}
}

type controllerImpl struct {
	reporter ErrorReporter
	expectationsByObject objectMap
}

// getExpectations returns the list of registered expectations for the named
// method of the supplied object, or an empty slice if none have been
// registered. When this method returns, it is guaranteed that
// c.expectationsByObject has an entry for the object.
func (c *controllerImpl) getExpectations(
	o MockObject,
	methodName string) []*InternalExpectation {
	id := o.Oglemock_Id()

	// Look up the mock object.
	expectationsByMethod, ok := c.expectationsByObject[id]
	if !ok {
		expectationsByMethod = methodMap{}
		c.expectationsByObject[id] = expectationsByMethod
	}

	result, ok := expectationsByMethod[methodName]
	if !ok {
		return []*InternalExpectation{}
	}

	return result
}

// addExpectation adds an expectation to the list registered for the named
// method of the supplied mock object.
func (c *controllerImpl) addExpectation(
	o MockObject,
	methodName string,
	exp *InternalExpectation) {
	// Get the existing list.
	existing := c.getExpectations(o, methodName)

	// Store a modified list.
	id := o.Oglemock_Id()
	c.expectationsByObject[id][methodName] = append(existing, exp)
}

func (c *controllerImpl) ExpectCall(
	o MockObject,
	methodName string,
	fileName string,
	lineNumber int) PartialExpecation {
	// Find the signature for the requested method.
	oType := reflect.TypeOf(o)
	method, ok := oType.MethodByName(methodName)
	if !ok {
		c.reporter.ReportFatalError(
			fileName,
			lineNumber,
			errors.New("Unknown method: " + methodName))
		return nil
	}

	partialAlreadyCalled := false
	return func(args ...interface{}) Expectation {
		// This function should only be called once.
		if partialAlreadyCalled {
			c.reporter.ReportFatalError(
				fileName,
				lineNumber,
				errors.New("Partial expectation called more than once."))
			return nil
		}

		partialAlreadyCalled = true

		// Make sure that the number of args is legal. Keep in mind that the
		// method's type has an extra receiver arg.
		if len(args) != method.Type.NumIn() - 1 {
			c.reporter.ReportFatalError(
				fileName,
				lineNumber,
				errors.New(
					fmt.Sprintf(
						"Expectation for %s given wrong number of arguments: " +
						"expected %d, got %d.",
						methodName,
						method.Type.NumIn() - 1,
						len(args))))
			return nil
		}

		// Create an expectation and insert it into the controller's map.
		exp := InternalNewExpectation(
			c.reporter,
			method.Type,
			args,
			fileName,
			lineNumber)

		c.addExpectation(o, methodName, exp)

		// Return the expectation to the user.
		return exp
	}
}

func (c *controllerImpl) Finish() {
	// Check whether the minimum cardinality for each registered expectation has
	// been satisfied.
	for _, expectationsByMethod := range c.expectationsByObject {
		for methodName, expectations := range expectationsByMethod {
			for _, exp := range expectations {
				minCardinality, _ := computeCardinality(exp)
				if exp.NumMatches < minCardinality {
					c.reporter.ReportError(
						exp.FileName,
						exp.LineNumber,
						errors.New(
							fmt.Sprintf(
								"Unsatisfied expectation; expected %s to be called " +
								"at least %d times; called %d times.",
								methodName,
								minCardinality,
								exp.NumMatches)))
				}
			}
		}
	}
}

// expectationMatches checks the matchers for the expectation against the
// supplied arguments.
func expectationMatches(exp *InternalExpectation, args []interface{}) bool {
	matchers := exp.ArgMatchers
	if len(args) != len(matchers) {
		panic("expectationMatches: len(args)")
	}

	// Check each matcher.
	for i, matcher := range matchers {
		if err := matcher.Matches(args[i]); err != nil {
			return false
		}
	}

	return true
}

// chooseExpectation returns the expectation that matches the supplied
// arguments. If there is more than one such expectation, the one furthest
// along in the list for the method is returned. If there is no such
// expectation, nil is returned.
func (c *controllerImpl) chooseExpectation(
	o MockObject,
	methodName string,
	args []interface{}) *InternalExpectation {
	// Do we have any expectations for this method?
	expectations := c.getExpectations(o, methodName)
	if len(expectations) == 0 {
		return nil
	}

	for i := len(expectations) - 1; i >= 0; i-- {
		if (expectationMatches(expectations[i], args)) {
			return expectations[i]
		}
	}

	return nil
}

// makeZeroReturnValues creates a []interface{} containing appropriate zero
// values for returning from the supplied method type.
func makeZeroReturnValues(method reflect.Method) []interface{} {
	methodType := method.Type
	result := make([]interface{}, methodType.NumOut())

	for i, _ := range result {
		outType := methodType.Out(i)
		zeroVal := reflect.Zero(outType)
		result[i] = zeroVal.Interface()
	}

	return result
}

// computeCardinality decides on the [min, max] range of the number of expected
// matches for the supplied expectations, according to the rules documented in
// expectation.go.
func computeCardinality(exp *InternalExpectation) (min, max uint) {
	// Explicit cardinality.
	if exp.ExpectedNumMatches >= 0 {
		min = uint(exp.ExpectedNumMatches)
		max = min
		return
	}

	// Implicit count based on one-time actions.
	if len(exp.OneTimeActions) != 0 {
		min = uint(len(exp.OneTimeActions))
		max = min

		// If there is a fallback action, this is only a lower bound.
		if exp.FallbackAction != nil {
			max = math.MaxUint32
		}

		return
	}

	// Implicit lack of restriction based on a fallback action being configured.
	if exp.FallbackAction != nil {
		min = 0
		max = math.MaxUint32
		return
	}

	// Implicit cardinality of one.
	min = 1
	max = 1
	return
}

// chooseAction returns the action that should be invoked for the i'th match to
// the supplied expectation (counting from zero). If the implicit "return zero
// values" action should be used, it returns nil.
func chooseAction(i uint, exp *InternalExpectation) Action {
	// Exhaust one-time actions first.
	if i < uint(len(exp.OneTimeActions)) {
		return exp.OneTimeActions[i]
	}

	// Fallback action (or nil if none is configured).
	return exp.FallbackAction
}

func (c *controllerImpl) HandleMethodCall(
	o MockObject,
	methodName string,
	fileName string,
	lineNumber int,
	args []interface{}) []interface{} {
	// Find the signature for the requested method.
	oType := reflect.TypeOf(o)
	method, ok := oType.MethodByName(methodName)
	if !ok {
		c.reporter.ReportFatalError(
			fileName,
			lineNumber,
			errors.New("Unknown method: " + methodName))
		return nil
	}

	// HACK(jacobsa): Make sure we got the correct number of arguments. This will
	// need to be refined when issue #5 (variadic methods) is handled.
	if len(args) != method.Type.NumIn() - 1 {
		c.reporter.ReportFatalError(
			fileName,
			lineNumber,
			errors.New(
				fmt.Sprintf(
					"Wrong number of arguments: expected %d; got %d",
					method.Type.NumIn() - 1,
					len(args))))
		return nil
	}

	// Find an expectation matching this call.
	expectation := c.chooseExpectation(o, methodName, args)
	if expectation == nil {
		c.reporter.ReportError(
			fileName,
			lineNumber,
			errors.New(
				fmt.Sprintf("Unexpected call to %s with args: %v", methodName, args)))

		return makeZeroReturnValues(method)
	}

	// Increase the number of matches recorded, and check whether we're over the
	// number expected.
	expectation.NumMatches++
	_, maxCardinality := computeCardinality(expectation)
	if expectation.NumMatches > maxCardinality {
		c.reporter.ReportError(
			expectation.FileName,
			expectation.LineNumber,
			errors.New(
				fmt.Sprintf(
					"Unexpected call to %s: " +
						"expected to be called at most %d times; called %d times.",
					methodName,
					maxCardinality,
					expectation.NumMatches)))

		return makeZeroReturnValues(method)
	}

	// Choose an action to invoke. If there is none, just return zero values.
	action := chooseAction(expectation.NumMatches - 1, expectation)
	if action == nil {
		return makeZeroReturnValues(method)
	}

	// Let the action take over.
	return action.Invoke(args)
}
<commit_msg>Fixed an out of date comment.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package oglemock

import (
	"errors"
	"fmt"
	"math"
	"reflect"
)

// PartialExpecation is a function that should be called exactly once with
// expected arguments or matchers in order to set up an expected method call.
// See Controller.ExpectMethodCall below. It returns an expectation that can be
// further modified (e.g. by calling WillOnce).
//
// If the arguments are of the wrong type, the function reports a fatal error
// and returns nil.
type PartialExpecation func(...interface{}) Expectation

// Controller represents an object that implements the central logic of
// oglemock: recording and verifying expectations, responding to mock method
// calls, and so on.
type Controller interface {
	// ExpectCall expresses an expectation that the method of the given name
	// should be called on the supplied mock object. It returns a function that
	// should be called with the expected arguments, matchers for the arguments,
	// or a mix of both.
	//
	// fileName and lineNumber should indicate the line on which the expectation
	// was made, if known.
	//
	// For example:
	//
	//     mockWriter := [...]
	//     controller.ExpectCall(mockWriter, "Write", "foo.go", 17)(ElementsAre(0x1))
	//         .WillOnce(Return(1, nil))
	//
	// If the mock object doesn't have a method of the supplied name, the
	// function reports a fatal error and returns nil.
	ExpectCall(
		o MockObject,
		methodName string,
		fileName string,
		lineNumber int) PartialExpecation

	// Finish causes the controller to check for any unsatisfied expectations,
	// and report them as errors if they exist.
	//
	// The controller may panic if any of its methods (including this one) are
	// called after Finish is called.
	Finish()

	// HandleMethodCall looks for a registered expectation matching the call of
	// the given method on mock object o, invokes the appropriate action (if
	// any), and returns the values returned by that action (if any).
	//
	// If the action returns nothing, the controller returns zero values. If
	// there is no matching expectation, the controller reports an error and
	// returns zero values.
	//
	// If the mock object doesn't have a method of the supplied name, the
	// arguments are of the wrong type, or the action returns the wrong types,
	// the function reports a fatal error.
	//
	// HandleMethodCall is exported for the sake of mock implementations, and
	// should not be used directly.
	HandleMethodCall(
		o MockObject,
		methodName string,
		fileName string,
		lineNumber int,
		args []interface{}) []interface{}
}

// methodMap represents a map from method name to set of expectations for that
// method.
type methodMap map[string][]*InternalExpectation

// objectMap represents a map from mock object ID to a methodMap for that object.
type objectMap map[uintptr]methodMap

// NewController sets up a fresh controller, without any expectations set, and
// configures the controller to use the supplied error reporter.
func NewController(reporter ErrorReporter) Controller {
	return &controllerImpl{reporter, objectMap{}}
}

type controllerImpl struct {
	reporter ErrorReporter
	expectationsByObject objectMap
}

// getExpectations returns the list of registered expectations for the named
// method of the supplied object, or an empty slice if none have been
// registered. When this method returns, it is guaranteed that
// c.expectationsByObject has an entry for the object.
func (c *controllerImpl) getExpectations(
	o MockObject,
	methodName string) []*InternalExpectation {
	id := o.Oglemock_Id()

	// Look up the mock object.
	expectationsByMethod, ok := c.expectationsByObject[id]
	if !ok {
		expectationsByMethod = methodMap{}
		c.expectationsByObject[id] = expectationsByMethod
	}

	result, ok := expectationsByMethod[methodName]
	if !ok {
		return []*InternalExpectation{}
	}

	return result
}

// addExpectation adds an expectation to the list registered for the named
// method of the supplied mock object.
func (c *controllerImpl) addExpectation(
	o MockObject,
	methodName string,
	exp *InternalExpectation) {
	// Get the existing list.
	existing := c.getExpectations(o, methodName)

	// Store a modified list.
	id := o.Oglemock_Id()
	c.expectationsByObject[id][methodName] = append(existing, exp)
}

func (c *controllerImpl) ExpectCall(
	o MockObject,
	methodName string,
	fileName string,
	lineNumber int) PartialExpecation {
	// Find the signature for the requested method.
	oType := reflect.TypeOf(o)
	method, ok := oType.MethodByName(methodName)
	if !ok {
		c.reporter.ReportFatalError(
			fileName,
			lineNumber,
			errors.New("Unknown method: " + methodName))
		return nil
	}

	partialAlreadyCalled := false
	return func(args ...interface{}) Expectation {
		// This function should only be called once.
		if partialAlreadyCalled {
			c.reporter.ReportFatalError(
				fileName,
				lineNumber,
				errors.New("Partial expectation called more than once."))
			return nil
		}

		partialAlreadyCalled = true

		// Make sure that the number of args is legal. Keep in mind that the
		// method's type has an extra receiver arg.
		if len(args) != method.Type.NumIn() - 1 {
			c.reporter.ReportFatalError(
				fileName,
				lineNumber,
				errors.New(
					fmt.Sprintf(
						"Expectation for %s given wrong number of arguments: " +
						"expected %d, got %d.",
						methodName,
						method.Type.NumIn() - 1,
						len(args))))
			return nil
		}

		// Create an expectation and insert it into the controller's map.
		exp := InternalNewExpectation(
			c.reporter,
			method.Type,
			args,
			fileName,
			lineNumber)

		c.addExpectation(o, methodName, exp)

		// Return the expectation to the user.
		return exp
	}
}

func (c *controllerImpl) Finish() {
	// Check whether the minimum cardinality for each registered expectation has
	// been satisfied.
	for _, expectationsByMethod := range c.expectationsByObject {
		for methodName, expectations := range expectationsByMethod {
			for _, exp := range expectations {
				minCardinality, _ := computeCardinality(exp)
				if exp.NumMatches < minCardinality {
					c.reporter.ReportError(
						exp.FileName,
						exp.LineNumber,
						errors.New(
							fmt.Sprintf(
								"Unsatisfied expectation; expected %s to be called " +
								"at least %d times; called %d times.",
								methodName,
								minCardinality,
								exp.NumMatches)))
				}
			}
		}
	}
}

// expectationMatches checks the matchers for the expectation against the
// supplied arguments.
func expectationMatches(exp *InternalExpectation, args []interface{}) bool {
	matchers := exp.ArgMatchers
	if len(args) != len(matchers) {
		panic("expectationMatches: len(args)")
	}

	// Check each matcher.
	for i, matcher := range matchers {
		if err := matcher.Matches(args[i]); err != nil {
			return false
		}
	}

	return true
}

// chooseExpectation returns the expectation that matches the supplied
// arguments. If there is more than one such expectation, the one furthest
// along in the list for the method is returned. If there is no such
// expectation, nil is returned.
func (c *controllerImpl) chooseExpectation(
	o MockObject,
	methodName string,
	args []interface{}) *InternalExpectation {
	// Do we have any expectations for this method?
	expectations := c.getExpectations(o, methodName)
	if len(expectations) == 0 {
		return nil
	}

	for i := len(expectations) - 1; i >= 0; i-- {
		if (expectationMatches(expectations[i], args)) {
			return expectations[i]
		}
	}

	return nil
}

// makeZeroReturnValues creates a []interface{} containing appropriate zero
// values for returning from the supplied method type.
func makeZeroReturnValues(method reflect.Method) []interface{} {
	methodType := method.Type
	result := make([]interface{}, methodType.NumOut())

	for i, _ := range result {
		outType := methodType.Out(i)
		zeroVal := reflect.Zero(outType)
		result[i] = zeroVal.Interface()
	}

	return result
}

// computeCardinality decides on the [min, max] range of the number of expected
// matches for the supplied expectations, according to the rules documented in
// expectation.go.
func computeCardinality(exp *InternalExpectation) (min, max uint) {
	// Explicit cardinality.
	if exp.ExpectedNumMatches >= 0 {
		min = uint(exp.ExpectedNumMatches)
		max = min
		return
	}

	// Implicit count based on one-time actions.
	if len(exp.OneTimeActions) != 0 {
		min = uint(len(exp.OneTimeActions))
		max = min

		// If there is a fallback action, this is only a lower bound.
		if exp.FallbackAction != nil {
			max = math.MaxUint32
		}

		return
	}

	// Implicit lack of restriction based on a fallback action being configured.
	if exp.FallbackAction != nil {
		min = 0
		max = math.MaxUint32
		return
	}

	// Implicit cardinality of one.
	min = 1
	max = 1
	return
}

// chooseAction returns the action that should be invoked for the i'th match to
// the supplied expectation (counting from zero). If the implicit "return zero
// values" action should be used, it returns nil.
func chooseAction(i uint, exp *InternalExpectation) Action {
	// Exhaust one-time actions first.
	if i < uint(len(exp.OneTimeActions)) {
		return exp.OneTimeActions[i]
	}

	// Fallback action (or nil if none is configured).
	return exp.FallbackAction
}

func (c *controllerImpl) HandleMethodCall(
	o MockObject,
	methodName string,
	fileName string,
	lineNumber int,
	args []interface{}) []interface{} {
	// Find the signature for the requested method.
	oType := reflect.TypeOf(o)
	method, ok := oType.MethodByName(methodName)
	if !ok {
		c.reporter.ReportFatalError(
			fileName,
			lineNumber,
			errors.New("Unknown method: " + methodName))
		return nil
	}

	// HACK(jacobsa): Make sure we got the correct number of arguments. This will
	// need to be refined when issue #5 (variadic methods) is handled.
	if len(args) != method.Type.NumIn() - 1 {
		c.reporter.ReportFatalError(
			fileName,
			lineNumber,
			errors.New(
				fmt.Sprintf(
					"Wrong number of arguments: expected %d; got %d",
					method.Type.NumIn() - 1,
					len(args))))
		return nil
	}

	// Find an expectation matching this call.
	expectation := c.chooseExpectation(o, methodName, args)
	if expectation == nil {
		c.reporter.ReportError(
			fileName,
			lineNumber,
			errors.New(
				fmt.Sprintf("Unexpected call to %s with args: %v", methodName, args)))

		return makeZeroReturnValues(method)
	}

	// Increase the number of matches recorded, and check whether we're over the
	// number expected.
	expectation.NumMatches++
	_, maxCardinality := computeCardinality(expectation)
	if expectation.NumMatches > maxCardinality {
		c.reporter.ReportError(
			expectation.FileName,
			expectation.LineNumber,
			errors.New(
				fmt.Sprintf(
					"Unexpected call to %s: " +
						"expected to be called at most %d times; called %d times.",
					methodName,
					maxCardinality,
					expectation.NumMatches)))

		return makeZeroReturnValues(method)
	}

	// Choose an action to invoke. If there is none, just return zero values.
	action := chooseAction(expectation.NumMatches - 1, expectation)
	if action == nil {
		return makeZeroReturnValues(method)
	}

	// Let the action take over.
	return action.Invoke(args)
}
<|endoftext|>


<commit_before><commit_msg>CLI: inform when seitan has no label instead of displaying empty name<commit_after><|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"math/rand"
	"net/mail"
	"net/smtp"
	"net/textproto"
	"os"
	"os/user"
	"reflect"
	"regexp"
	"strings"
	"time"
	"crypto/tls"
	"github.com/blackjack/syslog"
)

var config = &Configuration{
	Verbose:     false,
	ConfigFile:  "/etc/go-ssmtp.ini",
	Port:        25,
	Server:      "127.0.0.1",
	Postmaster:  "postmaster",
	ScanMessage: false,
}

type Configuration struct {
	Verbose                      bool
	ConfigFile                   string
	Hostname                     string
	Server                       string
	Port                         int
	Postmaster                   string
	ScanMessage                  bool
	Authentication_User          string
	Authentication_Password      string
	Authentication_Identity      string
	Authentication_Mechanism     string
	Authentication_ForceStartTLS bool
	Message_To                   []string
	Message_From                 string
	Message_FromName             string
	Message_FromCronDaemon       bool
}

func generateMessageId() string {
	const CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	bytes := make([]byte, 16)

	for i, r := 0, rand.New(rand.NewSource(time.Now().UnixNano())); i < len(bytes); i++ {
		bytes[i] = CHARS[r.Intn(len(CHARS))]
	}

	return string(bytes)
}

func (c *Configuration) ParseFile(file string) error {
	var matchSection = regexp.MustCompile(`^\[([^]]+)\]$`)
	var matchPair = regexp.MustCompile(`^([^#;=]+)=(.*)$`)

	f, err := os.Open(file)

	if err != nil {
		return err
	}

	defer f.Close()

	s := bufio.NewScanner(f)
	s.Split(bufio.ScanLines)
	var n, section = 1, ""

	for s.Scan() {
		l := s.Text()

		if 0 == len(l) || ';' == l[0] {
			continue
		} else if parts := matchSection.FindStringSubmatch(l); parts != nil {
			section = parts[1]
		} else if parts := matchPair.FindStringSubmatch(l); parts != nil {
			k, v := parts[1], parts[2]

			if section != "" {
				k = section + "_" + k
			}

			if !c.Get(k).IsValid() {
				fmt.Fprintf(os.Stderr, "Warning: unknown configuration variable %s, line %d\n", k, n)
			} else if "string" == config.Get(k).Type().String() {
				c.Get(k).SetString(v)
			} else if "bool" == config.Get(k).Type().String() {
				c.Get(k).SetBool("1" == v)
			}
		} else {
			return fmt.Errorf("Failed to parse config, line %d: %s", n, l)
		}

		n++
	}

	return nil
}

func (c *Configuration) Get(k string) reflect.Value {
	r := reflect.ValueOf(c)
	return reflect.Indirect(r).FieldByName(k)
}

func compose() (*mail.Message, error) {
	// Make sure we can re-use Stdin even after being consumed by mail.ReadMessage
	b := bytes.Buffer{}
	b.ReadFrom(os.Stdin)
	msg := b.String()

	m, err := mail.ReadMessage(bytes.NewBufferString(msg))
	if err != nil {
		if config.ScanMessage {
			return nil, fmt.Errorf("ScanMessage: cannot parse message: %s", err)
		}

		// Assume there are no headers in the message
		m = &mail.Message{
			Header: mail.Header(textproto.MIMEHeader{}),
			Body:   bufio.NewReader(bytes.NewBufferString(msg)),
		}
	}

	// Make sure all required fields are set
	if 0 == len(m.Header["From"]) {
		m.Header["From"] = []string{(&mail.Address{config.Message_FromName, config.Message_From}).String()}
	} else if from, err := mail.ParseAddress(m.Header["From"][0]); config.ScanMessage && err == nil {
		// Parse and put in config; to be used by c.Mail
		config.Message_From = from.Address;
	}

	if 0 == len(m.Header["To"]) {
		m.Header["To"] = config.Message_To
	}

	if 0 == len(m.Header["Date"]) {
		m.Header["Date"] = []string{time.Now().Format("Mon, 2 Jan 2006 15:04:05 -0700")}
	}

	if 0 == len(m.Header["Message-Id"]) {
		m.Header["Message-Id"] = []string{"<GOSSMTP." + generateMessageId() + "@" + config.Hostname + ">"}
	}

	return m, nil
}

func connect() (*smtp.Client, error) {
	c, err := smtp.Dial(fmt.Sprintf("%s:%d", config.Server, config.Port))

	if err != nil {
		return nil, fmt.Errorf("while connecting to %s on port %d: %s", config.Server, config.Port, err)
	}

	if err := c.Hello(config.Hostname); err != nil {
		return nil, fmt.Errorf("while sending Hello `%s`: %s", config.Hostname, err)
	}

	if ok, _ := c.Extension("STARTTLS"); ok {
			if err = c.StartTLS(&tls.Config{ServerName: config.Server}); err != nil {
			return nil, fmt.Errorf("while enabling startTLS: %s", err)
		}
	} else if config.Authentication_ForceStartTLS {
		return nil, fmt.Errorf("server does not support StartTLS")
	}

	switch config.Authentication_Mechanism {
	case "CRAM-MD5":
		auth := smtp.CRAMMD5Auth(
			config.Authentication_User,
			config.Authentication_Password,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				return nil, fmt.Errorf("Info: using authentication: CRAM-MD5")
			}
		}

	case "PLAIN":
		auth := smtp.PlainAuth(
			config.Authentication_Identity,
			config.Authentication_User,
			config.Authentication_Password,
			config.Server,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				fmt.Println("Info: using authentication: PLAIN")
			}
		}

	default:
		if config.Verbose {
			fmt.Println("Info: not using authentication")
		}
	}

	return c, nil
}

func send(c *smtp.Client, m *mail.Message) error {
	if err := c.Mail(config.Message_From); err != nil {
		return fmt.Errorf("while setting From `%s`: %s", config.Message_From, err)
	}

	if config.ScanMessage {
		for _, i := range []string{"To", "Cc", "Bcc"} {
			if 0 == len(m.Header[i]) {
				continue
			}

			if l, err := m.Header.AddressList(i); err != nil {
				fmt.Fprintf(os.Stderr, "ScanMessage: Could not parse recipients in %s `%s`; %s", i, l, err)
			} else {
				for _, v := range l {
					config.Message_To = append(config.Message_To, v.Address)
				}
			}
		}

		if 0 == len(config.Message_To) {
			fmt.Fprintln(os.Stderr, "ScanMessage: No recipients found in message-body")
		}
	}

	for _, to := range config.Message_To {
		if err := c.Rcpt(to); err != nil {
			return fmt.Errorf("while setting Recipient `%s`: %s", to, err)
		}
	}

	w, err := c.Data()
	if err != nil {
		return fmt.Errorf("while setting Data: %s", err)
	}

	var s = ""
	for k, h := range m.Header {
		for _, v := range h {
			s += k + ": " + v + "\r\n"
		}
	}

	b := bytes.Buffer{}
	b.ReadFrom(m.Body)

	if _, err := w.Write([]byte(s + "\r\n" + b.String())); err != nil {
		return fmt.Errorf("while sending message: %s", err)
	}

	if err = w.Close(); err != nil {
		return fmt.Errorf("while closing message: %s", err)
	}

	if err = c.Quit(); err != nil {
		return fmt.Errorf("while closing connection: %s", err)
	}

	return nil
}

func init() {
	if h, err := os.Hostname(); err == nil {
		config.Hostname = h
	} else {
		config.Hostname = "localhost"
	}

	if u, err := user.Current(); err == nil {
		config.Message_From = u.Username + "@" + config.Hostname

		if u.Name != "" {
			config.Message_FromName = u.Name
		} else {
			config.Message_FromName = u.Username
		}
	}

	if -1 == strings.Index(config.Postmaster, "@") {
		config.Postmaster += "@" + config.Hostname
	}

	syslog.Openlog("go-ssmtp", syslog.LOG_PID, syslog.LOG_USER)

	var ignore bool
	flag.BoolVar(&ignore, "i", false, "Ignore")
	flag.BoolVar(&ignore, "odi", false, "Ignore")
	flag.BoolVar(&config.Message_FromCronDaemon, "FCronDaemon", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Message_FromCronDaemon, "FAnacron", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Verbose, "v", config.Verbose, "Enable verbose mode")
	flag.StringVar(&config.ConfigFile, "C", config.ConfigFile, "Use alternate configuration file")
	flag.StringVar(&config.Message_From, "f", config.Message_From, "Manually specify the sender-address of the email")
	flag.StringVar(&config.Message_FromName, "F", config.Message_FromName, "Manually specify the sender-name of the email")
	flag.BoolVar(&config.ScanMessage, "t", config.ScanMessage, "Scan message for recipients")
}

func main() {
	// Don't throw an error when encountering an unknown flag (for sendmail compat)
	flag.CommandLine.Init(os.Args[0], flag.ContinueOnError)

	flag.Parse()

	if config.Message_FromCronDaemon {
		config.Message_FromName = "CronDaemon"
	}

	// Map all local users to Postmaster address
	config.Message_To = flag.Args()
	for i, to := range config.Message_To {
		if -1 == strings.Index(to, "@") {
			config.Message_To[i] = (&mail.Address{to, config.Postmaster}).String()
		}
	}

	if err := config.ParseFile(config.ConfigFile); err != nil {
		fmt.Fprintf(os.Stderr, "Error while parsing configuration: %s\n", err)
		os.Exit(2)
	}

	if config.Verbose {
		fmt.Printf("%#v\n", *config)
	}

	if len(config.Message_To) == 0 && !config.ScanMessage {
		fmt.Fprintln(os.Stderr, "Error: no recipients supplied")
		os.Exit(1)
	}

	m, err := compose()
	if err != nil {
		syslog.Errf("ComposeError: %s", err)
		fmt.Fprintf(os.Stderr, "ComposeError: %s\n", err)
		os.Exit(2)
	}

	c, err := connect()
	if err != nil {
		syslog.Errf("ConnectError: %s", err)
		fmt.Fprintf(os.Stderr, "ConnectError: %s\n", err)
		os.Exit(3)
	}

	if err := send(c, m); err != nil {
		syslog.Errf("SendError: %s", err)
		fmt.Fprintf(os.Stderr, "SendError: %s\n", err)
		os.Exit(4)
	}

	var subject string = "(unknown)"
	if len(m.Header["Subject"]) > 0 {
		subject = m.Header["Subject"][0]
	}

	syslog.Syslogf(syslog.LOG_INFO, "[%s] Sent mail; subject \"%s\"; from %s; to %#v", m.Header["Message-Id"][0], subject, config.Message_From, config.Message_To);

	if config.Verbose {
		fmt.Println("Info: send successful")
	}
}
<commit_msg>Parse config-file before mapping local users to Postmaster<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"math/rand"
	"net/mail"
	"net/smtp"
	"net/textproto"
	"os"
	"os/user"
	"reflect"
	"regexp"
	"strings"
	"time"
	"crypto/tls"
	"github.com/blackjack/syslog"
)

var config = &Configuration{
	Verbose:     false,
	ConfigFile:  "/etc/go-ssmtp.ini",
	Port:        25,
	Server:      "127.0.0.1",
	Postmaster:  "postmaster",
	ScanMessage: false,
}

type Configuration struct {
	Verbose                      bool
	ConfigFile                   string
	Hostname                     string
	Server                       string
	Port                         int
	Postmaster                   string
	ScanMessage                  bool
	Authentication_User          string
	Authentication_Password      string
	Authentication_Identity      string
	Authentication_Mechanism     string
	Authentication_ForceStartTLS bool
	Message_To                   []string
	Message_From                 string
	Message_FromName             string
	Message_FromCronDaemon       bool
}

func generateMessageId() string {
	const CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	bytes := make([]byte, 16)

	for i, r := 0, rand.New(rand.NewSource(time.Now().UnixNano())); i < len(bytes); i++ {
		bytes[i] = CHARS[r.Intn(len(CHARS))]
	}

	return string(bytes)
}

func (c *Configuration) ParseFile(file string) error {
	var matchSection = regexp.MustCompile(`^\[([^]]+)\]$`)
	var matchPair = regexp.MustCompile(`^([^#;=]+)=(.*)$`)

	f, err := os.Open(file)

	if err != nil {
		return err
	}

	defer f.Close()

	s := bufio.NewScanner(f)
	s.Split(bufio.ScanLines)
	var n, section = 1, ""

	for s.Scan() {
		l := s.Text()

		if 0 == len(l) || ';' == l[0] {
			continue
		} else if parts := matchSection.FindStringSubmatch(l); parts != nil {
			section = parts[1]
		} else if parts := matchPair.FindStringSubmatch(l); parts != nil {
			k, v := parts[1], parts[2]

			if section != "" {
				k = section + "_" + k
			}

			if !c.Get(k).IsValid() {
				fmt.Fprintf(os.Stderr, "Warning: unknown configuration variable %s, line %d\n", k, n)
			} else if "string" == config.Get(k).Type().String() {
				c.Get(k).SetString(v)
			} else if "bool" == config.Get(k).Type().String() {
				c.Get(k).SetBool("1" == v)
			}
		} else {
			return fmt.Errorf("Failed to parse config, line %d: %s", n, l)
		}

		n++
	}

	return nil
}

func (c *Configuration) Get(k string) reflect.Value {
	r := reflect.ValueOf(c)
	return reflect.Indirect(r).FieldByName(k)
}

func compose() (*mail.Message, error) {
	// Make sure we can re-use Stdin even after being consumed by mail.ReadMessage
	b := bytes.Buffer{}
	b.ReadFrom(os.Stdin)
	msg := b.String()

	m, err := mail.ReadMessage(bytes.NewBufferString(msg))
	if err != nil {
		if config.ScanMessage {
			return nil, fmt.Errorf("ScanMessage: cannot parse message: %s", err)
		}

		// Assume there are no headers in the message
		m = &mail.Message{
			Header: mail.Header(textproto.MIMEHeader{}),
			Body:   bufio.NewReader(bytes.NewBufferString(msg)),
		}
	}

	// Make sure all required fields are set
	if 0 == len(m.Header["From"]) {
		m.Header["From"] = []string{(&mail.Address{config.Message_FromName, config.Message_From}).String()}
	} else if from, err := mail.ParseAddress(m.Header["From"][0]); config.ScanMessage && err == nil {
		// Parse and put in config; to be used by c.Mail
		config.Message_From = from.Address;
	}

	if 0 == len(m.Header["To"]) {
		m.Header["To"] = config.Message_To
	}

	if 0 == len(m.Header["Date"]) {
		m.Header["Date"] = []string{time.Now().Format("Mon, 2 Jan 2006 15:04:05 -0700")}
	}

	if 0 == len(m.Header["Message-Id"]) {
		m.Header["Message-Id"] = []string{"<GOSSMTP." + generateMessageId() + "@" + config.Hostname + ">"}
	}

	return m, nil
}

func connect() (*smtp.Client, error) {
	c, err := smtp.Dial(fmt.Sprintf("%s:%d", config.Server, config.Port))

	if err != nil {
		return nil, fmt.Errorf("while connecting to %s on port %d: %s", config.Server, config.Port, err)
	}

	if err := c.Hello(config.Hostname); err != nil {
		return nil, fmt.Errorf("while sending Hello `%s`: %s", config.Hostname, err)
	}

	if ok, _ := c.Extension("STARTTLS"); ok {
			if err = c.StartTLS(&tls.Config{ServerName: config.Server}); err != nil {
			return nil, fmt.Errorf("while enabling startTLS: %s", err)
		}
	} else if config.Authentication_ForceStartTLS {
		return nil, fmt.Errorf("server does not support StartTLS")
	}

	switch config.Authentication_Mechanism {
	case "CRAM-MD5":
		auth := smtp.CRAMMD5Auth(
			config.Authentication_User,
			config.Authentication_Password,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				return nil, fmt.Errorf("Info: using authentication: CRAM-MD5")
			}
		}

	case "PLAIN":
		auth := smtp.PlainAuth(
			config.Authentication_Identity,
			config.Authentication_User,
			config.Authentication_Password,
			config.Server,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				fmt.Println("Info: using authentication: PLAIN")
			}
		}

	default:
		if config.Verbose {
			fmt.Println("Info: not using authentication")
		}
	}

	return c, nil
}

func send(c *smtp.Client, m *mail.Message) error {
	if err := c.Mail(config.Message_From); err != nil {
		return fmt.Errorf("while setting From `%s`: %s", config.Message_From, err)
	}

	if config.ScanMessage {
		for _, i := range []string{"To", "Cc", "Bcc"} {
			if 0 == len(m.Header[i]) {
				continue
			}

			if l, err := m.Header.AddressList(i); err != nil {
				fmt.Fprintf(os.Stderr, "ScanMessage: Could not parse recipients in %s `%s`; %s", i, l, err)
			} else {
				for _, v := range l {
					config.Message_To = append(config.Message_To, v.Address)
				}
			}
		}

		if 0 == len(config.Message_To) {
			fmt.Fprintln(os.Stderr, "ScanMessage: No recipients found in message-body")
		}
	}

	for _, to := range config.Message_To {
		if err := c.Rcpt(to); err != nil {
			return fmt.Errorf("while setting Recipient `%s`: %s", to, err)
		}
	}

	w, err := c.Data()
	if err != nil {
		return fmt.Errorf("while setting Data: %s", err)
	}

	var s = ""
	for k, h := range m.Header {
		for _, v := range h {
			s += k + ": " + v + "\r\n"
		}
	}

	b := bytes.Buffer{}
	b.ReadFrom(m.Body)

	if _, err := w.Write([]byte(s + "\r\n" + b.String())); err != nil {
		return fmt.Errorf("while sending message: %s", err)
	}

	if err = w.Close(); err != nil {
		return fmt.Errorf("while closing message: %s", err)
	}

	if err = c.Quit(); err != nil {
		return fmt.Errorf("while closing connection: %s", err)
	}

	return nil
}

func init() {
	if h, err := os.Hostname(); err == nil {
		config.Hostname = h
	} else {
		config.Hostname = "localhost"
	}

	if u, err := user.Current(); err == nil {
		config.Message_From = u.Username + "@" + config.Hostname

		if u.Name != "" {
			config.Message_FromName = u.Name
		} else {
			config.Message_FromName = u.Username
		}
	}

	if -1 == strings.Index(config.Postmaster, "@") {
		config.Postmaster += "@" + config.Hostname
	}

	syslog.Openlog("go-ssmtp", syslog.LOG_PID, syslog.LOG_USER)

	var ignore bool
	flag.BoolVar(&ignore, "i", false, "Ignore")
	flag.BoolVar(&ignore, "odi", false, "Ignore")
	flag.BoolVar(&config.Message_FromCronDaemon, "FCronDaemon", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Message_FromCronDaemon, "FAnacron", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Verbose, "v", config.Verbose, "Enable verbose mode")
	flag.StringVar(&config.ConfigFile, "C", config.ConfigFile, "Use alternate configuration file")
	flag.StringVar(&config.Message_From, "f", config.Message_From, "Manually specify the sender-address of the email")
	flag.StringVar(&config.Message_FromName, "F", config.Message_FromName, "Manually specify the sender-name of the email")
	flag.BoolVar(&config.ScanMessage, "t", config.ScanMessage, "Scan message for recipients")
}

func main() {
	// Don't throw an error when encountering an unknown flag (for sendmail compat)
	flag.CommandLine.Init(os.Args[0], flag.ContinueOnError)

	flag.Parse()

	if config.Message_FromCronDaemon {
		config.Message_FromName = "CronDaemon"
	}

	if err := config.ParseFile(config.ConfigFile); err != nil {
		fmt.Fprintf(os.Stderr, "Error while parsing configuration: %s\n", err)
		os.Exit(2)
	}

	// Map all local users to Postmaster address
	config.Message_To = flag.Args()
	for i, to := range config.Message_To {
		if -1 == strings.Index(to, "@") {
			config.Message_To[i] = (&mail.Address{to, config.Postmaster}).String()
		}
	}

	if config.Verbose {
		fmt.Printf("%#v\n", *config)
	}

	if len(config.Message_To) == 0 && !config.ScanMessage {
		fmt.Fprintln(os.Stderr, "Error: no recipients supplied")
		os.Exit(1)
	}

	m, err := compose()
	if err != nil {
		syslog.Errf("ComposeError: %s", err)
		fmt.Fprintf(os.Stderr, "ComposeError: %s\n", err)
		os.Exit(2)
	}

	c, err := connect()
	if err != nil {
		syslog.Errf("ConnectError: %s", err)
		fmt.Fprintf(os.Stderr, "ConnectError: %s\n", err)
		os.Exit(3)
	}

	if err := send(c, m); err != nil {
		syslog.Errf("SendError: %s", err)
		fmt.Fprintf(os.Stderr, "SendError: %s\n", err)
		os.Exit(4)
	}

	var subject string = "(unknown)"
	if len(m.Header["Subject"]) > 0 {
		subject = m.Header["Subject"][0]
	}

	syslog.Syslogf(syslog.LOG_INFO, "[%s] Sent mail; subject \"%s\"; from %s; to %#v", m.Header["Message-Id"][0], subject, config.Message_From, config.Message_To);

	if config.Verbose {
		fmt.Println("Info: send successful")
	}
}
<|endoftext|>


<commit_before>package tspsa

import (
	"math/rand"
	"math"
	"fmt"
	"io/ioutil"
	"strings"
	"strconv"
)

/*
 * Wrapper to call SA with random points
 * it: Itterations
 * t: temp
 * tmin: Min Temp
 * c: coolrate
 * x: Number of x coordinates
 * y: Number of y coordinates
 * p: Number of Points
 * v: Verbose
 */
func RunSARandom(it int, t float64, tmin float64, c float64, x int, y int, p int, v bool) Route {
	return RunSA(it, t, tmin, c, CreateRandomMAP(x, y, p), v)
}

/* TODO
 * Run Simmulated Annealing Algorithm from a given XML file
 */
func RunSAFromFile(it int, t float64, tmin float64, c float64, f string, v bool) Route {
	lines, err := readFile(f)
	if err != nil {
		fmt.Println(err.Error())
	}
	n := createNodesFromString(lines)
	return RunSA(it, t, tmin, c, n, v)
}
/*
 * l: splice of strings as lines in a file
 */
func createNodesFromString(lines []string) []Node {
	var r []Node
	for i := 0; i < len(lines); i++ {
		l := strings.Fields(lines[i])
		if len(l) == 3 {
			x, err1 := strconv.Atoi(l[1])
			y, err2 := strconv.Atoi(l[2])
			if err1 == nil && err2 == nil {
				n := Node{x, y}
				r = append(r, n)
			}
		}
	}
	return r
}

/*
 * File parsing
 * f: filename
 */
func readFile(f string) ([]string, error) {
	file, err := ioutil.ReadFile(f)
	if err != nil {
		return nil, err
	}
	return strings.Split(string(file), "\n"), nil
}

/*
 * Run the SA algorithm with the given itterations, temp, min temp, coolrate, and a splice of Node objects
 *
 * i:    Itterations
 * t: 	 temp
 * tmin: temp min
 * c: 	 coolrate
 */
func RunSA(it int, t float64, tmin float64, c float64, n []Node, p bool) Route {
	// Set the Routes for the current SA given the list of nodes
	cur  := Route{n, math.MaxFloat64}
	cur.CalcDistance() // old cost
	best := Route{n, math.MaxFloat64}
	next := Route{n, math.MaxFloat64}
	l := cur.Nodes() // Length
	for t > tmin {
		for i := 0; i < it; i++ {
			next.SwapNodes(rand.Intn(l), rand.Intn(l))
			next.CalcDistance()
			if acceptProb(cur.D, next.D, t) >= 0.5 {
				cur.R = next.R
				cur.D = next.D
			}
			if (cur.D < best.D) {
				best.R = cur.R
				best.D = cur.D
			}
		}
		t = t * c
	}
	if p {
		fmt.Println(best.String())
		fmt.Printf("Distance: %.6f\n", best.D)
	}
	return best
}

/*
 * acceptance Probability Calculation
 * This should return 1.0 if the new energy is greater than the current energy
 * Else it will return the acceptance Probability
 */
func acceptProb(e float64, ne float64, t float64) float64 {
	if ne > e {
		return 1
	} else {
		// acceptance probability
		return math.Exp((e - ne) / t)
	}
}

<commit_msg>update comment for run from a file<commit_after>package tspsa

import (
	"math/rand"
	"math"
	"fmt"
	"io/ioutil"
	"strings"
	"strconv"
)

/*
 * Wrapper to call SA with random points
 * it: Itterations
 * t: temp
 * tmin: Min Temp
 * c: coolrate
 * x: Number of x coordinates
 * y: Number of y coordinates
 * p: Number of Points
 * v: Verbose
 */
func RunSARandom(it int, t float64, tmin float64, c float64, x int, y int, p int, v bool) Route {
	return RunSA(it, t, tmin, c, CreateRandomMAP(x, y, p), v)
}

/*
 * Run Simmulated Annealing Algorithm from a given tsp file
 * it: Itterations
 * t: temp
 * tmin: Min Temp
 * c: Cool Rate
 * f: File Name
 * v: Verbose
 */
func RunSAFromFile(it int, t float64, tmin float64, c float64, f string, v bool) Route {
	lines, err := readFile(f)
	if err != nil {
		fmt.Println(err.Error())
	}
	n := createNodesFromString(lines)
	return RunSA(it, t, tmin, c, n, v)
}

/*
 * l: splice of strings as lines in a file
 */
func createNodesFromString(lines []string) []Node {
	var r []Node
	for i := 0; i < len(lines); i++ {
		l := strings.Fields(lines[i])
		if len(l) == 3 {
			x, err1 := strconv.Atoi(l[1])
			y, err2 := strconv.Atoi(l[2])
			if err1 == nil && err2 == nil {
				n := Node{x, y}
				r = append(r, n)
			}
		}
	}
	return r
}

/*
 * File parsing
 * f: filename
 */
func readFile(f string) ([]string, error) {
	file, err := ioutil.ReadFile(f)
	if err != nil {
		return nil, err
	}
	return strings.Split(string(file), "\n"), nil
}

/*
 * Run the SA algorithm with the given itterations, temp, min temp, coolrate, and a splice of Node objects
 *
 * i:    Itterations
 * t: 	 temp
 * tmin: temp min
 * c: 	 coolrate
 */
func RunSA(it int, t float64, tmin float64, c float64, n []Node, p bool) Route {
	// Set the Routes for the current SA given the list of nodes
	cur  := Route{n, math.MaxFloat64}
	cur.CalcDistance() // old cost
	best := Route{n, math.MaxFloat64}
	next := Route{n, math.MaxFloat64}
	l := cur.Nodes() // Length
	for t > tmin {
		for i := 0; i < it; i++ {
			next.SwapNodes(rand.Intn(l), rand.Intn(l))
			next.CalcDistance()
			if acceptProb(cur.D, next.D, t) >= 0.5 {
				cur.R = next.R
				cur.D = next.D
			}
			if (cur.D < best.D) {
				best.R = cur.R
				best.D = cur.D
			}
		}
		t = t * c
	}
	if p {
		fmt.Println(best.String())
		fmt.Printf("Distance: %.6f\n", best.D)
	}
	return best
}

/*
 * acceptance Probability Calculation
 * This should return 1.0 if the new energy is greater than the current energy
 * Else it will return the acceptance Probability
 */
func acceptProb(e float64, ne float64, t float64) float64 {
	if ne > e {
		return 1
	} else {
		// acceptance probability
		return math.Exp((e - ne) / t)
	}
}

<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type RSS struct {
	Channel Channel `xml:"channel"`
	Item    []Item  `xml:"item"`
}

type Channel struct {
	Title       string `xml:"title"`
	Link        string `xml:"link"`
	Description string `xml:"description"`
}

type Item struct {
	Title     string `xml:"title"`
	Link      string `xml:"link"`
	Bookmarks int    `xml:"bookmarkcount"`
}

func hotentryUrl(keyword string, threshold int) string {
	tmpl := `http://b.hatena.ne.jp/search/tag?q=%s&users=%d&mode=rss`
	ret := fmt.Sprintf(tmpl, keyword, threshold)

	return ret
}

func main() {
	threshold := flag.Int("t", 3, "threshold of bookmarks")
	limit := flag.Int("l", 10, "limit of printing entries")
	flag.Parse()

	key := flag.Arg(0)
	if key == "" {
		fmt.Printf("Please specified 'keyword'!!\n")
		os.Exit(1)
	}

	url := hotentryUrl(key, *threshold)
	response, err := http.Get(url)
	if err != nil {
		log.Printf("Can't download '%s'", url)
		os.Exit(1)
	}
	defer response.Body.Close()

	bytes, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Printf("Can't read response: %s", err.Error())
		os.Exit(1)
	}

	var rss RSS
	if err := xml.Unmarshal(bytes, &rss); err != nil {
		fmt.Printf("Error: %s\n", err.Error())
		return
	}

	if *limit > len(rss.Item) {
		fmt.Printf("Limit '%s' is too long", *limit)
		*limit = len(rss.Item)
	}

	for i, item := range rss.Item[:*limit] {
		fmt.Printf("%2d: %s [%d]\n", i+1, item.Title, item.Bookmarks)
	}
}
<commit_msg>use pflag package instead of flag<commit_after>package main

import (
	"encoding/xml"
	"fmt"
	flag "github.com/ogier/pflag"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type RSS struct {
	Channel Channel `xml:"channel"`
	Item    []Item  `xml:"item"`
}

type Channel struct {
	Title       string `xml:"title"`
	Link        string `xml:"link"`
	Description string `xml:"description"`
}

type Item struct {
	Title     string `xml:"title"`
	Link      string `xml:"link"`
	Bookmarks int    `xml:"bookmarkcount"`
}

func hotentryUrl(keyword string, threshold int) string {
	tmpl := `http://b.hatena.ne.jp/search/tag?q=%s&users=%d&mode=rss`
	ret := fmt.Sprintf(tmpl, keyword, threshold)

	return ret
}

func main() {
	threshold := flag.IntP("threshold", "t", 3, "threshold of bookmarks")
	limit := flag.IntP("limit", "l", 10, "limit of printing entries")
	flag.Parse()

	key := flag.Arg(0)
	if key == "" {
		fmt.Printf("Please specified 'keyword'!!\n")
		os.Exit(1)
	}

	url := hotentryUrl(key, *threshold)
	response, err := http.Get(url)
	if err != nil {
		log.Printf("Can't download '%s'", url)
		os.Exit(1)
	}
	defer response.Body.Close()

	bytes, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Printf("Can't read response: %s", err.Error())
		os.Exit(1)
	}

	var rss RSS
	if err := xml.Unmarshal(bytes, &rss); err != nil {
		fmt.Printf("Error: %s\n", err.Error())
		return
	}

	if *limit > len(rss.Item) {
		fmt.Printf("Limit '%s' is too long", *limit)
		*limit = len(rss.Item)
	}

	for i, item := range rss.Item[:*limit] {
		fmt.Printf("%2d: %s [%d]\n", i+1, item.Title, item.Bookmarks)
	}
}
<|endoftext|>


<commit_before><commit_msg>logging: avoid sending zero latency for request entries<commit_after><|endoftext|>


<commit_before>package soaap

import (
	"encoding/gob"
	"errors"
	"fmt"
	"math"
	"os"
	"strings"
)

type CallGraph struct {
	Nodes map[string]GraphNode
	Calls map[Call]int
}

//
// Create a new, empty CallGraph with enough capacity to hold some calls.
//
func NewCallGraph() CallGraph {
	return CallGraph{
		make(map[string]GraphNode),
		make(map[Call]int),
	}
}

//
// Load a CallGraph from a binary-encoded file.
//
func LoadGraph(f *os.File, report func(string)) (CallGraph, error) {
	var graph CallGraph
	err := gob.NewDecoder(f).Decode(&graph)

	return graph, err
}

func (cg *CallGraph) AddCall(caller string, callee string) {
	cg.Calls[Call{caller, callee}] += 1
}

//
// Save a CallGraph to an os.File using a binary encoding.
//
func (cg *CallGraph) Save(f *os.File) error {
	return gob.NewEncoder(f).Encode(cg)
}

//
// Simplify a CallGraph by collapsing call chains and dropping any
// unreferenced calls.
//
func (cg *CallGraph) Simplify() {
}

func (cg *CallGraph) Union(g CallGraph) error {
	for id, node := range g.Nodes {
		// If we already have a GraphNode with this identifier,
		// merge the two descriptions and tag sets.
		if n, have := cg.Nodes[id]; have {
			if n.Name != node.Name {
				return errors.New(fmt.Sprintf(
					"Nodes in CallGraph union have"+
						" same identifier ('%s') but"+
						" different names ('%s' vs '%s')",
					id, n.Name, node.Name))
			}

			if n.Description != node.Description {
				node.Description =
					n.Description + "\\n" + node.Description
			}

			for tag := range n.Tags {
				node.Tags[tag] = true
			}
		}

		cg.Nodes[id] = node
	}

	for call, count := range g.Calls {
		cg.Calls[call] += count
	}

	return nil
}

//
// A node in a call graph.
//
// This is derived from a call site or other program location, but can have
// an arbitrary name and description appropriate to a particular analysis.
//
type GraphNode struct {
	Name        string
	Description string

	// A vulnerability (current or previous) is known at this location.
	CVE []CVE

	// The name of this node's sandbox (or the empty string if unsandboxed).
	Sandbox string

	// The name of the sandbox(es) that own the data being accessed.
	Owners []string

	Tags map[string]bool
}

//
// Construct a GraphViz Dot description of a GraphNode.
//
// This applies SOAAP-specific styling depending on a node's tags.
//
func (n GraphNode) Dot() string {
	attrs := map[string]interface{}{
		"label": n.Description,
	}

	return fmt.Sprintf("\"%s\" %s;", n.Name, dotAttrs(attrs))
}

func (n GraphNode) HasTag(tag string) bool {
	_, present := n.Tags[tag]
	return present
}

type Call struct {
	// Identifier of the caller.
	Caller string

	// Identifier of the callee.
	Callee string
}

// Output GraphViz for a Call.
func (c Call) Dot(graph CallGraph, weight int) string {
	caller := graph.Nodes[c.Caller]
	callee := graph.Nodes[c.Callee]

	attrs := map[string]interface{}{
		"penwidth": weight,
		"weight":   weight,
	}

	return fmt.Sprintf("\"%s\" -> \"%s\" %s;\n",
		caller.Name, callee.Name, dotAttrs(attrs))
}

//
// A function that extracts a CallGraph from SOAAP Results.
//
type graphFn func(results Results, progress func(string)) CallGraph

var graphExtractors map[string]graphFn = map[string]graphFn{
	"privaccess": PrivAccessGraph,
	"vuln":       VulnGraph,
}

func GraphAnalyses() []string {
	keys := make([]string, len(graphExtractors))

	i := 0
	for k, _ := range graphExtractors {
		keys[i] = k
		i++
	}

	return keys
}

type callSiteLabeler func(CallSite) (string, GraphNode)

//
// Construct a callgraph from SOAAP's vulnerability analysis.
//
func VulnGraph(results Results, progress func(string)) CallGraph {
	graph := NewCallGraph()

	for _, v := range results.Vulnerabilities {
		trace := results.Traces[v.Trace]
		top := true

		fn := func(cs CallSite) (string, GraphNode) {
			key := cs.String() + " " + v.Sandbox

			desc := cs.Function
			if v.Sandbox != "" {
				desc += "\\n<<" + v.Sandbox + ">>"
			}

			var node GraphNode
			node.Name = cs.String() + "_" + v.Sandbox
			node.Description = desc
			node.Sandbox = v.Sandbox

			if top {
				node.CVE = v.CVE
				top = false
			}

			return key, node
		}

		graph.Union(trace.graph(results.Traces, fn))
	}

	return graph
}

//
// Construct a callgraph of sandbox-private data accesses outside of sandboxes.
//
func PrivAccessGraph(results Results, progress func(string)) CallGraph {
	graph := NewCallGraph()
	accesses := results.PrivateAccess
	total := len(accesses)
	chunk := int(math.Ceil(math.Pow(10, math.Log10(float64(total)/500))))

	go progress(fmt.Sprintf("Processing %d private accesses", total))

	count := 0
	for _, a := range accesses {
		trace := results.Traces[a.Trace]

		fn := func(cs CallSite) (string, GraphNode) {
			sandboxes := strings.Join(a.Sandboxes, ",")
			key := cs.String() + " " + sandboxes

			desc := cs.Function
			if sandboxes != "" {
				desc += "\\n<<" + sandboxes + ">>"
			}

			var node GraphNode
			node.Name = cs.String() + "_" + sandboxes
			node.Description = desc
			node.Owners = a.Sandboxes

			return key, node
		}

		graph.Union(trace.graph(results.Traces, fn))

		count++
		if count%chunk == 0 {
			go progress(
				fmt.Sprintf("Processed %d/%d accesses",
					count, total))
		}
	}

	return graph
}

//
// Graph a single CallTrace, using a callSiteLabeler function to convert
// CallSite instances into graph nodes with identifiers, tags, etc.,
// appropriate to the analysis we're performing.
//
func (t CallTrace) graph(traces []CallTrace, nm callSiteLabeler) CallGraph {
	graph := NewCallGraph()
	var callee string

	t.Foreach(traces, func(cs CallSite) {
		identifier, node := nm(cs)
		graph.Nodes[identifier] = node

		caller := identifier

		if callee != "" {
			graph.AddCall(caller, callee)
		}

		callee = caller
	})

	return graph
}

//
// Format a map as a GraphViz attribute list.
//
func dotAttrs(attrs map[string]interface{}) string {
	fields := make([]string, len(attrs))

	i := 0
	for k, v := range attrs {
		switch v.(type) {
		case string:
			v = fmt.Sprintf("\"%s\"", v)
		}

		fields[i] = fmt.Sprintf("\"%s\" = %v", k, v)
		i++
	}

	return fmt.Sprintf("[ %s ]", strings.Join(fields, ", "))
}
<commit_msg>Style each GraphNode using CVE, Sandbox, etc.<commit_after>package soaap

import (
	"encoding/gob"
	"errors"
	"fmt"
	"math"
	"os"
	"strings"
)

type CallGraph struct {
	Nodes map[string]GraphNode
	Calls map[Call]int
}

//
// Create a new, empty CallGraph with enough capacity to hold some calls.
//
func NewCallGraph() CallGraph {
	return CallGraph{
		make(map[string]GraphNode),
		make(map[Call]int),
	}
}

//
// Load a CallGraph from a binary-encoded file.
//
func LoadGraph(f *os.File, report func(string)) (CallGraph, error) {
	var graph CallGraph
	err := gob.NewDecoder(f).Decode(&graph)

	return graph, err
}

func (cg *CallGraph) AddCall(caller string, callee string) {
	cg.Calls[Call{caller, callee}] += 1
}

//
// Save a CallGraph to an os.File using a binary encoding.
//
func (cg *CallGraph) Save(f *os.File) error {
	return gob.NewEncoder(f).Encode(cg)
}

//
// Simplify a CallGraph by collapsing call chains and dropping any
// unreferenced calls.
//
func (cg *CallGraph) Simplify() {
}

func (cg *CallGraph) Union(g CallGraph) error {
	for id, node := range g.Nodes {
		// If we already have a GraphNode with this identifier,
		// merge the two descriptions and tag sets.
		if n, have := cg.Nodes[id]; have {
			if n.Name != node.Name {
				return errors.New(fmt.Sprintf(
					"Nodes in CallGraph union have"+
						" same identifier ('%s') but"+
						" different names ('%s' vs '%s')",
					id, n.Name, node.Name))
			}

			if n.Description != node.Description {
				node.Description =
					n.Description + "\\n" + node.Description
			}

			for tag := range n.Tags {
				node.Tags[tag] = true
			}
		}

		cg.Nodes[id] = node
	}

	for call, count := range g.Calls {
		cg.Calls[call] += count
	}

	return nil
}

//
// A node in a call graph.
//
// This is derived from a call site or other program location, but can have
// an arbitrary name and description appropriate to a particular analysis.
//
type GraphNode struct {
	Name        string
	Description string

	// A vulnerability (current or previous) is known at this location.
	CVE []CVE

	// The name of this node's sandbox (or the empty string if unsandboxed).
	Sandbox string

	// The name of the sandbox(es) that own the data being accessed.
	Owners []string

	Tags map[string]bool
}

//
// Construct a GraphViz Dot description of a GraphNode.
//
// This applies SOAAP-specific styling depending on a node's tags.
//
func (n GraphNode) Dot() string {
	attrs := map[string]interface{}{
		"label": n.Description,
		"style": "filled",
	}

	switch true {
	case len(n.CVE) > 0 && n.Sandbox != "":
		// A vulnerability has been mitigated through sandboxing!
		attrs["fillcolor"] = "#ffff66cc"
		attrs["shape"] = "octagon"

	case len(n.CVE) > 0:
		// A vulnerability exists/existed outside a sandbox.
		attrs["fillcolor"] = "#ff9999cc"
		attrs["shape"] = "doubleoctagon"

	case len(n.Owners) > 0:
		// Sandbox-private data was accessed outside the sandbox.
		attrs["fillcolor"] = "#ff99cccc"
		attrs["shape"] = "invhouse"

	case n.Sandbox != "":
		attrs["fillcolor"] = "#99ff9999"
		attrs["style"] = "dashed,filled"

	default:
		attrs["fillcolor"] = "#cccccccc"
	}

	return fmt.Sprintf("\"%s\" %s;", n.Name, dotAttrs(attrs))
}

func (n GraphNode) HasTag(tag string) bool {
	_, present := n.Tags[tag]
	return present
}

type Call struct {
	// Identifier of the caller.
	Caller string

	// Identifier of the callee.
	Callee string
}

// Output GraphViz for a Call.
func (c Call) Dot(graph CallGraph, weight int) string {
	caller := graph.Nodes[c.Caller]
	callee := graph.Nodes[c.Callee]

	attrs := map[string]interface{}{
		"penwidth": weight,
		"weight":   weight,
	}

	return fmt.Sprintf("\"%s\" -> \"%s\" %s;\n",
		caller.Name, callee.Name, dotAttrs(attrs))
}

//
// A function that extracts a CallGraph from SOAAP Results.
//
type graphFn func(results Results, progress func(string)) CallGraph

var graphExtractors map[string]graphFn = map[string]graphFn{
	"privaccess": PrivAccessGraph,
	"vuln":       VulnGraph,
}

func GraphAnalyses() []string {
	keys := make([]string, len(graphExtractors))

	i := 0
	for k, _ := range graphExtractors {
		keys[i] = k
		i++
	}

	return keys
}

type callSiteLabeler func(CallSite) (string, GraphNode)

//
// Construct a callgraph from SOAAP's vulnerability analysis.
//
func VulnGraph(results Results, progress func(string)) CallGraph {
	graph := NewCallGraph()

	for _, v := range results.Vulnerabilities {
		trace := results.Traces[v.Trace]
		top := true

		fn := func(cs CallSite) (string, GraphNode) {
			key := cs.String() + " " + v.Sandbox

			desc := cs.Function
			if v.Sandbox != "" {
				desc += "\\n<<" + v.Sandbox + ">>"
			}

			var node GraphNode
			node.Name = cs.String() + "_" + v.Sandbox
			node.Description = desc
			node.Sandbox = v.Sandbox

			if top {
				node.CVE = v.CVE
				top = false
			}

			return key, node
		}

		graph.Union(trace.graph(results.Traces, fn))
	}

	return graph
}

//
// Construct a callgraph of sandbox-private data accesses outside of sandboxes.
//
func PrivAccessGraph(results Results, progress func(string)) CallGraph {
	graph := NewCallGraph()
	accesses := results.PrivateAccess
	total := len(accesses)
	chunk := int(math.Ceil(math.Pow(10, math.Log10(float64(total)/500))))

	go progress(fmt.Sprintf("Processing %d private accesses", total))

	count := 0
	for _, a := range accesses {
		trace := results.Traces[a.Trace]

		fn := func(cs CallSite) (string, GraphNode) {
			sandboxes := strings.Join(a.Sandboxes, ",")
			key := cs.String() + " " + sandboxes

			desc := cs.Function
			if sandboxes != "" {
				desc += "\\n<<" + sandboxes + ">>"
			}

			var node GraphNode
			node.Name = cs.String() + "_" + sandboxes
			node.Description = desc
			node.Owners = a.Sandboxes

			return key, node
		}

		graph.Union(trace.graph(results.Traces, fn))

		count++
		if count%chunk == 0 {
			go progress(
				fmt.Sprintf("Processed %d/%d accesses",
					count, total))
		}
	}

	return graph
}

//
// Graph a single CallTrace, using a callSiteLabeler function to convert
// CallSite instances into graph nodes with identifiers, tags, etc.,
// appropriate to the analysis we're performing.
//
func (t CallTrace) graph(traces []CallTrace, nm callSiteLabeler) CallGraph {
	graph := NewCallGraph()
	var callee string

	t.Foreach(traces, func(cs CallSite) {
		identifier, node := nm(cs)
		graph.Nodes[identifier] = node

		caller := identifier

		if callee != "" {
			graph.AddCall(caller, callee)
		}

		callee = caller
	})

	return graph
}

//
// Format a map as a GraphViz attribute list.
//
func dotAttrs(attrs map[string]interface{}) string {
	fields := make([]string, len(attrs))

	i := 0
	for k, v := range attrs {
		switch v.(type) {
		case string:
			v = fmt.Sprintf("\"%s\"", v)
		}

		fields[i] = fmt.Sprintf("\"%s\" = %v", k, v)
		i++
	}

	return fmt.Sprintf("[ %s ]", strings.Join(fields, ", "))
}
<|endoftext|>


<commit_before>package handler

import (
	"encoding/json"
	"html/template"
	"net/http"

	"github.com/graphql-go/graphql"
)

// page is the page data structure of the rendered GraphiQL page
type graphiqlPage struct {
	GraphiqlVersion string
	QueryString     string
	ResultString    string
	VariablesString string
	OperationName   string
}

// renderGraphiQL renders the GraphiQL GUI
func renderGraphiQL(w http.ResponseWriter, params graphql.Params) {
	t := template.New("GraphiQL")
	t, err := t.Parse(graphiqlTemplate)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Create variables string
	vars, err := json.MarshalIndent(params.VariableValues, "", "  ")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	varsString := string(vars)
	if varsString == "null" {
		varsString = ""
	}

	// Create result string
	var resString string
	if params.RequestString == "" {
		resString = ""
	} else {
		result, err := json.MarshalIndent(graphql.Do(params), "", "  ")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		resString = string(result)
	}

	p := graphiqlPage{
		GraphiqlVersion: graphiqlVersion,
		QueryString:     params.RequestString,
		ResultString:    resString,
		VariablesString: varsString,
		OperationName:   params.OperationName,
	}

	err = t.ExecuteTemplate(w, "index", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	return
}

// graphiqlVersion is the current version of GraphiQL
const graphiqlVersion = "0.11.10"

// tmpl is the page template to render GraphiQL
const graphiqlTemplate = `
{{ define "index" }}

<!DOCTYPE html>

  <meta charset="utf-8" />
  <title>GraphiQL</title>
  <meta name="robots" content="noindex" />

  <link href="//cdn.jsdelivr.net/npm/graphiql@{{ .GraphiqlVersion }}/graphiql.css" rel="stylesheet" />

{{ end }}
`
<commit_msg>Upgrade GraphiQL to 0.11.11<commit_after>package handler

import (
	"encoding/json"
	"html/template"
	"net/http"

	"github.com/graphql-go/graphql"
)

// graphiqlData is the page data structure of the rendered GraphiQL page
type graphiqlData struct {
	GraphiqlVersion string
	QueryString     string
	VariablesString string
	OperationName   string
	ResultString    string
}

// renderGraphiQL renders the GraphiQL GUI
func renderGraphiQL(w http.ResponseWriter, params graphql.Params) {
	t := template.New("GraphiQL")
	t, err := t.Parse(graphiqlTemplate)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Create variables string
	vars, err := json.MarshalIndent(params.VariableValues, "", "  ")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	varsString := string(vars)
	if varsString == "null" {
		varsString = ""
	}

	// Create result string
	var resString string
	if params.RequestString == "" {
		resString = ""
	} else {
		result, err := json.MarshalIndent(graphql.Do(params), "", "  ")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		resString = string(result)
	}

	d := graphiqlData{
		GraphiqlVersion: graphiqlVersion,
		QueryString:     params.RequestString,
		ResultString:    resString,
		VariablesString: varsString,
		OperationName:   params.OperationName,
	}
	err = t.ExecuteTemplate(w, "index", d)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	return
}

// graphiqlVersion is the current version of GraphiQL
const graphiqlVersion = "0.11.11"

// tmpl is the page template to render GraphiQL
const graphiqlTemplate = `
{{ define "index" }}

<!DOCTYPE html>

  <meta charset="utf-8" />
  <title>GraphiQL</title>
  <meta name="robots" content="noindex" />
  <meta name="referrer" content="origin">

  <link href="//cdn.jsdelivr.net/npm/graphiql@{{ .GraphiqlVersion }}/graphiql.css" rel="stylesheet" />

Loading...

{{ end }}
`
<|endoftext|>


<commit_before>package neurgo

import (
	"github.com/couchbaselabs/go.assert"
	"github.com/couchbaselabs/logg"
	"math"
	"testing"
)

func TestSigmoid(t *testing.T) {
	assert.Equals(t, Sigmoid(0), 0.5)
	assert.True(t, Sigmoid(10) > 0.9)
	assert.True(t, Sigmoid(-10) < 0.1)
}

func TestEqualsWithMaxDelta(t *testing.T) {
	assert.True(t, EqualsWithMaxDelta(0.99999, 1.00000, .01))
	assert.False(t, EqualsWithMaxDelta(0.95, 1.00000, .01))
}

func TestVectorEqualsWithMaxDelta(t *testing.T) {

	xValues := []float64{0.99999, 0.00000}
	yValues := []float64{1.00000, 0.00001}

	assert.True(t, vectorEqualsWithMaxDelta(xValues, yValues, .01))

	xValues = []float64{0.95, 0.00000}
	yValues = []float64{1.00000, 1.00000}

	assert.False(t, vectorEqualsWithMaxDelta(xValues, yValues, .01))
}

func TestSumOfSquaresError(t *testing.T) {
	expected := []float64{.5}
	actual := []float64{1}
	error := SumOfSquaresError(expected, actual)
	nearlyEqualsPoint25 := EqualsWithMaxDelta(error, 0.25, .01)
	assert.True(t, nearlyEqualsPoint25)
}

func TestSafeScalarInverse(t *testing.T) {
	value := SafeScalarInverse(0)
	assert.True(t, value > 1000000)
	assert.True(t, EqualsWithMaxDelta(SafeScalarInverse(1), 1.0, .0001))
}

func TestRandomInRange(t *testing.T) {
	assert.True(t, RandomInRange(-1*math.Pi, math.Pi) <= math.Pi)
	assert.True(t, RandomInRange(-1*math.Pi, math.Pi) >= -1*math.Pi)
}

func TestRandomIntInRange(t *testing.T) {
	SeedRandom()
	result := RandomIntInRange(1, 4)
	assert.True(t, result >= 1)
	assert.True(t, result <= 4)

	found0 := false
	found1 := false
	found2 := false
	for i := 0; i < 1000; i++ {
		randInt := RandomIntInRange(0, 2)
		if randInt == 0 {
			found0 = true
		}
		if randInt == 1 {
			found1 = true
		}
		if randInt == 2 {
			found2 = true
		}

	}
	assert.True(t, found0)
	assert.True(t, found1)
	assert.False(t, found2)

}

func TestIntModuleProper(t *testing.T) {
	assert.False(t, IntModuloProper(0, 100))
	assert.True(t, IntModuloProper(500, 100))
}

func TestNormalizeInRange(t *testing.T) {

	logg.LogKeys["TEST"] = true
	params := NormalizeParams{
		SourceRangeStart: 0.0,
		SourceRangeEnd:   31.0,
		TargetRangeStart: -1.0,
		TargetRangeEnd:   1.0,
	}

	testPairs := [][]float64{[]float64{0.0, -1.0}, []float64{31.0, 1.0}}

	for _, testPair := range testPairs {
		origValue := testPair[0]
		expectedValue := testPair[1]
		actualValue := NormalizeInRange(params, origValue)
		delta := 0.01
		logg.LogTo("TEST", "actual: %v, expected: %v", actualValue, expectedValue)
		assert.True(t, EqualsWithMaxDelta(actualValue, expectedValue, delta))
	}

}
<commit_msg>add another test data point<commit_after>package neurgo

import (
	"github.com/couchbaselabs/go.assert"
	"github.com/couchbaselabs/logg"
	"math"
	"testing"
)

func TestSigmoid(t *testing.T) {
	assert.Equals(t, Sigmoid(0), 0.5)
	assert.True(t, Sigmoid(10) > 0.9)
	assert.True(t, Sigmoid(-10) < 0.1)
}

func TestEqualsWithMaxDelta(t *testing.T) {
	assert.True(t, EqualsWithMaxDelta(0.99999, 1.00000, .01))
	assert.False(t, EqualsWithMaxDelta(0.95, 1.00000, .01))
}

func TestVectorEqualsWithMaxDelta(t *testing.T) {

	xValues := []float64{0.99999, 0.00000}
	yValues := []float64{1.00000, 0.00001}

	assert.True(t, vectorEqualsWithMaxDelta(xValues, yValues, .01))

	xValues = []float64{0.95, 0.00000}
	yValues = []float64{1.00000, 1.00000}

	assert.False(t, vectorEqualsWithMaxDelta(xValues, yValues, .01))
}

func TestSumOfSquaresError(t *testing.T) {
	expected := []float64{.5}
	actual := []float64{1}
	error := SumOfSquaresError(expected, actual)
	nearlyEqualsPoint25 := EqualsWithMaxDelta(error, 0.25, .01)
	assert.True(t, nearlyEqualsPoint25)
}

func TestSafeScalarInverse(t *testing.T) {
	value := SafeScalarInverse(0)
	assert.True(t, value > 1000000)
	assert.True(t, EqualsWithMaxDelta(SafeScalarInverse(1), 1.0, .0001))
}

func TestRandomInRange(t *testing.T) {
	assert.True(t, RandomInRange(-1*math.Pi, math.Pi) <= math.Pi)
	assert.True(t, RandomInRange(-1*math.Pi, math.Pi) >= -1*math.Pi)
}

func TestRandomIntInRange(t *testing.T) {
	SeedRandom()
	result := RandomIntInRange(1, 4)
	assert.True(t, result >= 1)
	assert.True(t, result <= 4)

	found0 := false
	found1 := false
	found2 := false
	for i := 0; i < 1000; i++ {
		randInt := RandomIntInRange(0, 2)
		if randInt == 0 {
			found0 = true
		}
		if randInt == 1 {
			found1 = true
		}
		if randInt == 2 {
			found2 = true
		}

	}
	assert.True(t, found0)
	assert.True(t, found1)
	assert.False(t, found2)

}

func TestIntModuleProper(t *testing.T) {
	assert.False(t, IntModuloProper(0, 100))
	assert.True(t, IntModuloProper(500, 100))
}

func TestNormalizeInRange(t *testing.T) {

	logg.LogKeys["TEST"] = true
	params := NormalizeParams{
		SourceRangeStart: 0.0,
		SourceRangeEnd:   31.0,
		TargetRangeStart: -1.0,
		TargetRangeEnd:   1.0,
	}

	testPairs := [][]float64{
		[]float64{0.0, -1.0},
		[]float64{31.0, 1.0},
		[]float64{15.5, 0.0},
	}

	for _, testPair := range testPairs {
		origValue := testPair[0]
		expectedValue := testPair[1]
		actualValue := NormalizeInRange(params, origValue)
		delta := 0.01
		logg.LogTo("TEST", "actual: %v, expected: %v", actualValue, expectedValue)
		assert.True(t, EqualsWithMaxDelta(actualValue, expectedValue, delta))
	}

}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

// Package coredns is the implementation of pkg/dnsprovider interface for CoreDNS
package coredns

import (
	"fmt"
	etcdc "github.com/coreos/etcd/client"
	"github.com/golang/glog"
	"gopkg.in/gcfg.v1"
	"io"
	"k8s.io/kubernetes/federation/pkg/dnsprovider"
	"strconv"
	"strings"
)

// "coredns" should be used to use this DNS provider
const (
	ProviderName = "coredns"
)

// Config to override defaults
type Config struct {
	Global struct {
		EtcdEndpoints string `gcfg:"etcd-endpoints"`
		DNSZones      string `gcfg:"zones"`
	}
}

func init() {
	dnsprovider.RegisterDnsProvider(ProviderName, func(config io.Reader) (dnsprovider.Interface, error) {
		return newCoreDNSProviderInterface(config)
	})
}

// newCoreDnsProviderInterface creates a new instance of an CoreDNS DNS Interface.
func newCoreDNSProviderInterface(config io.Reader) (*Interface, error) {
	etcdEndpoints := "http://federation-dns-server-etcd:2379"
	etcdPathPrefix := "skydns"
	dnsZones := ""

	// Possibly override defaults with config below
	if config != nil {
		var cfg Config
		if err := gcfg.ReadInto(&cfg, config); err != nil {
			glog.Errorf("Couldn't read config: %v", err)
			return nil, err
		}
		etcdEndpoints = cfg.Global.EtcdEndpoints
		dnsZones = cfg.Global.DNSZones
	}
	glog.Infof("Using CoreDNS DNS provider")

	if dnsZones == "" {
		return nil, fmt.Errorf("Need to provide at least one DNS Zone")
	}

	etcdCfg := etcdc.Config{
		Endpoints: strings.Split(etcdEndpoints, ","),
		Transport: etcdc.DefaultTransport,
	}

	c, err := etcdc.New(etcdCfg)
	if err != nil {
		return nil, fmt.Errorf("Create etcd client from the config failed")
	}
	etcdKeysAPI := etcdc.NewKeysAPI(c)

	intf := newInterfaceWithStub(etcdKeysAPI)
	intf.etcdPathPrefix = etcdPathPrefix
	zoneList := strings.Split(dnsZones, ",")

	intf.zones = Zones{intf: intf}
	for index, zoneName := range zoneList {
		zone := Zone{domain: zoneName, id: strconv.Itoa(index), zones: &intf.zones}
		intf.zones.zoneList = append(intf.zones.zoneList, zone)
	}

	return intf, nil
}
<commit_msg>Add coredns-endpoints to CoreDNS provider config<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

// Package coredns is the implementation of pkg/dnsprovider interface for CoreDNS
package coredns

import (
	"fmt"
	etcdc "github.com/coreos/etcd/client"
	"github.com/golang/glog"
	"gopkg.in/gcfg.v1"
	"io"
	"k8s.io/kubernetes/federation/pkg/dnsprovider"
	"strconv"
	"strings"
)

// "coredns" should be used to use this DNS provider
const (
	ProviderName = "coredns"
)

// Config to override defaults
type Config struct {
	Global struct {
		EtcdEndpoints    string `gcfg:"etcd-endpoints"`
		DNSZones         string `gcfg:"zones"`
		CoreDNSEndpoints string `gcfg:"coredns-endpoints"`
	}
}

func init() {
	dnsprovider.RegisterDnsProvider(ProviderName, func(config io.Reader) (dnsprovider.Interface, error) {
		return newCoreDNSProviderInterface(config)
	})
}

// newCoreDnsProviderInterface creates a new instance of an CoreDNS DNS Interface.
func newCoreDNSProviderInterface(config io.Reader) (*Interface, error) {
	etcdEndpoints := "http://federation-dns-server-etcd:2379"
	etcdPathPrefix := "skydns"
	dnsZones := ""

	// Possibly override defaults with config below
	if config != nil {
		var cfg Config
		if err := gcfg.ReadInto(&cfg, config); err != nil {
			glog.Errorf("Couldn't read config: %v", err)
			return nil, err
		}
		etcdEndpoints = cfg.Global.EtcdEndpoints
		dnsZones = cfg.Global.DNSZones
	}
	glog.Infof("Using CoreDNS DNS provider")

	if dnsZones == "" {
		return nil, fmt.Errorf("Need to provide at least one DNS Zone")
	}

	etcdCfg := etcdc.Config{
		Endpoints: strings.Split(etcdEndpoints, ","),
		Transport: etcdc.DefaultTransport,
	}

	c, err := etcdc.New(etcdCfg)
	if err != nil {
		return nil, fmt.Errorf("Create etcd client from the config failed")
	}
	etcdKeysAPI := etcdc.NewKeysAPI(c)

	intf := newInterfaceWithStub(etcdKeysAPI)
	intf.etcdPathPrefix = etcdPathPrefix
	zoneList := strings.Split(dnsZones, ",")

	intf.zones = Zones{intf: intf}
	for index, zoneName := range zoneList {
		zone := Zone{domain: zoneName, id: strconv.Itoa(index), zones: &intf.zones}
		intf.zones.zoneList = append(intf.zones.zoneList, zone)
	}

	return intf, nil
}
<|endoftext|>


<commit_before>//go:build linux
// +build linux

/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package pidlimit

import (
	"io/ioutil"
	"strconv"
	"syscall"
	"time"

	"k8s.io/apimachinery/pkg/apis/meta/v1"
	statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
)

// Stats provides basic information about max and current process count
func Stats() (*statsapi.RlimitStats, error) {
	rlimit := &statsapi.RlimitStats{}

	if content, err := ioutil.ReadFile("/proc/sys/kernel/pid_max"); err == nil {
		if maxPid, err := strconv.ParseInt(string(content[:len(content)-1]), 10, 64); err == nil {
			rlimit.MaxPID = &maxPid
		}
	}

	var info syscall.Sysinfo_t
	syscall.Sysinfo(&info)
	procs := int64(info.Procs)
	rlimit.NumOfRunningProcesses = &procs

	rlimit.Time = v1.NewTime(time.Now())

	return rlimit, nil
}
<commit_msg>Read number of running processes from /proc/loadavg.<commit_after>//go:build linux
// +build linux

/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package pidlimit

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

	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
)

// Stats provides basic information about max and current process count
func Stats() (*statsapi.RlimitStats, error) {
	rlimit := &statsapi.RlimitStats{}

	if content, err := ioutil.ReadFile("/proc/sys/kernel/pid_max"); err == nil {
		if maxPid, err := strconv.ParseInt(string(content[:len(content)-1]), 10, 64); err == nil {
			rlimit.MaxPID = &maxPid
		}
	}

	// Prefer to read "/proc/loadavg" when possible because sysinfo(2)
	// returns truncated number when greater than 65538. See
	// https://github.com/kubernetes/kubernetes/issues/107107
	if procs, err := runningTaskCount(); err == nil {
		rlimit.NumOfRunningProcesses = &procs
	} else {
		var info syscall.Sysinfo_t
		syscall.Sysinfo(&info)
		procs := int64(info.Procs)
		rlimit.NumOfRunningProcesses = &procs
	}

	rlimit.Time = v1.NewTime(time.Now())

	return rlimit, nil
}

func runningTaskCount() (int64, error) {
	// Example: 1.36 3.49 4.53 2/3518 3715089
	bytes, err := ioutil.ReadFile("/proc/loadavg")
	if err != nil {
		return 0, err
	}
	fields := strings.Fields(string(bytes))
	if len(fields) < 5 {
		return 0, fmt.Errorf("not enough fields in /proc/loadavg")
	}
	subfields := strings.Split(fields[3], "/")
	if len(subfields) != 2 {
		return 0, fmt.Errorf("error parsing fourth field of /proc/loadavg")
	}
	return strconv.ParseInt(subfields[1], 10, 64)
}
<|endoftext|>


<commit_before>package notification_test

import (
	"encoding/json"
	"testing"

	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/notification"
	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/order"
	"github.com/stretchr/testify/assert"
)

func TestNotificationMapping(t *testing.T) {
	cases := map[string]struct {
		pld      []byte
		expected interface{}
		err      func(*testing.T, error)
	}{
		"on-req": {
			pld: []byte(`[
				0,
				"n",
				[
					1611922089,"on-req",null,null,
					[
						1201469553,0,788,"tBTCUSD",1611922089073,1611922089073,0.001,0.001,"EXCHANGE LIMIT",
						null,null,null,0,"ACTIVE",null,null,33,0,0,0,null,null,null,0,0,null,null,null,
						"API>BFX",null,null,null
					],
					null,"SUCCESS","Submitting exchange limit buy order for 0.001 BTC."
				]
			]`),
			expected: &notification.Notification{
				MTS:       1611922089,
				Type:      "on-req",
				MessageID: 0,
				NotifyInfo: order.New{
					ID:            1201469553,
					GID:           0,
					CID:           788,
					Symbol:        "tBTCUSD",
					MTSCreated:    1611922089073,
					MTSUpdated:    1611922089073,
					Amount:        0.001,
					AmountOrig:    0.001,
					Type:          "EXCHANGE LIMIT",
					TypePrev:      "",
					MTSTif:        0,
					Flags:         0,
					Status:        "ACTIVE",
					Price:         33,
					PriceAvg:      0,
					PriceTrailing: 0,
					PriceAuxLimit: 0,
					Notify:        false,
					Hidden:        false,
					PlacedID:      0,
					Routing:       "API>BFX",
					Meta:          nil,
				},
				Code:   0,
				Status: "SUCCESS",
				Text:   "Submitting exchange limit buy order for 0.001 BTC.",
			},
			err: func(t *testing.T, err error) {
				assert.NoError(t, err)
			},
		},
		"on-req snapshot": {
			pld: []byte(`[
				0,
				"n",
				[
					1611922089,"on-req",null,null,
					[[
						1201469553,0,788,"tBTCUSD",1611922089073,1611922089073,0.001,0.001,"EXCHANGE LIMIT",
						null,null,null,0,"ACTIVE",null,null,33,0,0,0,null,null,null,0,0,null,null,null,
						"API>BFX",null,null,null
					]],
					null,"SUCCESS","Submitting exchange limit buy order for 0.001 BTC."
				]
			]`),
			expected: &notification.Notification{
				MTS:       1611922089,
				Type:      "on-req",
				MessageID: 0,
				NotifyInfo: &order.Snapshot{
					Snapshot: []*order.Order{
						{
							ID:            1201469553,
							GID:           0,
							CID:           788,
							Symbol:        "tBTCUSD",
							MTSCreated:    1611922089073,
							MTSUpdated:    1611922089073,
							Amount:        0.001,
							AmountOrig:    0.001,
							Type:          "EXCHANGE LIMIT",
							TypePrev:      "",
							MTSTif:        0,
							Flags:         0,
							Status:        "ACTIVE",
							Price:         33,
							PriceAvg:      0,
							PriceTrailing: 0,
							PriceAuxLimit: 0,
							Notify:        false,
							Hidden:        false,
							PlacedID:      0,
							Routing:       "API>BFX",
							Meta:          nil,
						},
					},
				},
				Code:   0,
				Status: "SUCCESS",
				Text:   "Submitting exchange limit buy order for 0.001 BTC.",
			},
			err: func(t *testing.T, err error) {
				assert.NoError(t, err)
			},
		},
	}

	for k, v := range cases {
		t.Run(k, func(t *testing.T) {
			var raw []interface{}
			json.Unmarshal(v.pld, &raw)
			pldRaw := raw[len(raw)-1]
			pld := pldRaw.([]interface{})

			got, err := notification.FromRaw(pld)
			v.err(t, err)
			assert.Equal(t, v.expected, got)
		})
	}
}
<commit_msg>ou-req notification raw data mapping to data structure<commit_after>package notification_test

import (
	"encoding/json"
	"testing"

	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/notification"
	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/order"
	"github.com/stretchr/testify/assert"
)

func TestNotificationMapping(t *testing.T) {
	cases := map[string]struct {
		pld      []byte
		expected interface{}
		err      func(*testing.T, error)
	}{
		"on-req": {
			pld: []byte(`[
				0,
				"n",
				[
					1611922089,"on-req",null,null,
					[
						1201469553,0,788,"tBTCUSD",1611922089073,1611922089073,0.001,0.001,"EXCHANGE LIMIT",
						null,null,null,0,"ACTIVE",null,null,33,0,0,0,null,null,null,0,0,null,null,null,
						"API>BFX",null,null,null
					],
					null,"SUCCESS","Submitting exchange limit buy order for 0.001 BTC."
				]
			]`),
			expected: &notification.Notification{
				MTS:       1611922089,
				Type:      "on-req",
				MessageID: 0,
				NotifyInfo: order.New{
					ID:            1201469553,
					GID:           0,
					CID:           788,
					Symbol:        "tBTCUSD",
					MTSCreated:    1611922089073,
					MTSUpdated:    1611922089073,
					Amount:        0.001,
					AmountOrig:    0.001,
					Type:          "EXCHANGE LIMIT",
					TypePrev:      "",
					MTSTif:        0,
					Flags:         0,
					Status:        "ACTIVE",
					Price:         33,
					PriceAvg:      0,
					PriceTrailing: 0,
					PriceAuxLimit: 0,
					Notify:        false,
					Hidden:        false,
					PlacedID:      0,
					Routing:       "API>BFX",
					Meta:          nil,
				},
				Code:   0,
				Status: "SUCCESS",
				Text:   "Submitting exchange limit buy order for 0.001 BTC.",
			},
			err: func(t *testing.T, err error) {
				assert.NoError(t, err)
			},
		},
		"on-req snapshot": {
			pld: []byte(`[
				0,
				"n",
				[
					1611922089,"on-req",null,null,
					[[
						1201469553,0,788,"tBTCUSD",1611922089073,1611922089073,0.001,0.001,"EXCHANGE LIMIT",
						null,null,null,0,"ACTIVE",null,null,33,0,0,0,null,null,null,0,0,null,null,null,
						"API>BFX",null,null,null
					]],
					null,"SUCCESS","Submitting exchange limit buy order for 0.001 BTC."
				]
			]`),
			expected: &notification.Notification{
				MTS:       1611922089,
				Type:      "on-req",
				MessageID: 0,
				NotifyInfo: &order.Snapshot{
					Snapshot: []*order.Order{
						{
							ID:            1201469553,
							GID:           0,
							CID:           788,
							Symbol:        "tBTCUSD",
							MTSCreated:    1611922089073,
							MTSUpdated:    1611922089073,
							Amount:        0.001,
							AmountOrig:    0.001,
							Type:          "EXCHANGE LIMIT",
							TypePrev:      "",
							MTSTif:        0,
							Flags:         0,
							Status:        "ACTIVE",
							Price:         33,
							PriceAvg:      0,
							PriceTrailing: 0,
							PriceAuxLimit: 0,
							Notify:        false,
							Hidden:        false,
							PlacedID:      0,
							Routing:       "API>BFX",
							Meta:          nil,
						},
					},
				},
				Code:   0,
				Status: "SUCCESS",
				Text:   "Submitting exchange limit buy order for 0.001 BTC.",
			},
			err: func(t *testing.T, err error) {
				assert.NoError(t, err)
			},
		},
		"ou-req": {
			pld: []byte(`[
				0,
				"n",
				[
					1575289447641,"ou-req",null,null,
					[
						1185815100,null,1575289350475,"tETHUSD",1575289351944,1575289351948,-3,
						-3,"LIMIT",null,null,null,0,"ACTIVE",null,null,240,0,0,0,null,null,null,
						0,0,null,null,null,"API>BFX",null,null,null
					],
					null,"SUCCESS","Submitting update to limit sell order for 3 ETH."
				]
			]`),
			expected: &notification.Notification{
				MTS:       1575289447641,
				Type:      "ou-req",
				MessageID: 0,
				NotifyInfo: order.Update{
					ID:            1185815100,
					GID:           0,
					CID:           1575289350475,
					Symbol:        "tETHUSD",
					MTSCreated:    1575289351944,
					MTSUpdated:    1575289351948,
					Amount:        -3,
					AmountOrig:    -3,
					Type:          "LIMIT",
					TypePrev:      "",
					MTSTif:        0,
					Flags:         0,
					Status:        "ACTIVE",
					Price:         240,
					PriceAvg:      0,
					PriceTrailing: 0,
					PriceAuxLimit: 0,
					Notify:        false,
					Hidden:        false,
					PlacedID:      0,
					Routing:       "API>BFX",
					Meta:          nil,
				},
				Code:   0,
				Status: "SUCCESS",
				Text:   "Submitting update to limit sell order for 3 ETH.",
			},
			err: func(t *testing.T, err error) {
				assert.NoError(t, err)
			},
		},
	}

	for k, v := range cases {
		t.Run(k, func(t *testing.T) {
			var raw []interface{}
			json.Unmarshal(v.pld, &raw)
			pldRaw := raw[len(raw)-1]
			pld := pldRaw.([]interface{})

			got, err := notification.FromRaw(pld)
			v.err(t, err)
			assert.Equal(t, v.expected, got)
		})
	}
}
<|endoftext|>