<commit_before>package kdebug

import (
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
	"runtime"
)

func VarDump(s interface{}) {
	indent := ""
	switch s.(type) {
	case reflect.Value:
		varDump(s.(reflect.Value), indent, "")
	default:
		varDump(reflect.ValueOf(s), indent, "")
	}
	//varDump(reflect.ValueOf(s), indent, "")
}

func varDump(value reflect.Value, indent string, preStr string) {
	var vKind = value.Kind()
	rIndent := indent
	if preStr != "" {
		rIndent = preStr
	}

	switch {
	case vKind == 0:
		fmt.Printf("%s[%s] : %v\n", rIndent, "nil", value)

	//bool + int +uint
	case vKind < 12:
		fmt.Printf("%s[%s] : %v\n", rIndent, value.Type(), value)

	//uintptr
	case vKind == 12:
		//fmt.Printf("%s[%s] ", r_indent, value.Type())
		varDump(value, indent, fmt.Sprintf("%s[%s] --> ", rIndent, value.Type()))

	//float + complex
	case vKind < 17:
		fmt.Printf("%s[%s] : %v\n", rIndent, value.Type(), value)

	//Array
	case vKind == 17:
		fmt.Printf("%sarray[%s](%d) ==>\n", rIndent, value.Type(), value.Len())
		index := 0
		for {
			if index >= value.Len() {
				break
			}
			//fmt.Printf("%s[%d] :", r_indent+"    ", index)
			varDump(value.Index(index), "    "+indent, fmt.Sprintf("%s[%d] :", rIndent+"    ", index))
			index++
		}

	//chan\func\Interface
	case vKind < 21:
		fmt.Printf("%s[%s]%v\n", rIndent, value.Type(), value)

	//Map
	case vKind == 21:
		fmt.Printf("%smap[%s](%d) ==>\n", rIndent, value.Type(), value.Len())
		keys := value.MapKeys()
		for _, key := range keys {
			//fmt.Printf("%s[%s] : ", indent+"    ", key)
			varDump(value.MapIndex(key), "    "+indent, fmt.Sprintf("%s\"%v\" : ", indent+"    ", key))
		}

	//ptr
	case vKind == 22:
		//fmt.Printf("%s[%s] -->\n", indent, value.Type())
		varDump(reflect.Indirect(value), indent, fmt.Sprintf("%s[%s] --> ", rIndent, value.Type()))

	//slice
	case vKind == 23:
		fmt.Printf("%sslice[%s](%d) ==>\n", rIndent, value.Type(), value.Len())
		//fmt.Printf("%s%s", indent+"    ", t.Field(k).Name)
		index := 0
		for {
			if index >= value.Len() {
				break
			}
			//fmt.Printf("%s[%d] : ", r_indent+"    ", index)
			varDump(value.Index(index), "    "+indent, fmt.Sprintf("%s[%d] : ", indent+"    ", index))
			index++
		}
		fmt.Printf("%s//end %s\n", indent, vKind.String())

	//string
	case vKind == 24:
		fmt.Printf("%s[%s](%d) ==> \"%s\"\n", rIndent, value.Type(), value.Len(), value)

	//Struct
	case vKind == 25:
		fmt.Printf("%sstruct[%s] ==> {\n", rIndent, value.Type())

		t := value.Type()
		for k := 0; k < value.NumField(); k++ {
			varDump(value.Field(k), indent+"    ", fmt.Sprintf("%s%s ", indent+"    ", t.Field(k).Name))

		}
		fmt.Printf("%s} //end %s\n", indent, vKind.String())

	//Unsafeptr
	case vKind == 26:
		//fmt.Printf("%s[%s] -->\n", r_indent, vKind.String())
		varDump(reflect.Indirect(value), indent, fmt.Sprintf("%s[%s] --> ", rIndent, vKind.String()))

	default:
		fmt.Printf("%s[%s] : %v\n", rIndent, "Unknown", value)
	}

	return
}

func GetFuncName() (string, error) {
	pc, _, _, succ := runtime.Caller(1)
	if !succ {
		return "", errors.New("get current function name failed")
	}

	return runtime.FuncForPC(pc).Name(), nil
}

//note: 如果字段的tag 设置不是符合规范的，则用tag返回时值是不确定的
func Struct2Map(obj interface{}, useTag bool, tag string) map[string]interface{} {
	defer func() {
		if err := recover(); err != nil {
			io.WriteString(os.Stderr, fmt.Sprintf("%v", err))
		}
	}()

	obj_type := reflect.TypeOf(obj)
	obj_value := reflect.ValueOf(obj)

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

	for i := 0; i < obj_type.NumField(); i++ {
		r_fields := obj_type.Field(i)

		//check type
		if useTag {
			if r_fields.Tag.Get(tag) != "" {
				res[r_fields.Tag.Get(tag)] = obj_value.FieldByName(r_fields.Name)
				continue
			}
		}

		//use param
		res[r_fields.Name] = obj_value.FieldByName(r_fields.Name)
	}

	return res

}
<commit_msg>perfect format<commit_after>package kdebug

import (
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
	"runtime"
)

// VarDump 输出一个数据的完整数据类型，和PHP的var_dump函数很相似
func VarDump(s interface{}) {
	indent := ""
	switch s.(type) {
	case reflect.Value:
		varDump(s.(reflect.Value), indent, "")
	default:
		varDump(reflect.ValueOf(s), indent, "")
	}
	//varDump(reflect.ValueOf(s), indent, "")
}

func varDump(value reflect.Value, indent string, preStr string) {
	var vKind = value.Kind()
	rIndent := indent
	if preStr != "" {
		rIndent = preStr
	}

	switch {
	case vKind == 0:
		fmt.Printf("%s[%s] : %v\n", rIndent, "nil", value)

	//bool + int +uint
	case vKind < 12:
		fmt.Printf("%s[%s] : %v\n", rIndent, value.Type(), value)

	//uintptr
	case vKind == 12:
		//fmt.Printf("%s[%s] ", r_indent, value.Type())
		varDump(value, indent, fmt.Sprintf("%s[%s] --> ", rIndent, value.Type()))

	//float + complex
	case vKind < 17:
		fmt.Printf("%s[%s] : %v\n", rIndent, value.Type(), value)

	//Array
	case vKind == 17:
		fmt.Printf("%sarray[%s](%d) ==>\n", rIndent, value.Type(), value.Len())
		index := 0
		for {
			if index >= value.Len() {
				break
			}
			//fmt.Printf("%s[%d] :", r_indent+"    ", index)
			varDump(value.Index(index), "    "+indent, fmt.Sprintf("%s[%d] :", rIndent+"    ", index))
			index++
		}

	//chan\func\Interface
	case vKind < 21:
		fmt.Printf("%s[%s]%v\n", rIndent, value.Type(), value)

	//Map
	case vKind == 21:
		fmt.Printf("%smap[%s](%d) ==>\n", rIndent, value.Type(), value.Len())
		keys := value.MapKeys()
		for _, key := range keys {
			//fmt.Printf("%s[%s] : ", indent+"    ", key)
			varDump(value.MapIndex(key), "    "+indent, fmt.Sprintf("%s\"%v\" : ", indent+"    ", key))
		}

	//ptr
	case vKind == 22:
		//fmt.Printf("%s[%s] -->\n", indent, value.Type())
		varDump(reflect.Indirect(value), indent, fmt.Sprintf("%s[%s] --> ", rIndent, value.Type()))

	//slice
	case vKind == 23:
		fmt.Printf("%sslice[%s](%d) ==>\n", rIndent, value.Type(), value.Len())
		//fmt.Printf("%s%s", indent+"    ", t.Field(k).Name)
		index := 0
		for {
			if index >= value.Len() {
				break
			}
			//fmt.Printf("%s[%d] : ", r_indent+"    ", index)
			varDump(value.Index(index), "    "+indent, fmt.Sprintf("%s[%d] : ", indent+"    ", index))
			index++
		}
		fmt.Printf("%s//end %s\n", indent, vKind.String())

	//string
	case vKind == 24:
		fmt.Printf("%s[%s](%d) ==> \"%s\"\n", rIndent, value.Type(), value.Len(), value)

	//Struct
	case vKind == 25:
		fmt.Printf("%sstruct[%s] ==> {\n", rIndent, value.Type())

		t := value.Type()
		for k := 0; k < value.NumField(); k++ {
			varDump(value.Field(k), indent+"    ", fmt.Sprintf("%s%s ", indent+"    ", t.Field(k).Name))

		}
		fmt.Printf("%s} //end %s\n", indent, vKind.String())

	//Unsafeptr
	case vKind == 26:
		//fmt.Printf("%s[%s] -->\n", r_indent, vKind.String())
		varDump(reflect.Indirect(value), indent, fmt.Sprintf("%s[%s] --> ", rIndent, vKind.String()))

	default:
		fmt.Printf("%s[%s] : %v\n", rIndent, "Unknown", value)
	}

	return
}

// GetFuncName 获取函数名，用来做DEBUG
func GetFuncName() (string, error) {
	pc, _, _, succ := runtime.Caller(1)
	if !succ {
		return "", errors.New("get current function name failed")
	}

	return runtime.FuncForPC(pc).Name(), nil
}

//Struct2Map 用来把struct 转成map
//note: 如果字段的tag 设置不是符合规范的，则用tag返回时值是不确定的
func Struct2Map(obj interface{}, useTag bool, tag string) map[string]interface{} {
	defer func() {
		if err := recover(); err != nil {
			io.WriteString(os.Stderr, fmt.Sprintf("%v", err))
		}
	}()

	objType := reflect.TypeOf(obj)
	objValue := reflect.ValueOf(obj)

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

	for i := 0; i < objType.NumField(); i++ {
		rFields := objType.Field(i)

		//check type
		if useTag {
			if rFields.Tag.Get(tag) != "" {
				res[rFields.Tag.Get(tag)] = objValue.FieldByName(rFields.Name)
				continue
			}
		}

		//use param
		res[rFields.Name] = objValue.FieldByName(rFields.Name)
	}

	return res

}
<|endoftext|>


<commit_before>package validator

import (
	"fmt"
	"reflect"
	"strconv"
)

const (
	arrayIndexFieldName = "%s" + leftBracket + "%d" + rightBracket
	mapIndexFieldName   = "%s" + leftBracket + "%v" + rightBracket
)

// per validate contruct
type validate struct {
	v              *Validate
	top            reflect.Value
	ns             []byte
	actualNs       []byte
	errs           ValidationErrors
	isPartial      bool
	hasExcludes    bool
	includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
	misc           []byte

	// StructLevel & FieldLevel fields
	slflParent reflect.Value
	slCurrent  reflect.Value
	slNs       []byte
	slStructNs []byte
	flField    reflect.Value
	flParam    string
}

// parent and current will be the same the first run of validateStruct
func (v *validate) validateStruct(parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) {

	cs, ok := v.v.structCache.Get(typ)
	if !ok {
		cs = v.v.extractStructCache(current, typ.Name())
	}

	if len(ns) == 0 {

		ns = append(ns, cs.Name...)
		ns = append(ns, '.')

		structNs = append(structNs, cs.Name...)
		structNs = append(structNs, '.')
	}

	// ct is nil on top level struct, and structs as fields that have no tag info
	// so if nil or if not nil and the structonly tag isn't present
	if ct == nil || ct.typeof != typeStructOnly {

		for _, f := range cs.fields {

			if v.isPartial {

				_, ok = v.includeExclude[string(append(structNs, f.Name...))]

				if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) {
					continue
				}
			}

			v.traverseField(parent, current.Field(f.Idx), ns, structNs, f, f.cTags)
		}
	}

	// check if any struct level validations, after all field validations already checked.
	// first iteration will have no info about nostructlevel tag, and is checked prior to
	// calling the next iteration of validateStruct called from traverseField.
	if cs.fn != nil {

		v.slflParent = parent
		v.slCurrent = current
		v.slNs = ns
		v.slStructNs = structNs

		cs.fn(v)
	}
}

// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns []byte, structNs []byte, cf *cField, ct *cTag) {

	var typ reflect.Type
	var kind reflect.Kind
	var nullable bool

	current, kind, nullable = v.extractTypeInternal(current, nullable)

	switch kind {
	case reflect.Ptr, reflect.Interface, reflect.Invalid:

		if ct == nil {
			return
		}

		if ct.typeof == typeOmitEmpty {
			return
		}

		if ct.hasTag {

			if kind == reflect.Invalid {

				v.errs = append(v.errs,
					&fieldError{
						tag:         ct.aliasTag,
						actualTag:   ct.tag,
						ns:          string(append(ns, cf.AltName...)),
						structNs:    string(append(structNs, cf.Name...)),
						field:       cf.AltName,
						structField: cf.Name,
						param:       ct.param,
						kind:        kind,
					},
				)

				return
			}

			v.errs = append(v.errs,
				&fieldError{
					tag:         ct.aliasTag,
					actualTag:   ct.tag,
					ns:          string(append(ns, cf.AltName...)),
					structNs:    string(append(structNs, cf.Name...)),
					field:       cf.AltName,
					structField: cf.Name,
					value:       current.Interface(),
					param:       ct.param,
					kind:        kind,
					typ:         current.Type(),
				},
			)

			return
		}

	case reflect.Struct:

		typ = current.Type()

		if typ != timeType {

			if ct != nil {
				ct = ct.next
			}

			if ct != nil && ct.typeof == typeNoStructLevel {
				return
			}

			// if len == 0 then validating using 'Var' or 'VarWithValue'
			// Var - doesn't make much sense to do it that way, should call 'Struct', but no harm...
			// VarWithField - this allows for validating against each field withing the struct against a specific value
			//                pretty handly in certain situations
			if len(ns) > 0 {
				ns = append(append(ns, cf.AltName...), '.')
				structNs = append(append(structNs, cf.Name...), '.')
			}

			v.validateStruct(current, current, typ, ns, structNs, ct)
			return
		}
	}

	if !ct.hasTag {
		return
	}

	typ = current.Type()

OUTER:
	for {
		if ct == nil {
			return
		}

		switch ct.typeof {

		case typeOmitEmpty:

			// set Field Level fields
			v.slflParent = parent
			v.flField = current
			v.flParam = ""

			if !nullable && !hasValue(v) {
				return
			}

			ct = ct.next
			continue

		case typeDive:

			ct = ct.next

			// traverse slice or map here
			// or panic ;)
			switch kind {
			case reflect.Slice, reflect.Array:

				var i64 int64
				reusableCF := &cField{}

				// TODO: cache pool &cField
				for i := 0; i < current.Len(); i++ {

					i64 = int64(i)

					v.misc = append(v.misc[0:0], cf.Name...)
					v.misc = append(v.misc, '[')
					v.misc = strconv.AppendInt(v.misc, i64, 10)
					v.misc = append(v.misc, ']')

					reusableCF.Name = string(v.misc)

					v.misc = append(v.misc[0:0], cf.AltName...)
					v.misc = append(v.misc, '[')
					v.misc = strconv.AppendInt(v.misc, i64, 10)
					v.misc = append(v.misc, ']')

					reusableCF.AltName = string(v.misc)

					v.traverseField(parent, current.Index(i), ns, structNs, reusableCF, ct)
				}

			case reflect.Map:

				var pv string
				reusableCF := &cField{}

				for _, key := range current.MapKeys() {

					pv = fmt.Sprintf("%v", key.Interface())

					v.misc = append(v.misc[0:0], cf.Name...)
					v.misc = append(v.misc, '[')
					v.misc = append(v.misc, pv...)
					v.misc = append(v.misc, ']')

					reusableCF.Name = string(v.misc)

					v.misc = append(v.misc[0:0], cf.AltName...)
					v.misc = append(v.misc, '[')
					v.misc = append(v.misc, pv...)
					v.misc = append(v.misc, ']')

					reusableCF.AltName = string(v.misc)

					v.traverseField(parent, current.MapIndex(key), ns, structNs, reusableCF, ct)
				}

			default:
				// throw error, if not a slice or map then should not have gotten here
				// bad dive tag
				panic("dive error! can't dive on a non slice or map")
			}

			return

		case typeOr:

			v.misc = v.misc[0:0]

			for {

				// set Field Level fields
				v.slflParent = parent
				v.flField = current
				v.flParam = ct.param

				if ct.fn(v) {

					// drain rest of the 'or' values, then continue or leave
					for {

						ct = ct.next

						if ct == nil {
							return
						}

						if ct.typeof != typeOr {
							continue OUTER
						}
					}
				}

				v.misc = append(v.misc, '|')
				v.misc = append(v.misc, ct.tag...)

				if ct.next == nil {
					// if we get here, no valid 'or' value and no more tags

					if ct.hasAlias {

						v.errs = append(v.errs,
							&fieldError{
								tag:         ct.aliasTag,
								actualTag:   ct.actualAliasTag,
								ns:          string(append(ns, cf.AltName...)),
								structNs:    string(append(structNs, cf.Name...)),
								field:       cf.AltName,
								structField: cf.Name,
								value:       current.Interface(),
								param:       ct.param,
								kind:        kind,
								typ:         typ,
							},
						)

					} else {

						v.errs = append(v.errs,
							&fieldError{
								tag:         string(v.misc)[1:],
								actualTag:   string(v.misc)[1:],
								ns:          string(append(ns, cf.AltName...)),
								structNs:    string(append(structNs, cf.Name...)),
								field:       cf.AltName,
								structField: cf.Name,
								value:       current.Interface(),
								param:       ct.param,
								kind:        kind,
								typ:         typ,
							},
						)
					}

					return
				}

				ct = ct.next
			}

		default:

			// set Field Level fields
			v.slflParent = parent
			v.flField = current
			v.flParam = ct.param

			if !ct.fn(v) {

				v.errs = append(v.errs,
					&fieldError{
						tag:         ct.aliasTag,
						actualTag:   ct.tag,
						ns:          string(append(ns, cf.AltName...)),
						structNs:    string(append(structNs, cf.Name...)),
						field:       cf.AltName,
						structField: cf.Name,
						value:       current.Interface(),
						param:       ct.param,
						kind:        kind,
						typ:         typ,
					},
				)

				return

			}

			ct = ct.next
		}
	}

}
<commit_msg>remove TODO: tried it, only helped with 1 allocation, not worth the overhead and potential contention<commit_after>package validator

import (
	"fmt"
	"reflect"
	"strconv"
)

const (
	arrayIndexFieldName = "%s" + leftBracket + "%d" + rightBracket
	mapIndexFieldName   = "%s" + leftBracket + "%v" + rightBracket
)

// per validate contruct
type validate struct {
	v              *Validate
	top            reflect.Value
	ns             []byte
	actualNs       []byte
	errs           ValidationErrors
	isPartial      bool
	hasExcludes    bool
	includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
	misc           []byte

	// StructLevel & FieldLevel fields
	slflParent reflect.Value
	slCurrent  reflect.Value
	slNs       []byte
	slStructNs []byte
	flField    reflect.Value
	flParam    string
}

// parent and current will be the same the first run of validateStruct
func (v *validate) validateStruct(parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) {

	cs, ok := v.v.structCache.Get(typ)
	if !ok {
		cs = v.v.extractStructCache(current, typ.Name())
	}

	if len(ns) == 0 {

		ns = append(ns, cs.Name...)
		ns = append(ns, '.')

		structNs = append(structNs, cs.Name...)
		structNs = append(structNs, '.')
	}

	// ct is nil on top level struct, and structs as fields that have no tag info
	// so if nil or if not nil and the structonly tag isn't present
	if ct == nil || ct.typeof != typeStructOnly {

		for _, f := range cs.fields {

			if v.isPartial {

				_, ok = v.includeExclude[string(append(structNs, f.Name...))]

				if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) {
					continue
				}
			}

			v.traverseField(parent, current.Field(f.Idx), ns, structNs, f, f.cTags)
		}
	}

	// check if any struct level validations, after all field validations already checked.
	// first iteration will have no info about nostructlevel tag, and is checked prior to
	// calling the next iteration of validateStruct called from traverseField.
	if cs.fn != nil {

		v.slflParent = parent
		v.slCurrent = current
		v.slNs = ns
		v.slStructNs = structNs

		cs.fn(v)
	}
}

// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns []byte, structNs []byte, cf *cField, ct *cTag) {

	var typ reflect.Type
	var kind reflect.Kind
	var nullable bool

	current, kind, nullable = v.extractTypeInternal(current, nullable)

	switch kind {
	case reflect.Ptr, reflect.Interface, reflect.Invalid:

		if ct == nil {
			return
		}

		if ct.typeof == typeOmitEmpty {
			return
		}

		if ct.hasTag {

			if kind == reflect.Invalid {

				v.errs = append(v.errs,
					&fieldError{
						tag:         ct.aliasTag,
						actualTag:   ct.tag,
						ns:          string(append(ns, cf.AltName...)),
						structNs:    string(append(structNs, cf.Name...)),
						field:       cf.AltName,
						structField: cf.Name,
						param:       ct.param,
						kind:        kind,
					},
				)

				return
			}

			v.errs = append(v.errs,
				&fieldError{
					tag:         ct.aliasTag,
					actualTag:   ct.tag,
					ns:          string(append(ns, cf.AltName...)),
					structNs:    string(append(structNs, cf.Name...)),
					field:       cf.AltName,
					structField: cf.Name,
					value:       current.Interface(),
					param:       ct.param,
					kind:        kind,
					typ:         current.Type(),
				},
			)

			return
		}

	case reflect.Struct:

		typ = current.Type()

		if typ != timeType {

			if ct != nil {
				ct = ct.next
			}

			if ct != nil && ct.typeof == typeNoStructLevel {
				return
			}

			// if len == 0 then validating using 'Var' or 'VarWithValue'
			// Var - doesn't make much sense to do it that way, should call 'Struct', but no harm...
			// VarWithField - this allows for validating against each field withing the struct against a specific value
			//                pretty handly in certain situations
			if len(ns) > 0 {
				ns = append(append(ns, cf.AltName...), '.')
				structNs = append(append(structNs, cf.Name...), '.')
			}

			v.validateStruct(current, current, typ, ns, structNs, ct)
			return
		}
	}

	if !ct.hasTag {
		return
	}

	typ = current.Type()

OUTER:
	for {
		if ct == nil {
			return
		}

		switch ct.typeof {

		case typeOmitEmpty:

			// set Field Level fields
			v.slflParent = parent
			v.flField = current
			v.flParam = ""

			if !nullable && !hasValue(v) {
				return
			}

			ct = ct.next
			continue

		case typeDive:

			ct = ct.next

			// traverse slice or map here
			// or panic ;)
			switch kind {
			case reflect.Slice, reflect.Array:

				var i64 int64
				reusableCF := &cField{}

				for i := 0; i < current.Len(); i++ {

					i64 = int64(i)

					v.misc = append(v.misc[0:0], cf.Name...)
					v.misc = append(v.misc, '[')
					v.misc = strconv.AppendInt(v.misc, i64, 10)
					v.misc = append(v.misc, ']')

					reusableCF.Name = string(v.misc)

					v.misc = append(v.misc[0:0], cf.AltName...)
					v.misc = append(v.misc, '[')
					v.misc = strconv.AppendInt(v.misc, i64, 10)
					v.misc = append(v.misc, ']')

					reusableCF.AltName = string(v.misc)

					v.traverseField(parent, current.Index(i), ns, structNs, reusableCF, ct)
				}

			case reflect.Map:

				var pv string
				reusableCF := &cField{}

				for _, key := range current.MapKeys() {

					pv = fmt.Sprintf("%v", key.Interface())

					v.misc = append(v.misc[0:0], cf.Name...)
					v.misc = append(v.misc, '[')
					v.misc = append(v.misc, pv...)
					v.misc = append(v.misc, ']')

					reusableCF.Name = string(v.misc)

					v.misc = append(v.misc[0:0], cf.AltName...)
					v.misc = append(v.misc, '[')
					v.misc = append(v.misc, pv...)
					v.misc = append(v.misc, ']')

					reusableCF.AltName = string(v.misc)

					v.traverseField(parent, current.MapIndex(key), ns, structNs, reusableCF, ct)
				}

			default:
				// throw error, if not a slice or map then should not have gotten here
				// bad dive tag
				panic("dive error! can't dive on a non slice or map")
			}

			return

		case typeOr:

			v.misc = v.misc[0:0]

			for {

				// set Field Level fields
				v.slflParent = parent
				v.flField = current
				v.flParam = ct.param

				if ct.fn(v) {

					// drain rest of the 'or' values, then continue or leave
					for {

						ct = ct.next

						if ct == nil {
							return
						}

						if ct.typeof != typeOr {
							continue OUTER
						}
					}
				}

				v.misc = append(v.misc, '|')
				v.misc = append(v.misc, ct.tag...)

				if ct.next == nil {
					// if we get here, no valid 'or' value and no more tags

					if ct.hasAlias {

						v.errs = append(v.errs,
							&fieldError{
								tag:         ct.aliasTag,
								actualTag:   ct.actualAliasTag,
								ns:          string(append(ns, cf.AltName...)),
								structNs:    string(append(structNs, cf.Name...)),
								field:       cf.AltName,
								structField: cf.Name,
								value:       current.Interface(),
								param:       ct.param,
								kind:        kind,
								typ:         typ,
							},
						)

					} else {

						v.errs = append(v.errs,
							&fieldError{
								tag:         string(v.misc)[1:],
								actualTag:   string(v.misc)[1:],
								ns:          string(append(ns, cf.AltName...)),
								structNs:    string(append(structNs, cf.Name...)),
								field:       cf.AltName,
								structField: cf.Name,
								value:       current.Interface(),
								param:       ct.param,
								kind:        kind,
								typ:         typ,
							},
						)
					}

					return
				}

				ct = ct.next
			}

		default:

			// set Field Level fields
			v.slflParent = parent
			v.flField = current
			v.flParam = ct.param

			if !ct.fn(v) {

				v.errs = append(v.errs,
					&fieldError{
						tag:         ct.aliasTag,
						actualTag:   ct.tag,
						ns:          string(append(ns, cf.AltName...)),
						structNs:    string(append(structNs, cf.Name...)),
						field:       cf.AltName,
						structField: cf.Name,
						value:       current.Interface(),
						param:       ct.param,
						kind:        kind,
						typ:         typ,
					},
				)

				return

			}

			ct = ct.next
		}
	}

}
<|endoftext|>


<commit_before>// Copyright 2013 Matthew Baird
// 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 gochimp

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

var mandrill, err = NewMandrill(os.Getenv("MANDRILL_KEY"))
var user string = os.Getenv("MANDRILL_USER")

func TestPing(t *testing.T) {
	response, err := mandrill.Ping()
	if response != "PONG!" {
		t.Error(fmt.Sprintf("failed to return PONG!, returned [%s]", response), err)
	}
}

func TestUserInfo(t *testing.T) {
	response, err := mandrill.UserInfo()
	if err != nil {
		t.Error("Error:", err)
	}
	if response.Username != user {
		t.Error("wrong user")
	}
}

func TestUserSenders(t *testing.T) {
	response, err := mandrill.UserSenders()
	if response == nil {
		t.Error("response was nil", err)
	}
	if err != nil {
		t.Error("Error:", err)
	}
}

func TestMessageSending(t *testing.T) {
	var message Message = Message{Html: "hi there", Text: "hello text", Subject: "Test Mail", FromEmail: user,
		FromName: user}
	message.AddRecipients(Recipient{Email: user, Name: user, Type: "to"})
	message.AddRecipients(Recipient{Email: user, Name: user, Type: "cc"})
	message.AddRecipients(Recipient{Email: user, Name: user, Type: "bcc"})
	response, err := mandrill.MessageSend(message, false)
	if err != nil {
		t.Error("Error:", err)
	}
	if response != nil && len(response) > 0 {
		if len(response) != 3 {
			t.Errorf("Did not send to all users. Expected 3, got %d", len(response))
		} else {
			if response[0].Email != user || response[1].Email != user || response[2].Email != user {
				t.Errorf(
					"Wrong email recipient, expecting %s,, got (%s, %s, %s)",
					user,
					response[0].Email,
					response[1].Email,
					response[2].Email,
				)
			}
		}
	} else {
		t.Errorf("No response, probably due to API KEY issues")
	}
}

const testTemplateName string = "test_transactional_template"

func TestTemplateAdd(t *testing.T) {
	// delete the test template if it exists already
	mandrill.TemplateDelete(testTemplateName)
	template, err := mandrill.TemplateAdd(testTemplateName, readTemplate("templates/transactional_basic.html"), true)
	if err != nil {
		t.Error("Error:", err)
	}
	if template.Name != "test_transactional_template" {
		t.Errorf("Wrong template name, expecting %s, got %s", testTemplateName, template.Name)
	}
	// try recreating, should error out
	template, err = mandrill.TemplateAdd(testTemplateName, readTemplate("templates/transactional_basic.html"), true)
	if err == nil {
		t.Error("Should have error'd on duplicate template")
	}
}

func TestTemplateList(t *testing.T) {
	_, err := mandrill.TemplateAdd("listTest", "testing 123", true)
	if err != nil {
		t.Error("Error:", err)
	}
	templates, err := mandrill.TemplateList()
	if err != nil {
		t.Error("Error:", err)
	}
	if len(templates) <= 0 {
		t.Errorf("Should have retrieved templates")
	}
	mandrill.TemplateDelete("listTest")
}

func TestTemplateInfo(t *testing.T) {
	template, err := mandrill.TemplateInfo(testTemplateName)
	if err != nil {
		t.Error("Error:", err)
	}
	if template.Name != "test_transactional_template" {
		t.Errorf("Wrong template name, expecting %s, got %s", testTemplateName, template.Name)
	}
}

func TestTemplateUpdate(t *testing.T) {
	// add a simple template
	template, err := mandrill.TemplateAdd("updateTest", "testing 123", true)
	template, err = mandrill.TemplateUpdate("updateTest", "testing 321", true)
	if err != nil {
		t.Error("Error:", err)
	}
	if template.Name != "updateTest" {
		t.Errorf("Wrong template name, expecting %s, got %s", "updateTest", template.Name)
	}
	if template.Code != "testing 321" {
		t.Errorf("Wrong template code, expecting %s, got %s", "testing 321", template.Code)
	}
	// be nice and tear down after test
	mandrill.TemplateDelete("updateTest")
}

func TestTemplatePublish(t *testing.T) {
	mandrill.TemplateDelete("publishTest")
	// add a simple template
	template, err := mandrill.TemplateAdd("publishTest", "testing 123", false)
	if err != nil {
		t.Error("Error:", err)
	}
	if template.Name != "publishTest" {
		t.Errorf("Wrong template name, expecting %s, got %v", testTemplateName, template.Name)
	}
	if template.PublishCode != "" {
		t.Errorf("Template should not have a publish code, got %v", template.PublishCode)
	}
	template, err = mandrill.TemplatePublish("publishTest")
	if err != nil {
		t.Error("Error:", err)
	}
	if template.Name != "publishTest" {
		t.Errorf("Wrong template name, expecting %s, got %v", testTemplateName, template.Name)
	}
	if template.PublishCode == "" {
		t.Errorf("Template should have a publish code, got %v", template.PublishCode)
	}
	mandrill.TemplateDelete("publishTest")
}

func TestTemplateRender(t *testing.T) {
	//make sure it's freshly added
	mandrill.TemplateDelete("renderTest")
	mandrill.TemplateAdd("renderTest", "*|MC:SUBJECT|*", true)
	//weak - should check results
	mergeVars := []Var{*NewVar("SUBJECT", "Hello, welcome")}
	result, err := mandrill.TemplateRender("renderTest", nil, mergeVars)
	if err != nil {
		t.Error("Error:", err)
	}
	if result != "Hello, welcome" {
		t.Errorf("Rendered Result incorrect, expecting %s, got %v", "Hello, welcome", result)
	}
}

func TestTemplateRender2(t *testing.T) {
	//make sure it's freshly added
	mandrill.TemplateDelete("renderTest")
	mandrill.TemplateAdd("renderTest", "

", true)
	//weak - should check results
	templateContent := []Var{*NewVar("std_content00", "Hello, welcome")}
	result, err := mandrill.TemplateRender("renderTest", templateContent, nil)
	if err != nil {
		t.Error("Error:", err)
	}
	if result != "
Hello, welcome
" {
		t.Errorf("Rendered Result incorrect, expecting %s, got %s", "
Hello, welcome
", result)
	}
}

func TestMessageTemplateSend(t *testing.T) {
	//make sure it's freshly added
	mandrill.TemplateDelete(testTemplateName)
	mandrill.TemplateAdd(testTemplateName, readTemplate("templates/transactional_basic.html"), true)
	//weak - should check results
	templateContent := []Var{*NewVar("std_content00", "Hello, welcome")}
	mergeVars := []Var{*NewVar("SUBJECT", "Hello, welcome")}
	var message Message = Message{Subject: "Test Template Mail", FromEmail: user,
		FromName: user, GlobalMergeVars: mergeVars}
	message.AddRecipients(Recipient{Email: user, Name: user})
	_, err := mandrill.MessageSendTemplate(testTemplateName, templateContent, message, true)
	if err != nil {
		t.Error("Error:", err)
	}
	//todo - how do we test this better?
}

func readTemplate(path string) string {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return string(b)
}

// senders tests

func TestSendersList(t *testing.T) {
	//make sure it's freshly added
	results, err := mandrill.SenderList()
	if err != nil {
		t.Error("Error:", err)
	}
	var foundUser = false
	for i := range results {
		var info Sender = results[i]
		fmt.Printf("sender:%v %s", info, info.Address)
		if info.Address == user {
			foundUser = true
		}
	}
	if !foundUser {
		t.Errorf("should have found User %s in [%v] length array", user, len(results))
	}
}

// incoming tests

func TestInboundDomainListAddCheckDelete(t *testing.T) {
	domainName := "improbable.example.com"
	domains, err := mandrill.InboundDomainList()
	if err != nil {
		t.Error("Error:", err)
	}
	originalCount := len(domains)
	domain, err := mandrill.InboundDomainAdd(domainName)
	if err != nil {
		t.Error("Error:", err)
	}
	domains, err = mandrill.InboundDomainList()
	if err != nil {
		t.Error("Error:", err)
	}
	newCount := len(domains)
	if newCount != originalCount+1 {
		t.Errorf("Expected %v domains, found %v after adding %v.", originalCount+1, newCount, domainName)
	}
	newDomain, err := mandrill.InboundDomainCheck(domainName)
	if err != nil {
		t.Error("Error:", err)
	}
	if domain.CreatedAt != newDomain.CreatedAt {
		t.Errorf("Domain check of %v and %v do not match.", domain.CreatedAt, newDomain.CreatedAt)
	}
	if domain.Domain != newDomain.Domain {
		t.Errorf("Domain check of %v and %v do not match.", domain.Domain, newDomain.Domain)
	}
	if domain.ValidMx != newDomain.ValidMx {
		t.Errorf("Domain check of %v and %v do not match.", domain.ValidMx, newDomain.ValidMx)
	}
	_, err = mandrill.InboundDomainDelete(domainName)
	if err != nil {
		t.Error("Error:", err)
	}
	domains, err = mandrill.InboundDomainList()
	if err != nil {
		t.Error("Error:", err)
	}
	deletedCount := len(domains)
	if deletedCount != originalCount {
		t.Errorf("Expected %v domains, found %v after deleting %v.", originalCount, deletedCount, domainName)
	}
}

func TestInboundDomainRoutesAndRaw(t *testing.T) {
	domainName := "www.google.com"
	emailAddress := "test"
	webhookUrl := fmt.Sprintf("http://%v/", domainName)
	_, err := mandrill.InboundDomainAdd(domainName)
	if err != nil {
		t.Error("Error:", err)
	}
	routeList, err := mandrill.RouteList(domainName)
	if err != nil {
		t.Error("Error:", err)
	}
	count := len(routeList)
	if count != 0 {
		t.Errorf("Expected no routes at %v, found %v.", domainName, count)
	}
	route, err := mandrill.RouteAdd(domainName, emailAddress, webhookUrl)
	if err != nil {
		t.Error("Error:", err)
	}
	if route.Pattern != emailAddress {
		t.Errorf("Expected pattern %v, found %v.", emailAddress, route.Pattern)
	}
	if route.Url != webhookUrl {
		t.Errorf("Expected URL %v, found %v.", webhookUrl, route.Url)
	}
	newDomainName := "www.google.com"
	newEmailAddress := "test2"
	newWebhookUrl := fmt.Sprintf("http://%v/", newDomainName)
	_, err = mandrill.InboundDomainCheck(newDomainName)
	if err != nil {
		t.Error("Error:", err)
	}
	route, err = mandrill.RouteUpdate(route.Id, newDomainName, newEmailAddress, newWebhookUrl)
	if err != nil {
		t.Error("Error:", err)
	}
	if route.Pattern != newEmailAddress {
		t.Errorf("Expected pattern %v, found %v.", newEmailAddress, route.Pattern)
	}
	if route.Url != newWebhookUrl {
		t.Errorf("Expected URL %v, found %v.", newWebhookUrl, route.Pattern)
	}
	route, err = mandrill.RouteDelete(route.Id)
	if err != nil {
		t.Error("Error:", err)
	}
	routeList, err = mandrill.RouteList(domainName)
	if err != nil {
		t.Error("Error:", err)
	}
	newCount := len(routeList)
	if newCount != count {
		t.Errorf("Expected %v routes at %v, found %v.", count, domainName, newCount)
	}
	rawMessage := "From: sender@example.com\nTo: test2@www.google.com\nSubject: Some Subject\n\nSome content."
	_, err = mandrill.SendRawMIME(rawMessage, []string{"test2@www.google.com"}, "test@www.google.com", "", "127.0.0.1")
	if err != nil {
		t.Error("Error:", err)
	}
	_, err = mandrill.InboundDomainDelete(domainName)
	if err != nil {
		t.Error("Error:", err)
	}
}
<commit_msg>better error reporting in tests.<commit_after>// Copyright 2013 Matthew Baird
// 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 gochimp

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

var mandrill, err = NewMandrill(os.Getenv("MANDRILL_KEY"))
var user string = os.Getenv("MANDRILL_USER")

func TestPing(t *testing.T) {
	response, err := mandrill.Ping()
	if response != "PONG!" {
		t.Error(fmt.Sprintf("failed to return PONG!, returned [%s]", response), err)
	}
}

func TestUserInfo(t *testing.T) {
	response, err := mandrill.UserInfo()
	if err != nil {
		t.Error("Error:", err)
	}
	if response.Username != user {
		t.Errorf("wrong user, was expecting %s", response.Username)
	}
}

func TestUserSenders(t *testing.T) {
	response, err := mandrill.UserSenders()
	if response == nil {
		t.Error("response was nil", err)
	}
	if err != nil {
		t.Error("Error:", err)
	}
}

func TestMessageSending(t *testing.T) {
	var message Message = Message{Html: "hi there", Text: "hello text", Subject: "Test Mail", FromEmail: user,
		FromName: user}
	message.AddRecipients(Recipient{Email: user, Name: user, Type: "to"})
	message.AddRecipients(Recipient{Email: user, Name: user, Type: "cc"})
	message.AddRecipients(Recipient{Email: user, Name: user, Type: "bcc"})
	response, err := mandrill.MessageSend(message, false)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if response != nil && len(response) > 0 {
		if len(response) != 3 {
			t.Errorf("Did not send to all users. Expected 3, got %d", len(response))
		} else {
			if response[0].Email != user || response[1].Email != user || response[2].Email != user {
				t.Errorf(
					"Wrong email recipient, expecting %s,, got (%s, %s, %s)",
					user,
					response[0].Email,
					response[1].Email,
					response[2].Email,
				)
			}
		}
	} else {
		t.Errorf("No response, probably due to API KEY issues")
	}
}

const testTemplateName string = "test_transactional_template"

func TestTemplateAdd(t *testing.T) {
	// delete the test template if it exists already
	mandrill.TemplateDelete(testTemplateName)
	template, err := mandrill.TemplateAdd(testTemplateName, readTemplate("templates/transactional_basic.html"), true)
	if err != nil {
		t.Errorf("Error: %v", err)
	}
	if template.Name != "test_transactional_template" {
		t.Errorf("Wrong template name, expecting %s, got %s", testTemplateName, template.Name)
	}
	// try recreating, should error out
	template, err = mandrill.TemplateAdd(testTemplateName, readTemplate("templates/transactional_basic.html"), true)
	if err == nil {
		t.Error("Should have error'd on duplicate template")
	}
}

func TestTemplateList(t *testing.T) {
	_, err := mandrill.TemplateAdd("listTest", "testing 123", true)
	if err != nil {
		t.Errorf("Error: %v", err)
	}
	templates, err := mandrill.TemplateList()
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if len(templates) <= 0 {
		t.Error("Should have retrieved templates")
	}
	mandrill.TemplateDelete("listTest")
}

func TestTemplateInfo(t *testing.T) {
	template, err := mandrill.TemplateInfo(testTemplateName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if template.Name != "test_transactional_template" {
		t.Errorf("Wrong template name, expecting %s, got %s", testTemplateName, template.Name)
	}
}

func TestTemplateUpdate(t *testing.T) {
	// add a simple template
	template, err := mandrill.TemplateAdd("updateTest", "testing 123", true)
	template, err = mandrill.TemplateUpdate("updateTest", "testing 321", true)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if template.Name != "updateTest" {
		t.Errorf("Wrong template name, expecting %s, got %s", "updateTest", template.Name)
	}
	if template.Code != "testing 321" {
		t.Errorf("Wrong template code, expecting %s, got %s", "testing 321", template.Code)
	}
	// be nice and tear down after test
	mandrill.TemplateDelete("updateTest")
}

func TestTemplatePublish(t *testing.T) {
	mandrill.TemplateDelete("publishTest")
	// add a simple template
	template, err := mandrill.TemplateAdd("publishTest", "testing 123", false)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if template.Name != "publishTest" {
		t.Errorf("Wrong template name, expecting %s, got %v", testTemplateName, template.Name)
	}
	if template.PublishCode != "" {
		t.Errorf("Template should not have a publish code, got %v", template.PublishCode)
	}
	template, err = mandrill.TemplatePublish("publishTest")
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if template.Name != "publishTest" {
		t.Errorf("Wrong template name, expecting %s, got %v", testTemplateName, template.Name)
	}
	if template.PublishCode == "" {
		t.Errorf("Template should have a publish code, got %v", template.PublishCode)
	}
	mandrill.TemplateDelete("publishTest")
}

func TestTemplateRender(t *testing.T) {
	//make sure it's freshly added
	mandrill.TemplateDelete("renderTest")
	mandrill.TemplateAdd("renderTest", "*|MC:SUBJECT|*", true)
	//weak - should check results
	mergeVars := []Var{*NewVar("SUBJECT", "Hello, welcome")}
	result, err := mandrill.TemplateRender("renderTest", nil, mergeVars)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if result != "Hello, welcome" {
		t.Errorf("Rendered Result incorrect, expecting %s, got %v", "Hello, welcome", result)
	}
}

func TestTemplateRender2(t *testing.T) {
	//make sure it's freshly added
	mandrill.TemplateDelete("renderTest")
	mandrill.TemplateAdd("renderTest", "

", true)
	//weak - should check results
	templateContent := []Var{*NewVar("std_content00", "Hello, welcome")}
	result, err := mandrill.TemplateRender("renderTest", templateContent, nil)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if result != "
Hello, welcome
" {
		t.Errorf("Rendered Result incorrect, expecting %s, got %s", "
Hello, welcome
", result)
	}
}

func TestMessageTemplateSend(t *testing.T) {
	//make sure it's freshly added
	mandrill.TemplateDelete(testTemplateName)
	mandrill.TemplateAdd(testTemplateName, readTemplate("templates/transactional_basic.html"), true)
	//weak - should check results
	templateContent := []Var{*NewVar("std_content00", "Hello, welcome")}
	mergeVars := []Var{*NewVar("SUBJECT", "Hello, welcome")}
	var message Message = Message{Subject: "Test Template Mail", FromEmail: user,
		FromName: user, GlobalMergeVars: mergeVars}
	message.AddRecipients(Recipient{Email: user, Name: user})
	_, err := mandrill.MessageSendTemplate(testTemplateName, templateContent, message, true)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	//todo - how do we test this better?
}

func readTemplate(path string) string {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return string(b)
}

// senders tests

func TestSendersList(t *testing.T) {
	//make sure it's freshly added
	results, err := mandrill.SenderList()
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	var foundUser = false
	for i := range results {
		var info Sender = results[i]
		fmt.Printf("sender:%v %s", info, info.Address)
		if info.Address == user {
			foundUser = true
		}
	}
	if !foundUser {
		t.Errorf("should have found User %s in [%v] length array", user, len(results))
	}
}

// incoming tests

func TestInboundDomainListAddCheckDelete(t *testing.T) {
	domainName := "improbable.example.com"
	domains, err := mandrill.InboundDomainList()
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	originalCount := len(domains)
	domain, err := mandrill.InboundDomainAdd(domainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	domains, err = mandrill.InboundDomainList()
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	newCount := len(domains)
	if newCount != originalCount+1 {
		t.Errorf("Expected %v domains, found %v after adding %v.", originalCount+1, newCount, domainName)
	}
	newDomain, err := mandrill.InboundDomainCheck(domainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if domain.CreatedAt != newDomain.CreatedAt {
		t.Errorf("Domain check of %v and %v do not match.", domain.CreatedAt, newDomain.CreatedAt)
	}
	if domain.Domain != newDomain.Domain {
		t.Errorf("Domain check of %v and %v do not match.", domain.Domain, newDomain.Domain)
	}
	if domain.ValidMx != newDomain.ValidMx {
		t.Errorf("Domain check of %v and %v do not match.", domain.ValidMx, newDomain.ValidMx)
	}
	_, err = mandrill.InboundDomainDelete(domainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	domains, err = mandrill.InboundDomainList()
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	deletedCount := len(domains)
	if deletedCount != originalCount {
		t.Errorf("Expected %v domains, found %v after deleting %v.", originalCount, deletedCount, domainName)
	}
}

func TestInboundDomainRoutesAndRaw(t *testing.T) {
	domainName := "www.google.com"
	emailAddress := "test"
	webhookUrl := fmt.Sprintf("http://%v/", domainName)
	_, err := mandrill.InboundDomainAdd(domainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	routeList, err := mandrill.RouteList(domainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	count := len(routeList)
	if count != 0 {
		t.Errorf("Expected no routes at %v, found %v.", domainName, count)
	}
	route, err := mandrill.RouteAdd(domainName, emailAddress, webhookUrl)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if route.Pattern != emailAddress {
		t.Errorf("Expected pattern %v, found %v.", emailAddress, route.Pattern)
	}
	if route.Url != webhookUrl {
		t.Errorf("Expected URL %v, found %v.", webhookUrl, route.Url)
	}
	newDomainName := "www.google.com"
	newEmailAddress := "test2"
	newWebhookUrl := fmt.Sprintf("http://%v/", newDomainName)
	_, err = mandrill.InboundDomainCheck(newDomainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	route, err = mandrill.RouteUpdate(route.Id, newDomainName, newEmailAddress, newWebhookUrl)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	if route.Pattern != newEmailAddress {
		t.Errorf("Expected pattern %v, found %v.", newEmailAddress, route.Pattern)
	}
	if route.Url != newWebhookUrl {
		t.Errorf("Expected URL %v, found %v.", newWebhookUrl, route.Pattern)
	}
	route, err = mandrill.RouteDelete(route.Id)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	routeList, err = mandrill.RouteList(domainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	newCount := len(routeList)
	if newCount != count {
		t.Errorf("Expected %v routes at %v, found %v.", count, domainName, newCount)
	}
	rawMessage := "From: sender@example.com\nTo: test2@www.google.com\nSubject: Some Subject\n\nSome content."
	_, err = mandrill.SendRawMIME(rawMessage, []string{"test2@www.google.com"}, "test@www.google.com", "", "127.0.0.1")
	if err != nil {
		t.Errorf("Error:%v", err)
	}
	_, err = mandrill.InboundDomainDelete(domainName)
	if err != nil {
		t.Errorf("Error:%v", err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package golang

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_gopathDependencyPackageInfo(t *testing.T) {
	t.Run("TestPeer", func(t *testing.T) {
		deps, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "github.com/hyperledger/fabric/cmd/peer")
		require.NoError(t, err, "failed to get dependencyPackageInfo")

		var found bool
		for _, pi := range deps {
			if pi.ImportPath == "github.com/hyperledger/fabric/cmd/peer" {
				found = true
				break
			}
		}
		require.True(t, found, "expected to find the peer package")
	})

	t.Run("TestIncomplete", func(t *testing.T) {
		_, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "github.com/hyperledger/fabric/core/chaincode/platforms/golang/testdata/src/chaincodes/BadImport")
		require.EqualError(t, err, "failed to calculate dependencies: incomplete package: bogus/package")
	})

	t.Run("TestFromGoroot", func(t *testing.T) {
		deps, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "os")
		require.NoError(t, err)
		require.Empty(t, deps)
	})

	t.Run("TestFailure", func(t *testing.T) {
		_, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "./doesnotexist")
		require.EqualError(t, err, "listing deps for package ./doesnotexist failed: exit status 1")
	})
}

func TestPackageInfoFiles(t *testing.T) {
	packageInfo := &PackageInfo{
		GoFiles:        []string{"file1.go", "file2.go"},
		CFiles:         []string{"file1.c", "file2.c"},
		CgoFiles:       []string{"file_cgo1.go", "file_cgo2.go"},
		HFiles:         []string{"file1.h", "file2.h"},
		SFiles:         []string{"file1.s", "file2.s"},
		IgnoredGoFiles: []string{"file1_ignored.go", "file2_ignored.go"},
	}
	expected := []string{
		"file1.go", "file2.go",
		"file1.c", "file2.c",
		"file_cgo1.go", "file_cgo2.go",
		"file1.h", "file2.h",
		"file1.s", "file2.s",
		"file1_ignored.go", "file2_ignored.go",
	}
	require.Equal(t, expected, packageInfo.Files())
}

func Test_listModuleInfo(t *testing.T) {
	cwd, err := os.Getwd()
	require.NoError(t, err, "failed to get working directory")
	defer func() {
		err := os.Chdir(cwd)
		require.NoError(t, err)
	}()

	err = os.Chdir("testdata/ccmodule")
	require.NoError(t, err, "failed to change to module directory")

	moduleDir, err := os.Getwd()
	require.NoError(t, err, "failed to get module working directory")

	mi, err := listModuleInfo("GOPROXY=https://proxy.golang.org")
	require.NoError(t, err, "failed to get module info")

	expected := &ModuleInfo{
		ModulePath: "ccmodule",
		ImportPath: "ccmodule",
		Dir:        moduleDir,
		GoMod:      filepath.Join(moduleDir, "go.mod"),
	}
	require.Equal(t, expected, mi)

	err = os.Chdir("nested")
	require.NoError(t, err, "failed to change to module directory")

	mi, err = listModuleInfo("GOPROXY=https://proxy.golang.org")
	require.NoError(t, err, "failed to get module info")

	expected = &ModuleInfo{
		ModulePath: "ccmodule",
		ImportPath: "ccmodule/nested",
		Dir:        moduleDir,
		GoMod:      filepath.Join(moduleDir, "go.mod"),
	}
	require.Equal(t, expected, mi)
}

func Test_listModuleInfoFailure(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "module")
	require.NoError(t, err, "failed to create temporary directory")

	cwd, err := os.Getwd()
	require.NoError(t, err, "failed to get working directory")
	defer func() {
		err := os.Chdir(cwd)
		require.NoError(t, err)
	}()
	err = os.Chdir(tempDir)
	require.NoError(t, err, "failed to change to temporary directory")

	_, err = listModuleInfo()
	require.EqualError(t, err, "'go list' failed with: go: cannot find main module; see 'go help modules': exit status 1")
}
<commit_msg>platform/golang: loosen assertion for Go 1.16.2 (#2480)<commit_after>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package golang

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_gopathDependencyPackageInfo(t *testing.T) {
	t.Run("TestPeer", func(t *testing.T) {
		deps, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "github.com/hyperledger/fabric/cmd/peer")
		require.NoError(t, err, "failed to get dependencyPackageInfo")

		var found bool
		for _, pi := range deps {
			if pi.ImportPath == "github.com/hyperledger/fabric/cmd/peer" {
				found = true
				break
			}
		}
		require.True(t, found, "expected to find the peer package")
	})

	t.Run("TestIncomplete", func(t *testing.T) {
		_, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "github.com/hyperledger/fabric/core/chaincode/platforms/golang/testdata/src/chaincodes/BadImport")
		require.EqualError(t, err, "failed to calculate dependencies: incomplete package: bogus/package")
	})

	t.Run("TestFromGoroot", func(t *testing.T) {
		deps, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "os")
		require.NoError(t, err)
		require.Empty(t, deps)
	})

	t.Run("TestFailure", func(t *testing.T) {
		_, err := gopathDependencyPackageInfo(runtime.GOOS, runtime.GOARCH, "./doesnotexist")
		require.EqualError(t, err, "listing deps for package ./doesnotexist failed: exit status 1")
	})
}

func TestPackageInfoFiles(t *testing.T) {
	packageInfo := &PackageInfo{
		GoFiles:        []string{"file1.go", "file2.go"},
		CFiles:         []string{"file1.c", "file2.c"},
		CgoFiles:       []string{"file_cgo1.go", "file_cgo2.go"},
		HFiles:         []string{"file1.h", "file2.h"},
		SFiles:         []string{"file1.s", "file2.s"},
		IgnoredGoFiles: []string{"file1_ignored.go", "file2_ignored.go"},
	}
	expected := []string{
		"file1.go", "file2.go",
		"file1.c", "file2.c",
		"file_cgo1.go", "file_cgo2.go",
		"file1.h", "file2.h",
		"file1.s", "file2.s",
		"file1_ignored.go", "file2_ignored.go",
	}
	require.Equal(t, expected, packageInfo.Files())
}

func Test_listModuleInfo(t *testing.T) {
	cwd, err := os.Getwd()
	require.NoError(t, err, "failed to get working directory")
	defer func() {
		err := os.Chdir(cwd)
		require.NoError(t, err)
	}()

	err = os.Chdir("testdata/ccmodule")
	require.NoError(t, err, "failed to change to module directory")

	moduleDir, err := os.Getwd()
	require.NoError(t, err, "failed to get module working directory")

	mi, err := listModuleInfo("GOPROXY=https://proxy.golang.org")
	require.NoError(t, err, "failed to get module info")

	expected := &ModuleInfo{
		ModulePath: "ccmodule",
		ImportPath: "ccmodule",
		Dir:        moduleDir,
		GoMod:      filepath.Join(moduleDir, "go.mod"),
	}
	require.Equal(t, expected, mi)

	err = os.Chdir("nested")
	require.NoError(t, err, "failed to change to module directory")

	mi, err = listModuleInfo("GOPROXY=https://proxy.golang.org")
	require.NoError(t, err, "failed to get module info")

	expected = &ModuleInfo{
		ModulePath: "ccmodule",
		ImportPath: "ccmodule/nested",
		Dir:        moduleDir,
		GoMod:      filepath.Join(moduleDir, "go.mod"),
	}
	require.Equal(t, expected, mi)
}

func Test_listModuleInfoFailure(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "module")
	require.NoError(t, err, "failed to create temporary directory")

	cwd, err := os.Getwd()
	require.NoError(t, err, "failed to get working directory")
	defer func() {
		err := os.Chdir(cwd)
		require.NoError(t, err)
	}()
	err = os.Chdir(tempDir)
	require.NoError(t, err, "failed to change to temporary directory")

	_, err = listModuleInfo()
	require.ErrorContains(t, err, "'go list' failed with: go: ")
	require.ErrorContains(t, err, "see 'go help modules': exit status 1")
}
<|endoftext|>


<commit_before>
package main

import "fmt"
import "os"
import "strconv"
import "time"

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func readPin(pin int) int {
    ainName := fmt.Sprintf("/sys/devices/ocp.3/helper.15/AIN%d", pin)
    ainInput, err := os.Open(ainName)
    check(err)
	text := make([]byte, 10)
	count, err := ainInput.Read(text)
	check(err)
	s := string(text[0:count-1])
	val,err := strconv.Atoi(s)
	check(err)
    err = ainInput.Close();
    check(err)
    return val
}

var values = []int{0,0,0,0,0,0,0}

func ReadAIO() []int {
	for p:=0; p<7; p++ {
		values[p] = readPin(p)
	}
    return values
}

func setGPIO(pin int, value int) {
	pinName := fmt.Sprintf("/sys/class/gpio/gpio%d/value", pin)
    gpioOutput, err := os.Create(pinName)
    check(err)
    s := fmt.Sprintf("%d",value)
	count, err := gpioOutput.Write( []byte(s))
	check(err)
	count++
    err = gpioOutput.Close();
    check(err)
    return
}

func setChannel (channel int) {
	setGPIO(23, channel&1)
	setGPIO(47, channel&2)
	setGPIO(27, channel&4)
	setGPIO(22, channel&8)
}

func readSensor(bank int) []int {
	values := make([]int,16,16)
	for i:=0; i<16; i++{
		setChannel(i)
		values[i] = readPin(bank)
	}
	return values
}

func main() {
	setChannel(0);
    for i:=0; i<10000000; i++ {
    	values := readSensor(0)
    	fmt.Printf("%.4d\n", values)
		time.Sleep(1)
	}
}
<commit_msg>Add read pin functionality to setup.go<commit_after>
package main

import "fmt"
import "os"
import "strconv"
import "time"

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func readPin(bank int) int {
//    time.Sleep(100 * time.Millisecond)
    ainName := fmt.Sprintf("/sys/devices/ocp.3/helper.15/AIN%d", bank)
    ainInput, err := os.OpenFile(ainName, os.O_RDONLY,0444)
    check(err)
	text := make([]byte, 10)
	count, err := ainInput.Read(text)
	time.Sleep(50 * time.Millisecond)
	count, err = ainInput.Read(text)
	if (err != nil) {
		count, err = ainInput.Read(text)
		check(err)
	}
	s := string(text[0:count-1])
	val,err := strconv.Atoi(s)
	check(err)
    err = ainInput.Close();
    check(err)
//    fmt.Printf("%d ", val)
//	time.Sleep(10 * time.Millisecond)
	return val
}

func readGPIO(pin int) int {
    gpioName := fmt.Sprintf("/sys/class/gpio/gpio%d/value", pin)
    gpioInput, err := os.Open(gpioName)
    check(err)
	text := make([]byte, 10)
	count, err := gpioInput.Read(text)
	if (err != nil) {
		count, err = gpioInput.Read(text)
		check(err)
	}
	_ = count
	s := string(text[0:count-1])
	val,err := strconv.Atoi(s)
	check(err)
    err = gpioInput.Close();
    check(err)
//    fmt.Printf("%d ", val)
    return val
}

func setGPIO(pin int, value int) {
	pinName := fmt.Sprintf("/sys/class/gpio/gpio%d/value", pin)
    gpioOutput, err := os.Create(pinName)
    check(err)
    s := fmt.Sprintf("%d",value)
	count, err := gpioOutput.Write( []byte(s))
	check(err)
	_ = count
//	fmt.Printf("wrote: %d", count)
    err = gpioOutput.Close();
    check(err)
    return
}

func setChannel (channel int) {
//	fmt.Printf("Chan:%d",channel)
	setGPIO(23, channel&1)
	setGPIO(47, channel&2/2)
	setGPIO(27, channel&4/4)
	setGPIO(22, channel&8/8)
 //   fmt.Printf("%d -> %d %d %d %d ", channel, channel&1,channel&2/2,channel&4/4,channel&8/8)
 //   val23 := readGPIO(23)
 //   val47 := readGPIO(47)
 //   val27 := readGPIO(27)
 //   val22 := readGPIO(22)
//    fmt.Printf("(%d %d %d %d)\n ", val23,val47,val27,val22)
}

func readSensor(bank int) []int {
	values := make([]int,16,16)
	for i:=0; i<16; i++{
		setChannel(i)
		pValue := readPin(bank)
		pValue = readPin(bank)
		pValue = readPin(bank)
		pValue = readPin(bank)
		pValue = readPin(bank)
		pValue = readPin(bank)
		pValue = readPin(bank)
		pValue = readPin(bank)
		values[i] = pValue
//   		fmt.Printf(" Value: %d\n", pValue)
	}
	return values
}

func printSensor(bank int, values []int){
	fmt.Printf("%d ", bank)
	for i:=0; i<16; i++ {
		if values[i] > 300 {
			fmt.Printf("X ")
		} else {
			fmt.Printf("- ")
		}
	}
	fmt.Printf("\n")
}

func main() {
    for i:=0; i<10000000; i++ {
    	values0 := readSensor(0)
    	values1 := readSensor(1)
    	printSensor(0,values0)
    	printSensor(1,values1)
    	fmt.Printf("\n")
//		time.Sleep(1000 * time.Millisecond)
	}
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"log"
	"os"

	"github.com/labstack/echo"
	"github.com/nats-io/nats"
)

func setup() {
	var err error
	natsURI := os.Getenv("NATS_URI")
	if natsURI == "" {
		natsURI = nats.DefaultURL
	}

	n, err = nats.Connect(natsURI)
	if err != nil {
		log.Panic(err)
	}

	secret = os.Getenv("JWT_SECRET")
	if secret == "" {
		panic("No JWT secret was set!")
	}
}

func setupRoutes(api *echo.Group) {
	// Setup user routes
	api.GET("/users/", getUsersHandler)
	api.GET("/users/:user", getUserHandler)
	api.Post("/users/", createUserHandler)
	api.Put("/users/:user", updateUserHandler)
	api.Delete("/users/:user", deleteUserHandler)

	// Setup group routes
	api.GET("/groups/", getGroupsHandler)
	api.GET("/groups/:group", getGroupHandler)
	api.Post("/groups/", createGroupHandler)
	api.Put("/groups/:group", updateGroupHandler)
	api.Delete("/groups/:group", deleteGroupHandler)

	// Setup datacenter routes
	api.GET("/datacenters/", getDatacentersHandler)
	api.GET("/datacenters/:datacenter", getDatacenterHandler)
	api.Post("/datacenters/", createDatacenterHandler)
	api.Put("/datacenters/:datacenter", updateDatacenterHandler)
	api.Delete("/datacenters/:datacenter", deleteDatacenterHandler)

	// Setup service routes
	api.GET("/services/", getServicesHandler)
	api.GET("/services/:service", getServiceHandler)
	api.Post("/services/", createServiceHandler)
	api.Put("/services/:service", updateServiceHandler)
	api.Delete("/services/:service", deleteServiceHandler)
}
<commit_msg>Get JWT token from config<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"log"
	"os"
	"time"

	"github.com/labstack/echo"
	"github.com/nats-io/nats"
)

func setup() {
	var err error
	natsURI := os.Getenv("NATS_URI")
	if natsURI == "" {
		natsURI = nats.DefaultURL
	}

	n, err = nats.Connect(natsURI)
	if err != nil {
		log.Panic(err)
	}

	secret = os.Getenv("JWT_SECRET")
	if secret == "" {
		token, err := n.Request("config.get.jwt_token", []byte(""), 1*time.Second)
		if err != nil {
			panic("Can't get jwt_config config")
		}

		secret = string(token.Data)
	}
}

func setupRoutes(api *echo.Group) {
	// Setup user routes
	api.GET("/users/", getUsersHandler)
	api.GET("/users/:user", getUserHandler)
	api.Post("/users/", createUserHandler)
	api.Put("/users/:user", updateUserHandler)
	api.Delete("/users/:user", deleteUserHandler)

	// Setup group routes
	api.GET("/groups/", getGroupsHandler)
	api.GET("/groups/:group", getGroupHandler)
	api.Post("/groups/", createGroupHandler)
	api.Put("/groups/:group", updateGroupHandler)
	api.Delete("/groups/:group", deleteGroupHandler)

	// Setup datacenter routes
	api.GET("/datacenters/", getDatacentersHandler)
	api.GET("/datacenters/:datacenter", getDatacenterHandler)
	api.Post("/datacenters/", createDatacenterHandler)
	api.Put("/datacenters/:datacenter", updateDatacenterHandler)
	api.Delete("/datacenters/:datacenter", deleteDatacenterHandler)

	// Setup service routes
	api.GET("/services/", getServicesHandler)
	api.GET("/services/:service", getServiceHandler)
	api.Post("/services/", createServiceHandler)
	api.Put("/services/:service", updateServiceHandler)
	api.Delete("/services/:service", deleteServiceHandler)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"unicode"
)

const (
	PACKET_TYPE = iota
	NAME
	PAYLOAD
	DESC
	LITERAL
)

var (
	SYNTAX_ERROR = errors.New("syntax error")
)

type api_expr struct {
	packet_type string
	name        string
	payload     string
	desc        string
}

type token struct {
	typ     int
	literal string
	r       rune
}

type Lexer struct {
	reader *bytes.Buffer
}

func (lex *Lexer) init(r io.Reader) {
	bts, err := ioutil.ReadAll(r)
	if err != nil {
		log.Println(err)
	}

	// 清除注释
	re := regexp.MustCompile("(?m:^#(.*)$)")
	bts = re.ReplaceAllLiteral(bts, nil)
	lex.reader = bytes.NewBuffer(bts)
}

func (lex *Lexer) keyword() *token {
	var r rune
	var err error
	for {
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			return nil
		} else if unicode.IsSpace(r) {
			continue
		}
		break
	}

	var runes []rune
	for {
		runes = append(runes, r)
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			break
		} else if unicode.IsLetter(r) || unicode.IsNumber(r) || r == '_' {
			continue
		} else {
			lex.reader.UnreadRune()
			break
		}
	}
	t := &token{}
	t.literal = string(runes)
	switch t.literal {
	case "packet_type":
		t.typ = PACKET_TYPE
	case "name":
		t.typ = NAME
	case "payload":
		t.typ = PAYLOAD
	case "desc":
		t.typ = DESC
	}
	return t
}

func (lex *Lexer) r() *token {
	var r rune
	var err error
	for {
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			return nil
		} else if unicode.IsSpace(r) {
			continue
		}
		break
	}

	t := &token{}
	t.r = r
	return t
}

func (lex *Lexer) str() *token {
	var r rune
	var err error
	for {
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			return nil
		} else if unicode.IsSpace(r) {
			continue
		}
		break
	}

	var runes []rune
	for {
		runes = append(runes, r)
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			break
		} else if r == '\r' || r == '\n' {
			break
		}
	}

	t := &token{}
	t.literal = string(runes)
	return t
}

func (lex *Lexer) eof() bool {
	for {
		r, _, err := lex.reader.ReadRune()
		if err == io.EOF {
			log.Println(r, err)
			return true
		} else if unicode.IsSpace(r) {
			continue
		} else {
			lex.reader.UnreadRune()
			return false
		}
	}

	return true
}

//////////////////////////////////////////////////////////////
type Parser struct {
	exprs []api_expr
	lexer *Lexer
}

func (p *Parser) init(lex *Lexer) {
	p.lexer = lex
}

func (p *Parser) match(r rune) {
	t := p.lexer.r()
	check(t)
	if t.r != r {
		log.Fatal(SYNTAX_ERROR)
	}
}

func (p *Parser) packet_type() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != PACKET_TYPE {
		log.Fatal(SYNTAX_ERROR)
	}
}

func (p *Parser) name() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != NAME {
		log.Fatal(SYNTAX_ERROR)
	}
}
func (p *Parser) payload() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != PAYLOAD {
		log.Fatal(SYNTAX_ERROR)
	}
}
func (p *Parser) desc() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != DESC {
		log.Fatal(SYNTAX_ERROR)
	}
}

func (p *Parser) literal() string {
	t := p.lexer.str()
	check(t)
	return t.literal
}

func (p *Parser) expr() bool {
	api := api_expr{}
	if p.lexer.eof() {
		return false
	}
	p.packet_type()
	p.match(':')
	api.packet_type = p.literal()
	p.name()
	p.match(':')
	api.name = p.literal()
	p.payload()
	p.match(':')
	api.payload = p.literal()
	p.desc()
	p.match(':')
	api.desc = p.literal()

	p.exprs = append(p.exprs, api)
	return true
}

func check(t *token) {
	if t == nil {
		log.Fatal(SYNTAX_ERROR)
	}
}

func main() {
	lexer := Lexer{}
	lexer.init(os.Stdin)
	p := Parser{}
	p.init(&lexer)
	for p.expr() {
	}
	log.Println(p.exprs)
}
<commit_msg>update<commit_after>package main

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"unicode"
)

const (
	PACKET_TYPE = iota
	NAME
	PAYLOAD
	DESC
	LITERAL
)

var (
	SYNTAX_ERROR = errors.New("syntax error")
)

type api_expr struct {
	packet_type string
	name        string
	payload     string
	desc        string
}

type token struct {
	typ     int
	literal string
	r       rune
}

type Lexer struct {
	reader *bytes.Buffer
}

func (lex *Lexer) init(r io.Reader) {
	bts, err := ioutil.ReadAll(r)
	if err != nil {
		log.Println(err)
	}

	// 清除注释
	re := regexp.MustCompile("(?m:^#(.*)$)")
	bts = re.ReplaceAllLiteral(bts, nil)
	lex.reader = bytes.NewBuffer(bts)
}

func (lex *Lexer) keyword() *token {
	var r rune
	var err error
	for {
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			return nil
		} else if unicode.IsSpace(r) {
			continue
		}
		break
	}

	var runes []rune
	for {
		runes = append(runes, r)
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			break
		} else if unicode.IsLetter(r) || unicode.IsNumber(r) || r == '_' {
			continue
		} else {
			lex.reader.UnreadRune()
			break
		}
	}
	t := &token{}
	t.literal = string(runes)
	switch t.literal {
	case "packet_type":
		t.typ = PACKET_TYPE
	case "name":
		t.typ = NAME
	case "payload":
		t.typ = PAYLOAD
	case "desc":
		t.typ = DESC
	default:
		log.Fatal(SYNTAX_ERROR)
	}
	return t
}

func (lex *Lexer) r() *token {
	var r rune
	var err error
	for {
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			return nil
		} else if unicode.IsSpace(r) {
			continue
		}
		break
	}

	t := &token{}
	t.r = r
	return t
}

func (lex *Lexer) str() *token {
	var r rune
	var err error
	for {
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			return nil
		} else if unicode.IsSpace(r) {
			continue
		}
		break
	}

	var runes []rune
	for {
		runes = append(runes, r)
		r, _, err = lex.reader.ReadRune()
		if err == io.EOF {
			break
		} else if r == '\r' || r == '\n' {
			break
		}
	}

	t := &token{}
	t.literal = string(runes)
	return t
}

func (lex *Lexer) eof() bool {
	for {
		r, _, err := lex.reader.ReadRune()
		if err == io.EOF {
			log.Println(r, err)
			return true
		} else if unicode.IsSpace(r) {
			continue
		} else {
			lex.reader.UnreadRune()
			return false
		}
	}

	return true
}

//////////////////////////////////////////////////////////////
type Parser struct {
	exprs []api_expr
	lexer *Lexer
}

func (p *Parser) init(lex *Lexer) {
	p.lexer = lex
}

func (p *Parser) match(r rune) {
	t := p.lexer.r()
	check(t)
	if t.r != r {
		log.Fatal(SYNTAX_ERROR)
	}
}

func (p *Parser) packet_type() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != PACKET_TYPE {
		log.Fatal(SYNTAX_ERROR)
	}
}

func (p *Parser) name() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != NAME {
		log.Fatal(SYNTAX_ERROR)
	}
}
func (p *Parser) payload() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != PAYLOAD {
		log.Fatal(SYNTAX_ERROR)
	}
}
func (p *Parser) desc() {
	t := p.lexer.keyword()
	check(t)
	if t.typ != DESC {
		log.Fatal(SYNTAX_ERROR)
	}
}

func (p *Parser) literal() string {
	t := p.lexer.str()
	check(t)
	return t.literal
}

func (p *Parser) expr() bool {
	api := api_expr{}
	if p.lexer.eof() {
		return false
	}
	p.packet_type()
	p.match(':')
	api.packet_type = p.literal()
	p.name()
	p.match(':')
	api.name = p.literal()
	p.payload()
	p.match(':')
	api.payload = p.literal()
	p.desc()
	p.match(':')
	api.desc = p.literal()

	p.exprs = append(p.exprs, api)
	return true
}

func check(t *token) {
	if t == nil {
		log.Fatal(SYNTAX_ERROR)
	}
}

func main() {
	lexer := Lexer{}
	lexer.init(os.Stdin)
	p := Parser{}
	p.init(&lexer)
	for p.expr() {
	}
	log.Println(p.exprs)
}
<|endoftext|>


<commit_before>package stores

import (
	"context"
	"fmt"
	"time"

	"github.com/go-kit/log/level"
	"github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/model/labels"

	"github.com/grafana/loki/pkg/storage/chunk"
	"github.com/grafana/loki/pkg/storage/chunk/fetcher"
	"github.com/grafana/loki/pkg/storage/errors"
	"github.com/grafana/loki/pkg/storage/stores/index/stats"
	"github.com/grafana/loki/pkg/storage/stores/series"
	util_log "github.com/grafana/loki/pkg/util/log"
	"github.com/grafana/loki/pkg/util/spanlogger"
	"github.com/grafana/loki/pkg/util/validation"
)

var _ Store = &compositeStore{}

type StoreLimits interface {
	MaxChunksPerQueryFromStore(userID string) int
	MaxQueryLength(userID string) time.Duration
}

type ChunkWriter interface {
	Put(ctx context.Context, chunks []chunk.Chunk) error
	PutOne(ctx context.Context, from, through model.Time, chunk chunk.Chunk) error
}

type compositeStoreEntry struct {
	start model.Time
	Store
}

type storeEntry struct {
	limits  StoreLimits
	stop    func()
	fetcher *fetcher.Fetcher
	index   series.IndexStore
	ChunkWriter
}

func (c *storeEntry) GetChunkRefs(ctx context.Context, userID string, from, through model.Time, allMatchers ...*labels.Matcher) ([][]chunk.Chunk, []*fetcher.Fetcher, error) {
	if ctx.Err() != nil {
		return nil, nil, ctx.Err()
	}
	log, ctx := spanlogger.New(ctx, "GetChunkRefs")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	log.Log(
		"shortcut", shortcut,
		"from", from.Time(),
		"through", through.Time(),
		"err", err,
	)
	if err != nil {
		return nil, nil, err
	} else if shortcut {
		return nil, nil, nil
	}

	refs, err := c.index.GetChunkRefs(ctx, userID, from, through, allMatchers...)

	chunks := make([]chunk.Chunk, len(refs))
	for i, ref := range refs {
		chunks[i] = chunk.Chunk{
			ChunkRef: ref,
		}
	}

	return [][]chunk.Chunk{chunks}, []*fetcher.Fetcher{c.fetcher}, err
}

func (c *storeEntry) GetSeries(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) ([]labels.Labels, error) {
	return c.index.GetSeries(ctx, userID, from, through, matchers...)
}

func (c *storeEntry) SetChunkFilterer(chunkFilter chunk.RequestChunkFilterer) {
	c.index.SetChunkFilterer(chunkFilter)
}

// LabelNamesForMetricName retrieves all label names for a metric name.
func (c *storeEntry) LabelNamesForMetricName(ctx context.Context, userID string, from, through model.Time, metricName string) ([]string, error) {
	log, ctx := spanlogger.New(ctx, "SeriesStore.LabelNamesForMetricName")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	if err != nil {
		return nil, err
	} else if shortcut {
		return nil, nil
	}
	level.Debug(log).Log("metric", metricName)

	return c.index.LabelNamesForMetricName(ctx, userID, from, through, metricName)
}

func (c *storeEntry) LabelValuesForMetricName(ctx context.Context, userID string, from, through model.Time, metricName string, labelName string, matchers ...*labels.Matcher) ([]string, error) {
	log, ctx := spanlogger.New(ctx, "SeriesStore.LabelValuesForMetricName")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	if err != nil {
		return nil, err
	} else if shortcut {
		return nil, nil
	}

	return c.index.LabelValuesForMetricName(ctx, userID, from, through, metricName, labelName, matchers...)
}

func (c *storeEntry) Stats(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) (*stats.Stats, error) {
	log, ctx := spanlogger.New(ctx, "SeriesStore.Stats")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	if err != nil {
		return nil, err
	} else if shortcut {
		return nil, nil
	}

	return c.index.Stats(ctx, userID, from, through, matchers...)
}

func (c *storeEntry) validateQueryTimeRange(ctx context.Context, userID string, from *model.Time, through *model.Time) (bool, error) {
	//nolint:ineffassign,staticcheck //Leaving ctx even though we don't currently use it, we want to make it available for when we might need it and hopefully will ensure us using the correct context at that time

	if *through < *from {
		return false, errors.QueryError(fmt.Sprintf("invalid query, through < from (%s < %s)", through, from))
	}

	maxQueryLength := c.limits.MaxQueryLength(userID)
	if maxQueryLength > 0 && (*through).Sub(*from) > maxQueryLength {
		return false, errors.QueryError(fmt.Sprintf(validation.ErrQueryTooLong, (*through).Sub(*from), maxQueryLength))
	}

	now := model.Now()

	if from.After(now) {
		// time-span start is in future ... regard as legal
		level.Info(util_log.WithContext(ctx, util_log.Logger)).Log("msg", "whole timerange in future, yield empty resultset", "through", through, "from", from, "now", now)
		return true, nil
	}

	if through.After(now.Add(5 * time.Minute)) {
		// time-span end is in future ... regard as legal
		level.Info(util_log.WithContext(ctx, util_log.Logger)).Log("msg", "adjusting end timerange from future to now", "old_through", through, "new_through", now)
		*through = now // Avoid processing future part - otherwise some schemas could fail with eg non-existent table gripes
	}

	return false, nil
}

func (c *storeEntry) GetChunkFetcher(tm model.Time) *fetcher.Fetcher {
	return c.fetcher
}

func (c *storeEntry) Stop() {
	if c.stop != nil {
		c.stop()
	}
}
<commit_msg>Set log level for GetChunkRefs log (#6677)<commit_after>package stores

import (
	"context"
	"fmt"
	"time"

	"github.com/go-kit/log/level"
	"github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/model/labels"

	"github.com/grafana/loki/pkg/storage/chunk"
	"github.com/grafana/loki/pkg/storage/chunk/fetcher"
	"github.com/grafana/loki/pkg/storage/errors"
	"github.com/grafana/loki/pkg/storage/stores/index/stats"
	"github.com/grafana/loki/pkg/storage/stores/series"
	util_log "github.com/grafana/loki/pkg/util/log"
	"github.com/grafana/loki/pkg/util/spanlogger"
	"github.com/grafana/loki/pkg/util/validation"
)

var _ Store = &compositeStore{}

type StoreLimits interface {
	MaxChunksPerQueryFromStore(userID string) int
	MaxQueryLength(userID string) time.Duration
}

type ChunkWriter interface {
	Put(ctx context.Context, chunks []chunk.Chunk) error
	PutOne(ctx context.Context, from, through model.Time, chunk chunk.Chunk) error
}

type compositeStoreEntry struct {
	start model.Time
	Store
}

type storeEntry struct {
	limits  StoreLimits
	stop    func()
	fetcher *fetcher.Fetcher
	index   series.IndexStore
	ChunkWriter
}

func (c *storeEntry) GetChunkRefs(ctx context.Context, userID string, from, through model.Time, allMatchers ...*labels.Matcher) ([][]chunk.Chunk, []*fetcher.Fetcher, error) {
	if ctx.Err() != nil {
		return nil, nil, ctx.Err()
	}
	log, ctx := spanlogger.New(ctx, "GetChunkRefs")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	level.Debug(log).Log(
		"shortcut", shortcut,
		"from", from.Time(),
		"through", through.Time(),
		"err", err,
	)
	if err != nil {
		return nil, nil, err
	} else if shortcut {
		return nil, nil, nil
	}

	refs, err := c.index.GetChunkRefs(ctx, userID, from, through, allMatchers...)

	chunks := make([]chunk.Chunk, len(refs))
	for i, ref := range refs {
		chunks[i] = chunk.Chunk{
			ChunkRef: ref,
		}
	}

	return [][]chunk.Chunk{chunks}, []*fetcher.Fetcher{c.fetcher}, err
}

func (c *storeEntry) GetSeries(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) ([]labels.Labels, error) {
	return c.index.GetSeries(ctx, userID, from, through, matchers...)
}

func (c *storeEntry) SetChunkFilterer(chunkFilter chunk.RequestChunkFilterer) {
	c.index.SetChunkFilterer(chunkFilter)
}

// LabelNamesForMetricName retrieves all label names for a metric name.
func (c *storeEntry) LabelNamesForMetricName(ctx context.Context, userID string, from, through model.Time, metricName string) ([]string, error) {
	log, ctx := spanlogger.New(ctx, "SeriesStore.LabelNamesForMetricName")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	if err != nil {
		return nil, err
	} else if shortcut {
		return nil, nil
	}
	level.Debug(log).Log("metric", metricName)

	return c.index.LabelNamesForMetricName(ctx, userID, from, through, metricName)
}

func (c *storeEntry) LabelValuesForMetricName(ctx context.Context, userID string, from, through model.Time, metricName string, labelName string, matchers ...*labels.Matcher) ([]string, error) {
	log, ctx := spanlogger.New(ctx, "SeriesStore.LabelValuesForMetricName")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	if err != nil {
		return nil, err
	} else if shortcut {
		return nil, nil
	}

	return c.index.LabelValuesForMetricName(ctx, userID, from, through, metricName, labelName, matchers...)
}

func (c *storeEntry) Stats(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) (*stats.Stats, error) {
	log, ctx := spanlogger.New(ctx, "SeriesStore.Stats")
	defer log.Span.Finish()

	shortcut, err := c.validateQueryTimeRange(ctx, userID, &from, &through)
	if err != nil {
		return nil, err
	} else if shortcut {
		return nil, nil
	}

	return c.index.Stats(ctx, userID, from, through, matchers...)
}

func (c *storeEntry) validateQueryTimeRange(ctx context.Context, userID string, from *model.Time, through *model.Time) (bool, error) {
	//nolint:ineffassign,staticcheck //Leaving ctx even though we don't currently use it, we want to make it available for when we might need it and hopefully will ensure us using the correct context at that time

	if *through < *from {
		return false, errors.QueryError(fmt.Sprintf("invalid query, through < from (%s < %s)", through, from))
	}

	maxQueryLength := c.limits.MaxQueryLength(userID)
	if maxQueryLength > 0 && (*through).Sub(*from) > maxQueryLength {
		return false, errors.QueryError(fmt.Sprintf(validation.ErrQueryTooLong, (*through).Sub(*from), maxQueryLength))
	}

	now := model.Now()

	if from.After(now) {
		// time-span start is in future ... regard as legal
		level.Info(util_log.WithContext(ctx, util_log.Logger)).Log("msg", "whole timerange in future, yield empty resultset", "through", through, "from", from, "now", now)
		return true, nil
	}

	if through.After(now.Add(5 * time.Minute)) {
		// time-span end is in future ... regard as legal
		level.Info(util_log.WithContext(ctx, util_log.Logger)).Log("msg", "adjusting end timerange from future to now", "old_through", through, "new_through", now)
		*through = now // Avoid processing future part - otherwise some schemas could fail with eg non-existent table gripes
	}

	return false, nil
}

func (c *storeEntry) GetChunkFetcher(tm model.Time) *fetcher.Fetcher {
	return c.fetcher
}

func (c *storeEntry) Stop() {
	if c.stop != nil {
		c.stop()
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package spdy

import (
	"io"
	"net"
	"net/http"
	"sync"
	"testing"
	"time"

	"k8s.io/apimachinery/pkg/util/httpstream"
)

func runProxy(t *testing.T, backendUrl string, proxyUrl chan<- string, proxyDone chan<- struct{}) {
	listener, err := net.Listen("tcp4", "localhost:0")
	if err != nil {
		t.Fatalf("error listening: %v", err)
	}
	defer listener.Close()

	proxyUrl <- listener.Addr().String()

	clientConn, err := listener.Accept()
	if err != nil {
		t.Errorf("proxy: error accepting client connection: %v", err)
		return
	}

	backendConn, err := net.Dial("tcp4", backendUrl)
	if err != nil {
		t.Errorf("proxy: error dialing backend: %v", err)
		return
	}
	defer backendConn.Close()

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		io.Copy(backendConn, clientConn)
	}()

	go func() {
		defer wg.Done()
		io.Copy(clientConn, backendConn)
	}()

	wg.Wait()

	proxyDone <- struct{}{}
}

func runServer(t *testing.T, backendUrl chan<- string, serverDone chan<- struct{}) {
	listener, err := net.Listen("tcp4", "localhost:0")
	if err != nil {
		t.Fatalf("server: error listening: %v", err)
	}
	defer listener.Close()

	backendUrl <- listener.Addr().String()

	conn, err := listener.Accept()
	if err != nil {
		t.Errorf("server: error accepting connection: %v", err)
		return
	}

	streamChan := make(chan httpstream.Stream)
	replySentChan := make(chan (<-chan struct{}))
	spdyConn, err := NewServerConnection(conn, func(stream httpstream.Stream, replySent <-chan struct{}) error {
		streamChan <- stream
		replySentChan <- replySent
		return nil
	})
	if err != nil {
		t.Errorf("server: error creating spdy connection: %v", err)
		return
	}

	stream := <-streamChan
	replySent := <-replySentChan
	<-replySent

	buf := make([]byte, 1)
	_, err = stream.Read(buf)
	if err != io.EOF {
		t.Errorf("server: unexpected read error: %v", err)
		return
	}

	<-spdyConn.CloseChan()
	raw := spdyConn.(*connection).conn
	if err := raw.Wait(15 * time.Second); err != nil {
		t.Errorf("server: timed out waiting for connection closure: %v", err)
	}

	serverDone <- struct{}{}
}

func TestConnectionCloseIsImmediateThroughAProxy(t *testing.T) {
	serverDone := make(chan struct{})
	backendUrlChan := make(chan string)
	go runServer(t, backendUrlChan, serverDone)
	backendUrl := <-backendUrlChan

	proxyDone := make(chan struct{})
	proxyUrlChan := make(chan string)
	go runProxy(t, backendUrl, proxyUrlChan, proxyDone)
	proxyUrl := <-proxyUrlChan

	conn, err := net.Dial("tcp4", proxyUrl)
	if err != nil {
		t.Fatalf("client: error connecting to proxy: %v", err)
	}

	spdyConn, err := NewClientConnection(conn)
	if err != nil {
		t.Fatalf("client: error creating spdy connection: %v", err)
	}

	if _, err := spdyConn.CreateStream(http.Header{}); err != nil {
		t.Fatalf("client: error creating stream: %v", err)
	}

	spdyConn.Close()
	raw := spdyConn.(*connection).conn
	if err := raw.Wait(15 * time.Second); err != nil {
		t.Fatalf("client: timed out waiting for connection closure: %v", err)
	}

	expired := time.NewTimer(15 * time.Second)
	defer expired.Stop()
	i := 0
	for {
		select {
		case <-expired.C:
			t.Fatalf("timed out waiting for proxy and/or server closure")
		case <-serverDone:
			i++
		case <-proxyDone:
			i++
		}
		if i == 2 {
			break
		}
	}
}
<commit_msg>apimachinery: fix bugs in a Test function<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package spdy

import (
	"io"
	"net"
	"net/http"
	"sync"
	"testing"
	"time"

	"k8s.io/apimachinery/pkg/util/httpstream"
)

func runProxy(t *testing.T, backendUrl string, proxyUrl chan<- string, proxyDone chan<- struct{}, errCh chan<- error) {
	listener, err := net.Listen("tcp4", "localhost:0")
	if err != nil {
		errCh <- err
		return
	}
	defer listener.Close()

	proxyUrl <- listener.Addr().String()

	clientConn, err := listener.Accept()
	if err != nil {
		t.Errorf("proxy: error accepting client connection: %v", err)
		return
	}

	backendConn, err := net.Dial("tcp4", backendUrl)
	if err != nil {
		t.Errorf("proxy: error dialing backend: %v", err)
		return
	}
	defer backendConn.Close()

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		io.Copy(backendConn, clientConn)
	}()

	go func() {
		defer wg.Done()
		io.Copy(clientConn, backendConn)
	}()

	wg.Wait()

	proxyDone <- struct{}{}
}

func runServer(t *testing.T, backendUrl chan<- string, serverDone chan<- struct{}, errCh chan<- error) {
	listener, err := net.Listen("tcp4", "localhost:0")
	if err != nil {
		errCh <- err
		return
	}
	defer listener.Close()

	backendUrl <- listener.Addr().String()

	conn, err := listener.Accept()
	if err != nil {
		t.Errorf("server: error accepting connection: %v", err)
		return
	}

	streamChan := make(chan httpstream.Stream)
	replySentChan := make(chan (<-chan struct{}))
	spdyConn, err := NewServerConnection(conn, func(stream httpstream.Stream, replySent <-chan struct{}) error {
		streamChan <- stream
		replySentChan <- replySent
		return nil
	})
	if err != nil {
		t.Errorf("server: error creating spdy connection: %v", err)
		return
	}

	stream := <-streamChan
	replySent := <-replySentChan
	<-replySent

	buf := make([]byte, 1)
	_, err = stream.Read(buf)
	if err != io.EOF {
		t.Errorf("server: unexpected read error: %v", err)
		return
	}

	<-spdyConn.CloseChan()
	raw := spdyConn.(*connection).conn
	if err := raw.Wait(15 * time.Second); err != nil {
		t.Errorf("server: timed out waiting for connection closure: %v", err)
	}

	serverDone <- struct{}{}
}

func TestConnectionCloseIsImmediateThroughAProxy(t *testing.T) {
	errCh := make(chan error)

	serverDone := make(chan struct{}, 1)
	backendUrlChan := make(chan string)
	go runServer(t, backendUrlChan, serverDone, errCh)

	var backendUrl string
	select {
	case err := <-errCh:
		t.Fatalf("server: error listening: %v", err)
	case backendUrl = <-backendUrlChan:
	}

	proxyDone := make(chan struct{}, 1)
	proxyUrlChan := make(chan string)
	go runProxy(t, backendUrl, proxyUrlChan, proxyDone, errCh)

	var proxyUrl string
	select {
	case err := <-errCh:
		t.Fatalf("error listening: %v", err)
	case proxyUrl = <-proxyUrlChan:
	}

	conn, err := net.Dial("tcp4", proxyUrl)
	if err != nil {
		t.Fatalf("client: error connecting to proxy: %v", err)
	}

	spdyConn, err := NewClientConnection(conn)
	if err != nil {
		t.Fatalf("client: error creating spdy connection: %v", err)
	}

	if _, err := spdyConn.CreateStream(http.Header{}); err != nil {
		t.Fatalf("client: error creating stream: %v", err)
	}

	spdyConn.Close()
	raw := spdyConn.(*connection).conn
	if err := raw.Wait(15 * time.Second); err != nil {
		t.Fatalf("client: timed out waiting for connection closure: %v", err)
	}

	expired := time.NewTimer(15 * time.Second)
	defer expired.Stop()
	i := 0
	for {
		select {
		case <-expired.C:
			t.Fatalf("timed out waiting for proxy and/or server closure")
		case <-serverDone:
			i++
		case <-proxyDone:
			i++
		}
		if i == 2 {
			break
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"

	"github.com/krasoffski/gomill/htcmap"
)

const (
	width      = 600
	height     = 300
	cells      = 100
	xyrange    = 30.0
	xyscale    = width / 2 / xyrange
	multiplier = 0.4
	zscale     = height * multiplier
	angle      = math.Pi / 6
)

var (
	sin30 = math.Sin(angle)
	cos30 = math.Cos(angle)
)

type point struct {
	x, y, z float64
}

func (p *point) real() bool {
	return !math.IsNaN(p.z)
}

func main() {
	fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+
		"width='%d' height='%d'>\n", width, height)

	points := make([]point, 0)
	var min, max float64

	for i := 0; i < cells; i++ {
		for j := 0; j < cells; j++ {
			ax, ay, az := calculate(i+1, j)
			bx, by, bz := calculate(i, j)
			cx, cy, cz := calculate(i, j+1)
			dx, dy, dz := calculate(i+1, j+1)

			color := htcmap.AsStr((bz+dz)/2, -0.13, +0.13)

			fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g' "+
				"style='stroke:green; fill:%s; stroke-width:0.7'/>\n",
				ax, ay, bx, by, cx, cy, dx, dy, color)
		}
	}
	fmt.Println("</svg>")
}

func calculate(i, j int) (float64, float64, float64) {
	x := xyrange * (float64(i)/cells - 0.5)
	y := xyrange * (float64(j)/cells - 0.5)

	z := f1(x, y)
	return x, y, z
}

func transform(p point) (float64, float64) {
	sx := width/2 + (x-y)*cos30*xyscale
	sy := height/2 + (x+y)*sin30*xyscale - z*zscale

	return sx, sy
}

func f1(x, y float64) float64 {
	r := math.Hypot(x, y)
	return math.Sin(r) / r
}

func f2(x, y float64) float64 {
	return x * math.Exp(-x*x-y*y)
}
<commit_msg>Adding new types for task 3.1 and 3.3.<commit_after>package main

import (
	"fmt"
	"math"
)

const (
	width      = 600
	height     = 300
	cells      = 100
	xyrange    = 30.0
	xyscale    = width / 2 / xyrange
	multiplier = 0.4
	zscale     = height * multiplier
	angle      = math.Pi / 6
)

var (
	sin30 = math.Sin(angle)
	cos30 = math.Cos(angle)
)

type Point struct {
	X, Y, Z float64
}

func NewPoint(i, j int, f func(float64, float64) float64) (*Point, error) {
	x := xyrange * (float64(i)/cells - 0.5)
	y := xyrange * (float64(j)/cells - 0.5)
	z := f(x, y)
	if math.IsNaN(z) {
		return nil, fmt.Errorf("error: function returned non real number")
	}
	return &Point{x, y, z}, nil
}

type Isometric struct {
	Sx, Sy float64
}

func NewIsometric(p Point) Isometric {
	sx := width/2 + (p.X-p.Y)*cos30*xyscale
	sy := height/2 + (p.X+p.Y)*sin30*xyscale - p.Z*zscale
	return Isometric{Sx: sx, Sy: sy}
}

type Polygon struct {
	A, B, C, D Isometric
	Color      string
}

func (p *Polygon) String() string {
	return fmt.Sprintf("<polygon points='%g,%g %g,%g %g,%g %g,%g' "+
		"style='stroke:green; fill:%s; stroke-width:0.7'/>\n",
		p.A.Sx, p.A.Sy, p.B.Sx, p.B.Sy, p.C.Sx, p.C.Sy, p.D.Sx, p.D.Sy, p.Color)
}

func main() {
	fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+
		"width='%d' height='%d'>\n", width, height)

	// points := make([]Point, 0, cells*cells)
	// var min, max float64

	for i := 0; i < cells; i++ {
		for j := 0; j < cells; j++ {
			_, aErr := NewPoint(i+1, j, f1)
			_, bErr := NewPoint(i, j, f1)
			_, cErr := NewPoint(i, j+1, f1)
			_, dErr := NewPoint(i+1, j+1, f1)

			fmt.Printf("%v %v %v %v\n", aErr, bErr, cErr, dErr)

			// color := htcmap.AsStr((bz+dz)/2, -0.13, +0.13)

		}
	}
	fmt.Println("</svg>")
}

func f1(x, y float64) float64 {
	r := math.Hypot(x, y)
	return math.Sin(r) / r
}

func f2(x, y float64) float64 {
	return x * math.Exp(-x*x-y*y)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"jbossinfo"
	"net/http"
	"time"
)

var (
	JbossStatusUrls = map[string]string{
		"TST": "http://127.0.0.1:8080/status?XML=true",
	}
)

func getCurrentInfo(site string) *jbossinfo.JbossStatus {
	fmt.Printf("Trying to get xml from: %s\n", JbossStatusUrls[site])

	resp, respErr := http.Get(JbossStatusUrls[site])
	if respErr != nil {
		fmt.Printf("Can't get jboss xml: %s\n", respErr)
		return nil
	}

	info, infoErr := jbossinfo.ParseJbossInfoXML(resp.Body)
	if infoErr != nil {
		fmt.Printf("Parsing jboss xml failed: %s\n", infoErr)
		return nil
	}

	return info
}

func pullJboss(sites []string, interval time.Duration) {

	queue := make(chan *InsertRequest, 100)
	ok := sqliteWriteHandler(queue)

	ticker := time.Tick(interval)

	go func() {
		for now := range ticker {
			for _, site := range sites {
				info := getCurrentInfo(site)

				queue <- &InsertRequest{site, now, info}
			}
		}
		queue <- nil
	}()
	<-ok
}
<commit_msg>jboss2sqlite, fix pulling into sqlite<commit_after>package main

import (
	"fmt"
	"jbossinfo"
	"net/http"
	"time"
)

var (
	JbossStatusUrls = map[string]string{
		"TST": "http://127.0.0.1:8080/status?XML=true",
	}
)

func getCurrentInfo(site string) *jbossinfo.JbossStatus {
	fmt.Printf("Trying to get xml from: %s\n", JbossStatusUrls[site])

	resp, respErr := http.Get(JbossStatusUrls[site])
	if respErr != nil {
		fmt.Printf("Can't get jboss xml: %s\n", respErr)
		return nil
	}

	info, infoErr := jbossinfo.ParseJbossInfoXML(resp.Body)
	if infoErr != nil {
		fmt.Printf("Parsing jboss xml failed: %s\n", infoErr)
		return nil
	}

	return info
}

func pullSite(site string, now time.Time, queue chan *InsertRequest) {
	fmt.Printf("pulling %s: %s\n", site, now.Format(time.RFC3339))
	info := getCurrentInfo(site)

	queue <- &InsertRequest{site, now, info}
}

func pullJboss(sites []string, interval time.Duration) {
	for _, site := range sites {
		if JbossStatusUrls[site] == "" {
			fmt.Printf("Error, %s is an unkonwn site\n", site)
			return
		}
	}

	ticker := time.Tick(interval)

	for _ = range ticker {
		queue := make(chan *InsertRequest, 10)
		ok := sqliteWriteHandler(queue)

    // remember to parallelize pullSite, but remember that the sqlite close has to come after all are done
		for _, site := range sites {
			pullSite(site, time.Now(), queue)
		}

		queue <- nil
		<-ok
	}
}
<|endoftext|>