<commit_before>// Copyright 2019 Istio 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 istioctl

import (
	"testing"

	"istio.io/istio/pkg/test/framework"
	"istio.io/istio/pkg/test/framework/components/environment"
	"istio.io/istio/pkg/test/framework/label"
)

func TestMain(m *testing.M) {
	framework.
		NewSuite("nop-test", m).
		Label(label.CustomSetup).
		Run()
}

// Legacy CI targets try to call this folder and fail if there are no tests. Until that is cleaned up,
// Have a nop test.
func TestNothing(t *testing.T) {
	// You can specify additional constraints using the more verbose form
	framework.NewTest(t).
		Label(label.Postsubmit).
		RequiresEnvironment(environment.Native).
		Run(func(ctx framework.TestContext) {})
}
<commit_msg>Clean up istioctl test directory (#19667)<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016, Alan Chen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package web3

import (
	"bytes"
	"encoding/json"
	"fmt"
	"math"
	"math/big"
	"regexp"
	"strconv"
	"strings"

	"github.com/tonnerre/golang-go.crypto/sha3"
)

var (
	big0    = big.NewInt(0)
	rat0    = big.NewRat(0, 1)
	unitMap = map[string]string{
		"noether":    "0",
		"wei":        "1",
		"kwei":       "1000",
		"Kwei":       "1000",
		"babbage":    "1000",
		"femtoether": "1000",
		"mwei":       "1000000",
		"Mwei":       "1000000",
		"lovelace":   "1000000",
		"picoether":  "1000000",
		"gwei":       "1000000000",
		"Gwei":       "1000000000",
		"shannon":    "1000000000",
		"nanoether":  "1000000000",
		"nano":       "1000000000",
		"szabo":      "1000000000000",
		"microether": "1000000000000",
		"micro":      "1000000000000",
		"finney":     "1000000000000000",
		"milliether": "1000000000000000",
		"milli":      "1000000000000000",
		"ether":      "1000000000000000000",
		"kether":     "1000000000000000000000",
		"grand":      "1000000000000000000000",
		"mether":     "1000000000000000000000000",
		"gether":     "1000000000000000000000000000",
		"tether":     "1000000000000000000000000000000",
	}
)

// Web3 Standard interface
// See https://github.com/ethereum/wiki/wiki/JavaScript-API#web3js-api-reference
type Web3 struct {
	provider       Provider
	requestManager *RequestManager
}

// NewWeb3 creates a new web3 object.
func NewWeb3(provider Provider) *Web3 {
	return &Web3{provider: provider, requestManager: newRequestManager(provider)}
}

// IsConnected checks if a connection to a node exists.
func (web3 *Web3) IsConnected() bool {
	return true
}

// SetProvider sets provider.
func (web3 *Web3) SetProvider(provider Provider) {
	web3.provider = provider
}

// CurrentProvider returns the current provider.
func (web3 *Web3) CurrentProvider() Provider {
	return web3.provider
}

// Reset state of web3. Resets everything except manager. Uninstalls all
// filters. Stops polling. If keepSyncing is true, it will uninstall all
// filters, but will keep the web3.eth.IsSyncing() polls.
func (web3 *Web3) Reset(keepSyncing bool) {

}

// Sha3 returns Keccak-256 (not the standardized SHA3-256) of the given data.
func (web3 *Web3) Sha3(data string, options interface{}) string {
	opt := struct {
		Encoding string `json:"encoding"`
	}{
		"default",
	}

checkEncoding:
	switch options.(type) {
	case string:
		if err := json.Unmarshal([]byte(options.(string)), &opt); err != nil {
			return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
		}
		break checkEncoding
	default:
		var err error
		var optBytes []byte
		if optBytes, err = json.Marshal(options); err != nil {
			return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
		}

		if err = json.Unmarshal(optBytes, &opt); err != nil {
			return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
		}
		break checkEncoding
	}

	if opt.Encoding == "hex" {
		d := data
		if strings.Index(data, "0x") == 0 {
			d = strings.Replace(data, "0x", "", -1)
		}
		return "0x" + web3.bytesToHex(web3.sha3Hash(web3.hexToBytes(d)))
	}
	return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
}

// ToHex converts any value into HEX.
func (web3 *Web3) ToHex(value interface{}) string {
	switch value.(type) {
	case bool:
		v := value.(bool)
		if v {
			return "0x1"
		}
		return "0x0"
	case string:
		jsonBytes, err := json.Marshal(value)
		if err != nil {
			return web3.FromDecimal(value)
		}
		unquoted, err := strconv.Unquote(string(jsonBytes))
		if err != nil {
			return "0x" + web3.bytesToHex(jsonBytes)
		}
		return "0x" + web3.bytesToHex([]byte(unquoted))
	case *big.Int:
		return web3.FromDecimal(value)
	default:
		jsonBytes, err := json.Marshal(value)
		if err != nil {
			return web3.FromDecimal(value)
		}
		return "0x" + web3.bytesToHex(jsonBytes)
	}
}

// ToASCII converts a HEX string into a ASCII string.
func (web3 *Web3) ToASCII(hexString string) string {
	return string(bytes.Trim(web3.hexToBytes(hexString), "\x00"))
}

// FromASCII converts any ASCII string to a HEX string.
func (web3 *Web3) FromASCII(textString string, padding int) string {
	hex := ""
	for _, runeValue := range textString {
		hex += fmt.Sprintf("%x", runeValue)
	}

	l := len(hex)
	for i := 0; i < padding*2-l; i++ {
		hex += "0"
	}
	return "0x" + hex
}

// ToDecimal converts value to it"s decimal representation in string.
func (web3 *Web3) ToDecimal(value interface{}) string {
	n := web3.ToBigNumber(value)
	if n.IsInt() {
		return n.Num().String()
	}
	return n.String()
}

// FromDecimal converts value to it"s hex representation.
func (web3 *Web3) FromDecimal(value interface{}) string {
	number := web3.ToBigNumber(value)
	if number.IsInt() {
		result := number.Num().Text(16)

		if number.Cmp(rat0) < 0 {
			return "-0x" + result[1:]
		}
		return "0x" + result
	}

	v, _ := number.Float64()
	return fmt.Sprintf("%x", math.Float64bits(v))
}

// FromWei takes a number of wei and converts it to any other ether unit.
//
// Possible units are:
//   SI Short   SI Full        Effigy       Other
// - kwei       femtoether     babbage
// - mwei       picoether      lovelace
// - gwei       nanoether      shannon      nano
// - --         microether     szabo        micro
// - --         microether     szabo        micro
// - --         milliether     finney       milli
// - ether      --             --
// - kether                    --           grand
// - mether
// - gether
// - tether
func (web3 *Web3) FromWei(number string, unit string) string {
	num := web3.ToBigNumber(number)
	returnValue := num.Quo(num, web3.getValueOfUnit(unit))
	return returnValue.Num().String()
}

// ToWei takes a number of a unit and converts it to wei.
//
// Possible units are:
//   SI Short   SI Full        Effigy       Other
// - kwei       femtoether     babbage
// - mwei       picoether      lovelace
// - gwei       nanoether      shannon      nano
// - --         microether     szabo        micro
// - --         microether     szabo        micro
// - --         milliether     finney       milli
// - ether      --             --
// - kether                    --           grand
// - mether
// - gether
// - tether
func (web3 *Web3) ToWei(number interface{}, unit string) string {
	num := web3.ToBigNumber(number)
	returnValue := num.Mul(num, web3.getValueOfUnit(unit))
	return returnValue.Num().String()
}

// ToBigNumber takes an input and transforms it into an *big.Rat.
func (web3 *Web3) ToBigNumber(value interface{}) (result *big.Rat) {
	switch value.(type) {
	case *big.Rat:
		v := value.(*big.Rat)
		return v
	case *big.Int:
		v := value.(*big.Int)
		result = new(big.Rat)
		result.SetInt(v)
		return result
	case string:
		v := value.(string)
		i := new(big.Int)
		result = new(big.Rat)

		if strings.Index(v, "0x") == 0 || strings.Index(v, "-0x") == 0 {
			i.SetString(strings.Replace(v, "0x", "", -1), 16)
		} else {
			i.SetString(v, 10)
		}
		result.SetInt(i)
		return result
	}
	return result
}

// IsAddress checks if the given string is an address.
func (web3 *Web3) IsAddress(address string) bool {
	// basicMatcher := regexp.MustCompile("^(0x)?[0-9a-f]{40}$")
	// basicmatched := basicMatcher.MatchString(address)
	// if !basicmatched {
	// 	return false
	// }

	smallCapsMatcher := regexp.MustCompile("^(0x)?[0-9a-f]{40}$")
	smallCapsMatched := smallCapsMatcher.MatchString(address)
	allCapsMatcher := regexp.MustCompile("^(0x)?[0-9A-F]{40}$")
	allCapsMatched := allCapsMatcher.MatchString(address)
	if smallCapsMatched || allCapsMatched {
		return true
	}
	return web3.isChecksumAddress(address)
}

func (web3 *Web3) isChecksumAddress(address string) bool {
	addr := strings.Replace(address, "0x", "", -1)
	addressHash := web3.Sha3(strings.ToLower(addr), "")

	for i := 0; i < 40; i++ {
		d, err := strconv.ParseInt(string(addressHash[i]), 16, 32)
		if err != nil {
			return false
		}

		if d > 7 && strings.ToUpper(string(address[i])) == string(address[i]) ||
			d <= 7 && strings.ToLower(string(address[i])) == string(address[i]) {
			return false
		}
	}
	return true
}

func (web3 *Web3) bytesToHex(data []byte) string {
	buffer := new(bytes.Buffer)
	for _, b := range data {
		s := strconv.FormatInt(int64(b&0xFF), 16)
		if len(s) == 1 {
			buffer.WriteString("0")
		}
		buffer.WriteString(s)
	}
	return buffer.String()
}

func (web3 *Web3) hexToBytes(hex string) []byte {
	length := len(hex) / 2
	slice := make([]byte, length)
	rs := []rune(hex)

	for i := 0; i < length; i++ {
		s := string(rs[i*2 : i*2+2])
		value, _ := strconv.ParseInt(s, 16, 10)
		slice[i] = byte(value & 0xFF)
	}
	return slice
}

func (web3 *Web3) sha3Hash(data ...[]byte) []byte {
	d := sha3.NewKeccak256()
	for _, b := range data {
		d.Write(b)
	}
	return d.Sum(nil)
}

func (web3 *Web3) getValueOfUnit(unit string) *big.Rat {
	u := ""
	if strings.TrimSpace(unit) != "" {
		u = strings.ToLower(unit)
	} else {
		u = "ether"
	}

	if unitValue, ok := unitMap[u]; ok {
		value := new(big.Int)
		value.SetString(unitValue, 10)
		returnValue := new(big.Rat)
		returnValue.SetInt(value)
		return returnValue
	}

	keys := make([]string, 0, len(unitMap))
	for k := range unitMap {
		keys = append(keys, k)
	}
	panic(fmt.Sprintf("This unit doesn\"t exists, please use the one of the following units, %v", keys))
}
<commit_msg>Deal with spaces in unit string<commit_after>// Copyright (c) 2016, Alan Chen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package web3

import (
	"bytes"
	"encoding/json"
	"fmt"
	"math"
	"math/big"
	"regexp"
	"strconv"
	"strings"

	"github.com/tonnerre/golang-go.crypto/sha3"
)

var (
	big0    = big.NewInt(0)
	rat0    = big.NewRat(0, 1)
	unitMap = map[string]string{
		"noether":    "0",
		"wei":        "1",
		"kwei":       "1000",
		"Kwei":       "1000",
		"babbage":    "1000",
		"femtoether": "1000",
		"mwei":       "1000000",
		"Mwei":       "1000000",
		"lovelace":   "1000000",
		"picoether":  "1000000",
		"gwei":       "1000000000",
		"Gwei":       "1000000000",
		"shannon":    "1000000000",
		"nanoether":  "1000000000",
		"nano":       "1000000000",
		"szabo":      "1000000000000",
		"microether": "1000000000000",
		"micro":      "1000000000000",
		"finney":     "1000000000000000",
		"milliether": "1000000000000000",
		"milli":      "1000000000000000",
		"ether":      "1000000000000000000",
		"kether":     "1000000000000000000000",
		"grand":      "1000000000000000000000",
		"mether":     "1000000000000000000000000",
		"gether":     "1000000000000000000000000000",
		"tether":     "1000000000000000000000000000000",
	}
)

// Web3 Standard interface
// See https://github.com/ethereum/wiki/wiki/JavaScript-API#web3js-api-reference
type Web3 struct {
	provider       Provider
	requestManager *RequestManager
}

// NewWeb3 creates a new web3 object.
func NewWeb3(provider Provider) *Web3 {
	return &Web3{provider: provider, requestManager: newRequestManager(provider)}
}

// IsConnected checks if a connection to a node exists.
func (web3 *Web3) IsConnected() bool {
	return true
}

// SetProvider sets provider.
func (web3 *Web3) SetProvider(provider Provider) {
	web3.provider = provider
}

// CurrentProvider returns the current provider.
func (web3 *Web3) CurrentProvider() Provider {
	return web3.provider
}

// Reset state of web3. Resets everything except manager. Uninstalls all
// filters. Stops polling. If keepSyncing is true, it will uninstall all
// filters, but will keep the web3.eth.IsSyncing() polls.
func (web3 *Web3) Reset(keepSyncing bool) {

}

// Sha3 returns Keccak-256 (not the standardized SHA3-256) of the given data.
func (web3 *Web3) Sha3(data string, options interface{}) string {
	opt := struct {
		Encoding string `json:"encoding"`
	}{
		"default",
	}

checkEncoding:
	switch options.(type) {
	case string:
		if err := json.Unmarshal([]byte(options.(string)), &opt); err != nil {
			return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
		}
		break checkEncoding
	default:
		var err error
		var optBytes []byte
		if optBytes, err = json.Marshal(options); err != nil {
			return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
		}

		if err = json.Unmarshal(optBytes, &opt); err != nil {
			return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
		}
		break checkEncoding
	}

	if opt.Encoding == "hex" {
		d := data
		if strings.Index(data, "0x") == 0 {
			d = strings.Replace(data, "0x", "", -1)
		}
		return "0x" + web3.bytesToHex(web3.sha3Hash(web3.hexToBytes(d)))
	}
	return "0x" + web3.bytesToHex(web3.sha3Hash([]byte(data)))
}

// ToHex converts any value into HEX.
func (web3 *Web3) ToHex(value interface{}) string {
	switch value.(type) {
	case bool:
		v := value.(bool)
		if v {
			return "0x1"
		}
		return "0x0"
	case string:
		jsonBytes, err := json.Marshal(value)
		if err != nil {
			return web3.FromDecimal(value)
		}
		unquoted, err := strconv.Unquote(string(jsonBytes))
		if err != nil {
			return "0x" + web3.bytesToHex(jsonBytes)
		}
		return "0x" + web3.bytesToHex([]byte(unquoted))
	case *big.Int:
		return web3.FromDecimal(value)
	default:
		jsonBytes, err := json.Marshal(value)
		if err != nil {
			return web3.FromDecimal(value)
		}
		return "0x" + web3.bytesToHex(jsonBytes)
	}
}

// ToASCII converts a HEX string into a ASCII string.
func (web3 *Web3) ToASCII(hexString string) string {
	return string(bytes.Trim(web3.hexToBytes(hexString), "\x00"))
}

// FromASCII converts any ASCII string to a HEX string.
func (web3 *Web3) FromASCII(textString string, padding int) string {
	hex := ""
	for _, runeValue := range textString {
		hex += fmt.Sprintf("%x", runeValue)
	}

	l := len(hex)
	for i := 0; i < padding*2-l; i++ {
		hex += "0"
	}
	return "0x" + hex
}

// ToDecimal converts value to it"s decimal representation in string.
func (web3 *Web3) ToDecimal(value interface{}) string {
	n := web3.ToBigNumber(value)
	if n.IsInt() {
		return n.Num().String()
	}
	return n.String()
}

// FromDecimal converts value to it"s hex representation.
func (web3 *Web3) FromDecimal(value interface{}) string {
	number := web3.ToBigNumber(value)
	if number.IsInt() {
		result := number.Num().Text(16)

		if number.Cmp(rat0) < 0 {
			return "-0x" + result[1:]
		}
		return "0x" + result
	}

	v, _ := number.Float64()
	return fmt.Sprintf("%x", math.Float64bits(v))
}

// FromWei takes a number of wei and converts it to any other ether unit.
//
// Possible units are:
//   SI Short   SI Full        Effigy       Other
// - kwei       femtoether     babbage
// - mwei       picoether      lovelace
// - gwei       nanoether      shannon      nano
// - --         microether     szabo        micro
// - --         microether     szabo        micro
// - --         milliether     finney       milli
// - ether      --             --
// - kether                    --           grand
// - mether
// - gether
// - tether
func (web3 *Web3) FromWei(number string, unit string) string {
	num := web3.ToBigNumber(number)
	returnValue := num.Quo(num, web3.getValueOfUnit(unit))
	return returnValue.Num().String()
}

// ToWei takes a number of a unit and converts it to wei.
//
// Possible units are:
//   SI Short   SI Full        Effigy       Other
// - kwei       femtoether     babbage
// - mwei       picoether      lovelace
// - gwei       nanoether      shannon      nano
// - --         microether     szabo        micro
// - --         microether     szabo        micro
// - --         milliether     finney       milli
// - ether      --             --
// - kether                    --           grand
// - mether
// - gether
// - tether
func (web3 *Web3) ToWei(number interface{}, unit string) string {
	num := web3.ToBigNumber(number)
	returnValue := num.Mul(num, web3.getValueOfUnit(unit))
	return returnValue.Num().String()
}

// ToBigNumber takes an input and transforms it into an *big.Rat.
func (web3 *Web3) ToBigNumber(value interface{}) (result *big.Rat) {
	switch value.(type) {
	case *big.Rat:
		v := value.(*big.Rat)
		return v
	case *big.Int:
		v := value.(*big.Int)
		result = new(big.Rat)
		result.SetInt(v)
		return result
	case string:
		v := value.(string)
		i := new(big.Int)
		result = new(big.Rat)

		if strings.Index(v, "0x") == 0 || strings.Index(v, "-0x") == 0 {
			i.SetString(strings.Replace(v, "0x", "", -1), 16)
		} else {
			i.SetString(v, 10)
		}
		result.SetInt(i)
		return result
	}
	return result
}

// IsAddress checks if the given string is an address.
func (web3 *Web3) IsAddress(address string) bool {
	// basicMatcher := regexp.MustCompile("^(0x)?[0-9a-f]{40}$")
	// basicmatched := basicMatcher.MatchString(address)
	// if !basicmatched {
	// 	return false
	// }

	smallCapsMatcher := regexp.MustCompile("^(0x)?[0-9a-f]{40}$")
	smallCapsMatched := smallCapsMatcher.MatchString(address)
	allCapsMatcher := regexp.MustCompile("^(0x)?[0-9A-F]{40}$")
	allCapsMatched := allCapsMatcher.MatchString(address)
	if smallCapsMatched || allCapsMatched {
		return true
	}
	return web3.isChecksumAddress(address)
}

func (web3 *Web3) isChecksumAddress(address string) bool {
	addr := strings.Replace(address, "0x", "", -1)
	addressHash := web3.Sha3(strings.ToLower(addr), "")

	for i := 0; i < 40; i++ {
		d, err := strconv.ParseInt(string(addressHash[i]), 16, 32)
		if err != nil {
			return false
		}

		if d > 7 && strings.ToUpper(string(address[i])) == string(address[i]) ||
			d <= 7 && strings.ToLower(string(address[i])) == string(address[i]) {
			return false
		}
	}
	return true
}

func (web3 *Web3) bytesToHex(data []byte) string {
	buffer := new(bytes.Buffer)
	for _, b := range data {
		s := strconv.FormatInt(int64(b&0xFF), 16)
		if len(s) == 1 {
			buffer.WriteString("0")
		}
		buffer.WriteString(s)
	}
	return buffer.String()
}

func (web3 *Web3) hexToBytes(hex string) []byte {
	length := len(hex) / 2
	slice := make([]byte, length)
	rs := []rune(hex)

	for i := 0; i < length; i++ {
		s := string(rs[i*2 : i*2+2])
		value, _ := strconv.ParseInt(s, 16, 10)
		slice[i] = byte(value & 0xFF)
	}
	return slice
}

func (web3 *Web3) sha3Hash(data ...[]byte) []byte {
	d := sha3.NewKeccak256()
	for _, b := range data {
		d.Write(b)
	}
	return d.Sum(nil)
}

func (web3 *Web3) getValueOfUnit(unit string) *big.Rat {
	u := strings.TrimSpace(unit)
	if u != "" {
		u = strings.ToLower(u)
	} else {
		u = "ether"
	}

	if unitValue, ok := unitMap[u]; ok {
		value := new(big.Int)
		value.SetString(unitValue, 10)
		returnValue := new(big.Rat)
		returnValue.SetInt(value)
		return returnValue
	}

	keys := make([]string, 0, len(unitMap))
	for k := range unitMap {
		keys = append(keys, k)
	}
	panic(fmt.Sprintf("This unit doesn\"t exists, please use the one of the following units, %v", keys))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/jasonlvhit/gocron"
	"github.com/rafaeljusto/toglacier/internal/archive"
	"github.com/rafaeljusto/toglacier/internal/cloud"
	"github.com/rafaeljusto/toglacier/internal/storage"
	"github.com/urfave/cli"
)

var awsAccountID, awsVaultName, auditFile string
var backupPaths []string
var keepBackups = 10

func init() {
	var err error

	awsAccountID = os.Getenv("AWS_ACCOUNT_ID")
	awsVaultName = os.Getenv("AWS_VAULT_NAME")
	backupPaths = strings.Split(os.Getenv("TOGLACIER_PATH"), ",")
	auditFile = os.Getenv("TOGLACIER_AUDIT")

	if os.Getenv("TOGLACIER_KEEP_BACKUPS") != "" {
		if keepBackups, err = strconv.Atoi(os.Getenv("TOGLACIER_KEEP_BACKUPS")); err != nil {
			fmt.Printf("invalid number of backups to keep. details: %s", err)
			os.Exit(1)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "toglacier"
	app.Usage = "Send data to AWS Glacier service"
	app.Version = "2.0.0"
	app.Authors = []cli.Author{
		{
			Name:  "Rafael Dantas Justo",
			Email: "adm@rafael.net.br",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "sync",
			Usage: "backup now the desired paths to AWS Glacier",
			Action: func(c *cli.Context) error {
				backup()
				return nil
			},
		},
		{
			Name:      "get",
			Usage:     "retrieve a specific backup from AWS Glacier",
			ArgsUsage: "<archiveID>",
			Action: func(c *cli.Context) error {
				if backupFile := retrieveBackup(c.Args().First()); backupFile != "" {
					fmt.Printf("Backup recovered at %s\n", backupFile)
				}
				return nil
			},
		},
		{
			Name:      "remove",
			Aliases:   []string{"rm"},
			Usage:     "remove a specific backup from AWS Glacier",
			ArgsUsage: "<archiveID>",
			Action: func(c *cli.Context) error {
				removeBackup(c.Args().First())
				return nil
			},
		},
		{
			Name:    "list",
			Aliases: []string{"ls"},
			Usage:   "list all backups sent to AWS Glacier",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "remote,r",
					Usage: "retrieve the list from AWS Glacier (long wait)",
				},
			},
			Action: func(c *cli.Context) error {
				backups := listBackups(c.Bool("remote"))
				if len(backups) > 0 {
					fmt.Println("Date             | Vault Name       | Archive ID")
					fmt.Printf("%s-+-%s-+-%s\n", strings.Repeat("-", 16), strings.Repeat("-", 16), strings.Repeat("-", 138))
					for _, backup := range backups {
						fmt.Printf("%-16s | %-16s | %-138s\n", backup.CreatedAt.Format("2006-01-02 15:04"), backup.VaultName, backup.ID)
					}
				}
				return nil
			},
		},
		{
			Name:  "start",
			Usage: "run the scheduler (will block forever)",
			Action: func(c *cli.Context) error {
				scheduler := gocron.NewScheduler()
				scheduler.Every(1).Day().At("00:00").Do(backup, nil)
				scheduler.Every(1).Weeks().At("01:00").Do(removeOldBackups, nil)
				<-scheduler.Start()
				return nil
			},
		},
		{
			Name:      "encrypt",
			Aliases:   []string{"enc"},
			Usage:     "encrypt a password or secret",
			ArgsUsage: "<password>",
			Action: func(c *cli.Context) error {
				if pwd, err := cloud.PasswordEncrypt(c.Args().First()); err == nil {
					fmt.Printf("encrypted:%s\n", pwd)
				} else {
					fmt.Printf("error encrypting password. details: %s\n", err)
				}
				return nil
			},
		},
	}

	app.Run(os.Args)
}

func backup() {
	archive, err := archive.Build(backupPaths...)
	if err != nil {
		log.Println(err)
		return
	}
	defer os.Remove(archive)

	c, err := cloud.NewAWSCloud(awsAccountID, awsVaultName, false)
	if err != nil {
		log.Println(err)
		return
	}

	backup, err := c.Send(archive)
	if err != nil {
		log.Println(err)
		return
	}

	a := storage.NewAuditFile(auditFile)
	if err := a.Save(backup); err != nil {
		log.Println(err)
		return
	}
}

func listBackups(remote bool) []cloud.Backup {
	if remote {
		c, err := cloud.NewAWSCloud(awsAccountID, awsVaultName, false)
		if err != nil {
			log.Println(err)
			return nil
		}

		backups, err := c.List()
		if err != nil {
			log.Printf("error retrieving remote backups. details: %s", err)
		}
		return backups
	}

	a := storage.NewAuditFile(auditFile)
	backups, err := a.List()
	if err != nil {
		log.Println(err)
		return nil
	}
	return backups
}

func retrieveBackup(id string) string {
	c, err := cloud.NewAWSCloud(awsAccountID, awsVaultName, false)
	if err != nil {
		log.Println(err)
		return ""
	}

	backupFile, err := c.Get(id)
	if err != nil {
		log.Println(err)
		return ""
	}

	return backupFile
}

func removeBackup(id string) {
	c, err := cloud.NewAWSCloud(awsAccountID, awsVaultName, false)
	if err != nil {
		log.Println(err)
		return
	}

	if err := c.Remove(id); err != nil {
		log.Println(err)
		return
	}

	a := storage.NewAuditFile(auditFile)
	if err := a.Remove(id); err != nil {
		log.Println(err)
		return
	}
}

func removeOldBackups() {
	backups := listBackups(true)
	for i := keepBackups; i < len(backups); i++ {
		removeBackup(backups[i].ID)
	}
}
<commit_msg>Inject dependencies<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/jasonlvhit/gocron"
	"github.com/rafaeljusto/toglacier/internal/archive"
	"github.com/rafaeljusto/toglacier/internal/cloud"
	"github.com/rafaeljusto/toglacier/internal/storage"
	"github.com/urfave/cli"
)

var awsAccountID, awsVaultName, auditFile string
var backupPaths []string
var keepBackups = 10

func init() {
	var err error

	awsAccountID = os.Getenv("AWS_ACCOUNT_ID")
	awsVaultName = os.Getenv("AWS_VAULT_NAME")
	backupPaths = strings.Split(os.Getenv("TOGLACIER_PATH"), ",")
	auditFile = os.Getenv("TOGLACIER_AUDIT")

	if os.Getenv("TOGLACIER_KEEP_BACKUPS") != "" {
		if keepBackups, err = strconv.Atoi(os.Getenv("TOGLACIER_KEEP_BACKUPS")); err != nil {
			fmt.Printf("invalid number of backups to keep. details: %s", err)
			os.Exit(1)
		}
	}
}

func main() {
	awsCloud, err := cloud.NewAWSCloud(awsAccountID, awsVaultName, false)
	if err != nil {
		log.Println(err)
		return
	}
	auditFileStorage := storage.NewAuditFile(auditFile)

	app := cli.NewApp()
	app.Name = "toglacier"
	app.Usage = "Send data to AWS Glacier service"
	app.Version = "2.0.0"
	app.Authors = []cli.Author{
		{
			Name:  "Rafael Dantas Justo",
			Email: "adm@rafael.net.br",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "sync",
			Usage: "backup now the desired paths to AWS Glacier",
			Action: func(c *cli.Context) error {
				backup(awsCloud, auditFileStorage)
				return nil
			},
		},
		{
			Name:      "get",
			Usage:     "retrieve a specific backup from AWS Glacier",
			ArgsUsage: "<archiveID>",
			Action: func(c *cli.Context) error {
				if backupFile := retrieveBackup(c.Args().First(), awsCloud); backupFile != "" {
					fmt.Printf("Backup recovered at %s\n", backupFile)
				}
				return nil
			},
		},
		{
			Name:      "remove",
			Aliases:   []string{"rm"},
			Usage:     "remove a specific backup from AWS Glacier",
			ArgsUsage: "<archiveID>",
			Action: func(c *cli.Context) error {
				removeBackup(c.Args().First(), awsCloud, auditFileStorage)
				return nil
			},
		},
		{
			Name:    "list",
			Aliases: []string{"ls"},
			Usage:   "list all backups sent to AWS Glacier",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "remote,r",
					Usage: "retrieve the list from AWS Glacier (long wait)",
				},
			},
			Action: func(c *cli.Context) error {
				backups := listBackups(c.Bool("remote"), awsCloud, auditFileStorage)
				if len(backups) > 0 {
					fmt.Println("Date             | Vault Name       | Archive ID")
					fmt.Printf("%s-+-%s-+-%s\n", strings.Repeat("-", 16), strings.Repeat("-", 16), strings.Repeat("-", 138))
					for _, backup := range backups {
						fmt.Printf("%-16s | %-16s | %-138s\n", backup.CreatedAt.Format("2006-01-02 15:04"), backup.VaultName, backup.ID)
					}
				}
				return nil
			},
		},
		{
			Name:  "start",
			Usage: "run the scheduler (will block forever)",
			Action: func(c *cli.Context) error {
				scheduler := gocron.NewScheduler()
				scheduler.Every(1).Day().At("00:00").Do(backup, nil)
				scheduler.Every(1).Weeks().At("01:00").Do(removeOldBackups, nil)
				<-scheduler.Start()
				return nil
			},
		},
		{
			Name:      "encrypt",
			Aliases:   []string{"enc"},
			Usage:     "encrypt a password or secret",
			ArgsUsage: "<password>",
			Action: func(c *cli.Context) error {
				if pwd, err := cloud.PasswordEncrypt(c.Args().First()); err == nil {
					fmt.Printf("encrypted:%s\n", pwd)
				} else {
					fmt.Printf("error encrypting password. details: %s\n", err)
				}
				return nil
			},
		},
	}

	app.Run(os.Args)
}

func backup(c cloud.Cloud, s storage.Storage) {
	archive, err := archive.Build(backupPaths...)
	if err != nil {
		log.Println(err)
		return
	}
	defer os.Remove(archive)

	backup, err := c.Send(archive)
	if err != nil {
		log.Println(err)
		return
	}

	if err := s.Save(backup); err != nil {
		log.Println(err)
		return
	}
}

func listBackups(remote bool, c cloud.Cloud, s storage.Storage) []cloud.Backup {
	if remote {
		backups, err := c.List()
		if err != nil {
			log.Printf("error retrieving remote backups. details: %s", err)
		}
		return backups
	}

	backups, err := s.List()
	if err != nil {
		log.Println(err)
		return nil
	}
	return backups
}

func retrieveBackup(id string, c cloud.Cloud) string {
	backupFile, err := c.Get(id)
	if err != nil {
		log.Println(err)
		return ""
	}

	return backupFile
}

func removeBackup(id string, c cloud.Cloud, s storage.Storage) {
	if err := c.Remove(id); err != nil {
		log.Println(err)
		return
	}

	if err := s.Remove(id); err != nil {
		log.Println(err)
		return
	}
}

func removeOldBackups(c cloud.Cloud, s storage.Storage) {
	backups := listBackups(true, c, s)
	for i := keepBackups; i < len(backups); i++ {
		removeBackup(backups[i].ID, c, s)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"

	"github.com/codegangsta/cli"
	"github.com/termie/go-shutil"
)

func start(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/startup.sh")
	return cmd.Run()
}

func stop(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/shutdown.sh")
	return cmd.Run()
}

func restart(path string) {
	err := stop(path)
	if err != nil {
		fmt.Println("TomEE isn't started...")
	}

	fmt.Printf("Starting server..")
	err = start(path)
	if err != nil {
		fmt.Println("Error during start")
		return
	}

	fmt.Println("TomEE started")
}

func deploy(tomeePath, packageForDeploy string) error {
	_, packageName := path.Split(packageForDeploy)
	deployPath := tomeePath + "/webapps/"
	if strings.HasSuffix(packageForDeploy, ".ear") {
		deployPath = tomeePath + "/apps/"
		os.Mkdir(deployPath, 0744)
	}

	err := shutil.CopyFile(packageForDeploy, deployPath+packageName, true)
	if err != nil {
		return err
	}

	return nil
}

func createCommands() []cli.Command {
	pathFlag := cli.StringFlag{
		Name:   "path",
		Usage:  "path of the TomEE server. Default value: $TOMEE_HOME",
		EnvVar: "TOMEE_HOME",
	}

	startCommand := cli.Command{
		Name:  "start",
		Usage: "start the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			start(c.String("path"))
		},
	}

	stopCommand := cli.Command{
		Name:  "stop",
		Usage: "stop the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			stop(c.String("path"))
		},
	}

	restartCommand := cli.Command{
		Name:  "restart",
		Usage: "restart the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			restart(c.String("path"))
		},
	}

	deployCommand := cli.Command{
		Name:  "deploy",
		Usage: "deploy war/ear in TomEE",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			err := deploy(c.String("path"), c.Args().First())
			if err != nil {
				log.Fatal(err)
			}
			fmt.Println("Deployed in: " + c.String("path"))
		},
	}

	return []cli.Command{startCommand, stopCommand, restartCommand, deployCommand}
}

func main() {
	app := cli.NewApp()
	app.Name = "tomee-cli"
	app.Usage = "Command line tool helps system administrators and developers to manage a instance of TomEE server."
	app.Version = "1.0.0"
	app.Commands = createCommands()
	app.Run(os.Args)
}
<commit_msg>Added undeploy<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"

	"github.com/codegangsta/cli"
	"github.com/termie/go-shutil"
)

func start(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/startup.sh")
	return cmd.Run()
}

func stop(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/shutdown.sh")
	return cmd.Run()
}

func restart(path string) {
	err := stop(path)
	if err != nil {
		fmt.Println("TomEE isn't started...")
	}

	fmt.Printf("Starting server..")
	err = start(path)
	if err != nil {
		fmt.Println("Error during start")
		return
	}

	fmt.Println("TomEE started")
}

func undeploy(tomeePath, packageForUndeploy string) error {
	_, packageName := path.Split(packageForUndeploy)
	deployPath := tomeePath + "/webapps/"
	if strings.HasSuffix(packageForUndeploy, ".ear") {
		deployPath = tomeePath + "/apps"
	}

	err := os.RemoveAll(deployPath + packageName)
	if err != nil {
		return err
	}

	err = os.RemoveAll(deployPath + strings.TrimSuffix(packageName, path.Ext(packageName)))
	if err != nil {
		return err
	}

	return nil
}

func deploy(tomeePath, packageForDeploy string) error {
	_, packageName := path.Split(packageForDeploy)
	deployPath := tomeePath + "/webapps/"
	if strings.HasSuffix(packageForDeploy, ".ear") {
		deployPath = tomeePath + "/apps/"
		os.Mkdir(deployPath, 0744)
	}

	err := shutil.CopyFile(packageForDeploy, deployPath+packageName, true)
	if err != nil {
		return err
	}

	return nil
}

func createCommands() []cli.Command {
	pathFlag := cli.StringFlag{
		Name:   "path",
		Usage:  "path of the TomEE server. Default value: $TOMEE_HOME",
		EnvVar: "TOMEE_HOME",
	}

	startCommand := cli.Command{
		Name:  "start",
		Usage: "start the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			start(c.String("path"))
		},
	}

	stopCommand := cli.Command{
		Name:  "stop",
		Usage: "stop the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			stop(c.String("path"))
		},
	}

	restartCommand := cli.Command{
		Name:  "restart",
		Usage: "restart the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			restart(c.String("path"))
		},
	}

	undeployCommand := cli.Command{
		Name:  "undeploy",
		Usage: "undeploy war/ear in TomEE",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			err := undeploy(c.String("path"), c.Args().First())
			if err != nil {
				log.Fatal(err)
			}
			fmt.Println("Undeploy in: " + c.String("path"))
		},
	}

	deployCommand := cli.Command{
		Name:  "deploy",
		Usage: "deploy war/ear in TomEE",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			err := deploy(c.String("path"), c.Args().First())
			if err != nil {
				log.Fatal(err)
			}
			fmt.Println("Deployed in: " + c.String("path"))
		},
	}

	return []cli.Command{startCommand, stopCommand, restartCommand, deployCommand, undeployCommand}
}

func main() {
	app := cli.NewApp()
	app.Name = "tomee-cli"
	app.Usage = "Command line tool helps system administrators and developers to manage a instance of TomEE server."
	app.Version = "1.0.0"
	app.Commands = createCommands()
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package vm

import (
	"fmt"
	"github.com/goby-lang/goby/compiler/bytecode"
	"strings"
)

type thread struct {
	// a stack that holds call frames
	callFrameStack *callFrameStack
	// call frame pointer
	cfp int
	// data stack
	stack *stack
	// stack pointer
	sp int

	vm *VM
}

func (t *thread) getBlock(name string, filename filename) *instructionSet {
	return t.vm.getBlock(name, filename)
}

func (t *thread) getMethodIS(name string, filename filename) (*instructionSet, bool) {
	return t.vm.getMethodIS(name, filename)
}

func (t *thread) getClassIS(name string, filename filename) *instructionSet {
	return t.vm.getClassIS(name, filename)
}

func (t *thread) startFromTopFrame() {
	cf := t.callFrameStack.top()
	t.evalCallFrame(cf)
}

func (t *thread) evalCallFrame(cf *callFrame) {
	for cf.pc < len(cf.instructionSet.instructions) {
		i := cf.instructionSet.instructions[cf.pc]
		t.execInstruction(cf, i)
		if msg, yes := t.hasError(); yes {
			fmt.Println(msg)
			return
		}
	}
}

func (t *thread) hasError() (string, bool) {
	var hasError bool
	var msg string
	if t.stack.top() != nil {
		if err, ok := t.stack.top().Target.(*Error); ok {
			hasError = true
			msg = err.Message
		}
	}
	return msg, hasError
}

func (t *thread) execInstruction(cf *callFrame, i *instruction) {
	cf.pc++

	defer func() {
		if p := recover(); p != nil {
			if t.vm.stackTraceCount == 0 {
				fmt.Printf("Internal Error: %s\n", p)
			}
			t.vm.stackTraceCount++
			panic(p)
		}
	}()

	i.action.operation(t, cf, i.Params...)
}

func (t *thread) builtInMethodYield(blockFrame *callFrame, args ...Object) *Pointer {
	c := newCallFrame(blockFrame.instructionSet)
	c.blockFrame = blockFrame
	c.ep = blockFrame.ep
	c.self = blockFrame.self

	for i := 0; i < len(args); i++ {
		c.insertLCL(i, 0, args[i])
	}

	t.callFrameStack.push(c)
	t.startFromTopFrame()

	return t.stack.top()
}

func (t *thread) retrieveBlock(cf *callFrame, args []interface{}) (blockFrame *callFrame) {
	var blockName string
	var hasBlock bool

	if len(args) > 2 {
		hasBlock = true
		blockFlag := args[2].(string)
		blockName = strings.Split(blockFlag, ":")[1]
	} else {
		hasBlock = false
	}

	if hasBlock {
		block := t.getBlock(blockName, cf.instructionSet.filename)

		c := newCallFrame(block)
		c.isBlock = true
		c.ep = cf
		c.self = cf.self

		t.callFrameStack.push(c)

		blockFrame = c
	}

	return
}

func (t *thread) evalBuiltInMethod(receiver Object, method *BuiltInMethodObject, receiverPr, argCount, argPr int, blockFrame *callFrame) {
	methodBody := method.Fn(receiver)
	args := []Object{}

	for i := 0; i < argCount; i++ {
		args = append(args, t.stack.Data[argPr+i].Target)
	}

	evaluated := methodBody(t, args, blockFrame)

	_, ok := receiver.(*RClass)
	if method.Name == "new" && ok {
		instance, ok := evaluated.(*RObject)
		if ok && instance.InitializeMethod != nil {
			t.evalMethodObject(instance, instance.InitializeMethod, receiverPr, argCount, argPr, blockFrame)
		}
	}
	t.stack.Data[receiverPr] = &Pointer{evaluated}
	t.sp = receiverPr + 1
}

func (t *thread) evalMethodObject(receiver Object, method *MethodObject, receiverPr, argC, argPr int, blockFrame *callFrame) {
	var normalArgCount int

	c := newCallFrame(method.instructionSet)
	c.self = receiver

	for _, at := range method.instructionSet.argTypes {
		if at == bytecode.NormalArg {
			normalArgCount++
		}
	}

	if argC < normalArgCount {
		e := initErrorObject(ArgumentErrorClass, "Expect at least %d args for method '%s'. got: %d", normalArgCount, method.Name, argC)
		t.stack.push(&Pointer{e})
	} else if argC > method.argc {
		e := initErrorObject(ArgumentErrorClass, "Expect at most %d args for method '%s'. got: %d", method.argc, method.Name, argC)
		t.stack.push(&Pointer{e})
	} else {
		for i := 0; i < argC; i++ {
			c.insertLCL(i, 0, t.stack.Data[argPr+i].Target)
		}

		c.blockFrame = blockFrame
		t.callFrameStack.push(c)
		t.startFromTopFrame()
	}

	t.stack.Data[receiverPr] = t.stack.top()
	t.sp = receiverPr + 1
}

// TODO: Use this method to replace unnecessary panics
func (t *thread) returnError(msg string) {
	err := &Error{Message: msg}
	t.stack.push(&Pointer{err})
	panic(errorMessage(msg))
}

func (t *thread) UndefinedMethodError(methodName string, receiver Object) {
	err := initErrorObject(UndefinedMethodErrorClass, "Undefined Method '%+v' for %+v", methodName, receiver.toString())
	t.stack.push(&Pointer{err})
}

func (t *thread) UnsupportedMethodError(methodName string, receiver Object) *Error {
	return initErrorObject(UnsupportedMethodClass, "Unsupported Method %s for %+v", methodName, receiver.toString())
}
<commit_msg>Not panicking when thread returns error.<commit_after>package vm

import (
	"fmt"
	"github.com/goby-lang/goby/compiler/bytecode"
	"strings"
)

type thread struct {
	// a stack that holds call frames
	callFrameStack *callFrameStack
	// call frame pointer
	cfp int
	// data stack
	stack *stack
	// stack pointer
	sp int

	vm *VM
}

func (t *thread) getBlock(name string, filename filename) *instructionSet {
	return t.vm.getBlock(name, filename)
}

func (t *thread) getMethodIS(name string, filename filename) (*instructionSet, bool) {
	return t.vm.getMethodIS(name, filename)
}

func (t *thread) getClassIS(name string, filename filename) *instructionSet {
	return t.vm.getClassIS(name, filename)
}

func (t *thread) startFromTopFrame() {
	cf := t.callFrameStack.top()
	t.evalCallFrame(cf)
}

func (t *thread) evalCallFrame(cf *callFrame) {
	for cf.pc < len(cf.instructionSet.instructions) {
		i := cf.instructionSet.instructions[cf.pc]
		t.execInstruction(cf, i)
		if msg, yes := t.hasError(); yes {
			fmt.Println(msg)
			return
		}
	}
}

func (t *thread) hasError() (string, bool) {
	var hasError bool
	var msg string
	if t.stack.top() != nil {
		if err, ok := t.stack.top().Target.(*Error); ok {
			hasError = true
			msg = err.Message
		}
	}
	return msg, hasError
}

func (t *thread) execInstruction(cf *callFrame, i *instruction) {
	cf.pc++

	defer func() {
		if p := recover(); p != nil {
			if t.vm.stackTraceCount == 0 {
				fmt.Printf("Internal Error: %s\n", p)
			}
			t.vm.stackTraceCount++
			panic(p)
		}
	}()

	i.action.operation(t, cf, i.Params...)
}

func (t *thread) builtInMethodYield(blockFrame *callFrame, args ...Object) *Pointer {
	c := newCallFrame(blockFrame.instructionSet)
	c.blockFrame = blockFrame
	c.ep = blockFrame.ep
	c.self = blockFrame.self

	for i := 0; i < len(args); i++ {
		c.insertLCL(i, 0, args[i])
	}

	t.callFrameStack.push(c)
	t.startFromTopFrame()

	return t.stack.top()
}

func (t *thread) retrieveBlock(cf *callFrame, args []interface{}) (blockFrame *callFrame) {
	var blockName string
	var hasBlock bool

	if len(args) > 2 {
		hasBlock = true
		blockFlag := args[2].(string)
		blockName = strings.Split(blockFlag, ":")[1]
	} else {
		hasBlock = false
	}

	if hasBlock {
		block := t.getBlock(blockName, cf.instructionSet.filename)

		c := newCallFrame(block)
		c.isBlock = true
		c.ep = cf
		c.self = cf.self

		t.callFrameStack.push(c)

		blockFrame = c
	}

	return
}

func (t *thread) evalBuiltInMethod(receiver Object, method *BuiltInMethodObject, receiverPr, argCount, argPr int, blockFrame *callFrame) {
	methodBody := method.Fn(receiver)
	args := []Object{}

	for i := 0; i < argCount; i++ {
		args = append(args, t.stack.Data[argPr+i].Target)
	}

	evaluated := methodBody(t, args, blockFrame)

	_, ok := receiver.(*RClass)
	if method.Name == "new" && ok {
		instance, ok := evaluated.(*RObject)
		if ok && instance.InitializeMethod != nil {
			t.evalMethodObject(instance, instance.InitializeMethod, receiverPr, argCount, argPr, blockFrame)
		}
	}
	t.stack.Data[receiverPr] = &Pointer{evaluated}
	t.sp = receiverPr + 1
}

func (t *thread) evalMethodObject(receiver Object, method *MethodObject, receiverPr, argC, argPr int, blockFrame *callFrame) {
	var normalArgCount int

	c := newCallFrame(method.instructionSet)
	c.self = receiver

	for _, at := range method.instructionSet.argTypes {
		if at == bytecode.NormalArg {
			normalArgCount++
		}
	}

	if argC < normalArgCount {
		e := initErrorObject(ArgumentErrorClass, "Expect at least %d args for method '%s'. got: %d", normalArgCount, method.Name, argC)
		t.stack.push(&Pointer{e})
	} else if argC > method.argc {
		e := initErrorObject(ArgumentErrorClass, "Expect at most %d args for method '%s'. got: %d", method.argc, method.Name, argC)
		t.stack.push(&Pointer{e})
	} else {
		for i := 0; i < argC; i++ {
			c.insertLCL(i, 0, t.stack.Data[argPr+i].Target)
		}

		c.blockFrame = blockFrame
		t.callFrameStack.push(c)
		t.startFromTopFrame()
	}

	t.stack.Data[receiverPr] = t.stack.top()
	t.sp = receiverPr + 1
}

// TODO: Use this method to replace unnecessary panics
func (t *thread) returnError(msg string) {
	err := &Error{Message: msg}
	t.stack.push(&Pointer{err})
}

func (t *thread) UndefinedMethodError(methodName string, receiver Object) {
	err := initErrorObject(UndefinedMethodErrorClass, "Undefined Method '%+v' for %+v", methodName, receiver.toString())
	t.stack.push(&Pointer{err})
}

func (t *thread) UnsupportedMethodError(methodName string, receiver Object) *Error {
	return initErrorObject(UnsupportedMethodClass, "Unsupported Method %s for %+v", methodName, receiver.toString())
}
<|endoftext|>


<commit_before>package wdte_test

import (
	"fmt"
	"strings"
	"testing"

	"github.com/DeedleFake/wdte"
	"github.com/DeedleFake/wdte/std"
	"github.com/DeedleFake/wdte/std/math"
	"github.com/DeedleFake/wdte/std/stream"
)

func TestModule(t *testing.T) {
	const test = `
'stream' => s;

memo fib n => switch n {
	== 0 => 0;
	== 1 => 1;
	default => + (fib (- n 1)) (fib (- n 2));
};

memo fact n => switch n {
	<= 1 => 1;
	default => - n 1 -> fact -> * n;
};

main => (
	s.range 15
  -> s.map fib
	-> s.collect
	-> print;

	s.new [5; 2; fib 7]
	-> s.map (+ 2)
	-> s.collect
	-> print;

	fact 5 -> print;
);
`

	m, err := new(wdte.Module).Insert(std.Module()).Parse(
		strings.NewReader(test),
		wdte.ImportFunc(func(from string) (*wdte.Module, error) {
			switch from {
			case "stream":
				return stream.Module(), nil
			case "math":
				return math.Module(), nil
			}

			return nil, fmt.Errorf("Unknown import: %q", from)
		}),
	)
	if err != nil {
		t.Fatal(err)
	}

	m.Funcs["print"] = wdte.GoFunc(func(frame wdte.Frame, args ...wdte.Func) wdte.Func {
		frame = frame.WithID("print")

		if len(args) < 1 {
			return m.Funcs["print"]
		}

		a := args[0].Call(frame)
		if _, ok := a.(error); !ok {
			t.Logf("%v", a)
		}
		return a
	})

	//t.Log("Imports:")
	//for i := range m.Imports {
	//	t.Logf("\t%q", i)
	//}

	//t.Log("Funcs:")
	//for f := range m.Funcs {
	//	t.Logf("\t%q", f)
	//}

	if err, ok := m.Funcs["main"].Call(wdte.F()).(error); ok {
		t.Fatal(err)
	}
}
<commit_msg>wdte: Use std.Import for tests.<commit_after>package wdte_test

import (
	"strings"
	"testing"

	"github.com/DeedleFake/wdte"
	"github.com/DeedleFake/wdte/std"
)

func TestModule(t *testing.T) {
	const test = `
'stream' => s;

memo fib n => switch n {
	== 0 => 0;
	== 1 => 1;
	default => + (fib (- n 1)) (fib (- n 2));
};

memo fact n => switch n {
	<= 1 => 1;
	default => - n 1 -> fact -> * n;
};

main => (
	s.range 15
  -> s.map fib
	-> s.collect
	-> print;

	s.new [5; 2; fib 7]
	-> s.map (+ 2)
	-> s.collect
	-> print;

	fact 5 -> print;
);
`

	m, err := std.Module().Parse(strings.NewReader(test), std.Import)
	if err != nil {
		t.Fatal(err)
	}

	m.Funcs["print"] = wdte.GoFunc(func(frame wdte.Frame, args ...wdte.Func) wdte.Func {
		frame = frame.WithID("print")

		if len(args) < 1 {
			return m.Funcs["print"]
		}

		a := args[0].Call(frame)
		if _, ok := a.(error); !ok {
			t.Logf("%v", a)
		}
		return a
	})

	//t.Log("Imports:")
	//for i := range m.Imports {
	//	t.Logf("\t%q", i)
	//}

	//t.Log("Funcs:")
	//for f := range m.Funcs {
	//	t.Logf("\t%q", f)
	//}

	if err, ok := m.Funcs["main"].Call(wdte.F()).(error); ok {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package iputil

import (
	"bytes"
	"encoding/binary"
	"github.com/oopschen/xtunnel/sys"
	"net"
	"time"
)

const (
	maxConcurrent = 30
	// 5 seconds
	timeoutNanoMS = 5 * time.Second
	tryCount      = 4
)

type measureTime uint16
type ipMeta struct {
	ip    string
	avgMS measureTime
}

type icmpEchoRequest struct {
	typ      uint8
	code     uint8
	checksum uint16
	id       uint16
	seq      uint16
}

/**
*
find the nearest ip address in ips

* @param ips the list of ip
* @return the chosen ip in the ips
 */
func GetBestIP(ips []string) string {
	if nil == ips || 1 > len(ips) {
		return ""

	}

	curConcurrent := 0
	c := make(chan ipMeta, 128)
	defer close(c)
	ipTimeMap := make(map[string]measureTime)
	for _, ip := range ips {
		if 1 > len(ip) {
			continue
		}

		go checkPermform(c, ip)

		curConcurrent++
		if maxConcurrent >= curConcurrent {
			wait4Chan(c, ipTimeMap, curConcurrent)
			curConcurrent = 0
		}

	}

	wait4Chan(c, ipTimeMap, curConcurrent)

	bestIP := ""
	bestTime := measureTime(10000)
	for ip, time := range ipTimeMap {
		if bestTime > time {
			bestTime = time
			bestIP = ip

		}

	}

	return bestIP
}

func checkPermform(c chan ipMeta, ip string) {
	resultMeta := ipMeta{}

	conn, err := net.DialTimeout("ip4:icmp", ip, timeoutNanoMS)
	if nil != err {
		sys.Logger.Printf("socket %s", err)
		c <- resultMeta
		return

	}

	defer conn.Close()

	var (
		tolTime uint64 = 0
		count   uint16 = 0
		pId     uint16 = 0x78
		pSeq    uint16 = 0x45
		recvBuf        = make([]byte, 8) // only type code header id seq
	)

	for i := 0; i < tryCount; i++ {
		// send pkts
		pkt := createPkt(ip, pId, pSeq)
		if nil == pkt {
			sys.Logger.Printf("create packet %s", err)
			continue

		}

		timeStart := time.Now()

		_, err := conn.Write(pkt)
		if nil != err {
			sys.Logger.Printf("write packet %s", err)
			c <- resultMeta
			return

		}

		// read pkts
		conn.SetReadDeadline(time.Now().Add(timeoutNanoMS))
		_, err = conn.Read(recvBuf)
		if nil != err {
			tolTime += 100000
			count++
			continue

		}

		count++
		tolTime += uint64(time.Now().Sub(timeStart).Nanoseconds())

	}

	// send result to channel
	resultMeta.ip = ip
	// ms
	resultMeta.avgMS = measureTime(uint16(tolTime/1000000) / count)
	c <- resultMeta

}

func wait4Chan(c chan ipMeta, dest map[string]measureTime, num int) {
	for i := 0; i < num; i++ {
		meta, ok := <-c
		if !ok || "" == meta.ip {
			continue
		}
		dest[meta.ip] = meta.avgMS

	}

}

func createPkt(ip string, id uint16, seq uint16) []byte {
	out := new(bytes.Buffer)
	// type, code, checksum
	var icmpReq icmpEchoRequest
	icmpReq.typ = 8
	icmpReq.code = 0
	icmpReq.checksum = 0
	icmpReq.id = id
	icmpReq.seq = seq

	err := binary.Write(out, binary.BigEndian, icmpReq)
	if nil != err {
		return nil

	}

	// set checksum
	icmpReq.checksum = checksum(out.Bytes())

	// reset buf
	out.Reset()

	err = binary.Write(out, binary.BigEndian, icmpReq)
	if nil != err {
		return nil

	}

	return out.Bytes()
}

func checksum(data []byte) uint16 {
	var (
		sum    uint32
		length int = len(data)
		index  int
	)
	for length > 1 {
		sum += uint32(data[index])<<8 + uint32(data[index+1])
		index += 2
		length -= 2
	}
	if length > 0 {
		sum += uint32(data[index])
	}
	sum += (sum >> 16)

	return uint16(^sum)
}
<commit_msg>send pkts in all and read in all<commit_after>package iputil

import (
	"bytes"
	"encoding/binary"
	"github.com/oopschen/xtunnel/sys"
	"net"
	"time"
)

const (
	maxConcurrent = 30
	// 5 seconds
	timeoutNanoMS = 5 * time.Second
	tryCount      = 4
)

type measureTime uint16
type ipMeta struct {
	ip    string
	avgMS measureTime
}

type icmpEchoRequest struct {
	typ      uint8
	code     uint8
	checksum uint16
	id       uint16
	seq      uint16
}

/**
*
find the nearest ip address in ips

* @param ips the list of ip
* @return the chosen ip in the ips
 */
func GetBestIP(ips []string) string {
	if nil == ips || 1 > len(ips) {
		return ""

	}

	curConcurrent := 0
	c := make(chan ipMeta, 128)
	defer close(c)
	ipTimeMap := make(map[string]measureTime)
	for _, ip := range ips {
		if 1 > len(ip) {
			continue
		}

		go checkPermform(c, ip)

		curConcurrent++
		if maxConcurrent >= curConcurrent {
			wait4Chan(c, ipTimeMap, curConcurrent)
			curConcurrent = 0
		}

	}

	wait4Chan(c, ipTimeMap, curConcurrent)

	bestIP := ""
	bestTime := measureTime(10000)
	for ip, time := range ipTimeMap {
		if bestTime > time {
			bestTime = time
			bestIP = ip

		}

	}

	return bestIP
}

func checkPermform(c chan ipMeta, ip string) {
	resultMeta := ipMeta{}
	// always send meta to chan
	defer func() {
		c <- resultMeta

	}()

	conn, err := net.DialTimeout("ip4:icmp", ip, timeoutNanoMS)
	if nil != err {
		sys.Logger.Printf("socket %s", err)
		return

	}
	// always close conn if opened
	defer conn.Close()

	var (
		tolTime uint64 = 0
		pId     uint16 = 0x78
		pSeq    uint16 = 0x45
		recvBuf        = make([]byte, 8) // only type code header id seq
	)

	// start time
	timeStart := time.Now()

	// send pkts
	for i := 0; i < tryCount; i++ {
		pkt := createPkt(ip, pId, pSeq)
		if nil == pkt {
			sys.Logger.Printf("create packet %s", err)
			return

		}

		_, err := conn.Write(pkt)
		if nil != err {
			sys.Logger.Printf("write packet %s", err)
			return

		}
	}

	// recv pkts
	conn.SetReadDeadline(time.Now().Add(timeoutNanoMS))
	for i := 0; i < tryCount; i++ {
		_, err = conn.Read(recvBuf)
		if nil != err {
			sys.Logger.Printf("read packet %s", err)
			return
		}

	}

	tolTime = uint64(time.Now().Sub(timeStart).Nanoseconds())

	// send result to channel
	resultMeta.ip = ip
	// ms
	resultMeta.avgMS = measureTime(uint16(tolTime/1000000) / tryCount)
}

func wait4Chan(c chan ipMeta, dest map[string]measureTime, num int) {
	for i := 0; i < num; i++ {
		meta, ok := <-c
		if !ok || "" == meta.ip {
			continue
		}
		dest[meta.ip] = meta.avgMS

	}

}

func createPkt(ip string, id uint16, seq uint16) []byte {
	out := new(bytes.Buffer)
	// type, code, checksum
	var icmpReq icmpEchoRequest
	icmpReq.typ = 8
	icmpReq.code = 0
	icmpReq.checksum = 0
	icmpReq.id = id
	icmpReq.seq = seq

	err := binary.Write(out, binary.BigEndian, icmpReq)
	if nil != err {
		return nil

	}

	// set checksum
	icmpReq.checksum = checksum(out.Bytes())

	// reset buf
	out.Reset()

	err = binary.Write(out, binary.BigEndian, icmpReq)
	if nil != err {
		return nil

	}

	return out.Bytes()
}

func checksum(data []byte) uint16 {
	var (
		sum    uint32
		length int = len(data)
		index  int
	)
	for length > 1 {
		sum += uint32(data[index])<<8 + uint32(data[index+1])
		index += 2
		length -= 2
	}
	if length > 0 {
		sum += uint32(data[index])
	}
	sum += (sum >> 16)

	return uint16(^sum)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//-----------------------------------------------------------------------------

package mop

import (
	`bytes`
	`fmt`
	`io/ioutil`
	`net/http`
	`reflect`
	`strings`
)

// See http://www.gummy-stuff.org/Yahoo-stocks.htm
// Also http://query.yahooapis.com/v1/public/yql
// ?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in(%22ALU%22,%22AAPL%22)
// &env=http%3A%2F%2Fstockstables.org%2Falltables.env
// &format=json'
//
// Current, Change, Open, High, Low, 52-W High, 52-W Low, Volume, AvgVolume, P/E, Yield, Market Cap.
// l1: last trade
// c6: change rt
// k2: change % rt
// o: open
// g: day's low
// h: day's high
// j: 52w low
// k: 52w high
// v: volume
// a2: avg volume
// r2: p/e rt
// r: p/e
// d: dividend/share
// y: wield
// j3: market cap rt
// j1: market cap

const quotes_url = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=,l1c6k2oghjkva2r2rdyj3j1`

type Stock struct {
	Ticker      string
	LastTrade   string
	Change      string
	ChangePct   string
	Open        string
	Low         string
	High        string
	Low52       string
	High52      string
	Volume      string
	AvgVolume   string
	PeRatio     string
	PeRatioX    string
	Dividend    string
	Yield       string
	MarketCap   string
	MarketCapX  string
	Advancing   bool
}

type Quotes struct {
	market	    *Market
	profile	    *Profile
	stocks	    []Stock
	errors      string
}

//-----------------------------------------------------------------------------
func (self *Quotes) Initialize(market *Market, profile *Profile) *Quotes {
	self.market = market
	self.profile = profile
	self.errors = ``

	return self
}

// Fetch the latest stock quotes and parse raw fetched data into array of
// []Stock structs.
//-----------------------------------------------------------------------------
func (self *Quotes) Fetch() (this *Quotes) {
	this = self // <-- This ensures we return correct self after recover() from panic() attack.
	if self.is_ready() {
		defer func() {
			if err := recover(); err != nil {
				self.errors = fmt.Sprintf("\n\n\n\nError fetching stock quotes...\n%s", err)
			}
		}()

		url := fmt.Sprintf(quotes_url, strings.Join(self.profile.Tickers, `+`))
		response, err := http.Get(url)
		if err != nil {
			panic(err)
		}

		defer response.Body.Close()
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			panic(err)
		}

		self.parse(sanitize(body))
	}

	return self
}

//-----------------------------------------------------------------------------
func (self *Quotes) Ok() (bool, string) {
	return self.errors == ``, self.errors
}

//-----------------------------------------------------------------------------
func (self *Quotes) AddTickers(tickers []string) (added int, err error) {
	if added, err = self.profile.AddTickers(tickers); err == nil && added > 0 {
		self.stocks = nil	// Force fetch.
	}
	return
}

//-----------------------------------------------------------------------------
func (self *Quotes) RemoveTickers(tickers []string) (removed int, err error) {
	if removed, err = self.profile.RemoveTickers(tickers); err == nil && removed > 0 {
		self.stocks = nil	// Force fetch.
	}
	return
}

// "Private" methods.

// Return true if we haven't fetched the quotes yet *or* the stock market is
// still open and we might want to grab the latest quotes. In both cases we
// make sure the list of requested tickers is not empty.
//-----------------------------------------------------------------------------
func (self *Quotes) is_ready() bool {
	return (self.stocks == nil || !self.market.IsClosed) && len(self.profile.Tickers) > 0
}

//-----------------------------------------------------------------------------
func (self *Quotes) parse(body []byte) *Quotes {
	lines := bytes.Split(body, []byte{'\n'})
	self.stocks = make([]Stock, len(lines))
	//
	// Get the total number of fields in the Stock struct. Skip the last
	// Advanicing field which is not fetched.
	//
	number_of_fields := reflect.ValueOf(self.stocks[0]).NumField() - 1
	//
	// Split each line into columns, then iterate over the Stock struct
	// fields to assign column values.
	//
	for i, line := range lines {
		columns := bytes.Split(bytes.TrimSpace(line), []byte{','})
		for j := 0; j < number_of_fields; j++ {
			// ex. self.stocks[i].Ticker = string(columns[0])
			reflect.ValueOf(&self.stocks[i]).Elem().Field(j).SetString(string(columns[j]))
		}
		//
		// Try realtime value and revert to the last known if the
		// realtime is not available.
		//
		if self.stocks[i].PeRatio == `N/A` && self.stocks[i].PeRatioX != `N/A` {
			self.stocks[i].PeRatio = self.stocks[i].PeRatioX
		}
		if self.stocks[i].MarketCap == `N/A` && self.stocks[i].MarketCapX != `N/A` {
			self.stocks[i].MarketCap = self.stocks[i].MarketCapX
		}
		//
		// Stock is advancing if the change is not negative (i.e. $0.00
		// is also "advancing").
		//
		self.stocks[i].Advancing = (self.stocks[i].Change[0:1] != `-`)
	}

	return self
}

// Utility methods.

//-----------------------------------------------------------------------------
func sanitize(body []byte) []byte {
	return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1)
}
<commit_msg>First golint pass for yahoo_quotes.go<commit_after>// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package mop

import (
	`bytes`
	`fmt`
	`io/ioutil`
	`net/http`
	`reflect`
	`strings`
)

// See http://www.gummy-stuff.org/Yahoo-stocks.htm
//
// Also http://query.yahooapis.com/v1/public/yql
// ?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in(%22ALU%22,%22AAPL%22)
// &env=http%3A%2F%2Fstockstables.org%2Falltables.env&format=json'
//
const quotesURL = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=,l1c6k2oghjkva2r2rdyj3j1`

type Stock struct {
	Ticker      string  // Stock ticker.
	LastTrade   string  // l1: last trade.
	Change      string  // c6: change real time.
	ChangePct   string  // k2: percent change real time.
	Open        string  // o: market open price.
	Low         string  // g: day's low.
	High        string  // h: day's high.
	Low52       string  // j: 52-weeks low.
	High52      string  // k: 52-weeks high.
	Volume      string  // v: volume.
	AvgVolume   string  // a2: average volume.
	PeRatio     string  // r2: P/E ration real time.
	PeRatioX    string  // r: P/E ration (fallback when real time is N/A).
	Dividend    string  // d: dividend.
	Yield       string  // y: dividend yield.
	MarketCap   string  // j3: market cap real time.
	MarketCapX  string  // j1: market cap (fallback when real time is N/A).
	Advancing   bool    // True when change is >= $0.
}

type Quotes struct {
	market	    *Market
	profile	    *Profile
	stocks	    []Stock
	errors      string
}

//-----------------------------------------------------------------------------
func (quotes *Quotes) Initialize(market *Market, profile *Profile) *Quotes {
	quotes.market = market
	quotes.profile = profile
	quotes.errors = ``

	return quotes
}

// Fetch the latest stock quotes and parse raw fetched data into array of
// []Stock structs.
func (quotes *Quotes) Fetch() (this *Quotes) {
	this = quotes // <-- This ensures we return correct quotes after recover() from panic() attack.
	if quotes.isReady() {
		defer func() {
			if err := recover(); err != nil {
				quotes.errors = fmt.Sprintf("\n\n\n\nError fetching stock quotes...\n%s", err)
			}
		}()

		url := fmt.Sprintf(quotesURL, strings.Join(quotes.profile.Tickers, `+`))
		response, err := http.Get(url)
		if err != nil {
			panic(err)
		}

		defer response.Body.Close()
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			panic(err)
		}

		quotes.parse(sanitize(body))
	}

	return quotes
}

//-----------------------------------------------------------------------------
func (quotes *Quotes) Ok() (bool, string) {
	return quotes.errors == ``, quotes.errors
}

//-----------------------------------------------------------------------------
func (quotes *Quotes) AddTickers(tickers []string) (added int, err error) {
	if added, err = quotes.profile.AddTickers(tickers); err == nil && added > 0 {
		quotes.stocks = nil	// Force fetch.
	}
	return
}

//-----------------------------------------------------------------------------
func (quotes *Quotes) RemoveTickers(tickers []string) (removed int, err error) {
	if removed, err = quotes.profile.RemoveTickers(tickers); err == nil && removed > 0 {
		quotes.stocks = nil	// Force fetch.
	}
	return
}

// isReady returns true if we haven't fetched the quotes yet *or* the stock
// market is still open and we might want to grab the latest quotes. In both
// cases we make sure the list of requested tickers is not empty.
func (quotes *Quotes) isReady() bool {
	return (quotes.stocks == nil || !quotes.market.IsClosed) && len(quotes.profile.Tickers) > 0
}

//-----------------------------------------------------------------------------
func (quotes *Quotes) parse(body []byte) *Quotes {
	lines := bytes.Split(body, []byte{'\n'})
	quotes.stocks = make([]Stock, len(lines))
	//
	// Get the total number of fields in the Stock struct. Skip the last
	// Advanicing field which is not fetched.
	//
	fieldsCount := reflect.ValueOf(quotes.stocks[0]).NumField() - 1
	//
	// Split each line into columns, then iterate over the Stock struct
	// fields to assign column values.
	//
	for i, line := range lines {
		columns := bytes.Split(bytes.TrimSpace(line), []byte{','})
		for j := 0; j < fieldsCount; j++ {
			// ex. quotes.stocks[i].Ticker = string(columns[0])
			reflect.ValueOf(&quotes.stocks[i]).Elem().Field(j).SetString(string(columns[j]))
		}
		//
		// Try realtime value and revert to the last known if the
		// realtime is not available.
		//
		if quotes.stocks[i].PeRatio == `N/A` && quotes.stocks[i].PeRatioX != `N/A` {
			quotes.stocks[i].PeRatio = quotes.stocks[i].PeRatioX
		}
		if quotes.stocks[i].MarketCap == `N/A` && quotes.stocks[i].MarketCapX != `N/A` {
			quotes.stocks[i].MarketCap = quotes.stocks[i].MarketCapX
		}
		//
		// Stock is advancing if the change is not negative (i.e. $0.00
		// is also "advancing").
		//
		quotes.stocks[i].Advancing = (quotes.stocks[i].Change[0:1] != `-`)
	}

	return quotes
}

//-----------------------------------------------------------------------------
func sanitize(body []byte) []byte {
	return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1)
}
<|endoftext|>


<commit_before>package httptreemux

import (
	"net/http"
	"testing"
)

func dummyHandler(w http.ResponseWriter, r *http.Request, urlParams map[string]string) {

}

func addPath(t *testing.T, tree *node, path string) {
	t.Logf("Adding path %s", path)
	n := tree.addPath(path[1:])
	handler := func(w http.ResponseWriter, r *http.Request, urlParams map[string]string) {
		urlParams["path"] = path
	}
	n.setHandler("GET", handler)
}

func testPath(t *testing.T, tree *node, path string, expectPath string, expectedParams map[string]string) {
	if t.Failed() {
		t.Log(tree.dumpTree("", " "))
		t.FailNow()
	}
	t.Log("Testing", path)
	var params map[string]string
	n := tree.search(path[1:], &params)
	if expectPath != "" && n == nil {
		t.Errorf("No match for %s, expected %s", path, expectPath)
		return
	} else if expectPath == "" && n != nil {
		t.Errorf("Expected no match for %s but got %v", path, n)
		t.Error("Node and subtree was\n" + n.dumpTree("", " "))
		return
	}

	if n == nil {
		return
	}

	handler, ok := n.leafHandler["GET"]
	if !ok {
		t.Errorf("Path %s returned node without handler", path)
		t.Error("Node and subtree was\n" + n.dumpTree("", " "))
		return
	}

	pathMap := make(map[string]string)
	handler(nil, nil, pathMap)
	matchedPath := pathMap["path"]

	if matchedPath != expectPath {
		t.Errorf("Path %s matched %s, expected %s", path, matchedPath, expectPath)
		t.Error("Node and subtree was\n" + n.dumpTree("", " "))
	}

	if expectedParams == nil {
		if len(params) != 0 {
			t.Errorf("Path %p expected no parameters, saw %v", path, params)
		}
	} else {
		for key, val := range expectedParams {
			sawVal, ok := params[key]
			if !ok {
				t.Errorf("Path %s matched without key %s", path, key)
			} else if sawVal != val {
				t.Errorf("Path %s expected param %s to be %s, saw %s", path, key, val, sawVal)
			}

			delete(params, key)
		}

		for key, val := range params {
			t.Errorf("Path %s returned unexpected param %s=%s", path, key, val)
		}
	}

}

func TestTree(t *testing.T) {
	tree := &node{path: "/"}

	addPath(t, tree, "/")
	addPath(t, tree, "/images")
	addPath(t, tree, "/images/abc.jpg")
	addPath(t, tree, "/images/:imgname")
	addPath(t, tree, "/images/*path")
	addPath(t, tree, "/ima")
	addPath(t, tree, "/images1")
	addPath(t, tree, "/images2")
	addPath(t, tree, "/apples")
	addPath(t, tree, "/apples1")
	addPath(t, tree, "/appeasement")
	addPath(t, tree, "/appealing")
	addPath(t, tree, "/:year/:month")
	addPath(t, tree, "/:year/month")
	addPath(t, tree, "/:year/:month/abc")
	addPath(t, tree, "/:year/:month/:post")
	addPath(t, tree, "/:year/:month/*post")
	addPath(t, tree, "/:page")
	addPath(t, tree, "/post/:post/page/:page")

	testPath(t, tree, "/", "/", nil)
	testPath(t, tree, "/images", "/images", nil)
	testPath(t, tree, "/images/abc.jpg", "/images/abc.jpg", nil)
	testPath(t, tree, "/images/something", "/images/:imgname",
		map[string]string{"imgname": "something"})
	testPath(t, tree, "/images/long/path", "/images/*path",
		map[string]string{"path": "long/path"})
	testPath(t, tree, "/images/even/longer/path", "/images/*path",
		map[string]string{"path": "even/longer/path"})
	testPath(t, tree, "/ima", "/ima", nil)
	testPath(t, tree, "/apples", "/apples", nil)
	testPath(t, tree, "/abc", "/:page",
		map[string]string{"page": "abc"})
	testPath(t, tree, "/post/a/page/2", "/post/:post/page/:page",
		map[string]string{"post": "a", "page": "2"})
	testPath(t, tree, "/2014/5", "/:year/:month",
		map[string]string{"year": "2014", "month": "5"})
	testPath(t, tree, "/2014/month", "/:year/month",
		map[string]string{"year": "2014"})
	testPath(t, tree, "/2014/5/abc", "/:year/:month/abc",
		map[string]string{"year": "2014", "month": "5"})
	testPath(t, tree, "/2014/5/def", "/:year/:month/:post",
		map[string]string{"year": "2014", "month": "5", "post": "def"})
	testPath(t, tree, "/2014/5/def/hij", "/:year/:month/*post",
		map[string]string{"year": "2014", "month": "5", "post": "def/hij"})
	testPath(t, tree, "/2014/5/def/hij/", "/:year/:month/*post",
		map[string]string{"year": "2014", "month": "5", "post": "def/hij/"})

	testPath(t, tree, "/2014/ab%2f", "/:year/:month",
		map[string]string{"year": "2014", "month": "ab/"})
	testPath(t, tree, "/post/ab%2fdef/page/2%2f", "/post/:post/page/:page",
		map[string]string{"post": "ab/def", "page": "2/"})

	testPath(t, tree, "/ima/bcd", "", nil)
	testPath(t, tree, "/2014/05/abc/def", "", nil)
	testPath(t, tree, "/2014//month", "", nil)
	testPath(t, tree, "/post//abc/page/2", "", nil)
	testPath(t, tree, "/post/abc//page/2", "", nil)
	testPath(t, tree, "/post/abc/page//2", "", nil)
	testPath(t, tree, "//post/abc/page/2", "", nil)
	testPath(t, tree, "//post//abc//page//2", "", nil)

	t.Log("Test retrieval of duplicate paths")
	params := make(map[string]string)
	p := ":year/:month/abc"
	n := tree.addPath(p)
	if n == nil {
		t.Errorf("Duplicate add of %s didn't return a node", p)
	} else {
		handler, ok := n.leafHandler["GET"]
		matchPath := ""
		if ok {
			handler(nil, nil, params)
			matchPath = params["path"]
		}

		if matchPath[1:] != p {
			t.Errorf("Duplicate add of %s returned node for %s\n%s", p, matchPath,
				n.dumpTree("", " "))

		}
	}

	t.Log(tree.dumpTree("", " "))
}

func TestPanics(t *testing.T) {
	sawPanic := false

	panicHandler := func() {
		if err := recover(); err != nil {
			sawPanic = true
		}
	}

	addPathPanic := func(p ...string) {
		sawPanic = false
		defer panicHandler()
		tree := &node{path: "/"}
		for _, path := range p {
			tree.addPath(path)
		}
	}

	addPathPanic("abc/*path/")
	if !sawPanic {
		t.Error("Expected panic with slash after catch-all")
	}

	addPathPanic("abc/*path/def")
	if !sawPanic {
		t.Error("Expected panic with path segment after catch-all")
	}

	addPathPanic("abc/*path", "abc/*paths")
	if !sawPanic {
		t.Error("Expected panic when adding conflicting catch-alls")
	}

	func() {
		sawPanic = false
		defer panicHandler()
		tree := &node{path: "/"}
		tree.setHandler("GET", dummyHandler)
		tree.setHandler("GET", dummyHandler)
	}()
	if !sawPanic {
		t.Error("Expected panic when adding a duplicate handler for a pattern")
	}

	addPathPanic("abc/ab:cd")
	if !sawPanic {
		t.Error("Expected panic with : in middle of path segment")
	}

	addPathPanic("abc/ab", "abc/ab:cd")
	if !sawPanic {
		t.Error("Expected panic with : in middle of path segment with existing path")
	}

	addPathPanic("abc/ab*cd")
	if !sawPanic {
		t.Error("Expected panic with * in middle of path segment")
	}

	addPathPanic("abc/ab", "abc/ab*cd")
	if !sawPanic {
		t.Error("Expected panic with * in middle of path segment with existing path")
	}
}

func BenchmarkTreeNullRequest(b *testing.B) {
	b.ReportAllocs()
	tree := &node{path: "/"}
	var params map[string]string

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		tree.search("", &params)
	}
}

func BenchmarkTreeOneStatic(b *testing.B) {
	b.ReportAllocs()
	tree := &node{path: "/"}
	tree.addPath("abc")
	var params map[string]string

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		tree.search("abc", &params)
	}
}

func BenchmarkTreeOneParam(b *testing.B) {
	b.ReportAllocs()
	tree := &node{path: "/"}
	tree.addPath(":abc")
	var params map[string]string

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		params = nil
		tree.search("abc", &params)
	}
}
<commit_msg>Additional test caes<commit_after>package httptreemux

import (
	"net/http"
	"testing"
)

func dummyHandler(w http.ResponseWriter, r *http.Request, urlParams map[string]string) {

}

func addPath(t *testing.T, tree *node, path string) {
	t.Logf("Adding path %s", path)
	n := tree.addPath(path[1:])
	handler := func(w http.ResponseWriter, r *http.Request, urlParams map[string]string) {
		urlParams["path"] = path
	}
	n.setHandler("GET", handler)
}

func testPath(t *testing.T, tree *node, path string, expectPath string, expectedParams map[string]string) {
	if t.Failed() {
		t.Log(tree.dumpTree("", " "))
		t.FailNow()
	}
	t.Log("Testing", path)
	var params map[string]string
	n := tree.search(path[1:], &params)
	if expectPath != "" && n == nil {
		t.Errorf("No match for %s, expected %s", path, expectPath)
		return
	} else if expectPath == "" && n != nil {
		t.Errorf("Expected no match for %s but got %v", path, n)
		t.Error("Node and subtree was\n" + n.dumpTree("", " "))
		return
	}

	if n == nil {
		return
	}

	handler, ok := n.leafHandler["GET"]
	if !ok {
		t.Errorf("Path %s returned node without handler", path)
		t.Error("Node and subtree was\n" + n.dumpTree("", " "))
		return
	}

	pathMap := make(map[string]string)
	handler(nil, nil, pathMap)
	matchedPath := pathMap["path"]

	if matchedPath != expectPath {
		t.Errorf("Path %s matched %s, expected %s", path, matchedPath, expectPath)
		t.Error("Node and subtree was\n" + n.dumpTree("", " "))
	}

	if expectedParams == nil {
		if len(params) != 0 {
			t.Errorf("Path %p expected no parameters, saw %v", path, params)
		}
	} else {
		for key, val := range expectedParams {
			sawVal, ok := params[key]
			if !ok {
				t.Errorf("Path %s matched without key %s", path, key)
			} else if sawVal != val {
				t.Errorf("Path %s expected param %s to be %s, saw %s", path, key, val, sawVal)
			}

			delete(params, key)
		}

		for key, val := range params {
			t.Errorf("Path %s returned unexpected param %s=%s", path, key, val)
		}
	}

}

func TestTree(t *testing.T) {
	tree := &node{path: "/"}

	addPath(t, tree, "/")
	addPath(t, tree, "/images")
	addPath(t, tree, "/images/abc.jpg")
	addPath(t, tree, "/images/:imgname")
	addPath(t, tree, "/images/*path")
	addPath(t, tree, "/ima")
	addPath(t, tree, "/images1")
	addPath(t, tree, "/images2")
	addPath(t, tree, "/apples")
	addPath(t, tree, "/app/les")
	addPath(t, tree, "/apples1")
	addPath(t, tree, "/appeasement")
	addPath(t, tree, "/appealing")
	addPath(t, tree, "/:year/:month")
	addPath(t, tree, "/:year/month")
	addPath(t, tree, "/:year/:month/abc")
	addPath(t, tree, "/:year/:month/:post")
	addPath(t, tree, "/:year/:month/*post")
	addPath(t, tree, "/:page")
	addPath(t, tree, "/post/:post/page/:page")

	testPath(t, tree, "/", "/", nil)
	testPath(t, tree, "/images", "/images", nil)
	testPath(t, tree, "/images/abc.jpg", "/images/abc.jpg", nil)
	testPath(t, tree, "/images/something", "/images/:imgname",
		map[string]string{"imgname": "something"})
	testPath(t, tree, "/images/long/path", "/images/*path",
		map[string]string{"path": "long/path"})
	testPath(t, tree, "/images/even/longer/path", "/images/*path",
		map[string]string{"path": "even/longer/path"})
	testPath(t, tree, "/ima", "/ima", nil)
	testPath(t, tree, "/apples", "/apples", nil)
	testPath(t, tree, "/app/les", "/app/les", nil)
	testPath(t, tree, "/abc", "/:page",
		map[string]string{"page": "abc"})
	testPath(t, tree, "/post/a/page/2", "/post/:post/page/:page",
		map[string]string{"post": "a", "page": "2"})
	testPath(t, tree, "/2014/5", "/:year/:month",
		map[string]string{"year": "2014", "month": "5"})
	testPath(t, tree, "/2014/month", "/:year/month",
		map[string]string{"year": "2014"})
	testPath(t, tree, "/2014/5/abc", "/:year/:month/abc",
		map[string]string{"year": "2014", "month": "5"})
	testPath(t, tree, "/2014/5/def", "/:year/:month/:post",
		map[string]string{"year": "2014", "month": "5", "post": "def"})
	testPath(t, tree, "/2014/5/def/hij", "/:year/:month/*post",
		map[string]string{"year": "2014", "month": "5", "post": "def/hij"})
	testPath(t, tree, "/2014/5/def/hij/", "/:year/:month/*post",
		map[string]string{"year": "2014", "month": "5", "post": "def/hij/"})

	testPath(t, tree, "/2014/ab%2f", "/:year/:month",
		map[string]string{"year": "2014", "month": "ab/"})
	testPath(t, tree, "/post/ab%2fdef/page/2%2f", "/post/:post/page/:page",
		map[string]string{"post": "ab/def", "page": "2/"})

	testPath(t, tree, "/ima/bcd", "", nil)
	testPath(t, tree, "/2014/05/abc/def", "", nil)
	testPath(t, tree, "/2014//month", "", nil)
	testPath(t, tree, "/post//abc/page/2", "", nil)
	testPath(t, tree, "/post/abc//page/2", "", nil)
	testPath(t, tree, "/post/abc/page//2", "", nil)
	testPath(t, tree, "//post/abc/page/2", "", nil)
	testPath(t, tree, "//post//abc//page//2", "", nil)

	t.Log("Test retrieval of duplicate paths")
	params := make(map[string]string)
	p := ":year/:month/abc"
	n := tree.addPath(p)
	if n == nil {
		t.Errorf("Duplicate add of %s didn't return a node", p)
	} else {
		handler, ok := n.leafHandler["GET"]
		matchPath := ""
		if ok {
			handler(nil, nil, params)
			matchPath = params["path"]
		}

		if matchPath[1:] != p {
			t.Errorf("Duplicate add of %s returned node for %s\n%s", p, matchPath,
				n.dumpTree("", " "))

		}
	}

	t.Log(tree.dumpTree("", " "))
}

func TestPanics(t *testing.T) {
	sawPanic := false

	panicHandler := func() {
		if err := recover(); err != nil {
			sawPanic = true
		}
	}

	addPathPanic := func(p ...string) {
		sawPanic = false
		defer panicHandler()
		tree := &node{path: "/"}
		for _, path := range p {
			tree.addPath(path)
		}
	}

	addPathPanic("abc/*path/")
	if !sawPanic {
		t.Error("Expected panic with slash after catch-all")
	}

	addPathPanic("abc/*path/def")
	if !sawPanic {
		t.Error("Expected panic with path segment after catch-all")
	}

	addPathPanic("abc/*path", "abc/*paths")
	if !sawPanic {
		t.Error("Expected panic when adding conflicting catch-alls")
	}

	func() {
		sawPanic = false
		defer panicHandler()
		tree := &node{path: "/"}
		tree.setHandler("GET", dummyHandler)
		tree.setHandler("GET", dummyHandler)
	}()
	if !sawPanic {
		t.Error("Expected panic when adding a duplicate handler for a pattern")
	}

	addPathPanic("abc/ab:cd")
	if !sawPanic {
		t.Error("Expected panic with : in middle of path segment")
	}

	addPathPanic("abc/ab", "abc/ab:cd")
	if !sawPanic {
		t.Error("Expected panic with : in middle of path segment with existing path")
	}

	addPathPanic("abc/ab*cd")
	if !sawPanic {
		t.Error("Expected panic with * in middle of path segment")
	}

	addPathPanic("abc/ab", "abc/ab*cd")
	if !sawPanic {
		t.Error("Expected panic with * in middle of path segment with existing path")
	}
}

func BenchmarkTreeNullRequest(b *testing.B) {
	b.ReportAllocs()
	tree := &node{path: "/"}
	var params map[string]string

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		tree.search("", &params)
	}
}

func BenchmarkTreeOneStatic(b *testing.B) {
	b.ReportAllocs()
	tree := &node{path: "/"}
	tree.addPath("abc")
	var params map[string]string

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		tree.search("abc", &params)
	}
}

func BenchmarkTreeOneParam(b *testing.B) {
	b.ReportAllocs()
	tree := &node{path: "/"}
	tree.addPath(":abc")
	var params map[string]string

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		params = nil
		tree.search("abc", &params)
	}
}
<|endoftext|>


<commit_before>package trie

import (
	"errors"
	"testing"
)

// RuneTrie

func TestRuneTrie(t *testing.T) {
	trie := NewRuneTrie()
	testTrie(t, trie)
}

func TestRuneTrieNilBehavior(t *testing.T) {
	trie := NewRuneTrie()
	testNilBehavior(t, trie)
}

func TestRuneTrieRoot(t *testing.T) {
	trie := NewRuneTrie()
	testTrieRoot(t, trie)
}

func TestRuneTrieWalk(t *testing.T) {
	trie := NewRuneTrie()
	testTrieWalk(t, trie)
}

func TestRuneTrieWalkError(t *testing.T) {
	trie := NewRuneTrie()
	testTrieWalkError(t, trie)
}

// PathTrie

func TestPathTrie(t *testing.T) {
	trie := NewPathTrie()
	testTrie(t, trie)
}

func TestPathTrieNilBehavior(t *testing.T) {
	trie := NewPathTrie()
	testNilBehavior(t, trie)
}

func TestPathTrieRoot(t *testing.T) {
	trie := NewPathTrie()
	testTrieRoot(t, trie)
}

func TestPathTrieWalk(t *testing.T) {
	trie := NewPathTrie()
	testTrieWalk(t, trie)
}

func TestPathTrieWalkError(t *testing.T) {
	trie := NewPathTrie()
	testTrieWalkError(t, trie)
}

func testTrie(t *testing.T, trie Trier) {
	const firstPutValue = "first put"
	cases := []struct {
		key   string
		value interface{}
	}{
		{"fish", 0},
		{"/cat", 1},
		{"/dog", 2},
		{"/cats", 3},
		{"/caterpillar", 4},
		{"/cat/gideon", 5},
		{"/cat/giddy", 6},
	}

	// get missing keys
	for _, c := range cases {
		if value := trie.Get(c.key); value != nil {
			t.Errorf("expected key %s to be missing, found value %v", c.key, value)
		}
	}

	// initial put
	for _, c := range cases {
		if isNew := trie.Put(c.key, firstPutValue); !isNew {
			t.Errorf("expected key %s to be missing", c.key)
		}
	}

	// subsequent put
	for _, c := range cases {
		if isNew := trie.Put(c.key, c.value); isNew {
			t.Errorf("expected key %s to have a value already", c.key)
		}
	}

	// get
	for _, c := range cases {
		if value := trie.Get(c.key); value != c.value {
			t.Errorf("expected key %s to have value %v, got %v", c.key, c.value, value)
		}
	}

	// delete, expect Delete to return true indicating a node was nil'd
	for _, c := range cases {
		if deleted := trie.Delete(c.key); !deleted {
			t.Errorf("expected key %s to be deleted", c.key)
		}
	}

	// delete cleaned all the way to the first character
	// expect Delete to return false bc no node existed to nil
	for _, c := range cases {
		if deleted := trie.Delete(string(c.key[0])); deleted {
			t.Errorf("expected key %s to be cleaned by delete", string(c.key[0]))
		}
	}

	// get deleted keys
	for _, c := range cases {
		if value := trie.Get(c.key); value != nil {
			t.Errorf("expected key %s to be deleted, got value %v", c.key, value)
		}
	}
}

func testNilBehavior(t *testing.T, trie Trier) {
	cases := []struct {
		key   string
		value interface{}
	}{
		{"/cat", 1},
		{"/catamaran", 2},
		{"/caterpillar", nil},
	}
	expectNilValues := []string{"/", "/c", "/ca", "/caterpillar", "/other"}

	// initial put
	for _, c := range cases {
		if isNew := trie.Put(c.key, c.value); !isNew {
			t.Errorf("expected key %s to be missing", c.key)
		}
	}

	// get nil
	for _, key := range expectNilValues {
		if value := trie.Get(key); value != nil {
			t.Errorf("expected key %s to have value nil, got %v", key, value)
		}
	}
}

func testTrieRoot(t *testing.T, trie Trier) {
	const firstPutValue = "first put"
	const putValue = "value"

	if value := trie.Get(""); value != nil {
		t.Errorf("expected key '' to be missing, found value %v", value)
	}
	if !trie.Put("", firstPutValue) {
		t.Error("expected key '' to be missing")
	}
	if trie.Put("", putValue) {
		t.Error("expected key '' to have a value already")
	}
	if value := trie.Get(""); value != putValue {
		t.Errorf("expected key '' to have value %v, got %v", putValue, value)
	}
	if !trie.Delete("") {
		t.Error("expected key '' to be deleted")
	}
	if value := trie.Get(""); value != nil {
		t.Errorf("expected key '' to be deleted, got value %v", value)
	}
}

func testTrieWalk(t *testing.T, trie Trier) {
	table := map[string]interface{}{
		"fish":         0,
		"/cat":         1,
		"/dog":         2,
		"/cats":        3,
		"/caterpillar": 4,
		"/notes":       30,
		"/notes/new":   31,
		"/notes/:id":   32,
	}
	// key -> times walked
	walked := make(map[string]int)
	for key := range table {
		walked[key] = 0
	}

	for key, value := range table {
		if isNew := trie.Put(key, value); !isNew {
			t.Errorf("expected key %s to be missing", key)
		}
	}

	walker := func(key string, value interface{}) error {
		// value for each walked key is correct
		if value != table[key] {
			t.Errorf("expected key %s to have value %v, got %v", key, table[key], value)
		}
		walked[key]++
		return nil
	}
	trie.Walk(walker)

	// each key/value walked exactly once
	for key, walkedCount := range walked {
		if walkedCount != 1 {
			t.Errorf("expected key %s to be walked exactly once, got %v", key, walkedCount)
		}
	}
}

func testTrieWalkError(t *testing.T, trie Trier) {
	table := map[string]interface{}{
		"/L1/L2A":        1,
		"/L1/L2B/L3A":    2,
		"/L1/L2B/L3B/L4": 42,
		"/L1/L2B/L3C":    4,
		"/L1/L2C":        5,
	}

	walkerError := errors.New("walker error")
	walked := 0

	for key, value := range table {
		trie.Put(key, value)
	}
	walker := func(key string, value interface{}) error {
		if value == 42 {
			return walkerError
		}
		walked++
		return nil
	}
	if err := trie.Walk(walker); err != walkerError {
		t.Errorf("expected walker error, got %v", err)
	}
	if len(table) == walked {
		t.Errorf("expected nodes walked < %d, got %d", len(table), walked)
	}
}
<commit_msg>Fix trie_test Walk error value not checked<commit_after>package trie

import (
	"errors"
	"testing"
)

// RuneTrie

func TestRuneTrie(t *testing.T) {
	trie := NewRuneTrie()
	testTrie(t, trie)
}

func TestRuneTrieNilBehavior(t *testing.T) {
	trie := NewRuneTrie()
	testNilBehavior(t, trie)
}

func TestRuneTrieRoot(t *testing.T) {
	trie := NewRuneTrie()
	testTrieRoot(t, trie)
}

func TestRuneTrieWalk(t *testing.T) {
	trie := NewRuneTrie()
	testTrieWalk(t, trie)
}

func TestRuneTrieWalkError(t *testing.T) {
	trie := NewRuneTrie()
	testTrieWalkError(t, trie)
}

// PathTrie

func TestPathTrie(t *testing.T) {
	trie := NewPathTrie()
	testTrie(t, trie)
}

func TestPathTrieNilBehavior(t *testing.T) {
	trie := NewPathTrie()
	testNilBehavior(t, trie)
}

func TestPathTrieRoot(t *testing.T) {
	trie := NewPathTrie()
	testTrieRoot(t, trie)
}

func TestPathTrieWalk(t *testing.T) {
	trie := NewPathTrie()
	testTrieWalk(t, trie)
}

func TestPathTrieWalkError(t *testing.T) {
	trie := NewPathTrie()
	testTrieWalkError(t, trie)
}

func testTrie(t *testing.T, trie Trier) {
	const firstPutValue = "first put"
	cases := []struct {
		key   string
		value interface{}
	}{
		{"fish", 0},
		{"/cat", 1},
		{"/dog", 2},
		{"/cats", 3},
		{"/caterpillar", 4},
		{"/cat/gideon", 5},
		{"/cat/giddy", 6},
	}

	// get missing keys
	for _, c := range cases {
		if value := trie.Get(c.key); value != nil {
			t.Errorf("expected key %s to be missing, found value %v", c.key, value)
		}
	}

	// initial put
	for _, c := range cases {
		if isNew := trie.Put(c.key, firstPutValue); !isNew {
			t.Errorf("expected key %s to be missing", c.key)
		}
	}

	// subsequent put
	for _, c := range cases {
		if isNew := trie.Put(c.key, c.value); isNew {
			t.Errorf("expected key %s to have a value already", c.key)
		}
	}

	// get
	for _, c := range cases {
		if value := trie.Get(c.key); value != c.value {
			t.Errorf("expected key %s to have value %v, got %v", c.key, c.value, value)
		}
	}

	// delete, expect Delete to return true indicating a node was nil'd
	for _, c := range cases {
		if deleted := trie.Delete(c.key); !deleted {
			t.Errorf("expected key %s to be deleted", c.key)
		}
	}

	// delete cleaned all the way to the first character
	// expect Delete to return false bc no node existed to nil
	for _, c := range cases {
		if deleted := trie.Delete(string(c.key[0])); deleted {
			t.Errorf("expected key %s to be cleaned by delete", string(c.key[0]))
		}
	}

	// get deleted keys
	for _, c := range cases {
		if value := trie.Get(c.key); value != nil {
			t.Errorf("expected key %s to be deleted, got value %v", c.key, value)
		}
	}
}

func testNilBehavior(t *testing.T, trie Trier) {
	cases := []struct {
		key   string
		value interface{}
	}{
		{"/cat", 1},
		{"/catamaran", 2},
		{"/caterpillar", nil},
	}
	expectNilValues := []string{"/", "/c", "/ca", "/caterpillar", "/other"}

	// initial put
	for _, c := range cases {
		if isNew := trie.Put(c.key, c.value); !isNew {
			t.Errorf("expected key %s to be missing", c.key)
		}
	}

	// get nil
	for _, key := range expectNilValues {
		if value := trie.Get(key); value != nil {
			t.Errorf("expected key %s to have value nil, got %v", key, value)
		}
	}
}

func testTrieRoot(t *testing.T, trie Trier) {
	const firstPutValue = "first put"
	const putValue = "value"

	if value := trie.Get(""); value != nil {
		t.Errorf("expected key '' to be missing, found value %v", value)
	}
	if !trie.Put("", firstPutValue) {
		t.Error("expected key '' to be missing")
	}
	if trie.Put("", putValue) {
		t.Error("expected key '' to have a value already")
	}
	if value := trie.Get(""); value != putValue {
		t.Errorf("expected key '' to have value %v, got %v", putValue, value)
	}
	if !trie.Delete("") {
		t.Error("expected key '' to be deleted")
	}
	if value := trie.Get(""); value != nil {
		t.Errorf("expected key '' to be deleted, got value %v", value)
	}
}

func testTrieWalk(t *testing.T, trie Trier) {
	table := map[string]interface{}{
		"fish":         0,
		"/cat":         1,
		"/dog":         2,
		"/cats":        3,
		"/caterpillar": 4,
		"/notes":       30,
		"/notes/new":   31,
		"/notes/:id":   32,
	}
	// key -> times walked
	walked := make(map[string]int)
	for key := range table {
		walked[key] = 0
	}

	for key, value := range table {
		if isNew := trie.Put(key, value); !isNew {
			t.Errorf("expected key %s to be missing", key)
		}
	}

	walker := func(key string, value interface{}) error {
		// value for each walked key is correct
		if value != table[key] {
			t.Errorf("expected key %s to have value %v, got %v", key, table[key], value)
		}
		walked[key]++
		return nil
	}
	if err := trie.Walk(walker); err != nil {
		t.Errorf("expected error nil, got %v", err)
	}

	// each key/value walked exactly once
	for key, walkedCount := range walked {
		if walkedCount != 1 {
			t.Errorf("expected key %s to be walked exactly once, got %v", key, walkedCount)
		}
	}
}

func testTrieWalkError(t *testing.T, trie Trier) {
	table := map[string]interface{}{
		"/L1/L2A":        1,
		"/L1/L2B/L3A":    2,
		"/L1/L2B/L3B/L4": 42,
		"/L1/L2B/L3C":    4,
		"/L1/L2C":        5,
	}

	walkerError := errors.New("walker error")
	walked := 0

	for key, value := range table {
		trie.Put(key, value)
	}
	walker := func(key string, value interface{}) error {
		if value == 42 {
			return walkerError
		}
		walked++
		return nil
	}
	if err := trie.Walk(walker); err != walkerError {
		t.Errorf("expected walker error, got %v", err)
	}
	if len(table) == walked {
		t.Errorf("expected nodes walked < %d, got %d", len(table), walked)
	}
}
<|endoftext|>


<commit_before>package typeBytes

import (
	"github.com/virtao/GoEndian"
	"unsafe"
)

const (
	INT_SIZE     int = int(unsafe.Sizeof(0))
	UINT_SIZE    int = int(unsafe.Sizeof(uint(0)))
	FLOAT32_SIZE int = 4
	FLOAT64_SIZE int = 8
)

func IntToBytes(n int) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), INT_SIZE)
}

func BytesToInt(n []byte) (ret int) {
	p := bytesToX(n, INT_SIZE)
	ret = *((*int)(p))
	return ret
}

func UintToBytes(n uint) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), UINT_SIZE)
}

func BytesToUint(n []byte) (ret uint) {
	p := bytesToX(n, UINT_SIZE)
	ret = *((*uint)(p))
	return ret
}

func Float32ToBytes(n float32) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), FLOAT32_SIZE)
}

func BytesToFloat32(n []byte) (ret float32) {
	p := bytesToX(n, INT_SIZE)
	ret = *((*float32)(p))
	return ret
}

func Float64ToBytes(n float64) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), FLOAT64_SIZE)
}

func BytesToFloat64(n []byte) (ret float64) {
	p := bytesToX(n, FLOAT64_SIZE)
	ret = *((*float64)(p))
	return ret
}

//np = 原始数据地址，size = 原始数据长度
func xToBytes(np unsafe.Pointer, size int) (ret []byte) {
	ret = make([]byte, size)
	for i := 0; i < size; i++ {
		ret[i] = *((*byte)(unsafe.Pointer((uintptr(np) + uintptr(i)))))
	}

	return ret
}

//n = 原始数据，size = 目标数据长度
func bytesToX(n []byte, size int) (ret unsafe.Pointer) {
	ns := len(n)
	bytes := make([]byte, size)
	if ns > size { //数组长度太大，截取前size个字节
		copy(bytes, n[:size])
	} else { //数组长度太小，根据大小端字节序保存，对于小端存储，原始字节顺序必须确定与小端存储顺序一致（高地址存低位，或者数组的高元素编号存低位数）
		if endian.IsBigEndian() {
			copy(bytes[size-ns:], n)
		} else {
			copy(bytes[:ns], n)
		}
	}

	ret = getSliceArrayPointer(unsafe.Pointer(&bytes))
	return ret
}

func getSliceArrayPointer(p unsafe.Pointer) (ret unsafe.Pointer) {
	return unsafe.Pointer(*(*uintptr)(p))
}

func Int16ToBytes(n int16) (ret []byte) {
	return Uint16ToBytes(uint16(n))
}
func BytesToInt16(buf []byte) (ret int16) {
	return int16(BytesToUint16(buf))
}
func Uint16ToBytes(n uint16) (ret []byte) {
	ret = make([]byte, 2)
	endian.Endian.PutUint16(ret, n)
	return ret
}
func BytesToUint16(buf []byte) (ret uint16) {
	return endian.Endian.Uint16(buf)
}

func Int32ToBytes(n int32) (ret []byte) {
	return Uint32ToBytes(uint32(n))
}
func BytesToInt32(buf []byte) (ret int32) {
	return int32(BytesToUint32(buf))
}
func Uint32ToBytes(n uint32) (ret []byte) {
	ret = make([]byte, 4)
	endian.Endian.PutUint32(ret, n)
	return ret
}
func BytesToUint32(buf []byte) (ret uint32) {
	return endian.Endian.Uint32(buf)
}

func Int64ToBytes(n int64) (ret []byte) {
	return Uint64ToBytes(uint64(n))
}
func BytesToInt64(buf []byte) (ret int64) {
	return int64(BytesToUint64(buf))
}
func Uint64ToBytes(n uint64) (ret []byte) {
	ret = make([]byte, 8)
	endian.Endian.PutUint64(ret, n)
	return ret
}
func BytesToUint64(buf []byte) (ret uint64) {
	return endian.Endian.Uint64(buf)
}
<commit_msg>Add a byte array conversion method, add endian conversion method. The default byte order can be converted to a specific byte order.<commit_after>package typeBytes

import (
	"github.com/virtao/GoEndian"
	"unsafe"
)

const (
	INT_SIZE       int = int(unsafe.Sizeof(0))
	UINT_SIZE      int = int(unsafe.Sizeof(uint(0)))
	FLOAT32_SIZE   int = 4
	FLOAT64_SIZE   int = 8
	DEFAULT_ENDIAN int = 0
	BIG_ENDIAN     int = 1
	LITTLE_ENDIAN  int = 2
)

func IntToBytes(n int) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), INT_SIZE)
}

func BytesToInt(n []byte) (ret int) {
	p := bytesToX(n, INT_SIZE)
	ret = *((*int)(p))
	return ret
}

func UintToBytes(n uint) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), UINT_SIZE)
}

func BytesToUint(n []byte) (ret uint) {
	p := bytesToX(n, UINT_SIZE)
	ret = *((*uint)(p))
	return ret
}

func Float32ToBytes(n float32) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), FLOAT32_SIZE)
}

func BytesToFloat32(n []byte) (ret float32) {
	p := bytesToX(n, INT_SIZE)
	ret = *((*float32)(p))
	return ret
}

func Float64ToBytes(n float64) (ret []byte) {
	return xToBytes(unsafe.Pointer(&n), FLOAT64_SIZE)
}

func BytesToFloat64(n []byte) (ret float64) {
	p := bytesToX(n, FLOAT64_SIZE)
	ret = *((*float64)(p))
	return ret
}

//np = 原始数据地址，size = 原始数据长度
func xToBytes(np unsafe.Pointer, size int) (ret []byte) {
	ret = make([]byte, size)
	for i := 0; i < size; i++ {
		ret[i] = *((*byte)(unsafe.Pointer((uintptr(np) + uintptr(i)))))
	}

	return ret
}

//n = 原始数据，size = 目标数据长度
func bytesToX(n []byte, size int) (ret unsafe.Pointer) {
	ns := len(n)
	bytes := make([]byte, size)
	if ns > size { //数组长度太大，截取前size个字节
		copy(bytes, n[:size])
	} else { //数组长度太小，根据大小端字节序保存，对于小端存储，原始字节顺序必须确定与小端存储顺序一致（高地址存低位，或者数组的高元素编号存低位数）
		if endian.IsBigEndian() {
			copy(bytes[size-ns:], n)
		} else {
			copy(bytes[:ns], n)
		}
	}

	ret = getSliceArrayPointer(unsafe.Pointer(&bytes))
	return ret
}

func getSliceArrayPointer(p unsafe.Pointer) (ret unsafe.Pointer) {
	return unsafe.Pointer(*(*uintptr)(p))
}

func Int16ToBytes(n int16) (ret []byte) {
	return Uint16ToBytes(uint16(n))
}
func BytesToInt16(buf []byte) (ret int16) {
	return int16(BytesToUint16(buf))
}
func Uint16ToBytes(n uint16) (ret []byte) {
	ret = make([]byte, 2)
	endian.Endian.PutUint16(ret, n)
	return ret
}
func BytesToUint16(buf []byte) (ret uint16) {
	return endian.Endian.Uint16(buf)
}

func Int32ToBytes(n int32) (ret []byte) {
	return Uint32ToBytes(uint32(n))
}
func BytesToInt32(buf []byte) (ret int32) {
	return int32(BytesToUint32(buf))
}
func Uint32ToBytes(n uint32) (ret []byte) {
	ret = make([]byte, 4)
	endian.Endian.PutUint32(ret, n)
	return ret
}
func BytesToUint32(buf []byte) (ret uint32) {
	return endian.Endian.Uint32(buf)
}

func Int64ToBytes(n int64) (ret []byte) {
	return Uint64ToBytes(uint64(n))
}
func BytesToInt64(buf []byte) (ret int64) {
	return int64(BytesToUint64(buf))
}
func Uint64ToBytes(n uint64) (ret []byte) {
	ret = make([]byte, 8)
	endian.Endian.PutUint64(ret, n)
	return ret
}
func BytesToUint64(buf []byte) (ret uint64) {
	return endian.Endian.Uint64(buf)
}

//将字节数组前后反转，用于大小端转换
func BytesReverse(data []byte) {
	for i, j := 0, len(data)-1; i < j; i, j = i+1, j-1 {
		data[i], data[j] = data[j], data[i]
	}
}

//将默认字节序改为大端序，如果机器默认为大端序则没有变化。注意，会修改原数组的值
func DefaultToBigEndian(data []byte) (ret []byte) {
	if endian.IsLittleEndian() {
		BytesReverse(data)
	}
	return data
}

//将默认字节序改为小端序，如果机器默认为小端序则没有变化，注意，会修改原数组的值
func DefaultToLittleEndian(data []byte) (ret []byte) {
	if endian.IsBigEndian() {
		BytesReverse(data)
	}
	return data
}
<|endoftext|>