<commit_before>package vcfgo

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

// InfoMap holds the parsed Info field which can contain floats, ints and lists thereof.
type InfoMap map[string]interface{}

func (i InfoMap) Add(key string, o interface{}) {
	i[key] = o
	i["__order"] = append(i["__order"].([]string), key)
}

// Variant holds the information about a single site. It is analagous to a row in a VCF file.
type Variant struct {
	Chromosome string
	Pos        uint64
	Id         string
	Ref        string
	Alt        []string
	Quality    float32
	Filter     string
	Info       InfoMap
	Format     []string
	Samples    []*SampleGenotype
	// if lazy parsing, then just save the sample strings here.
	sampleStrings []string
	Header        *Header
	LineNumber    int64
}

// Is returns true if variants are the same by position and share at least 1 alternate allele.
func (v *Variant) Is(o *Variant) bool {
	if v.Pos != o.Pos || v.Chromosome != o.Chromosome || v.Ref != o.Ref {
		return false
	}
	for _, av := range v.Alt {
		for _, ov := range o.Alt {
			if av == ov {
				return true
			}
		}
	}
	return false
}

// Chrom returns the chromosome name.
func (v *Variant) Chrom() string {
	return v.Chromosome
}

// Start returns the 0-based start
func (v *Variant) Start() uint32 {
	return uint32(v.Pos - 1)
}

// End returns the 0-based start + the length of the reference allele.
func (v *Variant) End() uint32 {
	return uint32(v.Pos-1) + uint32(len(v.Ref))
}

func fmtFloat(v float32) string {
	var val string
	if v > 0.02 || v < -0.02 {
		val = fmt.Sprintf("%.2f", v)
	} else {
		val = fmt.Sprintf("%.5gf", v)
	}
	return val
}

func fmtFloat64(v float64) string {
	var val string
	if v > 0.02 || v < -0.02 {
		val = fmt.Sprintf("%.2f", v)
	} else {
		val = fmt.Sprintf("%.5gf", v)
	}
	return val
}

// String returns a string that matches the original info field.
func (m InfoMap) String() string {
	var order []string
	// use __order internally to keep order of keys.
	order, ok := m["__order"].([]string)
	if !ok {
		order = make([]string, 0)
		for k := range m {
			order = append(order, k)
		}
		sort.Strings(order)

	}
	s := ""
	for j, k := range order {
		v := m[k]
		if b, ok := v.(bool); ok && b {
			s += k
		} else {
			switch v.(type) {
			case float32:
				s += k + "=" + fmtFloat(v.(float32))
			case float64:
				s += k + "=" + fmtFloat64(v.(float64))
			case int:
				s += fmt.Sprintf("%s=%d", k, v.(int))
			case []interface{}:

				switch v.([]interface{})[0].(type) {
				case float64:
					for _, vv := range v.([]interface{}) {
						s += k + "=" + fmtFloat64(vv.(float64))
					}
				case int:
					for _, vv := range v.([]interface{}) {
						s += fmt.Sprintf("%s=%d", k, vv.(int))
					}
				}
			default:
				s += fmt.Sprintf("%s=%s", k, v.(string))
			}
		}
		if j < len(order)-1 && !strings.HasSuffix(s, ";") {
			s += ";"
		}
	}
	return s
}

// SampleGenotype holds the information about a sample. Several fields are pre-parsed, but
// all fields are kept in Fields as well.
type SampleGenotype struct {
	Phased bool
	GT     []int
	DP     int
	GL     []float32
	GQ     int
	MQ     int
	// TODO: add methods for Ref, Alt depth.
	Fields map[string]string
}

// String returns the string representation of the sample field.
func (sg *SampleGenotype) String(fields []string) string {
	s := make([]string, len(fields))
	for i, f := range fields {
		s[i] = sg.Fields[f]
	}
	return strings.Join(s, ":")
}

// NewSampleGenotype allocates the internals and returns a *SampleGenotype
func NewSampleGenotype() *SampleGenotype {
	s := &SampleGenotype{}
	s.GT = make([]int, 0, 2)
	s.GL = make([]float32, 0, 3)
	s.Fields = make(map[string]string)
	return s
}

// String gives a string representation of a variant
func (v *Variant) String() string {
	//#CHROM	POS	ID	REF	ALT	QUAL	FILTER	INFO	FORMAT	1_dad	1_mom	1_kid	2_dad	2_mom	2_kid	3_dad	3_mom	3_kid
	s := fmt.Sprintf("%s\t%d\t%s\t%s\t%s\t%.1f\t%s\t%s\t", v.Chromosome, v.Pos, v.Id, v.Ref, strings.Join(v.Alt, ","), v.Quality, v.Filter, v.Info)
	if len(v.Samples) > 0 {
		samps := make([]string, len(v.Samples))
		for i, s := range v.Samples {
			samps[i] = s.String(v.Format)
		}
		s += fmt.Sprintf("%s\t%s", strings.Join(v.Format, ":"), strings.Join(samps, "\t"))
	} else if v.sampleStrings != nil && len(v.sampleStrings) != 0 {
		s += fmt.Sprintf("%s\t%s", strings.Join(v.Format, ":"), strings.Join(v.sampleStrings, "\t"))
	}
	return s
}

// GetGenotypeField uses the information from the header to parse the correct time from a genotype field.
// It returns an interface that can be asserted to the expected type.
func (v *Variant) GetGenotypeField(g *SampleGenotype, field string, missing interface{}) (interface{}, error) {
	if g == nil {
		return missing, fmt.Errorf("GetGenotypeField: empty genotype when requesting %s", field)
	}
	h := v.Header
	format, ok := h.SampleFormats[field]
	if !ok {
		return nil, fmt.Errorf("GetGenotypeField: field not found in formats: %s", field)
	}
	value, ok := g.Fields[field]
	if !ok {
		return nil, fmt.Errorf("GetGenotypeField: field not found in genotypes: %s", field)
	}
	switch format.Type {
	case "Integer":
		var mv int
		var ok bool
		if mv, ok = missing.(int); !ok {
			return nil, fmt.Errorf("GetGenotypeField: bad non-int missing value: %v", missing)
		}
		return handleNumberType(format.Number, value, len(v.Alt), len(g.GT), true, mv)

	case "Float":
		var mv float32
		var ok bool
		if mv, ok = missing.(float32); !ok {
			return nil, fmt.Errorf("GetGenotypeField: bad non-float missing value: %v", missing)
		}
		return handleNumberType(format.Number, value, len(v.Alt), len(g.GT), false, mv)

	case "String", "Character", "Unknown":
		return value, nil

	case "Flag":
		return field, nil

	}

	return nil, fmt.Errorf("unknown format: %s", format.Type)
}

func handleNumberType(number string, value string, nAlts int, nGTs int, isInt bool, mv interface{}) (interface{}, error) {
	if number == "1" || !strings.Contains(value, ",") || number == "." || number == "" {
		if isInt {
			if value == "" || value == "." {
				return (mv).(int), nil
			}
			return strconv.Atoi(value)
		}
		if value == "" || value == "." {
			return (mv).(float32), nil
		}
		return strconv.ParseFloat(value, 32)
	}
	if count, err := strconv.Atoi(number); err == nil || number == "G" || number == "A" || number == "R" {
		if err != nil {
			switch number {
			case "G":
				count = nGTs * (nGTs + 1) / 2
			case "A":
				count = nAlts
			case "R":
				count = nAlts + 1
			}
			err = nil
		}
		var ret interface{}
		split := strings.Split(value, ",")
		if isInt {
			ret = make([]int, len(split), len(split))
		} else {
			ret = make([]float32, len(split), len(split))
		}

		var countErr error

		// caller can ignore error if they want, we still fill what we can.
		if len(split) != count {
			countErr = fmt.Errorf("number of fields (%d) does not match expected (%d) in '%s'", len(split), count, value)
		}
		for i, s := range split {
			if isInt {
				ri, err := strconv.Atoi(s) //, 10, 32)
				if err != nil {
					// if it's an error, we allow empty
					if s == "" || s == "." {
						ret.([]int)[i] = mv.(int)
						err = nil
					} else {
						return nil, fmt.Errorf("non integer type: %s", s)
					}
				} else {
					ret.([]int)[i] = int(ri)
				}
			} else {
				rf, err := strconv.ParseFloat(s, 32)
				if err != nil {
					// if it's an error, we allow empty
					if s == "" || s == "." {
						ret.([]float32)[i] = mv.(float32)
						err = nil
					} else {
						return nil, fmt.Errorf("non float type: %s", s)
					}
				} else {
					ret.([]float32)[i] = float32(rf)
				}
			}
		}
		return ret, countErr
	} else if number == "." || number == "" {
		return value, nil
	} else {
		return nil, fmt.Errorf("unknown number field: %s", number)
	}
}
<commit_msg>handle order and fix output formatting<commit_after>package vcfgo

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

// InfoMap holds the parsed Info field which can contain floats, ints and lists thereof.
type InfoMap map[string]interface{}

func (i InfoMap) Add(key string, o interface{}) {
	i[key] = o
	order := i["__order"].([]string)
	for i := len(order) - 1; i > -1; i-- {
		if key == order[i] {
			return
		}
	}
	i["__order"] = append(order, key)
}

// Variant holds the information about a single site. It is analagous to a row in a VCF file.
type Variant struct {
	Chromosome string
	Pos        uint64
	Id         string
	Ref        string
	Alt        []string
	Quality    float32
	Filter     string
	Info       InfoMap
	Format     []string
	Samples    []*SampleGenotype
	// if lazy parsing, then just save the sample strings here.
	sampleStrings []string
	Header        *Header
	LineNumber    int64
}

// Is returns true if variants are the same by position and share at least 1 alternate allele.
func (v *Variant) Is(o *Variant) bool {
	if v.Pos != o.Pos || v.Chromosome != o.Chromosome || v.Ref != o.Ref {
		return false
	}
	for _, av := range v.Alt {
		for _, ov := range o.Alt {
			if av == ov {
				return true
			}
		}
	}
	return false
}

// Chrom returns the chromosome name.
func (v *Variant) Chrom() string {
	return v.Chromosome
}

// Start returns the 0-based start
func (v *Variant) Start() uint32 {
	return uint32(v.Pos - 1)
}

// End returns the 0-based start + the length of the reference allele.
func (v *Variant) End() uint32 {
	return uint32(v.Pos-1) + uint32(len(v.Ref))
}

func fmtFloat(v float32) string {
	var val string
	if v > 0.02 || v < -0.02 {
		val = fmt.Sprintf("%.4f", v)
	} else {
		val = fmt.Sprintf("%.5g", v)
	}
	return strings.TrimRight(val, "0")
}

func fmtFloat64(v float64) string {
	var val string
	if v > 0.02 || v < -0.02 {
		val = fmt.Sprintf("%.4f", v)
	} else {
		val = fmt.Sprintf("%.5g", v)
	}
	return strings.TrimRight(val, "0")
}

// String returns a string that matches the original info field.
func (m InfoMap) String() string {
	var order []string
	// use __order internally to keep order of keys.
	order, ok := m["__order"].([]string)
	if !ok {
		order = make([]string, 0)
		for k := range m {
			order = append(order, k)
		}
		sort.Strings(order)

	}
	s := ""
	for j, k := range order {
		v := m[k]
		if b, ok := v.(bool); ok && b {
			s += k
		} else {
			switch v.(type) {
			case float32:
				s += k + "=" + fmtFloat(v.(float32))
			case float64:
				s += k + "=" + fmtFloat64(v.(float64))
			case int:
				s += fmt.Sprintf("%s=%d", k, v.(int))
			case []interface{}:

				switch v.([]interface{})[0].(type) {
				case float64:
					for _, vv := range v.([]interface{}) {
						s += k + "=" + fmtFloat64(vv.(float64))
					}
				case int:
					for _, vv := range v.([]interface{}) {
						s += fmt.Sprintf("%s=%d", k, vv.(int))
					}
				}
			default:
				s += fmt.Sprintf("%s=%s", k, v.(string))
			}
		}
		if j < len(order)-1 && !strings.HasSuffix(s, ";") {
			s += ";"
		}
	}
	return s
}

// SampleGenotype holds the information about a sample. Several fields are pre-parsed, but
// all fields are kept in Fields as well.
type SampleGenotype struct {
	Phased bool
	GT     []int
	DP     int
	GL     []float32
	GQ     int
	MQ     int
	// TODO: add methods for Ref, Alt depth.
	Fields map[string]string
}

// String returns the string representation of the sample field.
func (sg *SampleGenotype) String(fields []string) string {
	s := make([]string, len(fields))
	for i, f := range fields {
		s[i] = sg.Fields[f]
	}
	return strings.Join(s, ":")
}

// NewSampleGenotype allocates the internals and returns a *SampleGenotype
func NewSampleGenotype() *SampleGenotype {
	s := &SampleGenotype{}
	s.GT = make([]int, 0, 2)
	s.GL = make([]float32, 0, 3)
	s.Fields = make(map[string]string)
	return s
}

// String gives a string representation of a variant
func (v *Variant) String() string {
	//#CHROM	POS	ID	REF	ALT	QUAL	FILTER	INFO	FORMAT	1_dad	1_mom	1_kid	2_dad	2_mom	2_kid	3_dad	3_mom	3_kid
	s := fmt.Sprintf("%s\t%d\t%s\t%s\t%s\t%.1f\t%s\t%s\t", v.Chromosome, v.Pos, v.Id, v.Ref, strings.Join(v.Alt, ","), v.Quality, v.Filter, v.Info)
	if len(v.Samples) > 0 {
		samps := make([]string, len(v.Samples))
		for i, s := range v.Samples {
			samps[i] = s.String(v.Format)
		}
		s += fmt.Sprintf("%s\t%s", strings.Join(v.Format, ":"), strings.Join(samps, "\t"))
	} else if v.sampleStrings != nil && len(v.sampleStrings) != 0 {
		s += fmt.Sprintf("%s\t%s", strings.Join(v.Format, ":"), strings.Join(v.sampleStrings, "\t"))
	}
	return s
}

// GetGenotypeField uses the information from the header to parse the correct time from a genotype field.
// It returns an interface that can be asserted to the expected type.
func (v *Variant) GetGenotypeField(g *SampleGenotype, field string, missing interface{}) (interface{}, error) {
	if g == nil {
		return missing, fmt.Errorf("GetGenotypeField: empty genotype when requesting %s", field)
	}
	h := v.Header
	format, ok := h.SampleFormats[field]
	if !ok {
		return nil, fmt.Errorf("GetGenotypeField: field not found in formats: %s", field)
	}
	value, ok := g.Fields[field]
	if !ok {
		return nil, fmt.Errorf("GetGenotypeField: field not found in genotypes: %s", field)
	}
	switch format.Type {
	case "Integer":
		var mv int
		var ok bool
		if mv, ok = missing.(int); !ok {
			return nil, fmt.Errorf("GetGenotypeField: bad non-int missing value: %v", missing)
		}
		return handleNumberType(format.Number, value, len(v.Alt), len(g.GT), true, mv)

	case "Float":
		var mv float32
		var ok bool
		if mv, ok = missing.(float32); !ok {
			return nil, fmt.Errorf("GetGenotypeField: bad non-float missing value: %v", missing)
		}
		return handleNumberType(format.Number, value, len(v.Alt), len(g.GT), false, mv)

	case "String", "Character", "Unknown":
		return value, nil

	case "Flag":
		return field, nil

	}

	return nil, fmt.Errorf("unknown format: %s", format.Type)
}

func handleNumberType(number string, value string, nAlts int, nGTs int, isInt bool, mv interface{}) (interface{}, error) {
	if number == "1" || !strings.Contains(value, ",") || number == "." || number == "" {
		if isInt {
			if value == "" || value == "." {
				return (mv).(int), nil
			}
			return strconv.Atoi(value)
		}
		if value == "" || value == "." {
			return (mv).(float32), nil
		}
		return strconv.ParseFloat(value, 32)
	}
	if count, err := strconv.Atoi(number); err == nil || number == "G" || number == "A" || number == "R" {
		if err != nil {
			switch number {
			case "G":
				count = nGTs * (nGTs + 1) / 2
			case "A":
				count = nAlts
			case "R":
				count = nAlts + 1
			}
			err = nil
		}
		var ret interface{}
		split := strings.Split(value, ",")
		if isInt {
			ret = make([]int, len(split), len(split))
		} else {
			ret = make([]float32, len(split), len(split))
		}

		var countErr error

		// caller can ignore error if they want, we still fill what we can.
		if len(split) != count {
			countErr = fmt.Errorf("number of fields (%d) does not match expected (%d) in '%s'", len(split), count, value)
		}
		for i, s := range split {
			if isInt {
				ri, err := strconv.Atoi(s) //, 10, 32)
				if err != nil {
					// if it's an error, we allow empty
					if s == "" || s == "." {
						ret.([]int)[i] = mv.(int)
						err = nil
					} else {
						return nil, fmt.Errorf("non integer type: %s", s)
					}
				} else {
					ret.([]int)[i] = int(ri)
				}
			} else {
				rf, err := strconv.ParseFloat(s, 32)
				if err != nil {
					// if it's an error, we allow empty
					if s == "" || s == "." {
						ret.([]float32)[i] = mv.(float32)
						err = nil
					} else {
						return nil, fmt.Errorf("non float type: %s", s)
					}
				} else {
					ret.([]float32)[i] = float32(rf)
				}
			}
		}
		return ret, countErr
	} else if number == "." || number == "" {
		return value, nil
	} else {
		return nil, fmt.Errorf("unknown number field: %s", number)
	}
}
<|endoftext|>


<commit_before>package tq

import (
	"net/http"

	"github.com/git-lfs/git-lfs/lfsapi"
	"github.com/git-lfs/git-lfs/tools"
	"github.com/rubyist/tracerx"
)

const (
	maxVerifiesConfigKey     = "lfs.transfer.maxverifies"
	defaultMaxVerifyAttempts = 3
)

func verifyUpload(c *lfsapi.Client, remote string, t *Transfer) error {
	action, err := t.Actions.Get("verify")
	if err != nil {
		return err
	}
	if action == nil {
		return nil
	}

	req, err := http.NewRequest("POST", action.Href, nil)
	if err != nil {
		return err
	}

	err = lfsapi.MarshalToRequest(req, struct {
		Oid  string `json:"oid"`
		Size int64  `json:"size"`
	}{Oid: t.Oid, Size: t.Size})
	if err != nil {
		return err
	}

	for key, value := range action.Header {
		req.Header.Set(key, value)
	}
	req.Header.Set("Content-Type", "application/vnd.git-lfs+json")

	mv := c.GitEnv().Int(maxVerifiesConfigKey, defaultMaxVerifyAttempts)
	mv = tools.MaxInt(defaultMaxVerifyAttempts, mv)
	req = c.LogRequest(req, "lfs.verify")

	for i := 1; i <= mv; i++ {
		tracerx.Printf("tq: verify %s attempt #%d (max: %d)", t.Oid[:7], i, mv)

		var res *http.Response
		if t.Authenticated {
			res, err = c.Do(req)
		} else {
			res, err = c.DoWithAuth(remote, c.Endpoints.AccessFor(action.Href), req)
		}

		if err != nil {
			tracerx.Printf("tq: verify err: %+v", err.Error())
		} else {
			err = res.Body.Close()
			break
		}
	}
	return err
}
<commit_msg>tq: ensure we pass the correct Accept header in verify requests<commit_after>package tq

import (
	"net/http"

	"github.com/git-lfs/git-lfs/lfsapi"
	"github.com/git-lfs/git-lfs/tools"
	"github.com/rubyist/tracerx"
)

const (
	maxVerifiesConfigKey     = "lfs.transfer.maxverifies"
	defaultMaxVerifyAttempts = 3
)

func verifyUpload(c *lfsapi.Client, remote string, t *Transfer) error {
	action, err := t.Actions.Get("verify")
	if err != nil {
		return err
	}
	if action == nil {
		return nil
	}

	req, err := http.NewRequest("POST", action.Href, nil)
	if err != nil {
		return err
	}

	err = lfsapi.MarshalToRequest(req, struct {
		Oid  string `json:"oid"`
		Size int64  `json:"size"`
	}{Oid: t.Oid, Size: t.Size})
	if err != nil {
		return err
	}

	req.Header.Set("Content-Type", "application/vnd.git-lfs+json")
	req.Header.Set("Accept", "application/vnd.git-lfs+json")
	for key, value := range action.Header {
		req.Header.Set(key, value)
	}

	mv := c.GitEnv().Int(maxVerifiesConfigKey, defaultMaxVerifyAttempts)
	mv = tools.MaxInt(defaultMaxVerifyAttempts, mv)
	req = c.LogRequest(req, "lfs.verify")

	for i := 1; i <= mv; i++ {
		tracerx.Printf("tq: verify %s attempt #%d (max: %d)", t.Oid[:7], i, mv)

		var res *http.Response
		if t.Authenticated {
			res, err = c.Do(req)
		} else {
			res, err = c.DoWithAuth(remote, c.Endpoints.AccessFor(action.Href), req)
		}

		if err != nil {
			tracerx.Printf("tq: verify err: %+v", err.Error())
		} else {
			err = res.Body.Close()
			break
		}
	}
	return err
}
<|endoftext|>


<commit_before>package govector

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

const (
	NA = math.SmallestNonzeroFloat64
)

// rnd is a private prng so we don't alter global prng state
var (
	rnd      = rand.New(rand.NewSource(time.Now().UnixNano()))
	rndMutex = &sync.Mutex{}
)

type Vector []float64

// Copy returns a copy the input vector.  This is useful for functions that
// perform modification and shuffling on the order of the input vector.
func (x Vector) Copy() Vector {
	y := make(Vector, len(x))
	copy(y, x)
	return y
}

// Smooth takes a sliding window average of vector. Indices i and j refer to the
// the number of points you'd like to consider before and after a point in
// the average.
func (x Vector) Smooth(left, right uint) Vector {
	n := uint(len(x))
	smoothed := make(Vector, n)

	for index := uint(0); index < n; index++ {
		var leftmost uint
		if left < index {
			leftmost = index - left
		}

		rightmost := index + right + 1
		if rightmost > n {
			rightmost = n
		}

		window := x[leftmost:rightmost]
		smoothed[index] = window.Mean()
	}

	return smoothed
}

// Len, Swap, and Less are implemented to allow for direct
// sorting on Vector types.
func (x Vector) Len() int {
	return len(x)
}

func (x Vector) Swap(i, j int) {
	x[i], x[j] = x[j], x[i]
}

func (x Vector) Less(i, j int) bool {
	return x[i] < x[j]
}

func (x Vector) Sort() {
	sort.Sort(x)
}

// Sum returns the sum of the vector.
func (x Vector) Sum() float64 {
	s := 0.0
	for _, v := range x {
		s += v
	}
	return s
}

// Abs returns the absolute values of the vector elements.
func (x Vector) Abs() Vector {
	y := x.Copy()

	for i, _ := range y {
		y[i] = math.Abs(y[i])
	}

	return y
}

// Cumsum returns the cumulative sum of the vector.
func (x Vector) Cumsum() Vector {
	y := make(Vector, len(x))

	y[0] = x[0]

	i := 1
	for i < len(x) {
		y[i] = x[i] + y[i-1]
		i++
	}

	return y
}

// Mean returns the mean of the vector.
func (x Vector) Mean() float64 {
	s := x.Sum()

	n := float64(len(x))

	return s / n
}

// weightedSum returns the weighted sum of the vector.  This is really only useful in
// calculating the weighted mean.
func (x Vector) weightedSum(w Vector) (float64, error) {
	if len(x) != len(w) {
		return NA, fmt.Errorf("Length of weights unequal to vector length")
	}

	ws := 0.0
	for i, _ := range x {
		ws += x[i] * w[i]
	}
	return ws, nil
}

// WeightedMean returns the weighted mean of the vector for a given vector of weights.
func (x Vector) WeightedMean(w Vector) (float64, error) {
	ws, err := x.weightedSum(w)
	if err != nil {
		return NA, err
	}
	sw := w.Sum()

	return ws / sw, nil
}

// Variance caclulates the variance of the vector
func (x Vector) Variance() float64 {
	n := float64(len(x))
	if n == 1 {
		return 0
	} else if n < 2 {
		n = 2
	}

	m := x.Mean()

	ss := 0.0
	for _, v := range x {
		ss += math.Pow(v-m, 2.0)
	}

	return ss / (n - 1)
}

// Sd calculates the standard deviation of the vector
func (x Vector) Sd() float64 {
	return math.Sqrt(x.Variance())
}

// Max returns the maximum value of the vector
func (x Vector) Max() float64 {
	max := x[0]
	for _, v := range x {
		if v > max {
			max = v
		}
	}
	return max
}

// Min returns the minimum value of the vector
func (x Vector) Min() float64 {
	min := x[0]
	for _, v := range x {
		if v < min {
			min = v
		}
	}
	return min
}

// Ecdf returns the empirical cumulative distribution function.  The ECDF function
// will return the percentile of a given value relative to the vector.
func (x Vector) Ecdf() func(float64) float64 {
	y := x.Copy()

	y.Sort()
	n := len(y)

	empirical := func(q float64) float64 {
		i := 0
		for i < n {
			if q < y[i] {
				return float64(i) / float64(n)
			}
			i++
		}
		return 1.0
	}

	return empirical
}

// Apply returns the values of the vector applied to an arbitrary function, which must
// return a float64, since a Vector will be returned.
func (x Vector) Apply(f func(float64) float64) Vector {
	y := make(Vector, len(x))

	for i, v := range x {
		y[i] = f(v)
	}
	return y
}

// Filter returns the values that match the filter function.  Vector elements with return
// values of TRUE are filtered/removed.
func (x Vector) Filter(f func(float64) bool) Vector {
	y := make(Vector, 0, len(x))

	for _, v := range x {
		if !f(v) {
			y = append(y, v)
		}
	}

	return y
}

// Quantiles returns the quantiles of a vector corresponding to input quantiles using a
// weighted average approach for index interpolation.
func (x Vector) Quantiles(q Vector) Vector {
	y := x.Copy()

	y.Sort()

	n := float64(len(y))
	output := make(Vector, len(q))
	for i, quantile := range q {

		if n == 0.0 {
			output[i] = 0
			continue
		}

		fuzzyQuantile := quantile * n

		// the quantile lies directly on the value
		if fuzzyQuantile-math.Floor(fuzzyQuantile) == 0.5 {
			output[i] = float64(y[int(math.Floor(fuzzyQuantile))])
			continue
		}

		lowerIndex := math.Max(0, math.Floor(fuzzyQuantile)-1)
		upperIndex := math.Min(lowerIndex+1, n-1)

		values := Vector{float64(y[int(lowerIndex)]), float64(y[int(upperIndex)])}

		indexDiff := fuzzyQuantile - math.Floor(fuzzyQuantile)

		lowerWeight := 1.0
		upperWeight := 1.0

		if indexDiff > 0.0 {
			lowerWeight = 1.0 - indexDiff
			upperWeight = indexDiff
		}

		output[i], _ = values.WeightedMean(Vector{lowerWeight, upperWeight})
	}

	return output
}

// Diff returns a vector of length (n - 1) of the differences in the input vector
func (x Vector) Diff() Vector {
	n := len(x)

	if n < 2 {
		return Vector{NA}
	} else {
		d := make(Vector, n-1)

		i := 1
		for i < n {
			d[i-1] = x[i] - x[i-1]
			i++
		}
		return d
	}
}

// RelDiff returns a vector of the relative differences of the input vector
func (x Vector) RelDiff() Vector {
	n := len(x)

	if n < 2 {
		return Vector{NA}
	} else {
		d := make(Vector, n-1)

		i := 1
		for i < n {
			d[i-1] = (x[i] - x[i-1]) / x[i]
			i++
		}
		return d
	}
}

// Sample returns a sample of n elements of the original input vector.
func (x Vector) Sample(n int) Vector {
	// unprotected access to custom rand.Rand objects can cause panics
	// https://github.com/golang/go/issues/3611
	rndMutex.Lock()
	perm := rnd.Perm(len(x))
	rndMutex.Unlock()

	// sample n elements
	perm = perm[:n]

	y := make(Vector, n)
	for yi, permi := range perm {
		y[yi] = x[permi]
	}

	return y
}

// Shuffle returns a shuffled copy of the original input vector.
func (x Vector) Shuffle() Vector {
	return x.Sample(len(x))
}

// Join returns an (efficiently joined) vector of the input vectors.
func Join(vectors ...Vector) Vector {
	// figure out how big to make the resulting vector so we can
	// allocate efficiently
	n := 0
	for _, vector := range vectors {
		n += vector.Len()
	}

	i := 0
	v := make(Vector, n)
	for _, vector := range vectors {
		for _, value := range vector {
			v[i] = value
			i++
		}
	}

	return v
}

// Rank returns a vector of the ranked values of the input vector.
func (x Vector) Rank() Vector {
	y := x.Copy()

	y.Sort()

	// essentially equivalent to a minimum rank (tie) method
	rank := 0
	ranks := make(Vector, len(x))
	for i, _ := range y {
		for j, _ := range x {
			if y[i] == x[j] {
				ranks[j] = float64(rank)
				rank++
				break
			}
		}
	}
	return ranks
}

// Push appends the input vector with the value to be pushed.
func (x *Vector) Push(y float64) {
	*x = append(*x, y)
	return
}
<commit_msg>PushFixed can now handle the vector being grown by external modification<commit_after>package govector

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

const (
	NA = math.SmallestNonzeroFloat64
)

// rnd is a private prng so we don't alter global prng state
var (
	rnd      = rand.New(rand.NewSource(time.Now().UnixNano()))
	rndMutex = &sync.Mutex{}
)

type Vector []float64

// Copy returns a copy the input vector.  This is useful for functions that
// perform modification and shuffling on the order of the input vector.
func (x Vector) Copy() Vector {
	y := make(Vector, len(x))
	copy(y, x)
	return y
}

// Smooth takes a sliding window average of vector. Indices i and j refer to the
// the number of points you'd like to consider before and after a point in
// the average.
func (x Vector) Smooth(left, right uint) Vector {
	n := uint(len(x))
	smoothed := make(Vector, n)

	for index := uint(0); index < n; index++ {
		var leftmost uint
		if left < index {
			leftmost = index - left
		}

		rightmost := index + right + 1
		if rightmost > n {
			rightmost = n
		}

		window := x[leftmost:rightmost]
		smoothed[index] = window.Mean()
	}

	return smoothed
}

// Len, Swap, and Less are implemented to allow for direct
// sorting on Vector types.
func (x Vector) Len() int {
	return len(x)
}

func (x Vector) Swap(i, j int) {
	x[i], x[j] = x[j], x[i]
}

func (x Vector) Less(i, j int) bool {
	return x[i] < x[j]
}

func (x Vector) Sort() {
	sort.Sort(x)
}

// Sum returns the sum of the vector.
func (x Vector) Sum() float64 {
	s := 0.0
	for _, v := range x {
		s += v
	}
	return s
}

// Abs returns the absolute values of the vector elements.
func (x Vector) Abs() Vector {
	y := x.Copy()

	for i, _ := range y {
		y[i] = math.Abs(y[i])
	}

	return y
}

// Cumsum returns the cumulative sum of the vector.
func (x Vector) Cumsum() Vector {
	y := make(Vector, len(x))

	y[0] = x[0]

	i := 1
	for i < len(x) {
		y[i] = x[i] + y[i-1]
		i++
	}

	return y
}

// Mean returns the mean of the vector.
func (x Vector) Mean() float64 {
	s := x.Sum()

	n := float64(len(x))

	return s / n
}

// weightedSum returns the weighted sum of the vector.  This is really only useful in
// calculating the weighted mean.
func (x Vector) weightedSum(w Vector) (float64, error) {
	if len(x) != len(w) {
		return NA, fmt.Errorf("Length of weights unequal to vector length")
	}

	ws := 0.0
	for i, _ := range x {
		ws += x[i] * w[i]
	}
	return ws, nil
}

// WeightedMean returns the weighted mean of the vector for a given vector of weights.
func (x Vector) WeightedMean(w Vector) (float64, error) {
	ws, err := x.weightedSum(w)
	if err != nil {
		return NA, err
	}
	sw := w.Sum()

	return ws / sw, nil
}

// Variance caclulates the variance of the vector
func (x Vector) Variance() float64 {
	n := float64(len(x))
	if n == 1 {
		return 0
	} else if n < 2 {
		n = 2
	}

	m := x.Mean()

	ss := 0.0
	for _, v := range x {
		ss += math.Pow(v-m, 2.0)
	}

	return ss / (n - 1)
}

// Sd calculates the standard deviation of the vector
func (x Vector) Sd() float64 {
	return math.Sqrt(x.Variance())
}

// Max returns the maximum value of the vector
func (x Vector) Max() float64 {
	max := x[0]
	for _, v := range x {
		if v > max {
			max = v
		}
	}
	return max
}

// Min returns the minimum value of the vector
func (x Vector) Min() float64 {
	min := x[0]
	for _, v := range x {
		if v < min {
			min = v
		}
	}
	return min
}

// Ecdf returns the empirical cumulative distribution function.  The ECDF function
// will return the percentile of a given value relative to the vector.
func (x Vector) Ecdf() func(float64) float64 {
	y := x.Copy()

	y.Sort()
	n := len(y)

	empirical := func(q float64) float64 {
		i := 0
		for i < n {
			if q < y[i] {
				return float64(i) / float64(n)
			}
			i++
		}
		return 1.0
	}

	return empirical
}

// Apply returns the values of the vector applied to an arbitrary function, which must
// return a float64, since a Vector will be returned.
func (x Vector) Apply(f func(float64) float64) Vector {
	y := make(Vector, len(x))

	for i, v := range x {
		y[i] = f(v)
	}
	return y
}

// Filter returns the values that match the filter function.  Vector elements with return
// values of TRUE are filtered/removed.
func (x Vector) Filter(f func(float64) bool) Vector {
	y := make(Vector, 0, len(x))

	for _, v := range x {
		if !f(v) {
			y = append(y, v)
		}
	}

	return y
}

// Quantiles returns the quantiles of a vector corresponding to input quantiles using a
// weighted average approach for index interpolation.
func (x Vector) Quantiles(q Vector) Vector {
	y := x.Copy()

	y.Sort()

	n := float64(len(y))
	output := make(Vector, len(q))
	for i, quantile := range q {

		if n == 0.0 {
			output[i] = 0
			continue
		}

		fuzzyQuantile := quantile * n

		// the quantile lies directly on the value
		if fuzzyQuantile-math.Floor(fuzzyQuantile) == 0.5 {
			output[i] = float64(y[int(math.Floor(fuzzyQuantile))])
			continue
		}

		lowerIndex := math.Max(0, math.Floor(fuzzyQuantile)-1)
		upperIndex := math.Min(lowerIndex+1, n-1)

		values := Vector{float64(y[int(lowerIndex)]), float64(y[int(upperIndex)])}

		indexDiff := fuzzyQuantile - math.Floor(fuzzyQuantile)

		lowerWeight := 1.0
		upperWeight := 1.0

		if indexDiff > 0.0 {
			lowerWeight = 1.0 - indexDiff
			upperWeight = indexDiff
		}

		output[i], _ = values.WeightedMean(Vector{lowerWeight, upperWeight})
	}

	return output
}

// Diff returns a vector of length (n - 1) of the differences in the input vector
func (x Vector) Diff() Vector {
	n := len(x)

	if n < 2 {
		return Vector{NA}
	} else {
		d := make(Vector, n-1)

		i := 1
		for i < n {
			d[i-1] = x[i] - x[i-1]
			i++
		}
		return d
	}
}

// RelDiff returns a vector of the relative differences of the input vector
func (x Vector) RelDiff() Vector {
	n := len(x)

	if n < 2 {
		return Vector{NA}
	} else {
		d := make(Vector, n-1)

		i := 1
		for i < n {
			d[i-1] = (x[i] - x[i-1]) / x[i]
			i++
		}
		return d
	}
}

// Sample returns a sample of n elements of the original input vector.
func (x Vector) Sample(n int) Vector {
	// unprotected access to custom rand.Rand objects can cause panics
	// https://github.com/golang/go/issues/3611
	rndMutex.Lock()
	perm := rnd.Perm(len(x))
	rndMutex.Unlock()

	// sample n elements
	perm = perm[:n]

	y := make(Vector, n)
	for yi, permi := range perm {
		y[yi] = x[permi]
	}

	return y
}

// Shuffle returns a shuffled copy of the original input vector.
func (x Vector) Shuffle() Vector {
	return x.Sample(len(x))
}

// Join returns an (efficiently joined) vector of the input vectors.
func Join(vectors ...Vector) Vector {
	// figure out how big to make the resulting vector so we can
	// allocate efficiently
	n := 0
	for _, vector := range vectors {
		n += vector.Len()
	}

	i := 0
	v := make(Vector, n)
	for _, vector := range vectors {
		for _, value := range vector {
			v[i] = value
			i++
		}
	}

	return v
}

// Rank returns a vector of the ranked values of the input vector.
func (x Vector) Rank() Vector {
	y := x.Copy()

	y.Sort()

	// essentially equivalent to a minimum rank (tie) method
	rank := 0
	ranks := make(Vector, len(x))
	for i, _ := range y {
		for j, _ := range x {
			if y[i] == x[j] {
				ranks[j] = float64(rank)
				rank++
				break
			}
		}
	}
	return ranks
}

// Push appends the input vector with the value to be pushed.
func (x *Vector) Push(y float64) {
	*x = append(*x, y)
	return
}

//Append values to an array. Array size will not grow if unnecessary.
//It will grow if the cap has been extended by external modification.
func (x *Vector) PushFixed(y float64) error {
	lenx := len(*x)
	if lenx <= cap(*x) {
		slicex := (*x)[1:]
		z := make([]float64, lenx, lenx)
		copy(z, slicex)
		z[lenx-1] = y
		*x = z
		return nil
	} else {
		return fmt.Errorf("GoVector length greater than capacity!? len: %d cap: %d\n%#v", len(*x), cap(*x), x)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016-2020 The Libsacloud 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 libsacloud

// Version バージョン
const Version = "2.0.1"
<commit_msg>Bump to v2.0.2<commit_after>// Copyright 2016-2020 The Libsacloud 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 libsacloud

// Version バージョン
const Version = "2.0.2"
<|endoftext|>


<commit_before>package gobot

const version = "0.6.1"

func Version() string {
	return version
}
<commit_msg>Bump version to 0.6.2<commit_after>package gobot

const version = "0.6.2"

func Version() string {
	return version
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package dosa

// VERSION indicates the dosa client version
const VERSION = "3.2.0"
<commit_msg>Change version back to dev (#357)<commit_after>// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package dosa

// VERSION indicates the dosa client version
const VERSION = "dev"
<|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

// versionString is the sem-ver version string for yab.
// It will be bumped explicitly on releases.
var versionString = "0.4.0"
<commit_msg>Bump version to 0.5.0<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

// versionString is the sem-ver version string for yab.
// It will be bumped explicitly on releases.
var versionString = "0.5.0"
<|endoftext|>


<commit_before>package main

const VERSION = "0.5.2-alpha1"
<commit_msg>:tada: Bump up the version<commit_after>package main

const VERSION = "0.5.2"
<|endoftext|>


<commit_before>package brig

import "fmt"

const (
	// MajorVersion will be incremented on big releases.
	MajorVersion = 0
	// MinorVersion will be incremented on small releases.
	MinorVersion = 0
	// PatchVersion should be incremented on every released change.
	PatchVersion = 0
)

// Version returns a tuple of (major, minor, patch)
func Version() (int, int, int) {
	return MajorVersion, MinorVersion, PatchVersion
}

// VersionString returns a Maj.Min.Patch string.
func VersionString() string {
	return fmt.Sprintf("%d.%d.%d", MajorVersion, MinorVersion, PatchVersion)
}
<commit_msg>version: Make it look a bit more like SemVer<commit_after>package brig

import "fmt"

const (
	// Major will be incremented on big releases.
	Major = 0
	// Minor will be incremented on small releases.
	Minor = 0
	// Patch should be incremented on every released change.
	Patch = 0
	// PreRelease is an empty string for final releases, {alpha,beta} for pre-releases.
	PreRelease = "beta"
)

// Version returns a tuple of (major, minor, patch)
func Version() (int, int, int) {
	return Major, Minor, Patch
}

// VersionString returns a Maj.Min.Patch string.
func VersionString() string {
	return fmt.Sprintf("v%d.%d.%d-%s", Major, Minor, Patch, PreRelease)
}
<|endoftext|>


<commit_before>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.5.3"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "dev"
<commit_msg>Bumping up version<commit_after>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.5.3"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "rc1"
<|endoftext|>


<commit_before>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "0.3.3"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""
<commit_msg>0.4.0<commit_after>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "0.4.0"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""
<|endoftext|>


<commit_before>package main
const VERSION = "0.13"
<commit_msg>Release version 0.14<commit_after>package main
const VERSION = "0.14"
<|endoftext|>


<commit_before>// Copyright 2018 The Moov Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

// Version Number
const Version = "v0.6.0-rc5"
<commit_msg>release v0.6.0-rc6<commit_after>// Copyright 2018 The Moov Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

// Version Number
const Version = "v0.6.0-rc6"
<|endoftext|>


<commit_before>package sudoku

import (
	"testing"
)

func TestForcingChains(t *testing.T) {

	//Steps to test this:
	//* In the forcing chain helper, calculate the steps once, then
	//pass them in each time in a list of ~10 calls to solveTechniqueTEstHelper that we know are valid here.
	//* VERIFY MANUALLY that each step that is returned is actually a valid application of forcingchains.

	options := solveTechniqueTestHelperOptions{
		checkAllSteps: true,
	}

	grid, solver, steps := humanSolveTechniqueTestHelperStepGenerator(t,
		"forcingchain_test1.sdk", "Forcing Chain", options)

	options.stepsToCheck.grid = grid
	options.stepsToCheck.solver = solver
	options.stepsToCheck.steps = steps

	//OK, now we'll walk through all of the options in a loop and make sure they all show
	//up in the solve steps.

	type loopOptions struct {
		targetCells  []cellRef
		targetNums   IntSlice
		pointerCells []cellRef
		pointerNums  IntSlice
		description  string
	}

	tests := []loopOptions{
		{
			targetCells:  []cellRef{{0, 1}},
			targetNums:   IntSlice([]int{7}),
			pointerCells: []cellRef{{1, 0}},
			pointerNums:  IntSlice([]int{1, 2}),
			description:  "cell (1,0) only has two options, 1 and 2, and if you put either one in and see the chain of implications it leads to, both ones end up with 7 in cell (0,1), so we can just fill that number in",
		},
		{
			targetCells:  []cellRef{{1, 0}},
			targetNums:   IntSlice([]int{1}),
			pointerCells: []cellRef{{0, 6}},
			pointerNums:  IntSlice([]int{3, 7}),
			//Explicitly don't test description after the first one.
		},
	}

	for _, test := range tests {

		options.targetCells = test.targetCells
		options.targetNums = test.targetNums
		options.pointerCells = test.pointerCells
		options.pointerNums = test.pointerNums
		options.description = test.description

		humanSolveTechniqueTestHelper(t, "forcingchain_test1.sdk", "Forcing Chain", options)
	}

	//TODO: test all other valid steps that could be found at this grid state for this technique.

}
<commit_msg>Added a TODO<commit_after>package sudoku

import (
	"testing"
)

func TestForcingChains(t *testing.T) {

	//Steps to test this:
	//* In the forcing chain helper, calculate the steps once, then
	//pass them in each time in a list of ~10 calls to solveTechniqueTEstHelper that we know are valid here.
	//* VERIFY MANUALLY that each step that is returned is actually a valid application of forcingchains.

	options := solveTechniqueTestHelperOptions{
		checkAllSteps: true,
	}

	grid, solver, steps := humanSolveTechniqueTestHelperStepGenerator(t,
		"forcingchain_test1.sdk", "Forcing Chain", options)

	options.stepsToCheck.grid = grid
	options.stepsToCheck.solver = solver
	options.stepsToCheck.steps = steps

	//OK, now we'll walk through all of the options in a loop and make sure they all show
	//up in the solve steps.

	type loopOptions struct {
		targetCells  []cellRef
		targetNums   IntSlice
		pointerCells []cellRef
		pointerNums  IntSlice
		description  string
	}

	tests := []loopOptions{
		{
			targetCells:  []cellRef{{0, 1}},
			targetNums:   IntSlice([]int{7}),
			pointerCells: []cellRef{{1, 0}},
			pointerNums:  IntSlice([]int{1, 2}),
			description:  "cell (1,0) only has two options, 1 and 2, and if you put either one in and see the chain of implications it leads to, both ones end up with 7 in cell (0,1), so we can just fill that number in",
		},
		{
			targetCells:  []cellRef{{1, 0}},
			targetNums:   IntSlice([]int{1}),
			pointerCells: []cellRef{{0, 6}},
			pointerNums:  IntSlice([]int{3, 7}),
			//Explicitly don't test description after the first one.
		},
	}

	//TODO: Test here if len(tests) == len(steps), t.Error if not. That makes sure we aren't getting
	//EXTRA tests.

	for _, test := range tests {

		options.targetCells = test.targetCells
		options.targetNums = test.targetNums
		options.pointerCells = test.pointerCells
		options.pointerNums = test.pointerNums
		options.description = test.description

		humanSolveTechniqueTestHelper(t, "forcingchain_test1.sdk", "Forcing Chain", options)
	}

	//TODO: test all other valid steps that could be found at this grid state for this technique.

}
<|endoftext|>


<commit_before>package sudoku

import (
	"testing"
)

func TestForcingChains(t *testing.T) {

	//Steps to test this:
	//* In the forcing chain helper, calculate the steps once, then
	//pass them in each time in a list of ~10 calls to solveTechniqueTEstHelper that we know are valid here.
	//* VERIFY MANUALLY that each step that is returned is actually a valid application of forcingchains.

	options := solveTechniqueTestHelperOptions{
		checkAllSteps: true,
	}

	grid, solver, steps := humanSolveTechniqueTestHelperStepGenerator(t,
		"forcingchain_test1.sdk", "Forcing Chain", options)

	options.stepsToCheck.grid = grid
	options.stepsToCheck.solver = solver
	options.stepsToCheck.steps = steps

	//OK, now we'll walk through all of the options in a loop and make sure they all show
	//up in the solve steps.

	type loopOptions struct {
		targetCells  []cellRef
		targetNums   IntSlice
		pointerCells []cellRef
		pointerNums  IntSlice
		description  string
	}

	tests := []loopOptions{
		{
			targetCells:  []cellRef{{0, 1}},
			targetNums:   IntSlice([]int{7}),
			pointerCells: []cellRef{{1, 0}},
			pointerNums:  IntSlice([]int{1, 2}),
			description:  "cell (1,0) only has two options, 1 and 2, and if you put either one in and see the chain of implications it leads to, both ones end up with 7 in cell (0,1), so we can just fill that number in",
		},
		{
			targetCells:  []cellRef{{1, 0}},
			targetNums:   IntSlice([]int{1}),
			pointerCells: []cellRef{{0, 6}},
			pointerNums:  IntSlice([]int{3, 7}),
		},
	}

	for _, test := range tests {

		options.targetCells = test.targetCells
		options.targetNums = test.targetNums
		options.pointerCells = test.pointerCells
		options.pointerNums = test.pointerNums
		options.description = test.description

		humanSolveTechniqueTestHelper(t, "forcingchain_test1.sdk", "Forcing Chain", options)
	}

	//TODO: test all other valid steps that could be found at this grid state for this technique.

}
<commit_msg>Added a clarifying comment<commit_after>package sudoku

import (
	"testing"
)

func TestForcingChains(t *testing.T) {

	//Steps to test this:
	//* In the forcing chain helper, calculate the steps once, then
	//pass them in each time in a list of ~10 calls to solveTechniqueTEstHelper that we know are valid here.
	//* VERIFY MANUALLY that each step that is returned is actually a valid application of forcingchains.

	options := solveTechniqueTestHelperOptions{
		checkAllSteps: true,
	}

	grid, solver, steps := humanSolveTechniqueTestHelperStepGenerator(t,
		"forcingchain_test1.sdk", "Forcing Chain", options)

	options.stepsToCheck.grid = grid
	options.stepsToCheck.solver = solver
	options.stepsToCheck.steps = steps

	//OK, now we'll walk through all of the options in a loop and make sure they all show
	//up in the solve steps.

	type loopOptions struct {
		targetCells  []cellRef
		targetNums   IntSlice
		pointerCells []cellRef
		pointerNums  IntSlice
		description  string
	}

	tests := []loopOptions{
		{
			targetCells:  []cellRef{{0, 1}},
			targetNums:   IntSlice([]int{7}),
			pointerCells: []cellRef{{1, 0}},
			pointerNums:  IntSlice([]int{1, 2}),
			description:  "cell (1,0) only has two options, 1 and 2, and if you put either one in and see the chain of implications it leads to, both ones end up with 7 in cell (0,1), so we can just fill that number in",
		},
		{
			targetCells:  []cellRef{{1, 0}},
			targetNums:   IntSlice([]int{1}),
			pointerCells: []cellRef{{0, 6}},
			pointerNums:  IntSlice([]int{3, 7}),
			//Explicitly don't test description after the first one.
		},
	}

	for _, test := range tests {

		options.targetCells = test.targetCells
		options.targetNums = test.targetNums
		options.pointerCells = test.pointerCells
		options.pointerNums = test.pointerNums
		options.description = test.description

		humanSolveTechniqueTestHelper(t, "forcingchain_test1.sdk", "Forcing Chain", options)
	}

	//TODO: test all other valid steps that could be found at this grid state for this technique.

}
<|endoftext|>


<commit_before>package htmltest

import (
	// "path"
	"testing"
)

func TestImageExternalWorking(t *testing.T) {
	// passes for existing external images
	hT := tTestFileOpts("fixtures/images/existingImageExternal.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageExternalMissing(t *testing.T) {
	// fails for missing external images
	hT := tTestFileOpts("fixtures/images/missingImageExternal.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 1)
	// Issue contains "no such host"
	// tExpectIssue(t, hT, "no such host", 1)
}

func TestImageExternalMissingProtocolValid(t *testing.T) {
	// works for valid images missing the protocol
	hT := tTestFileOpts("fixtures/images/image_missing_protocol_valid.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageExternalMissingProtocolInvalid(t *testing.T) {
	// fails for invalid images missing the protocol
	hT := tTestFileOpts("fixtures/images/image_missing_protocol_invalid.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 1)
	// tExpectIssue(t, hT, message, 1)
}

func TestImageExternalInsecureDefault(t *testing.T) {
	// passes for HTTP images by default
	hT := tTestFileOpts("fixtures/images/src_http.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageExternalInsecureOption(t *testing.T) {
	// fails for HTTP images when asked
	hT := tTestFileOpts("fixtures/images/src_http.html",
		map[string]interface{}{"EnforceHTTPS": true, "VCREnable": true})
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "is not an HTTPS target", 1)
}

func TestImageInternalAbsolute(t *testing.T) {
	// properly checks absolute images
	hT := tTestFile("fixtures/images/rootRelativeImages.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageInternalRelative(t *testing.T) {
	// properly checks relative images
	hT := tTestFile("fixtures/images/relativeToSelf.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageInternalRelativeSubfolders(t *testing.T) {
	// properly checks relative images within subfolders
	hT := tTestFile("fixtures/resources/books/nestedRelativeImages.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageInternalMissing(t *testing.T) {
	// fails for missing internal images
	hT := tTestFile("fixtures/images/missingImageInternal.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "target does not exist", 1)
}

func TestImageInternalMissingCharsAndCases(t *testing.T) {
	// fails for image with default mac filename
	hT := tTestFile("fixtures/images/terribleImageName.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "target does not exist", 1)
}

func TestImageInternalWithBase(t *testing.T) {
	// properly checks relative images with base
	t.Skip("absolute base tags not supported")
	hT := tTestFile("fixtures/images/relativeWithBase.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageIgnorable(t *testing.T) {
	// ignores images marked as data-proofer-ignore
	hT := tTestFile("fixtures/images/ignorableImages.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcMising(t *testing.T) {
	// fails for image with no src
	hT := tTestFile("fixtures/images/missingImageSrc.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "src attribute missing", 1)
}

func TestImageSrcEmpty(t *testing.T) {
	// fails for image with empty src
	hT := tTestFile("fixtures/images/emptyImageSrc.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "src attribute empty", 1)
}

func TestImageSrcLineBreaks(t *testing.T) {
	// deals with linebreaks in src
	hT := tTestFileOpts("fixtures/images/lineBreaks.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

// TODO empty src

func TestImageSrcIgnored(t *testing.T) {
	// ignores images via url_ignore
	t.Skip("url ignore patterns not yet implemented")
	hT := tTestFile("fixtures/images/???.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcDataURI(t *testing.T) {
	// properly ignores data URI images
	hT := tTestFile("fixtures/images/workingDataURIImage.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcSet(t *testing.T) {
	// works for images with a srcset
	hT := tTestFile("fixtures/images/srcSetCheck.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcSetMissing(t *testing.T) {
	// fails for images with an alt but missing src or srcset
	hT := tTestFile("fixtures/images/srcSetMissingImage.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "src attribute missing", 1)
}

func TestImageSrcSetMissingAlt(t *testing.T) {
	// fails for images with a srcset but missing alt
	hT := tTestFile("fixtures/images/srcSetMissingAlt.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "alt attribute missing", 1)
}

func TestImageSrcSetMissingAltIgnore(t *testing.T) {
	// ignores missing alt tags when asked for srcset
	hT := tTestFileOpts("fixtures/images/srcSetIgnorable.html",
		map[string]interface{}{"IgnoreAltMissing": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageAltMissing(t *testing.T) {
	// fails for image without alt attribute
	hT := tTestFile("fixtures/images/missingImageAlt.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "alt attribute missing", 1)
}

func TestImageAltEmpty(t *testing.T) {
	// fails for image with an empty alt attribute
	hT := tTestFile("fixtures/images/missingImageAltText.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "alt text empty", 1)
}

func TestImageAltSpaces(t *testing.T) {
	// fails for image with nothing but spaces in alt attribute
	hT := tTestFile("fixtures/images/emptyImageAltText.html")
	tExpectIssueCount(t, hT, 3)
	tExpectIssue(t, hT, "alt text contains only whitespace", 1)
}

func TestImageAltIgnoreMissing(t *testing.T) {
	// ignores missing alt tags when asked
	hT := tTestFileOpts("fixtures/images/ignorableAltViaOptions.html",
		map[string]interface{}{"IgnoreAltMissing": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImagePre(t *testing.T) {
	// works for broken images within pre & code
	hT := tTestFile("fixtures/images/badImagesInPre.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageUsemap(t *testing.T) {
	// deals with valid usemap
	hT := tTestFile("fixtures/images/usemapValid.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageUsemapMapDoesNotExist(t *testing.T) {
	// detects usemap pointing to a non-existent map
	hT := tTestFile("fixtures/images/usemapMapDoesNotExist.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageUsemapReferenceInvalid(t *testing.T) {
	// detects usemap with reference formally invalid
	hT := tTestFile("fixtures/images/usemapReferenceInvalid.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageUsemapEmpty(t *testing.T) {
	// detects empty usemap
	hT := tTestFile("fixtures/images/usemapEmpty.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageUsemapInLink(t *testing.T) {
	// detects forbidden usemap in an <a> alement
	hT := tTestFile("fixtures/images/usemapInLink.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageUsemapInButton(t *testing.T) {
	// detects forbidden usemap in a <button> alement
	hT := tTestFile("fixtures/images/usemapInButton.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageMultipleProblems(t *testing.T) {
	hT := tTestFile("fixtures/images/multipleProblems.html")
	tExpectIssueCount(t, hT, 6)
	tExpectIssue(t, hT, "alt text empty", 1)
	tExpectIssue(t, hT, "target does not exist", 2)
	tExpectIssue(t, hT, "alt attribute missing", 1)
	tExpectIssue(t, hT, "src attribute missing", 1)
}
<commit_msg>check for a specific error message<commit_after>package htmltest

import (
	// "path"
	"testing"
)

func TestImageExternalWorking(t *testing.T) {
	// passes for existing external images
	hT := tTestFileOpts("fixtures/images/existingImageExternal.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageExternalMissing(t *testing.T) {
	// fails for missing external images
	hT := tTestFileOpts("fixtures/images/missingImageExternal.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 1)
	// Issue contains "no such host"
	// tExpectIssue(t, hT, "no such host", 1)
}

func TestImageExternalMissingProtocolValid(t *testing.T) {
	// works for valid images missing the protocol
	hT := tTestFileOpts("fixtures/images/image_missing_protocol_valid.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageExternalMissingProtocolInvalid(t *testing.T) {
	// fails for invalid images missing the protocol
	hT := tTestFileOpts("fixtures/images/image_missing_protocol_invalid.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 1)
	// tExpectIssue(t, hT, message, 1)
}

func TestImageExternalInsecureDefault(t *testing.T) {
	// passes for HTTP images by default
	hT := tTestFileOpts("fixtures/images/src_http.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageExternalInsecureOption(t *testing.T) {
	// fails for HTTP images when asked
	hT := tTestFileOpts("fixtures/images/src_http.html",
		map[string]interface{}{"EnforceHTTPS": true, "VCREnable": true})
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "is not an HTTPS target", 1)
}

func TestImageInternalAbsolute(t *testing.T) {
	// properly checks absolute images
	hT := tTestFile("fixtures/images/rootRelativeImages.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageInternalRelative(t *testing.T) {
	// properly checks relative images
	hT := tTestFile("fixtures/images/relativeToSelf.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageInternalRelativeSubfolders(t *testing.T) {
	// properly checks relative images within subfolders
	hT := tTestFile("fixtures/resources/books/nestedRelativeImages.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageInternalMissing(t *testing.T) {
	// fails for missing internal images
	hT := tTestFile("fixtures/images/missingImageInternal.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "target does not exist", 1)
}

func TestImageInternalMissingCharsAndCases(t *testing.T) {
	// fails for image with default mac filename
	hT := tTestFile("fixtures/images/terribleImageName.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "target does not exist", 1)
}

func TestImageInternalWithBase(t *testing.T) {
	// properly checks relative images with base
	t.Skip("absolute base tags not supported")
	hT := tTestFile("fixtures/images/relativeWithBase.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageIgnorable(t *testing.T) {
	// ignores images marked as data-proofer-ignore
	hT := tTestFile("fixtures/images/ignorableImages.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcMising(t *testing.T) {
	// fails for image with no src
	hT := tTestFile("fixtures/images/missingImageSrc.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "src attribute missing", 1)
}

func TestImageSrcEmpty(t *testing.T) {
	// fails for image with empty src
	hT := tTestFile("fixtures/images/emptyImageSrc.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "src attribute empty", 1)
}

func TestImageSrcLineBreaks(t *testing.T) {
	// deals with linebreaks in src
	hT := tTestFileOpts("fixtures/images/lineBreaks.html",
		map[string]interface{}{"VCREnable": true})
	tExpectIssueCount(t, hT, 0)
}

// TODO empty src

func TestImageSrcIgnored(t *testing.T) {
	// ignores images via url_ignore
	t.Skip("url ignore patterns not yet implemented")
	hT := tTestFile("fixtures/images/???.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcDataURI(t *testing.T) {
	// properly ignores data URI images
	hT := tTestFile("fixtures/images/workingDataURIImage.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcSet(t *testing.T) {
	// works for images with a srcset
	hT := tTestFile("fixtures/images/srcSetCheck.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageSrcSetMissing(t *testing.T) {
	// fails for images with an alt but missing src or srcset
	hT := tTestFile("fixtures/images/srcSetMissingImage.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "src attribute missing", 1)
}

func TestImageSrcSetMissingAlt(t *testing.T) {
	// fails for images with a srcset but missing alt
	hT := tTestFile("fixtures/images/srcSetMissingAlt.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "alt attribute missing", 1)
}

func TestImageSrcSetMissingAltIgnore(t *testing.T) {
	// ignores missing alt tags when asked for srcset
	hT := tTestFileOpts("fixtures/images/srcSetIgnorable.html",
		map[string]interface{}{"IgnoreAltMissing": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImageAltMissing(t *testing.T) {
	// fails for image without alt attribute
	hT := tTestFile("fixtures/images/missingImageAlt.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "alt attribute missing", 1)
}

func TestImageAltEmpty(t *testing.T) {
	// fails for image with an empty alt attribute
	hT := tTestFile("fixtures/images/missingImageAltText.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "alt text empty", 1)
}

func TestImageAltSpaces(t *testing.T) {
	// fails for image with nothing but spaces in alt attribute
	hT := tTestFile("fixtures/images/emptyImageAltText.html")
	tExpectIssueCount(t, hT, 3)
	tExpectIssue(t, hT, "alt text contains only whitespace", 1)
}

func TestImageAltIgnoreMissing(t *testing.T) {
	// ignores missing alt tags when asked
	hT := tTestFileOpts("fixtures/images/ignorableAltViaOptions.html",
		map[string]interface{}{"IgnoreAltMissing": true})
	tExpectIssueCount(t, hT, 0)
}

func TestImagePre(t *testing.T) {
	// works for broken images within pre & code
	hT := tTestFile("fixtures/images/badImagesInPre.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageUsemap(t *testing.T) {
	// deals with valid usemap
	hT := tTestFile("fixtures/images/usemapValid.html")
	tExpectIssueCount(t, hT, 0)
}

func TestImageUsemapMapDoesNotExist(t *testing.T) {
	// detects usemap pointing to a non-existent map
	hT := tTestFile("fixtures/images/usemapMapDoesNotExist.html")
	tExpectIssueCount(t, hT, 1)
	tExpectIssue(t, hT, "hash does not exist", 1)
}

func TestImageUsemapReferenceInvalid(t *testing.T) {
	// detects usemap with reference formally invalid
	hT := tTestFile("fixtures/images/usemapReferenceInvalid.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageUsemapEmpty(t *testing.T) {
	// detects empty usemap
	hT := tTestFile("fixtures/images/usemapEmpty.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageUsemapInLink(t *testing.T) {
	// detects forbidden usemap in an <a> alement
	hT := tTestFile("fixtures/images/usemapInLink.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageUsemapInButton(t *testing.T) {
	// detects forbidden usemap in a <button> alement
	hT := tTestFile("fixtures/images/usemapInButton.html")
	tExpectIssueCount(t, hT, 1)
}

func TestImageMultipleProblems(t *testing.T) {
	hT := tTestFile("fixtures/images/multipleProblems.html")
	tExpectIssueCount(t, hT, 6)
	tExpectIssue(t, hT, "alt text empty", 1)
	tExpectIssue(t, hT, "target does not exist", 2)
	tExpectIssue(t, hT, "alt attribute missing", 1)
	tExpectIssue(t, hT, "src attribute missing", 1)
}
<|endoftext|>


<commit_before>/*
Copyright AppsCode Inc. and Contributors

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 resourceeditors

import (
	"context"
	"embed"
	"fmt"
	iofs "io/fs"
	"reflect"
	"sort"

	kmapi "kmodules.xyz/client-go/api/v1"
	"kmodules.xyz/resource-metadata/apis/meta/v1alpha1"

	"github.com/pkg/errors"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/klog/v2"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/yaml"
)

//go:embed **/**/*.yaml
var fs embed.FS

func FS() embed.FS {
	return fs
}

var (
	reMap = map[string]*v1alpha1.ResourceEditor{}
)

func init() {
	if err := iofs.WalkDir(fs, ".", func(path string, d iofs.DirEntry, err error) error {
		if d.IsDir() || err != nil {
			return err
		}
		data, err := fs.ReadFile(path)
		if err != nil {
			return errors.Wrap(err, path)
		}
		var obj v1alpha1.ResourceEditor
		err = yaml.Unmarshal(data, &obj)
		if err != nil {
			return errors.Wrap(err, path)
		}
		reMap[obj.Name] = &obj

		return nil
	}); err != nil {
		panic(errors.Wrapf(err, "failed to load %s", reflect.TypeOf(v1alpha1.ResourceEditor{})))
	}
}

func DefaultEditorName(gvr schema.GroupVersionResource) string {
	if gvr.Group == "" && gvr.Version == "v1" {
		return fmt.Sprintf("core-v1-%s", gvr.Resource)
	}
	return fmt.Sprintf("%s-%s-%s", gvr.Group, gvr.Version, gvr.Resource)
}

func LoadByName(name string) (*v1alpha1.ResourceEditor, error) {
	if obj, ok := reMap[name]; ok {
		return obj, nil
	}
	return nil, apierrors.NewNotFound(v1alpha1.Resource(v1alpha1.ResourceKindResourceEditor), name)
}

func LoadDefaultByGVR(gvr schema.GroupVersionResource) (*v1alpha1.ResourceEditor, bool) {
	name := DefaultEditorName(gvr)
	obj, ok := reMap[name]
	return obj, ok
}

func LoadEditorByGVR(kc client.Client, gvr schema.GroupVersionResource) (*v1alpha1.ResourceEditor, bool) {
	var ed v1alpha1.ResourceEditor
	err := kc.Get(context.TODO(), client.ObjectKey{Name: DefaultEditorName(gvr)}, &ed)
	if err == nil {
		return &ed, true
	} else if client.IgnoreNotFound(err) != nil {
		klog.V(8).InfoS(fmt.Sprintf("failed to load resource editor for %+v", gvr))
	}
	return LoadDefaultByGVR(gvr)
}

func LoadEditorByResourceID(kc client.Client, rid *kmapi.ResourceID) (*v1alpha1.ResourceEditor, bool) {
	if rid == nil {
		return nil, false
	}
	return LoadEditorByGVR(kc, rid.GroupVersionResource())
}

func List() []v1alpha1.ResourceEditor {
	out := make([]v1alpha1.ResourceEditor, 0, len(reMap))
	for _, rl := range reMap {
		out = append(out, *rl)
	}
	sort.Slice(out, func(i, j int) bool {
		return out[i].Name < out[j].Name
	})
	return out
}

func Names() []string {
	out := make([]string, 0, len(reMap))
	for name := range reMap {
		out = append(out, name)
	}
	sort.Strings(out)
	return out
}
<commit_msg>harmonize helper Load method names<commit_after>/*
Copyright AppsCode Inc. and Contributors

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 resourceeditors

import (
	"context"
	"embed"
	"fmt"
	iofs "io/fs"
	"reflect"
	"sort"

	kmapi "kmodules.xyz/client-go/api/v1"
	"kmodules.xyz/resource-metadata/apis/meta/v1alpha1"

	"github.com/pkg/errors"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/klog/v2"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/yaml"
)

//go:embed **/**/*.yaml
var fs embed.FS

func FS() embed.FS {
	return fs
}

var (
	reMap = map[string]*v1alpha1.ResourceEditor{}
)

func init() {
	if err := iofs.WalkDir(fs, ".", func(path string, d iofs.DirEntry, err error) error {
		if d.IsDir() || err != nil {
			return err
		}
		data, err := fs.ReadFile(path)
		if err != nil {
			return errors.Wrap(err, path)
		}
		var obj v1alpha1.ResourceEditor
		err = yaml.Unmarshal(data, &obj)
		if err != nil {
			return errors.Wrap(err, path)
		}
		reMap[obj.Name] = &obj

		return nil
	}); err != nil {
		panic(errors.Wrapf(err, "failed to load %s", reflect.TypeOf(v1alpha1.ResourceEditor{})))
	}
}

func DefaultEditorName(gvr schema.GroupVersionResource) string {
	if gvr.Group == "" && gvr.Version == "v1" {
		return fmt.Sprintf("core-v1-%s", gvr.Resource)
	}
	return fmt.Sprintf("%s-%s-%s", gvr.Group, gvr.Version, gvr.Resource)
}

func LoadByName(name string) (*v1alpha1.ResourceEditor, error) {
	if obj, ok := reMap[name]; ok {
		return obj, nil
	}
	return nil, apierrors.NewNotFound(v1alpha1.Resource(v1alpha1.ResourceKindResourceEditor), name)
}

func LoadDefaultByGVR(gvr schema.GroupVersionResource) (*v1alpha1.ResourceEditor, bool) {
	name := DefaultEditorName(gvr)
	obj, ok := reMap[name]
	return obj, ok
}

func LoadByGVR(kc client.Client, gvr schema.GroupVersionResource) (*v1alpha1.ResourceEditor, bool) {
	var ed v1alpha1.ResourceEditor
	err := kc.Get(context.TODO(), client.ObjectKey{Name: DefaultEditorName(gvr)}, &ed)
	if err == nil {
		return &ed, true
	} else if client.IgnoreNotFound(err) != nil {
		klog.V(8).InfoS(fmt.Sprintf("failed to load resource editor for %+v", gvr))
	}
	return LoadDefaultByGVR(gvr)
}

func LoadByResourceID(kc client.Client, rid *kmapi.ResourceID) (*v1alpha1.ResourceEditor, bool) {
	if rid == nil {
		return nil, false
	}
	return LoadByGVR(kc, rid.GroupVersionResource())
}

func List() []v1alpha1.ResourceEditor {
	out := make([]v1alpha1.ResourceEditor, 0, len(reMap))
	for _, rl := range reMap {
		out = append(out, *rl)
	}
	sort.Slice(out, func(i, j int) bool {
		return out[i].Name < out[j].Name
	})
	return out
}

func Names() []string {
	out := make([]string, 0, len(reMap))
	for name := range reMap {
		out = append(out, name)
	}
	sort.Strings(out)
	return out
}
<|endoftext|>


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

package main

import (
	"fmt"
	"log"
	"time"
)

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

func main() {
	mw := new(MyMainWindow)

	var outTE *walk.TextEdit

	animal := new(Animal)

	if _, err := (MainWindow{
		AssignTo: &mw.MainWindow,
		Title:    "Walk Data Binding Example",
		MinSize:  Size{300, 200},
		Layout:   VBox{},
		Children: []Widget{
			PushButton{
				Text: "Edit Animal",
				OnClicked: func() {
					res, err := RunAnimalDialog(mw, animal)
					if err != nil {
						log.Print(err)
					} else if res == walk.DlgCmdOK {
						outTE.SetText(fmt.Sprintf("%+v", animal))
					}
				},
			},
			Label{
				Text: "animal:",
			},
			TextEdit{
				AssignTo: &outTE,
				ReadOnly: true,
				Text:     fmt.Sprintf("%+v", animal),
			},
		},
	}.Run()); err != nil {
		log.Fatal(err)
	}
}

type Animal struct {
	Name          string
	ArrivalDate   time.Time
	SpeciesId     int
	Sex           Sex
	Weight        float64
	PreferredFood string
	Domesticated  bool
	Remarks       string
}

type Species struct {
	Id   int
	Name string
}

func KnownSpecies() []*Species {
	return []*Species{
		{1, "Dog"},
		{2, "Cat"},
		{3, "Bird"},
		{4, "Fish"},
		{5, "Elephant"},
	}
}

type Sex byte

const (
	SexMale Sex = 1 + iota
	SexFemale
	SexHermaphrodite
)

type MyMainWindow struct {
	*walk.MainWindow
}

func RunAnimalDialog(owner walk.RootWidget, animal *Animal) (int, error) {
	var dlg *walk.Dialog
	var db *walk.DataBinder
	var ep walk.ErrorPresenter
	var acceptPB, cancelPB *walk.PushButton

	return Dialog{
		AssignTo:      &dlg,
		Title:         "Animal Details",
		DefaultButton: &acceptPB,
		CancelButton:  &cancelPB,
		DataBinder: DataBinder{
			AssignTo:       &db,
			DataSource:     animal,
			ErrorPresenter: ErrorPresenterRef{&ep},
		},
		MinSize: Size{300, 300},
		Layout:  VBox{},
		Children: []Widget{
			Composite{
				Layout: Grid{},
				Children: []Widget{
					Label{
						Row:    0,
						Column: 0,
						Text:   "Name:",
					},
					LineEdit{
						Row:    0,
						Column: 1,
						Text:   Bind("Name"),
					},
					Label{
						Row:    1,
						Column: 0,
						Text:   "Arrival Date:",
					},
					DateEdit{
						Row:    1,
						Column: 1,
						Date:   Bind("ArrivalDate"),
					},
					Label{
						Row:    2,
						Column: 0,
						Text:   "Species:",
					},
					ComboBox{
						Row:           2,
						Column:        1,
						Value:         Bind("SpeciesId", SelRequired{}),
						BindingMember: "Id",
						DisplayMember: "Name",
						Model:         KnownSpecies(),
					},
					RadioButtonGroupBox{
						Row:        3,
						Column:     0,
						ColumnSpan: 2,
						Title:      "Sex",
						Layout:     HBox{},
						DataMember: "Sex",
						Buttons: []RadioButton{
							RadioButton{
								Text:  "Male",
								Value: SexMale,
							},
							RadioButton{
								Text:  "Female",
								Value: SexFemale,
							},
							RadioButton{
								Text:  "Hermaphrodite",
								Value: SexHermaphrodite,
							},
						},
					},
					Label{
						Row:    4,
						Column: 0,
						Text:   "Weight:",
					},
					NumberEdit{
						Row:      4,
						Column:   1,
						Value:    Bind("Weight", Range{0.01, 9999.99}),
						Suffix:   " kg",
						Decimals: 2,
					},
					Label{
						Row:    5,
						Column: 0,
						Text:   "Preferred Food:",
					},
					ComboBox{
						Row:      5,
						Column:   1,
						Editable: true,
						Value:    Bind("PreferredFood"),
						Model:    []string{"Fruits", "Gras", "Fish", "Meat"},
					},
					Label{
						Row:    6,
						Column: 0,
						Text:   "Domesticated:",
					},
					CheckBox{
						Row:     6,
						Column:  1,
						Checked: Bind("Domesticated"),
					},
					VSpacer{
						Row:    7,
						Column: 0,
						Size:   8,
					},
					Label{
						Row:    8,
						Column: 0,
						Text:   "Remarks:",
					},
					TextEdit{
						Row:        9,
						Column:     0,
						ColumnSpan: 2,
						MinSize:    Size{100, 50},
						Text:       Bind("Remarks"),
					},
					LineErrorPresenter{
						AssignTo:   &ep,
						Row:        10,
						Column:     0,
						ColumnSpan: 2,
					},
				},
			},
			Composite{
				Layout: HBox{},
				Children: []Widget{
					HSpacer{},
					PushButton{
						AssignTo: &acceptPB,
						Text:     "OK",
						OnClicked: func() {
							if err := db.Submit(); err != nil {
								log.Print(err)
								return
							}

							dlg.Accept()
						},
					},
					PushButton{
						AssignTo:  &cancelPB,
						Text:      "Cancel",
						OnClicked: func() { dlg.Cancel() },
					},
				},
			},
		},
	}.Run(owner)
}
<commit_msg>examples/databinding: Minor edits<commit_after>// Copyright 2013 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"log"
	"time"
)

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

func main() {
	mw := new(MyMainWindow)

	var outTE *walk.TextEdit

	animal := new(Animal)

	if _, err := (MainWindow{
		AssignTo: &mw.MainWindow,
		Title:    "Walk Data Binding Example",
		MinSize:  Size{300, 200},
		Layout:   VBox{},
		Children: []Widget{
			PushButton{
				Text: "Edit Animal",
				OnClicked: func() {
					cmd, err := RunAnimalDialog(mw, animal)
					if err != nil {
						log.Print(err)
					} else if cmd == walk.DlgCmdOK {
						outTE.SetText(fmt.Sprintf("%+v", animal))
					}
				},
			},
			Label{
				Text: "animal:",
			},
			TextEdit{
				AssignTo: &outTE,
				ReadOnly: true,
				Text:     fmt.Sprintf("%+v", animal),
			},
		},
	}.Run()); err != nil {
		log.Fatal(err)
	}
}

type Animal struct {
	Name          string
	ArrivalDate   time.Time
	SpeciesId     int
	Sex           Sex
	Weight        float64
	PreferredFood string
	Domesticated  bool
	Remarks       string
}

type Species struct {
	Id   int
	Name string
}

func KnownSpecies() []*Species {
	return []*Species{
		{1, "Dog"},
		{2, "Cat"},
		{3, "Bird"},
		{4, "Fish"},
		{5, "Elephant"},
	}
}

type Sex byte

const (
	SexMale Sex = 1 + iota
	SexFemale
	SexHermaphrodite
)

type MyMainWindow struct {
	*walk.MainWindow
}

func RunAnimalDialog(owner walk.RootWidget, animal *Animal) (int, error) {
	var dlg *walk.Dialog
	var db *walk.DataBinder
	var ep walk.ErrorPresenter
	var acceptPB, cancelPB *walk.PushButton

	return Dialog{
		AssignTo:      &dlg,
		Title:         "Animal Details",
		DefaultButton: &acceptPB,
		CancelButton:  &cancelPB,
		DataBinder: DataBinder{
			AssignTo:       &db,
			DataSource:     animal,
			ErrorPresenter: ErrorPresenterRef{&ep},
		},
		MinSize: Size{300, 300},
		Layout:  VBox{},
		Children: []Widget{
			Composite{
				Layout: Grid{},
				Children: []Widget{
					Label{
						Row:    0,
						Column: 0,
						Text:   "Name:",
					},
					LineEdit{
						Row:    0,
						Column: 1,
						Text:   Bind("Name"),
					},
					Label{
						Row:    1,
						Column: 0,
						Text:   "Arrival Date:",
					},
					DateEdit{
						Row:    1,
						Column: 1,
						Date:   Bind("ArrivalDate"),
					},
					Label{
						Row:    2,
						Column: 0,
						Text:   "Species:",
					},
					ComboBox{
						Row:           2,
						Column:        1,
						Value:         Bind("SpeciesId", SelRequired{}),
						BindingMember: "Id",
						DisplayMember: "Name",
						Model:         KnownSpecies(),
					},
					RadioButtonGroupBox{
						Row:        3,
						Column:     0,
						ColumnSpan: 2,
						Title:      "Sex",
						Layout:     HBox{},
						DataMember: "Sex",
						Buttons: []RadioButton{
							RadioButton{
								Text:  "Male",
								Value: SexMale,
							},
							RadioButton{
								Text:  "Female",
								Value: SexFemale,
							},
							RadioButton{
								Text:  "Hermaphrodite",
								Value: SexHermaphrodite,
							},
						},
					},
					Label{
						Row:    4,
						Column: 0,
						Text:   "Weight:",
					},
					NumberEdit{
						Row:      4,
						Column:   1,
						Value:    Bind("Weight", Range{0.01, 9999.99}),
						Suffix:   " kg",
						Decimals: 2,
					},
					Label{
						Row:    5,
						Column: 0,
						Text:   "Preferred Food:",
					},
					ComboBox{
						Row:      5,
						Column:   1,
						Editable: true,
						Value:    Bind("PreferredFood"),
						Model:    []string{"Fruit", "Grass", "Fish", "Meat"},
					},
					Label{
						Row:    6,
						Column: 0,
						Text:   "Domesticated:",
					},
					CheckBox{
						Row:     6,
						Column:  1,
						Checked: Bind("Domesticated"),
					},
					VSpacer{
						Row:    7,
						Column: 0,
						Size:   8,
					},
					Label{
						Row:    8,
						Column: 0,
						Text:   "Remarks:",
					},
					TextEdit{
						Row:        9,
						Column:     0,
						ColumnSpan: 2,
						MinSize:    Size{100, 50},
						Text:       Bind("Remarks"),
					},
					LineErrorPresenter{
						AssignTo:   &ep,
						Row:        10,
						Column:     0,
						ColumnSpan: 2,
					},
				},
			},
			Composite{
				Layout: HBox{},
				Children: []Widget{
					HSpacer{},
					PushButton{
						AssignTo: &acceptPB,
						Text:     "OK",
						OnClicked: func() {
							if err := db.Submit(); err != nil {
								log.Print(err)
								return
							}

							dlg.Accept()
						},
					},
					PushButton{
						AssignTo:  &cancelPB,
						Text:      "Cancel",
						OnClicked: func() { dlg.Cancel() },
					},
				},
			},
		},
	}.Run(owner)
}
<|endoftext|>


<commit_before>// Copyright 2013,2014 The go-logger Authors. All rights reserved.
// This code is MIT licensed. See the LICENSE file for more info.

// Tests for the default standard logging object

package log

import (
	"bytes"
	"testing"
	"time"
)

func TestStdTemplate(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)
	SetStreams(&buf)

	SetFlags(LdebugFlags)

	SetTemplate("{{.Text}}")
	temp := Template()

	type test struct {
		Text string
	}

	err := temp.Execute(&buf, &test{"Hello, World!"})
	if err != nil {
		t.Fatal(err)
	}

	expe := "Hello, World!"

	if buf.String() != expe {
		t.Errorf("\nGot:\t%s\nExpect:\t%s\n", buf.String(), expe)
	}
}

func TestStdSetTemplate(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)
	SetStreams(&buf)

	SetFlags(LdebugFlags)

	SetTemplate("{{.Text}}")

	Debugln("Hello, World!")

	expe := "Hello, World!\n"

	if buf.String() != expe {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", buf.String(), expe)
	}
}

func TestStdSetTemplateBad(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)
	SetStreams(&buf)

	SetFlags(LdebugFlags)

	err := SetTemplate("{{.Text")

	Debugln("template: default:1: unclosed action")

	expe := "template: default:1: unclosed action"

	if err.Error() != expe {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", buf.String(), expe)
	}
}

func TestStdSetTemplateBadDataObjectPanic(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)

	SetStreams(&buf)

	SetFlags(LnoPrefix | Lindent)

	SetIndent(1)

	type test struct {
		Test string
	}

	err := SetTemplate("{{.Tes}}")
	if err != nil {
		t.Fatal(err)
	}

	defer func() {
		if r := recover(); r == nil {
			t.Errorf("\nGot:\t%q\nExpect:\tPANIC\n", buf.String())
		}
	}()

	Debugln("Hello, World!")

	// Reset the standard logging object
	SetTemplate(logFmt)
	SetIndent(0)
}

func TestStdDateFormat(t *testing.T) {
	dateFormat := DateFormat()

	expect := "Mon-20060102-15:04:05"

	if dateFormat != expect {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", dateFormat, expect)
	}
}

func TestStdSetDateFormat(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_ALL)

	SetStreams(&buf)

	SetFlags(Ldate)

	SetDateFormat("20060102-15:04:05")

	SetTemplate("{{.Date}}")

	Debugln("Hello")

	expect := time.Now().Format(DateFormat())

	if buf.String() != expect {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", buf.String(), expect)
	}

	// Reset the standard logging object
	SetTemplate(logFmt)
}

func TestStdFlags(t *testing.T) {
	SetFlags(LstdFlags)

	flags := Flags()

	expect := LstdFlags

	if flags != expect {
		t.Errorf("\nGot:\t%#v\nExpect:\t%#v\n", flags, expect)
	}
}

func TestStdLevel(t *testing.T) {
	SetLevel(LEVEL_DEBUG)

	level := Level()

	expect := "LEVEL_DEBUG"

	if level.String() != expect {
		t.Errorf("\nGot:\t%#v\nExpect:\t%#v\n", level, expect)
	}
}

func TestStdPrefix(t *testing.T) {
	SetPrefix("TEST::")

	prefix := Prefix()

	expect := "TEST::"

	if prefix != expect {
		t.Errorf("\nGot:\t%#v\nExpect:\t%#v\n", prefix, expect)
	}
}
<commit_msg>Add TestStdStreams()<commit_after>// Copyright 2013,2014 The go-logger Authors. All rights reserved.
// This code is MIT licensed. See the LICENSE file for more info.

// Tests for the default standard logging object

package log

import (
	"bytes"
	"testing"
	"time"
)

func TestStdTemplate(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)
	SetStreams(&buf)

	SetFlags(LdebugFlags)

	SetTemplate("{{.Text}}")
	temp := Template()

	type test struct {
		Text string
	}

	err := temp.Execute(&buf, &test{"Hello, World!"})
	if err != nil {
		t.Fatal(err)
	}

	expe := "Hello, World!"

	if buf.String() != expe {
		t.Errorf("\nGot:\t%s\nExpect:\t%s\n", buf.String(), expe)
	}
}

func TestStdSetTemplate(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)
	SetStreams(&buf)

	SetFlags(LdebugFlags)

	SetTemplate("{{.Text}}")

	Debugln("Hello, World!")

	expe := "Hello, World!\n"

	if buf.String() != expe {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", buf.String(), expe)
	}
}

func TestStdSetTemplateBad(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)
	SetStreams(&buf)

	SetFlags(LdebugFlags)

	err := SetTemplate("{{.Text")

	Debugln("template: default:1: unclosed action")

	expe := "template: default:1: unclosed action"

	if err.Error() != expe {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", buf.String(), expe)
	}
}

func TestStdSetTemplateBadDataObjectPanic(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_DEBUG)

	SetStreams(&buf)

	SetFlags(LnoPrefix | Lindent)

	SetIndent(1)

	type test struct {
		Test string
	}

	err := SetTemplate("{{.Tes}}")
	if err != nil {
		t.Fatal(err)
	}

	defer func() {
		if r := recover(); r == nil {
			t.Errorf("\nGot:\t%q\nExpect:\tPANIC\n", buf.String())
		}
	}()

	Debugln("Hello, World!")

	// Reset the standard logging object
	SetTemplate(logFmt)
	SetIndent(0)
}

func TestStdDateFormat(t *testing.T) {
	dateFormat := DateFormat()

	expect := "Mon-20060102-15:04:05"

	if dateFormat != expect {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", dateFormat, expect)
	}
}

func TestStdSetDateFormat(t *testing.T) {
	var buf bytes.Buffer

	SetLevel(LEVEL_ALL)

	SetStreams(&buf)

	SetFlags(Ldate)

	SetDateFormat("20060102-15:04:05")

	SetTemplate("{{.Date}}")

	Debugln("Hello")

	expect := time.Now().Format(DateFormat())

	if buf.String() != expect {
		t.Errorf("\nGot:\t%q\nExpect:\t%q\n", buf.String(), expect)
	}

	// Reset the standard logging object
	SetTemplate(logFmt)
}

func TestStdFlags(t *testing.T) {
	SetFlags(LstdFlags)

	flags := Flags()

	expect := LstdFlags

	if flags != expect {
		t.Errorf("\nGot:\t%#v\nExpect:\t%#v\n", flags, expect)
	}
}

func TestStdLevel(t *testing.T) {
	SetLevel(LEVEL_DEBUG)

	level := Level()

	expect := "LEVEL_DEBUG"

	if level.String() != expect {
		t.Errorf("\nGot:\t%#v\nExpect:\t%#v\n", level, expect)
	}
}

func TestStdPrefix(t *testing.T) {
	SetPrefix("TEST::")

	prefix := Prefix()

	expect := "TEST::"

	if prefix != expect {
		t.Errorf("\nGot:\t%#v\nExpect:\t%#v\n", prefix, expect)
	}
}

func TestStdStreams(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)

	bufT := Streams()

	if &buf != bufT[0] {
		t.Errorf("\nGot:\t%p\nExpect:\t%p\n", &buf, bufT[0])
	}
}
<|endoftext|>


<commit_before>package logging

import (
	"fmt"
	"github.com/dynport/dgtk/es"
	"github.com/dynport/dgtk/util"
	"github.com/streadway/amqp"
	"os"
	"strconv"
	"time"
)

var (
	allText = es.DynamicTemplates{
		{
			"all_text": es.DynamicTemplate{
				Match:            "*",
				MatchMappingType: "string",
				Mapping:          &es.DynamicTemplateMapping{Type: "string", Index: "not_analyzed"},
			},
		},
	}
)

const (
	LogsExchange = "syslog"
	DefaultTtl   = int32(60000)
)

func log(format string, i ...interface{}) {
	fmt.Printf(format+"\n", i...)
}

type Indexer struct {
	AMQPAddress        string
	ElasticSearchHost  string
	ElasticSearchIndex string
	ElasticSearchType  string
	QueueName          string
	BatchSize          int
	Ttl                int32
}

type ElasticSearchIndexMapping map[string]map[string]map[string]es.DynamicTemplates

func (indexer *Indexer) IndexMapping() ElasticSearchIndexMapping {
	return ElasticSearchIndexMapping{
		"mappings": {indexer.ElasticSearchType: {"dynamic_templates": allText}},
	}
}

func (indexer *Indexer) Run() {
	for {
		e := indexer.RunWithoutReconnect()
		if e != nil {
			fmt.Println("ERROR: " + e.Error())
			time.Sleep(1 * time.Second)
		} else {
			return
		}
	}
}

func (indexer *Indexer) RunWithoutReconnect() error {
	con, e := amqp.Dial(indexer.AMQPAddress)
	if e != nil {
		return e
	}
	defer con.Close()
	channel, e := con.Channel()
	if e != nil {
		return e
	}
	defer channel.Close()
	t := amqp.Table{}
	if indexer.Ttl == 0 {
		indexer.Ttl = DefaultTtl
	}
	t["x-message-ttl"] = indexer.Ttl
	_, e = channel.QueueDeclare(indexer.QueueName, false, false, false, false, t)
	if e != nil {
		return e
	}
	e = channel.QueueBind(indexer.QueueName, "*", LogsExchange, false, nil)
	if e != nil {
		return e
	}
	hostname, e := os.Hostname()
	if e != nil {
		return e
	}
	consumer := hostname + ":" + strconv.Itoa(os.Getegid())
	c, e := channel.Consume(indexer.QueueName, consumer, false, false, false, false, nil)
	if e != nil {
		return e
	}
	index := &es.Index{
		Host:      indexer.ElasticSearchHost,
		Index:     indexer.ElasticSearchIndex,
		Type:      indexer.ElasticSearchType,
		BatchSize: indexer.BatchSize,
		Debug:     true,
	}
	mapping, e := index.Mapping()
	if e != nil {
		return e
	}
	if mapping == nil {
		indexMapping := indexer.IndexMapping()
		log("creating mapping %#v", indexMapping)
		rsp, e := index.PutMapping(indexMapping)
		if e != nil {
			return e
		}
		log("created mapping %#v", string(rsp.Body))
	} else {
		log("%#v", mapping)
	}
	for del := range c {
		raw := string(del.Body)
		if line := parseLine(raw); line != nil {
			ok, e := index.EnqueueBulkIndex(util.MD5String(raw), line)
			if e != nil {
				log(e.Error())
			} else if ok {
				del.Ack(true)
			}
		}
	}
	index.RunBatchIndex()
	log("finished")
	return nil
}

type Parser interface {
	Parse(string) error
}

func parseLine(line string) Parser {
	parsers := []Parser{
		&NginxLine{},
		&UnicornLine{},
		&HAProxyLine{},
		&SyslogLine{},
	}
	for _, parser := range parsers {
		if e := parser.Parse(line); e == nil {
			return parser
		}
	}
	return nil
}
<commit_msg>refactorings<commit_after>package logging

import (
	"fmt"
	"github.com/dynport/dgtk/es"
	"github.com/dynport/dgtk/util"
	"github.com/streadway/amqp"
	"os"
	"strconv"
	"time"
)

var (
	allText = es.DynamicTemplates{
		{
			"all_text": es.DynamicTemplate{
				Match:            "*",
				MatchMappingType: "string",
				Mapping:          &es.DynamicTemplateMapping{Type: "string", Index: "not_analyzed"},
			},
		},
	}
)

const (
	LogsExchange = "syslog"
	DefaultTtl   = int32(60000)
)

func log(format string, i ...interface{}) {
	fmt.Printf(format+"\n", i...)
}

type Indexer struct {
	AMQPAddress        string
	ElasticSearchHost  string
	ElasticSearchIndex string
	ElasticSearchType  string
	QueueName          string
	BatchSize          int
	Ttl                int32
	Debug              bool
}

type ElasticSearchIndexMapping map[string]map[string]map[string]es.DynamicTemplates

func (indexer *Indexer) IndexMapping() ElasticSearchIndexMapping {
	return ElasticSearchIndexMapping{
		"mappings": {indexer.ElasticSearchType: {"dynamic_templates": allText}},
	}
}

func (indexer *Indexer) Run() {
	for {
		e := indexer.RunWithoutReconnect()
		if e != nil {
			fmt.Println("ERROR: " + e.Error())
			time.Sleep(1 * time.Second)
		} else {
			return
		}
	}
}

func (indexer *Indexer) NewEsIndex() *es.Index {
	return &es.Index{
		Host:      indexer.ElasticSearchHost,
		Index:     indexer.ElasticSearchIndex,
		Type:      indexer.ElasticSearchType,
		BatchSize: indexer.BatchSize,
		Debug:     indexer.Debug,
	}
}

func (indexer *Indexer) RunWithoutReconnect() error {
	con, e := amqp.Dial(indexer.AMQPAddress)
	if e != nil {
		return e
	}
	defer con.Close()
	channel, e := con.Channel()
	if e != nil {
		return e
	}
	defer channel.Close()
	t := amqp.Table{}
	if indexer.Ttl == 0 {
		indexer.Ttl = DefaultTtl
	}
	t["x-message-ttl"] = indexer.Ttl
	_, e = channel.QueueDeclare(indexer.QueueName, false, false, false, false, t)
	if e != nil {
		return e
	}
	e = channel.QueueBind(indexer.QueueName, "*", LogsExchange, false, nil)
	if e != nil {
		return e
	}
	hostname, e := os.Hostname()
	if e != nil {
		return e
	}
	consumer := hostname + ":" + strconv.Itoa(os.Getegid())
	c, e := channel.Consume(indexer.QueueName, consumer, false, false, false, false, nil)
	if e != nil {
		return e
	}
	index := indexer.NewEsIndex()
	e = indexer.CreateMappingWhenNotExists(index)
	if e != nil {
		return e
	}
	for del := range c {
		raw := string(del.Body)
		if line := parseLine(raw); line != nil {
			ok, e := index.EnqueueBulkIndex(util.MD5String(raw), line)
			if e != nil {
				log(e.Error())
			} else if ok {
				del.Ack(true)
			}
		}
	}
	index.RunBatchIndex()
	log("finished")
	return nil
}

func (indexer *Indexer) CreateMappingWhenNotExists(esIndex *es.Index) error {
	mapping, e := esIndex.Mapping()
	if e != nil {
		return e
	}
	if mapping == nil {
		indexMapping := indexer.IndexMapping()
		log("creating mapping %#v", indexMapping)
		rsp, e := esIndex.PutMapping(indexMapping)
		if e != nil {
			return e
		}
		log("created mapping %#v", string(rsp.Body))
	} else {
		log("mapping already exists!")
	}
	return nil
}

type Parser interface {
	Parse(string) error
}

func parseLine(line string) Parser {
	parsers := []Parser{
		&NginxLine{},
		&UnicornLine{},
		&HAProxyLine{},
		&SyslogLine{},
	}
	for _, parser := range parsers {
		if e := parser.Parse(line); e == nil {
			return parser
		}
	}
	return nil
}
<|endoftext|>