<commit_before>package filters

import (
	"fmt"
	"testing"
)

func TestAllAtributesAreCorrect(t *testing.T) {

	r := returnArrayString([]string{"ab", "bc"})
	fmt.Println(BeginsWithAny("pw", "gf", "rt"))
	fmt.Println(EqualTo("jiffy", 232332432.2342335))
	assertEqual("[\"ab\",\"bc\"]", r, t, "Did not make string array correctly")

}

func assertNoError(err error, tableName string, t *testing.T) {
	if err != nil {
		t.Errorf("Could not create table %s", tableName)
	}
}

func assertEqual(expected, got interface{}, t *testing.T, errorMessage string) {
	if expected != got {
		t.Errorf("%s => expected %s, got %s", errorMessage, expected, got)
	}
}
<commit_msg>added more unit tests<commit_after>package filters

import (
	"testing"
)

func TestCheckTypes(t *testing.T) {
	jsonType, err := checkTypes(23.4, numericT)
	assertNoError(err, t)
	if err == nil {
		assertEqual("float64", jsonType, t, "jsonType is incorrect")
	}
	jsonType, err = checkTypes("23.4", stringT)
	assertNoError(err, t)
	if err == nil {
		assertEqual("string", jsonType, t, "jsonType is incorrect")
	}
	jsonType, err = checkTypes(23, stringAndNumericT)
	assertNoError(err, t)
	if err == nil {
		assertEqual("int", jsonType, t, "jsonType is incorrect")
	}
	jsonType, err = checkTypes(23, numericT)
	assertNoError(err, t)
	if err == nil {
		assertEqual("int", jsonType, t, "jsonType is incorrect")
	}
	jsonType, err = checkTypes("23.4", numericT)
	assertError(err, t)
	jsonType, err = checkTypes(23.4, stringT)
	assertError(err, t)

	jsonType, err = checkTypes(true, stringAndNumericT)
	assertError(err, t)
}

func TestCheckTypesInArray(t *testing.T) {
	a :=  []interface{4.5,45.2}
	jsonType, err := checkTypesInArray(a, numericT)
	assertNoError(err, t)
	if err == nil {
		assertEqual("float64", jsonType, t, "jsonType is incorrect")
	}
	jsonType, err = checkTypes("23.4", stringT)
	assertNoError(err, t)
	if err == nil {
		assertEqual("string", jsonType, t, "jsonType is incorrect")
	}
	jsonType, err = checkTypes(23, stringAndNumericT)
	assertNoError(err, t)
	if err == nil {
		assertEqual("int", jsonType, t, "jsonType is incorrect")
	}
	jsonType, err = checkTypes("23.4", numericT)
	assertError(err, t)
	jsonType, err = checkTypes(23.4, stringT)
	assertError(err, t)

	jsonType, err = checkTypes(true, stringAndNumericT)
	assertError(err, t)
}

func TestFloatToString(t *testing.T) {

	assertEqual("3424.50", floatToString(3424.50), t, "Error in converting float to string")
	assertEqual("24.50", floatToString(24.50), t, "Error in converting float to string")
	assertEqual("99424.50", floatToString(99424.50), t, "Error in converting float to string")
	assertEqual("73231.51", floatToString(73231.5123), t, "Error in converting float to string")
	assertEqual("100000.00", floatToString(99999.996), t, "Error in converting float to string")
	assertEqual("101.78", floatToString(101.775), t, "Error in converting float to string")
	assertNotEqual("100000.00", floatToString(99999.99), t, "Error in converting float to string, values are not suppose to match")
}

func TestIntToString(t *testing.T) {

	assertEqual("23", intToString(23), t, "Error in converting int to string")
	assertEqual("234297345", intToString(234297345), t, "Error in converting int to string")
	assertEqual("723234234", intToString(723234234), t, "Error in converting int to string")
	assertEqual("1011010101", intToString(1011010101), t, "Error in converting int to string")

	assertNotEqual("23429734", intToString(2342982), t, "Error in converting int to string, values are not suppose to match")
	assertNotEqual("23429734", intToString(2342982), t, "Error in converting int to string, values are not suppose to match")
}

func TestBlank(t *testing.T) {
	assertEqual("{\"city\":{\"$blank\":true}}", Blank("city", true), t, "Error in testing Blank")
	assertEqual("{\"city\":{\"$blank\":false}}", Blank("city", false), t, "Error in testing Blank")

}

func TestBeginsWith(t *testing.T) {
	beginsWithOutput, err := BeginsWith("city", "low")
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"city\":{\"$bw\":\"low\"}}", beginsWithOutput, t, "Error in testing BeginsWith")
	}

}
func TestBeginsWithAny(t *testing.T) {
	beginsWithOutput, err := BeginsWithAny("state", "mass", "cali", "flor")
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"state\":{\"$bwin\":[\"mass\",\"cali\",\"flor\"]}}", beginsWithOutput, t, "Error in testing BeginsWith")
	}

}

func TestEqualsTo(t *testing.T) {
	beginsWithOutput, err := EqualTo("region", "CA")
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"region\":{\"$eq\":\"CA\"}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

	beginsWithOutput, err = EqualTo("category_id", 232)
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"category_id\":{\"$eq\":232}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

	beginsWithOutput, err = EqualTo("price", 101.77)
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"price\":{\"$eq\":101.77}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

}

func TestExcludes(t *testing.T) {
	beginsWithOutput, err := Excludes("region", "CA")
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"region\":{\"$excludes\":\"CA\"}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

	beginsWithOutput, err = Excludes("category_id", 232)
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"category_id\":{\"$excludes\":232}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

	beginsWithOutput, err = Excludes("price", 101.77)
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"price\":{\"$excludes\":101.77}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

}

func TestExcludesAny(t *testing.T) {
	beginsWithOutput, err := ExcludesAny("region", "CA", "VA", "MA")
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"region\":{\"$excludes_any\":[\"CA\",\"VA\",\"MA\"]}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

	beginsWithOutput, err = ExcludesAny("category_id", 232, 342, 232, 20284)
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"category_id\":{\"$excludes_any\":[232,342,232,20284]}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

	beginsWithOutput, err = ExcludesAny("price", 101.77, 77.67, 99.009, 67.644)
	assertEqual(nil, err, t, "function error was thrown")
	if err == nil {
		assertEqual("{\"price\":{\"$excludes_any\":[101.77,77.67,99.01,67.64]}}", beginsWithOutput, t, "Error in testing EqualsTo")
	}

}

func assertNoError(err error, t *testing.T) {
	if err != nil {
		t.Errorf("Error was thrown with message: " + err.Error())
	}
}

func assertError(err error, t *testing.T) {
	if err == nil {
		t.Errorf("Error was not triggered")
	}
}

func assertEqual(expected, got interface{}, t *testing.T, errorMessage string) {
	if expected != got {
		t.Errorf("%s => expected %s, got %s", errorMessage, expected, got)
	}
}

func assertNotEqual(expected, got interface{}, t *testing.T, errorMessage string) {
	if expected == got {
		t.Errorf("%s => expected %s, got %s", errorMessage, expected, got)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016-2017 Authors of Cilium
//
// 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 policy

import (
	"fmt"
	"net"

	"github.com/cilium/cilium/pkg/ip"
	"github.com/cilium/cilium/pkg/logfields"
	"github.com/cilium/cilium/pkg/policy/api"

	"github.com/sirupsen/logrus"
)

type rule struct {
	api.Rule

	fromEntities []api.EndpointSelector
	toEntities   []api.EndpointSelector
}

func (r *rule) String() string {
	return fmt.Sprintf("%v", r.EndpointSelector)
}

// sanitize has a side effect of populating the fromEntities and toEntities
// slices to avoid superfluent map accesses
func (r *rule) sanitize() error {
	if r == nil || r.EndpointSelector.LabelSelector == nil {
		return fmt.Errorf("nil rule")
	}

	if err := r.Rule.Sanitize(); err != nil {
		return err
	}

	if len(r.EndpointSelector.MatchLabels) == 0 &&
		len(r.EndpointSelector.MatchExpressions) == 0 {
		return fmt.Errorf("empty EndpointSelector")
	}

	// resetting entity selector slices
	r.fromEntities = []api.EndpointSelector{}
	r.toEntities = []api.EndpointSelector{}
	entities := []api.Entity{}

	ingressEntityCounter := 0
	for _, rule := range r.Ingress {
		entities = append(entities, rule.FromEntities...)
		ingressEntityCounter += len(rule.FromEntities)
	}

	for _, rule := range r.Egress {
		entities = append(entities, rule.ToEntities...)
	}

	for j, entity := range entities {
		selector, ok := api.EntitySelectorMapping[entity]
		if !ok {
			return fmt.Errorf("unsupported entity: %s", entity)
		}

		if j < ingressEntityCounter {
			r.fromEntities = append(r.fromEntities, selector)
		} else {
			r.toEntities = append(r.toEntities, selector)
		}
	}

	return nil
}

func (policy *L4Filter) addFromEndpoints(fromEndpoints []api.EndpointSelector) bool {

	if len(policy.FromEndpoints) == 0 && len(fromEndpoints) > 0 {
		log.WithFields(logrus.Fields{
			logfields.EndpointSelector: fromEndpoints,
			"policy":                   policy,
		}).Debug("skipping L4 filter as the endpoints are already covered.")
		return true
	}

	if len(policy.FromEndpoints) > 0 && len(fromEndpoints) == 0 {
		// new policy is more permissive than the existing policy
		// use a more permissive one
		policy.FromEndpoints = nil
	}

	policy.FromEndpoints = append(policy.FromEndpoints, fromEndpoints...)
	return false
}

func mergeL4Port(ctx *SearchContext, fromEndpoints []api.EndpointSelector, r api.PortRule, p api.PortProtocol,
	dir string, proto api.L4Proto, resMap L4PolicyMap) (int, error) {

	key := p.Port + "/" + string(proto)
	v, ok := resMap[key]
	if !ok {
		resMap[key] = CreateL4Filter(fromEndpoints, r, p, dir, proto)
		return 1, nil
	}
	l4Filter := CreateL4Filter(fromEndpoints, r, p, dir, proto)
	if l4Filter.L7Parser != "" {
		if v.L7Parser == "" {
			v.L7Parser = l4Filter.L7Parser
		} else if l4Filter.L7Parser != v.L7Parser {
			ctx.PolicyTrace("   Merge conflict: mismatching parsers %s/%s\n", l4Filter.L7Parser, v.L7Parser)
			return 0, fmt.Errorf("Cannot merge conflicting L7 parsers (%s/%s)", l4Filter.L7Parser, v.L7Parser)
		}
	}

	if l4Filter.L7RedirectPort != 0 {
		if v.L7RedirectPort == 0 {
			v.L7RedirectPort = l4Filter.L7RedirectPort
		} else if l4Filter.L7RedirectPort != v.L7RedirectPort {
			ctx.PolicyTrace("   Merge conflict: mismatching redirect ports %d/%d\n", l4Filter.L7RedirectPort, v.L7RedirectPort)
			return 0, fmt.Errorf("Cannot merge conflicting redirect ports (%d/%d)", l4Filter.L7RedirectPort, v.L7RedirectPort)
		}
	}

	if v.addFromEndpoints(fromEndpoints) && r.NumRules() == 0 {
		// skip this policy as it is already covered and it does not contain L7 rules
		return 1, nil
	}

	for hash, newL7Rules := range l4Filter.L7RulesPerEp {
		if ep, ok := v.L7RulesPerEp[hash]; ok {
			switch {
			case len(newL7Rules.HTTP) > 0:
				if len(ep.Kafka) > 0 {
					ctx.PolicyTrace("   Merge conflict: mismatching L7 rule types.\n")
					return 0, fmt.Errorf("Cannot merge conflicting L7 rule types")
				}

				for _, newRule := range newL7Rules.HTTP {
					if !newRule.Exists(ep) {
						ep.HTTP = append(ep.HTTP, newRule)
					}
				}
			case len(newL7Rules.Kafka) > 0:
				if len(ep.HTTP) > 0 {
					ctx.PolicyTrace("   Merge conflict: mismatching L7 rule types.\n")
					return 0, fmt.Errorf("Cannot merge conflicting L7 rule types")
				}

				for _, newRule := range newL7Rules.Kafka {
					if !newRule.Exists(ep) {
						ep.Kafka = append(ep.Kafka, newRule)
					}
				}
			default:
				ctx.PolicyTrace("   No L7 rules to merge.\n")
			}
			v.L7RulesPerEp[hash] = ep
		} else {
			v.L7RulesPerEp[hash] = newL7Rules
		}
	}

	resMap[key] = v
	return 1, nil
}

func mergeL4(ctx *SearchContext, dir string, fromEndpoints []api.EndpointSelector, portRules []api.PortRule,
	resMap L4PolicyMap) (int, error) {

	if len(portRules) == 0 {
		ctx.PolicyTrace("    No L4 rules\n")
		return 0, nil
	}

	found := 0
	var err error

	for _, r := range portRules {
		if fromEndpoints != nil {
			ctx.PolicyTrace("    Allows %s port %v from endpoints %v\n", dir, r.Ports, fromEndpoints)
		} else {
			ctx.PolicyTrace("    Allows %s port %v\n", dir, r.Ports)
		}

		if r.RedirectPort != 0 {
			ctx.PolicyTrace("      Redirect-To: %d\n", r.RedirectPort)
		}

		if r.Rules != nil {
			for _, l7 := range r.Rules.HTTP {
				ctx.PolicyTrace("        %+v\n", l7)
			}
		}

		l3match := false
		if ctx.From != nil && fromEndpoints != nil {
			for _, labels := range fromEndpoints {
				if labels.Matches(ctx.From) {
					l3match = true
					break
				}
			}
			if l3match == false {
				ctx.PolicyTrace("      Labels %s not found", ctx.From)
				continue
			}
		}
		ctx.PolicyTrace("      Found all required labels")

		for _, p := range r.Ports {
			var cnt int
			if p.Protocol != api.ProtoAny {
				cnt, err = mergeL4Port(ctx, fromEndpoints, r, p, dir, p.Protocol, resMap)
				if err != nil {
					return found, err
				}
				found += cnt
			} else {
				cnt, err = mergeL4Port(ctx, fromEndpoints, r, p, dir, api.ProtoTCP, resMap)
				if err != nil {
					return found, err
				}
				found += cnt

				cnt, err = mergeL4Port(ctx, fromEndpoints, r, p, dir, api.ProtoUDP, resMap)
				if err != nil {
					return found, err
				}
				found += cnt
			}
		}
	}

	return found, nil
}

func (state *traceState) selectRule(ctx *SearchContext, r *rule) {
	ctx.PolicyTrace("* Rule %s: selected\n", r)
	state.selectedRules++
}

func (state *traceState) unSelectRule(ctx *SearchContext, r *rule) {
	ctx.PolicyTraceVerbose("  Rule %s: did not select %+v\n", r, ctx.To)
}

func (r *rule) resolveL4Policy(ctx *SearchContext, state *traceState, result *L4Policy) (*L4Policy, error) {
	if !r.EndpointSelector.Matches(ctx.To) {
		state.unSelectRule(ctx, r)
		return nil, nil
	}

	state.selectRule(ctx, r)
	found := 0

	if !ctx.EgressL4Only {
		if len(r.Ingress) == 0 {
			ctx.PolicyTrace("    No L4 rules\n")
		}
		for _, r := range r.Ingress {
			cnt, err := mergeL4(ctx, "Ingress", r.FromEndpoints, r.ToPorts, result.Ingress)
			if err != nil {
				return nil, err
			}
			found += cnt
		}
	}

	if !ctx.IngressL4Only {
		if len(r.Egress) == 0 {
			ctx.PolicyTrace("    No L4 rules\n")
		}
		for _, r := range r.Egress {
			cnt, err := mergeL4(ctx, "Egress", nil, r.ToPorts, result.Egress)
			if err != nil {
				return nil, err
			}
			found += cnt
		}
	}

	if found > 0 {
		return result, nil
	}

	return nil, nil
}

func mergeL3(ctx *SearchContext, dir string, ipRules []api.CIDR, resMap *L3PolicyMap) int {
	found := 0

	for _, r := range ipRules {
		strCIDR := string(r)
		ctx.PolicyTrace("  Allows %s IP %s\n", dir, strCIDR)

		found += resMap.Insert(strCIDR)
	}

	return found
}

func computeResultantCIDRSet(cidrs []api.CIDRRule) []api.CIDR {
	var allResultantAllowedCIDRs []api.CIDR
	for _, s := range cidrs {
		// No need for error checking, as api.CIDRRule.Sanitize() already does.
		_, allowNet, _ := net.ParseCIDR(string(s.Cidr))

		var removeSubnets []*net.IPNet
		for _, t := range s.ExceptCIDRs {
			// No need for error checking, as api.CIDRRule.Sanitize() already
			// does.
			_, removeSubnet, _ := net.ParseCIDR(string(t))
			removeSubnets = append(removeSubnets, removeSubnet)
		}
		// No need for error checking, as have already validated that none of
		// the possible error cases can occur in ip.RemoveCIDRs
		resultantAllowedCIDRs, _ := ip.RemoveCIDRs([]*net.IPNet{allowNet}, removeSubnets)

		for _, u := range resultantAllowedCIDRs {
			allResultantAllowedCIDRs = append(allResultantAllowedCIDRs, api.CIDR(u.String()))
		}
	}
	return allResultantAllowedCIDRs
}

func (r *rule) resolveL3Policy(ctx *SearchContext, state *traceState, result *L3Policy) *L3Policy {
	if !r.EndpointSelector.Matches(ctx.To) {
		state.unSelectRule(ctx, r)
		return nil
	}

	state.selectRule(ctx, r)
	found := 0

	for _, r := range r.Ingress {
		// TODO (ianvernon): GH-1658
		var allCIDRs []api.CIDR
		allCIDRs = append(allCIDRs, r.FromCIDR...)

		allCIDRs = append(allCIDRs, computeResultantCIDRSet(r.FromCIDRSet)...)

		found += mergeL3(ctx, "Ingress", allCIDRs, &result.Ingress)
	}
	for _, r := range r.Egress {
		// TODO(ianvernon): GH-1658
		var allCIDRs []api.CIDR
		allCIDRs = append(allCIDRs, r.ToCIDR...)

		allCIDRs = append(allCIDRs, computeResultantCIDRSet(r.ToCIDRSet)...)

		found += mergeL3(ctx, "Egress", allCIDRs, &result.Egress)
	}

	if found > 0 {
		return result
	}

	ctx.PolicyTrace("    No L3 rules\n")
	return nil
}

func (r *rule) canReach(ctx *SearchContext, state *traceState) api.Decision {
	entitiesDecision := r.canReachEntities(ctx, state)

	if !r.EndpointSelector.Matches(ctx.To) {
		if entitiesDecision == api.Undecided {
			state.unSelectRule(ctx, r)
		} else {
			state.selectRule(ctx, r)
		}
		return entitiesDecision
	}

	state.selectRule(ctx, r)
	for _, r := range r.Ingress {
		for _, sel := range r.FromRequires {
			ctx.PolicyTrace("    Requires from labels %+v", sel)
			if !sel.Matches(ctx.From) {
				ctx.PolicyTrace("-     Labels %v not found\n", ctx.From)
				state.constrainedRules++
				return api.Denied
			}
			ctx.PolicyTrace("+     Found all required labels\n")
		}
	}

	// separate loop is needed as failure to meet FromRequires always takes
	// precedence over FromEndpoints
	for _, r := range r.Ingress {
		for _, sel := range r.FromEndpoints {
			ctx.PolicyTrace("    Allows from labels %+v", sel)
			if sel.Matches(ctx.From) {
				ctx.PolicyTrace("      Found all required labels")
				if len(r.ToPorts) == 0 {
					ctx.PolicyTrace("+       No L4 restrictions\n")
					state.matchedRules++
					return api.Allowed
				}
				ctx.PolicyTrace("        Rule restricts traffic to specific L4 destinations; deferring policy decision to L4 policy stage\n")
			} else {
				ctx.PolicyTrace("      Labels %v not found\n", ctx.From)
			}
		}
	}

	for _, entitySelector := range r.fromEntities {
		if entitySelector.Matches(ctx.From) {
			ctx.PolicyTrace("+     Found all required labels to match entity %s\n", entitySelector.String())
			state.matchedRules++
			return api.Allowed
		}

	}

	return entitiesDecision
}

func (r *rule) canReachEntities(ctx *SearchContext, state *traceState) api.Decision {
	for _, entitySelector := range r.toEntities {
		if entitySelector.Matches(ctx.To) {
			ctx.PolicyTrace("+     Found all required labels to match entity %s\n", entitySelector.String())
			state.matchedRules++
			return api.Allowed
		}
	}

	return api.Undecided
}
<commit_msg>policy: Convert comment to debug message<commit_after>// Copyright 2016-2017 Authors of Cilium
//
// 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 policy

import (
	"fmt"
	"net"

	"github.com/cilium/cilium/pkg/ip"
	"github.com/cilium/cilium/pkg/logfields"
	"github.com/cilium/cilium/pkg/policy/api"

	"github.com/sirupsen/logrus"
)

type rule struct {
	api.Rule

	fromEntities []api.EndpointSelector
	toEntities   []api.EndpointSelector
}

func (r *rule) String() string {
	return fmt.Sprintf("%v", r.EndpointSelector)
}

// sanitize has a side effect of populating the fromEntities and toEntities
// slices to avoid superfluent map accesses
func (r *rule) sanitize() error {
	if r == nil || r.EndpointSelector.LabelSelector == nil {
		return fmt.Errorf("nil rule")
	}

	if err := r.Rule.Sanitize(); err != nil {
		return err
	}

	if len(r.EndpointSelector.MatchLabels) == 0 &&
		len(r.EndpointSelector.MatchExpressions) == 0 {
		return fmt.Errorf("empty EndpointSelector")
	}

	// resetting entity selector slices
	r.fromEntities = []api.EndpointSelector{}
	r.toEntities = []api.EndpointSelector{}
	entities := []api.Entity{}

	ingressEntityCounter := 0
	for _, rule := range r.Ingress {
		entities = append(entities, rule.FromEntities...)
		ingressEntityCounter += len(rule.FromEntities)
	}

	for _, rule := range r.Egress {
		entities = append(entities, rule.ToEntities...)
	}

	for j, entity := range entities {
		selector, ok := api.EntitySelectorMapping[entity]
		if !ok {
			return fmt.Errorf("unsupported entity: %s", entity)
		}

		if j < ingressEntityCounter {
			r.fromEntities = append(r.fromEntities, selector)
		} else {
			r.toEntities = append(r.toEntities, selector)
		}
	}

	return nil
}

func (policy *L4Filter) addFromEndpoints(fromEndpoints []api.EndpointSelector) bool {

	if len(policy.FromEndpoints) == 0 && len(fromEndpoints) > 0 {
		log.WithFields(logrus.Fields{
			logfields.EndpointSelector: fromEndpoints,
			"policy":                   policy,
		}).Debug("skipping L4 filter as the endpoints are already covered.")
		return true
	}

	if len(policy.FromEndpoints) > 0 && len(fromEndpoints) == 0 {
		log.WithFields(logrus.Fields{
			logfields.EndpointSelector: fromEndpoints,
			"policy":                   policy,
		}).Debug("new L4 filter applies to all endpoints, making the policy more permissive.")
		policy.FromEndpoints = nil
	}

	policy.FromEndpoints = append(policy.FromEndpoints, fromEndpoints...)
	return false
}

func mergeL4Port(ctx *SearchContext, fromEndpoints []api.EndpointSelector, r api.PortRule, p api.PortProtocol,
	dir string, proto api.L4Proto, resMap L4PolicyMap) (int, error) {

	key := p.Port + "/" + string(proto)
	v, ok := resMap[key]
	if !ok {
		resMap[key] = CreateL4Filter(fromEndpoints, r, p, dir, proto)
		return 1, nil
	}
	l4Filter := CreateL4Filter(fromEndpoints, r, p, dir, proto)
	if l4Filter.L7Parser != "" {
		if v.L7Parser == "" {
			v.L7Parser = l4Filter.L7Parser
		} else if l4Filter.L7Parser != v.L7Parser {
			ctx.PolicyTrace("   Merge conflict: mismatching parsers %s/%s\n", l4Filter.L7Parser, v.L7Parser)
			return 0, fmt.Errorf("Cannot merge conflicting L7 parsers (%s/%s)", l4Filter.L7Parser, v.L7Parser)
		}
	}

	if l4Filter.L7RedirectPort != 0 {
		if v.L7RedirectPort == 0 {
			v.L7RedirectPort = l4Filter.L7RedirectPort
		} else if l4Filter.L7RedirectPort != v.L7RedirectPort {
			ctx.PolicyTrace("   Merge conflict: mismatching redirect ports %d/%d\n", l4Filter.L7RedirectPort, v.L7RedirectPort)
			return 0, fmt.Errorf("Cannot merge conflicting redirect ports (%d/%d)", l4Filter.L7RedirectPort, v.L7RedirectPort)
		}
	}

	if v.addFromEndpoints(fromEndpoints) && r.NumRules() == 0 {
		// skip this policy as it is already covered and it does not contain L7 rules
		return 1, nil
	}

	for hash, newL7Rules := range l4Filter.L7RulesPerEp {
		if ep, ok := v.L7RulesPerEp[hash]; ok {
			switch {
			case len(newL7Rules.HTTP) > 0:
				if len(ep.Kafka) > 0 {
					ctx.PolicyTrace("   Merge conflict: mismatching L7 rule types.\n")
					return 0, fmt.Errorf("Cannot merge conflicting L7 rule types")
				}

				for _, newRule := range newL7Rules.HTTP {
					if !newRule.Exists(ep) {
						ep.HTTP = append(ep.HTTP, newRule)
					}
				}
			case len(newL7Rules.Kafka) > 0:
				if len(ep.HTTP) > 0 {
					ctx.PolicyTrace("   Merge conflict: mismatching L7 rule types.\n")
					return 0, fmt.Errorf("Cannot merge conflicting L7 rule types")
				}

				for _, newRule := range newL7Rules.Kafka {
					if !newRule.Exists(ep) {
						ep.Kafka = append(ep.Kafka, newRule)
					}
				}
			default:
				ctx.PolicyTrace("   No L7 rules to merge.\n")
			}
			v.L7RulesPerEp[hash] = ep
		} else {
			v.L7RulesPerEp[hash] = newL7Rules
		}
	}

	resMap[key] = v
	return 1, nil
}

func mergeL4(ctx *SearchContext, dir string, fromEndpoints []api.EndpointSelector, portRules []api.PortRule,
	resMap L4PolicyMap) (int, error) {

	if len(portRules) == 0 {
		ctx.PolicyTrace("    No L4 rules\n")
		return 0, nil
	}

	found := 0
	var err error

	for _, r := range portRules {
		if fromEndpoints != nil {
			ctx.PolicyTrace("    Allows %s port %v from endpoints %v\n", dir, r.Ports, fromEndpoints)
		} else {
			ctx.PolicyTrace("    Allows %s port %v\n", dir, r.Ports)
		}

		if r.RedirectPort != 0 {
			ctx.PolicyTrace("      Redirect-To: %d\n", r.RedirectPort)
		}

		if r.Rules != nil {
			for _, l7 := range r.Rules.HTTP {
				ctx.PolicyTrace("        %+v\n", l7)
			}
		}

		l3match := false
		if ctx.From != nil && fromEndpoints != nil {
			for _, labels := range fromEndpoints {
				if labels.Matches(ctx.From) {
					l3match = true
					break
				}
			}
			if l3match == false {
				ctx.PolicyTrace("      Labels %s not found", ctx.From)
				continue
			}
		}
		ctx.PolicyTrace("      Found all required labels")

		for _, p := range r.Ports {
			var cnt int
			if p.Protocol != api.ProtoAny {
				cnt, err = mergeL4Port(ctx, fromEndpoints, r, p, dir, p.Protocol, resMap)
				if err != nil {
					return found, err
				}
				found += cnt
			} else {
				cnt, err = mergeL4Port(ctx, fromEndpoints, r, p, dir, api.ProtoTCP, resMap)
				if err != nil {
					return found, err
				}
				found += cnt

				cnt, err = mergeL4Port(ctx, fromEndpoints, r, p, dir, api.ProtoUDP, resMap)
				if err != nil {
					return found, err
				}
				found += cnt
			}
		}
	}

	return found, nil
}

func (state *traceState) selectRule(ctx *SearchContext, r *rule) {
	ctx.PolicyTrace("* Rule %s: selected\n", r)
	state.selectedRules++
}

func (state *traceState) unSelectRule(ctx *SearchContext, r *rule) {
	ctx.PolicyTraceVerbose("  Rule %s: did not select %+v\n", r, ctx.To)
}

func (r *rule) resolveL4Policy(ctx *SearchContext, state *traceState, result *L4Policy) (*L4Policy, error) {
	if !r.EndpointSelector.Matches(ctx.To) {
		state.unSelectRule(ctx, r)
		return nil, nil
	}

	state.selectRule(ctx, r)
	found := 0

	if !ctx.EgressL4Only {
		if len(r.Ingress) == 0 {
			ctx.PolicyTrace("    No L4 rules\n")
		}
		for _, r := range r.Ingress {
			cnt, err := mergeL4(ctx, "Ingress", r.FromEndpoints, r.ToPorts, result.Ingress)
			if err != nil {
				return nil, err
			}
			found += cnt
		}
	}

	if !ctx.IngressL4Only {
		if len(r.Egress) == 0 {
			ctx.PolicyTrace("    No L4 rules\n")
		}
		for _, r := range r.Egress {
			cnt, err := mergeL4(ctx, "Egress", nil, r.ToPorts, result.Egress)
			if err != nil {
				return nil, err
			}
			found += cnt
		}
	}

	if found > 0 {
		return result, nil
	}

	return nil, nil
}

func mergeL3(ctx *SearchContext, dir string, ipRules []api.CIDR, resMap *L3PolicyMap) int {
	found := 0

	for _, r := range ipRules {
		strCIDR := string(r)
		ctx.PolicyTrace("  Allows %s IP %s\n", dir, strCIDR)

		found += resMap.Insert(strCIDR)
	}

	return found
}

func computeResultantCIDRSet(cidrs []api.CIDRRule) []api.CIDR {
	var allResultantAllowedCIDRs []api.CIDR
	for _, s := range cidrs {
		// No need for error checking, as api.CIDRRule.Sanitize() already does.
		_, allowNet, _ := net.ParseCIDR(string(s.Cidr))

		var removeSubnets []*net.IPNet
		for _, t := range s.ExceptCIDRs {
			// No need for error checking, as api.CIDRRule.Sanitize() already
			// does.
			_, removeSubnet, _ := net.ParseCIDR(string(t))
			removeSubnets = append(removeSubnets, removeSubnet)
		}
		// No need for error checking, as have already validated that none of
		// the possible error cases can occur in ip.RemoveCIDRs
		resultantAllowedCIDRs, _ := ip.RemoveCIDRs([]*net.IPNet{allowNet}, removeSubnets)

		for _, u := range resultantAllowedCIDRs {
			allResultantAllowedCIDRs = append(allResultantAllowedCIDRs, api.CIDR(u.String()))
		}
	}
	return allResultantAllowedCIDRs
}

func (r *rule) resolveL3Policy(ctx *SearchContext, state *traceState, result *L3Policy) *L3Policy {
	if !r.EndpointSelector.Matches(ctx.To) {
		state.unSelectRule(ctx, r)
		return nil
	}

	state.selectRule(ctx, r)
	found := 0

	for _, r := range r.Ingress {
		// TODO (ianvernon): GH-1658
		var allCIDRs []api.CIDR
		allCIDRs = append(allCIDRs, r.FromCIDR...)

		allCIDRs = append(allCIDRs, computeResultantCIDRSet(r.FromCIDRSet)...)

		found += mergeL3(ctx, "Ingress", allCIDRs, &result.Ingress)
	}
	for _, r := range r.Egress {
		// TODO(ianvernon): GH-1658
		var allCIDRs []api.CIDR
		allCIDRs = append(allCIDRs, r.ToCIDR...)

		allCIDRs = append(allCIDRs, computeResultantCIDRSet(r.ToCIDRSet)...)

		found += mergeL3(ctx, "Egress", allCIDRs, &result.Egress)
	}

	if found > 0 {
		return result
	}

	ctx.PolicyTrace("    No L3 rules\n")
	return nil
}

func (r *rule) canReach(ctx *SearchContext, state *traceState) api.Decision {
	entitiesDecision := r.canReachEntities(ctx, state)

	if !r.EndpointSelector.Matches(ctx.To) {
		if entitiesDecision == api.Undecided {
			state.unSelectRule(ctx, r)
		} else {
			state.selectRule(ctx, r)
		}
		return entitiesDecision
	}

	state.selectRule(ctx, r)
	for _, r := range r.Ingress {
		for _, sel := range r.FromRequires {
			ctx.PolicyTrace("    Requires from labels %+v", sel)
			if !sel.Matches(ctx.From) {
				ctx.PolicyTrace("-     Labels %v not found\n", ctx.From)
				state.constrainedRules++
				return api.Denied
			}
			ctx.PolicyTrace("+     Found all required labels\n")
		}
	}

	// separate loop is needed as failure to meet FromRequires always takes
	// precedence over FromEndpoints
	for _, r := range r.Ingress {
		for _, sel := range r.FromEndpoints {
			ctx.PolicyTrace("    Allows from labels %+v", sel)
			if sel.Matches(ctx.From) {
				ctx.PolicyTrace("      Found all required labels")
				if len(r.ToPorts) == 0 {
					ctx.PolicyTrace("+       No L4 restrictions\n")
					state.matchedRules++
					return api.Allowed
				}
				ctx.PolicyTrace("        Rule restricts traffic to specific L4 destinations; deferring policy decision to L4 policy stage\n")
			} else {
				ctx.PolicyTrace("      Labels %v not found\n", ctx.From)
			}
		}
	}

	for _, entitySelector := range r.fromEntities {
		if entitySelector.Matches(ctx.From) {
			ctx.PolicyTrace("+     Found all required labels to match entity %s\n", entitySelector.String())
			state.matchedRules++
			return api.Allowed
		}

	}

	return entitiesDecision
}

func (r *rule) canReachEntities(ctx *SearchContext, state *traceState) api.Decision {
	for _, entitySelector := range r.toEntities {
		if entitySelector.Matches(ctx.To) {
			ctx.PolicyTrace("+     Found all required labels to match entity %s\n", entitySelector.String())
			state.matchedRules++
			return api.Allowed
		}
	}

	return api.Undecided
}
<|endoftext|>


<commit_before>package notifications

import (
	"encoding/json"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/citruspi/milou/configuration"
	"github.com/fzzy/radix/redis"
)

type Notification struct {
	Repository string `json:"repository"`
	Owner      string `json:"owner"`
	Commit     string `json:"commit"`
	Branch     string `json:"branch"`
}

var (
	conf configuration.Configuration
)

func init() {
	log.SetLevel(log.DebugLevel)

	conf = configuration.Load()
}

func (n Notification) Publish() {
	var err error
	var conn *redis.Client
	var channel string
	var message string
	var marshalled []byte
	var timeout time.Duration

	timeout := time.Duration(conf.Redis.Timeout) * time.Second

	conn, err := redis.DialTimeout("tcp", conf.Redis.Address, timeout)

	if err != nil {
		log.Fatal(err)
	} else {
		log.Info("Established connection to redis")
	}

	defer conn.Close()

	marshalled, err = json.Marshal(n)

	if err != nil {
		log.Fatal(err)
	}

	message = string(marshalled)

	channel = "milou." + n.Owner + "." + n.Repository

	conn.Cmd("publish", channel, message)

	log.WithFields(log.Fields{
		"message": message,
		"channel": channel,
	}).Info("Published notification")
}
<commit_msg>Fixed error re: no new variables on the left side...<commit_after>package notifications

import (
	"encoding/json"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/citruspi/milou/configuration"
	"github.com/fzzy/radix/redis"
)

type Notification struct {
	Repository string `json:"repository"`
	Owner      string `json:"owner"`
	Commit     string `json:"commit"`
	Branch     string `json:"branch"`
}

var (
	conf configuration.Configuration
)

func init() {
	log.SetLevel(log.DebugLevel)

	conf = configuration.Load()
}

func (n Notification) Publish() {
	var err error
	var conn *redis.Client
	var channel string
	var message string
	var marshalled []byte
	var timeout time.Duration

	timeout = time.Duration(conf.Redis.Timeout) * time.Second

	conn, err = redis.DialTimeout("tcp", conf.Redis.Address, timeout)

	if err != nil {
		log.Fatal(err)
	} else {
		log.Info("Established connection to redis")
	}

	defer conn.Close()

	marshalled, err = json.Marshal(n)

	if err != nil {
		log.Fatal(err)
	}

	message = string(marshalled)

	channel = "milou." + n.Owner + "." + n.Repository

	conn.Cmd("publish", channel, message)

	log.WithFields(log.Fields{
		"message": message,
		"channel": channel,
	}).Info("Published notification")
}
<|endoftext|>


<commit_before>// Copyright 2016 The etcd-operator 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 spec

// TODO: supports object store like s3
type BackupStorageType string

const (
	BackupStorageTypePersistentVolume = "PersistentVolume"
)

type BackupPolicy struct {
	// SnapshotIntervalInSecond specifies the interval between two snapshots.
	// The default interval is 1800 seconds.
	SnapshotIntervalInSecond int `json:"snapshotIntervalInSecond"`
	// MaxSnapshot is the maximum number of snapshot files to retain. 0 is disable backup.
	// If backup is disabled, the etcd cluster cannot recover from a
	// disaster failure (lose more than half of its members at the same
	// time).
	MaxSnapshot int `json:"maxSnapshot"`
	// VolumeSizeInMB specifies the required volume size to perform backups.
	// Controller will claim the required size before creating the etcd cluster for backup
	// purpose.
	// If the snapshot size is larger than the size specified, backup fails.
	VolumeSizeInMB int `json:"volumeSizeInMB"`
	// StorageType specifies the type of storage device to store backup files.
	// If it's not set by user, the default is "PersistentVolume".
	StorageType BackupStorageType `json:"storageType"`
	// CleanupStorageIfDeleted specified whether we want to cleanup the backup data if cluster is deleted.
	// By default, controller will keep the backup data.
	CleanupBackupIfDeleted bool `json:"cleanupBackupIfDeleted"`
}
<commit_msg>docs: rename controller -> operator<commit_after>// Copyright 2016 The etcd-operator 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 spec

// TODO: supports object store like s3
type BackupStorageType string

const (
	BackupStorageTypePersistentVolume = "PersistentVolume"
)

type BackupPolicy struct {
	// SnapshotIntervalInSecond specifies the interval between two snapshots.
	// The default interval is 1800 seconds.
	SnapshotIntervalInSecond int `json:"snapshotIntervalInSecond"`
	// MaxSnapshot is the maximum number of snapshot files to retain. 0 is disable backup.
	// If backup is disabled, the etcd cluster cannot recover from a
	// disaster failure (lose more than half of its members at the same
	// time).
	MaxSnapshot int `json:"maxSnapshot"`
	// VolumeSizeInMB specifies the required volume size to perform backups.
	// Operator will claim the required size before creating the etcd cluster for backup
	// purpose.
	// If the snapshot size is larger than the size specified, backup fails.
	VolumeSizeInMB int `json:"volumeSizeInMB"`
	// StorageType specifies the type of storage device to store backup files.
	// If it's not set by user, the default is "PersistentVolume".
	StorageType BackupStorageType `json:"storageType"`
	// CleanupStorageIfDeleted specified whether we want to cleanup the backup data if cluster is deleted.
	// By default, operator will keep the backup data.
	CleanupBackupIfDeleted bool `json:"cleanupBackupIfDeleted"`
}
<|endoftext|>


<commit_before>package checkerlution

type RandomThinker struct {
	ourTeamId int
}

func (r *RandomThinker) Start(ourTeamId int) {
	r.ourTeamId = ourTeamId
}

func (r RandomThinker) Think(gameState GameState) (bestMove ValidMove) {
	ourTeam := gameState.Teams[r.ourTeamId]
	allValidMoves := ourTeam.AllValidMoves()
	randomValidMoveIndex := randomIntInRange(0, len(allValidMoves))
	bestMove = allValidMoves[randomValidMoveIndex]
	return
}

func (r RandomThinker) Stop() {

}
<commit_msg>move random thinker to its own repo<commit_after><|endoftext|>


<commit_before>package client

var templates = map[string]string{
	"deployment": deploymentTmpl,
	"service":    serviceTmpl,
	"namespace":  namespaceTmpl,
}

// stripped image pull policy always
// imagePullPolicy: Always
var deploymentTmpl = `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: "{{ .Metadata.Name }}"
  namespace: "{{ .Metadata.Namespace }}"
  labels:
    {{- with .Metadata.Labels }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
  annotations:
    {{- with .Metadata.Annotations }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
spec:
  replicas: {{ .Spec.Replicas }}
  selector:
    matchLabels:
      {{- with .Spec.Selector.MatchLabels }}
      {{- range $key, $value := . }}
      {{ $key }}: "{{ $value }}"
      {{- end }}
      {{- end }}
  template:
    metadata:
      labels:
        {{- with .Spec.Template.Metadata.Labels }}
        {{- range $key, $value := . }}
        {{ $key }}: "{{ $value }}"
        {{- end }}
        {{- end }}
      annotations:
        {{- with .Spec.Template.Metadata.Annotations }}
        {{- range $key, $value := . }}
        {{ $key }}: "{{ $value }}"
        {{- end }}
        {{- end }}
    spec:
      imagePullSecrets:
      {{- with .Spec.Template.PodSpec.ImagePullSecrets }}
      {{- range . }}
      - {{ . }}
      {{ end }}
      containers:
      {{- with .Spec.Template.PodSpec.Containers }}
      {{- range . }}
        - name: {{ .Name }}
          env:
          {{- with .Env }}
          {{- range . }}
          - name: "{{ .Name }}"
            value: "{{ .Value }}"
          {{- end }}
          {{- end }}
          args:
          {{- range .Args }}
          - {{.}}
          {{- end }}
          command:
          {{- range .Command }}
          - {{.}}
          {{- end }}
          image: {{ .Image }}
          ports:
          {{- with .Ports }}
          {{- range . }}
          - containerPort: {{ .ContainerPort }}
            name: {{ .Name }}
          {{- end}}
          {{- end}}
      {{- end }}
      {{- end}}
`

var serviceTmpl = `
apiVersion: v1
kind: Service
metadata:
  name: "{{ .Metadata.Name }}"
  namespace: "{{ .Metadata.Namespace }}"
  labels:
    {{- with .Metadata.Labels }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
spec:
  selector:
    {{- with .Spec.Selector }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
  ports:
  {{- with .Spec.Ports }}
  {{- range . }}
  - name: "{{ .Name }}"
    port: {{ .Port }}
    protocol: {{ .Protocol }}
  {{- end }}
  {{- end }}
`

var namespaceTmpl = `
apiVersion: v1
kind: Namespace
metadata:
  name: "{{ .Metadata.Name }}"
  labels:
    {{- with .Metadata.Labels }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
`
<commit_msg>Fix template syntax<commit_after>package client

var templates = map[string]string{
	"deployment": deploymentTmpl,
	"service":    serviceTmpl,
	"namespace":  namespaceTmpl,
}

// stripped image pull policy always
// imagePullPolicy: Always
var deploymentTmpl = `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: "{{ .Metadata.Name }}"
  namespace: "{{ .Metadata.Namespace }}"
  labels:
    {{- with .Metadata.Labels }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
  annotations:
    {{- with .Metadata.Annotations }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
spec:
  replicas: {{ .Spec.Replicas }}
  selector:
    matchLabels:
      {{- with .Spec.Selector.MatchLabels }}
      {{- range $key, $value := . }}
      {{ $key }}: "{{ $value }}"
      {{- end }}
      {{- end }}
  template:
    metadata:
      labels:
        {{- with .Spec.Template.Metadata.Labels }}
        {{- range $key, $value := . }}
        {{ $key }}: "{{ $value }}"
        {{- end }}
        {{- end }}
      annotations:
        {{- with .Spec.Template.Metadata.Annotations }}
        {{- range $key, $value := . }}
        {{ $key }}: "{{ $value }}"
        {{- end }}
        {{- end }}
    spec:
      imagePullSecrets:
      {{- with .Spec.Template.PodSpec.ImagePullSecrets }}
      {{- range . }}
      - {{ . }}
      {{- end }}
      {{- end }}
      containers:
      {{- with .Spec.Template.PodSpec.Containers }}
      {{- range . }}
        - name: {{ .Name }}
          env:
          {{- with .Env }}
          {{- range . }}
          - name: "{{ .Name }}"
            value: "{{ .Value }}"
          {{- end }}
          {{- end }}
          args:
          {{- range .Args }}
          - {{.}}
          {{- end }}
          command:
          {{- range .Command }}
          - {{.}}
          {{- end }}
          image: {{ .Image }}
          ports:
          {{- with .Ports }}
          {{- range . }}
          - containerPort: {{ .ContainerPort }}
            name: {{ .Name }}
          {{- end}}
          {{- end}}
      {{- end }}
      {{- end}}
`

var serviceTmpl = `
apiVersion: v1
kind: Service
metadata:
  name: "{{ .Metadata.Name }}"
  namespace: "{{ .Metadata.Namespace }}"
  labels:
    {{- with .Metadata.Labels }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
spec:
  selector:
    {{- with .Spec.Selector }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
  ports:
  {{- with .Spec.Ports }}
  {{- range . }}
  - name: "{{ .Name }}"
    port: {{ .Port }}
    protocol: {{ .Protocol }}
  {{- end }}
  {{- end }}
`

var namespaceTmpl = `
apiVersion: v1
kind: Namespace
metadata:
  name: "{{ .Metadata.Name }}"
  labels:
    {{- with .Metadata.Labels }}
    {{- range $key, $value := . }}
    {{ $key }}: "{{ $value }}"
    {{- end }}
    {{- end }}
`
<|endoftext|>


<commit_before>package filter

import (
	"testing"

	"github.com/docker/docker/api/types"
	containertypes "github.com/docker/docker/api/types/container"
	networktypes "github.com/docker/docker/api/types/network"
	"github.com/docker/swarm/cluster"
	"github.com/docker/swarm/scheduler/node"
	"github.com/stretchr/testify/assert"
)

func TestDependencyFilterSimple(t *testing.T) {
	var (
		f     = DependencyFilter{}
		nodes = []*node.Node{
			{
				ID:   "node-0-id",
				Name: "node-0-name",
				Addr: "node-0",
				Containers: []*cluster.Container{{
					Container: types.Container{ID: "c0"},
					Config:    &cluster.ContainerConfig{},
				}},
			},

			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
				Containers: []*cluster.Container{{
					Container: types.Container{ID: "c1"},
					Config:    &cluster.ContainerConfig{},
				}},
			},

			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
				Containers: []*cluster.Container{{
					Container: types.Container{ID: "c2"},
					Config:    &cluster.ContainerConfig{},
				}},
			},
		}
		result []*node.Node
		err    error
		config *cluster.ContainerConfig
	)

	// No dependencies - make sure we don't filter anything out.
	config = &cluster.ContainerConfig{}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Equal(t, result, nodes)

	// volumes-from.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// volumes-from:rw
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0:rw"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// volumes-from:ro
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0:ro"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// link.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			Links: []string{"c1:foobar"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[1])

	// net.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			NetworkMode: containertypes.NetworkMode("container:c2"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[2])

	// net not prefixed by "container:" should be ignored.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			NetworkMode: containertypes.NetworkMode("bridge"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Equal(t, result, nodes)
}

func TestDependencyFilterMulti(t *testing.T) {
	var (
		f     = DependencyFilter{}
		nodes = []*node.Node{
			// nodes[0] has c0 and c1
			{
				ID:   "node-0-id",
				Name: "node-0-name",
				Addr: "node-0",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c0"},
						Config:    &cluster.ContainerConfig{},
					},
					{
						Container: types.Container{ID: "c1"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[1] has c2
			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c2"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[2] has nothing
			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
			},
		}
		result []*node.Node
		err    error
		config *cluster.ContainerConfig
	)

	// Depend on c0 which is on nodes[0]
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Depend on c1 which is on nodes[0]
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c1"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Depend on c0 AND c1 which are both on nodes[0]
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0", "c1"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Depend on c0 AND c2 which are on different nodes.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0", "c2"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.Error(t, err)
}

func TestDependencyFilterChaining(t *testing.T) {
	var (
		f     = DependencyFilter{}
		nodes = []*node.Node{
			// nodes[0] has c0 and c1
			{
				ID:   "node-0-id",
				Name: "node-0-name",
				Addr: "node-0",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c0"},
						Config:    &cluster.ContainerConfig{},
					},
					{
						Container: types.Container{ID: "c1"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[1] has c2
			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c2"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[2] has nothing
			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
			},
		}
		result []*node.Node
		err    error
		config *cluster.ContainerConfig
	)

	// Different dependencies on c0 and c1
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
			Links:       []string{"c1"},
			NetworkMode: containertypes.NetworkMode("container:c1"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Different dependencies on c0 and c2
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
			Links:       []string{"c2"},
			NetworkMode: containertypes.NetworkMode("container:c1"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.Error(t, err)
}
<commit_msg>remove result in returns of Filter() which is unused<commit_after>package filter

import (
	"testing"

	"github.com/docker/docker/api/types"
	containertypes "github.com/docker/docker/api/types/container"
	networktypes "github.com/docker/docker/api/types/network"
	"github.com/docker/swarm/cluster"
	"github.com/docker/swarm/scheduler/node"
	"github.com/stretchr/testify/assert"
)

func TestDependencyFilterSimple(t *testing.T) {
	var (
		f     = DependencyFilter{}
		nodes = []*node.Node{
			{
				ID:   "node-0-id",
				Name: "node-0-name",
				Addr: "node-0",
				Containers: []*cluster.Container{{
					Container: types.Container{ID: "c0"},
					Config:    &cluster.ContainerConfig{},
				}},
			},

			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
				Containers: []*cluster.Container{{
					Container: types.Container{ID: "c1"},
					Config:    &cluster.ContainerConfig{},
				}},
			},

			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
				Containers: []*cluster.Container{{
					Container: types.Container{ID: "c2"},
					Config:    &cluster.ContainerConfig{},
				}},
			},
		}
		result []*node.Node
		err    error
		config *cluster.ContainerConfig
	)

	// No dependencies - make sure we don't filter anything out.
	config = &cluster.ContainerConfig{}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Equal(t, result, nodes)

	// volumes-from.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// volumes-from:rw
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0:rw"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// volumes-from:ro
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0:ro"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// link.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			Links: []string{"c1:foobar"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[1])

	// net.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			NetworkMode: containertypes.NetworkMode("container:c2"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[2])

	// net not prefixed by "container:" should be ignored.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			NetworkMode: containertypes.NetworkMode("bridge"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Equal(t, result, nodes)
}

func TestDependencyFilterMulti(t *testing.T) {
	var (
		f     = DependencyFilter{}
		nodes = []*node.Node{
			// nodes[0] has c0 and c1
			{
				ID:   "node-0-id",
				Name: "node-0-name",
				Addr: "node-0",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c0"},
						Config:    &cluster.ContainerConfig{},
					},
					{
						Container: types.Container{ID: "c1"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[1] has c2
			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c2"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[2] has nothing
			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
			},
		}
		result []*node.Node
		err    error
		config *cluster.ContainerConfig
	)

	// Depend on c0 which is on nodes[0]
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Depend on c1 which is on nodes[0]
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c1"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Depend on c0 AND c1 which are both on nodes[0]
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0", "c1"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Depend on c0 AND c2 which are on different nodes.
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0", "c2"},
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	_, err = f.Filter(config, nodes, true)
	assert.Error(t, err)
}

func TestDependencyFilterChaining(t *testing.T) {
	var (
		f     = DependencyFilter{}
		nodes = []*node.Node{
			// nodes[0] has c0 and c1
			{
				ID:   "node-0-id",
				Name: "node-0-name",
				Addr: "node-0",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c0"},
						Config:    &cluster.ContainerConfig{},
					},
					{
						Container: types.Container{ID: "c1"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[1] has c2
			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
				Containers: []*cluster.Container{
					{
						Container: types.Container{ID: "c2"},
						Config:    &cluster.ContainerConfig{},
					},
				},
			},

			// nodes[2] has nothing
			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
			},
		}
		result []*node.Node
		err    error
		config *cluster.ContainerConfig
	)

	// Different dependencies on c0 and c1
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
			Links:       []string{"c1"},
			NetworkMode: containertypes.NetworkMode("container:c1"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = f.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Len(t, result, 1)
	assert.Equal(t, result[0], nodes[0])

	// Different dependencies on c0 and c2
	config = &cluster.ContainerConfig{
		Config: containertypes.Config{},
		HostConfig: containertypes.HostConfig{
			VolumesFrom: []string{"c0"},
			Links:       []string{"c2"},
			NetworkMode: containertypes.NetworkMode("container:c1"),
		},
		NetworkingConfig: networktypes.NetworkingConfig{}}
	_, err = f.Filter(config, nodes, true)
	assert.Error(t, err)
}
<|endoftext|>


<commit_before>package raster

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"io/ioutil"
)

var (
	// ErrUnknownVersion is returned when encountering an unknown
	// magic byte sequence. It is indicative of input in a newer
	// format, or input that isn't a CUPS raster stream at all.
	ErrUnknownVersion = errors.New("unsupported file format or version")

	// ErrUnsupported is returned when encountering an unsupported
	// feature. This includes unsupported color spaces, color
	// orderings or bit depths.
	ErrUnsupported = errors.New("unsupported feature")

	// ErrBufferTooSmall is returned from ReadLine and ReadAll when
	// the buffer is smaller than Page.LineSize or Page.TotalSize
	// respectively.
	ErrBufferTooSmall = errors.New("buffer too small")

	// ErrInvalidFormat is returned when encountering values that
	// aren't possible in the supported versions of the format.
	ErrInvalidFormat = errors.New("error in the format")
)

const (
	syncV1BE = "RaSt"
	syncV1LE = "tSaR"

	syncV2BE = "RaS2"
	syncV2LE = "2SaR"

	syncV3BE = "RaS3"
	syncV3LE = "3SaR"
)

func parseMagic(b []byte) (version int, bo binary.ByteOrder, ok bool) {
	if len(b) != 4 {
		return 0, nil, false
	}
	switch string(b) {
	case syncV1BE:
		return 1, binary.BigEndian, true
	case syncV2BE:
		return 2, binary.BigEndian, true
	case syncV3BE:
		return 3, binary.BigEndian, true
	case syncV1LE:
		return 1, binary.LittleEndian, true
	case syncV2LE:
		return 2, binary.LittleEndian, true
	case syncV3LE:
		return 3, binary.LittleEndian, true
	default:
		return 0, nil, false
	}
}

type countingReader struct {
	r io.Reader
	n int
}

func (r *countingReader) Read(b []byte) (n int, err error) {
	n, err = r.r.Read(b)
	r.n += n
	return n, err
}

type Decoder struct {
	r       *countingReader
	bo      binary.ByteOrder
	err     error
	version int
	curPage *Page
}

func NewDecoder(r io.Reader) (*Decoder, error) {
	d := &Decoder{r: &countingReader{r: r}}
	magic := make([]byte, 4)
	_, err := io.ReadFull(r, magic)
	if err != nil {
		return nil, err
	}
	var ok bool
	d.version, d.bo, ok = parseMagic(magic)
	if !ok {
		return nil, ErrUnknownVersion
	}
	return d, nil
}

type Page struct {
	Header    *Header
	dec       *Decoder
	line      []byte
	color     []byte
	lineRep   int
	linesRead int
}

// NextPage returns the next page in the raster stream. After a call
// to NextPage, all previously returned pages from this decoder cannot
// be used to decode image data anymore. Their header data, however,
// remains valid.
func (d *Decoder) NextPage() (*Page, error) {
	if d.curPage != nil {
		if err := d.curPage.discard(); err != nil {
			return nil, err
		}
	}
	var err error
	var h *Header

	n := d.r.n
	switch d.version {
	case 1:
		h, err = d.decodeV1Header()
	case 2, 3:
		h, err = d.decodeV2Header()
	default:
		// can't happen, NewDecoder rejects unknown versions
		panic("impossible")
	}
	if err == io.EOF && d.r.n != n {
		return nil, io.ErrUnexpectedEOF
	}
	if err != nil {
		return nil, err
	}
	bpc, err := bytesPerColor(h)
	if err != nil {
		return nil, err
	}
	p := &Page{
		Header: h,
		dec:    d,
		line:   make([]byte, 0, h.CUPSBytesPerLine),
		color:  make([]byte, bpc),
	}
	d.curPage = p
	return p, nil
}

func (p *Page) discard() error {
	n := p.UnreadLines() * int(p.LineSize())
	r := io.LimitReader(p.dec.r, int64(n))
	_, err := io.Copy(ioutil.Discard, r)
	if err == io.EOF {
		return io.ErrUnexpectedEOF
	}
	return err
}

// ReadLine returns the next line of pixels in the image.
func (p *Page) ReadLine(b []byte) error {
	if int64(len(b)) < int64(p.Header.CUPSBytesPerLine) {
		return ErrBufferTooSmall
	}
	if p.UnreadLines() == 0 {
		return io.EOF
	}
	p.linesRead++
	switch p.dec.version {
	case 1:
		return p.readRawLine(b)
	case 2:
		return p.readV2Line(b)
	case 3:
		return p.readRawLine(b)
	default:
		// can't happen, NewDecoder rejects unknown versions
		panic("impossible")
	}
}

func (p *Page) readV2Line(b []byte) (err error) {
	defer func() {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()

	if p.lineRep > 0 {
		p.lineRep--
		copy(b, p.line)
		return nil
	}

	var lineRep byte
	err = binary.Read(p.dec.r, p.dec.bo, &lineRep)
	if err != nil {
		return err
	}
	p.line = p.line[:0]
	// the count is stored as count - 1, but we're already reading the
	// first line, anyway.
	p.lineRep = int(lineRep)

	for len(p.line) < int(p.Header.CUPSBytesPerLine) {
		var n byte
		err := binary.Read(p.dec.r, p.dec.bo, &n)
		if err != nil {
			return err
		}
		if n <= 127 {
			// n repeating colors
			n := int(n + 1)
			_, err := io.ReadFull(p.dec.r, p.color)
			if err != nil {
				return err
			}

			for i := 0; i < n; i++ {
				p.line = append(p.line, p.color...)
			}
		} else {
			// n non-repeating colors
			n := 257 - int(n)
			for i := 0; i < n; i++ {
				_, err := io.ReadFull(p.dec.r, p.color)
				if err != nil {
					return err
				}
				p.line = append(p.line, p.color...)
			}
		}
	}
	copy(b, p.line)
	return nil
}

func (p *Page) readRawLine(b []byte) error {
	b = b[:p.Header.CUPSBytesPerLine]
	_, err := io.ReadFull(p.dec.r, b)
	return err
}

// UnreadLines returns the number of unread lines in the page.
func (p *Page) UnreadLines() int {
	return int(p.Header.CUPSHeight) - p.linesRead
}

// ReadAll reads the entire page into b. If ReadLine has been called
// previously, ReadAll will read the remainder of the page.
func (p *Page) ReadAll(b []byte) error {
	if len(b) < int(p.LineSize())*p.UnreadLines() {
		return ErrBufferTooSmall
	}
	n := p.UnreadLines()
	for i := uint32(0); i < uint32(n); i++ {
		start := i * p.Header.CUPSBytesPerLine
		end := start + p.Header.CUPSBytesPerLine
		err := p.ReadLine(b[start:end:end])
		if err == io.EOF {
			return io.ErrUnexpectedEOF
		}
		if err != nil {
			return err
		}
	}
	return nil
}

func cstring(b []byte) string {
	idx := bytes.IndexByte(b, 0)
	if idx < 0 {
		return ""
	}
	return string(b[:idx])
}

func (d *Decoder) readCString() string {
	if d.err != nil {
		return ""
	}
	b := make([]byte, 64)
	_, d.err = io.ReadFull(d.r, b)
	return cstring(b)
}

func (d *Decoder) readUint() uint32 {
	if d.err != nil {
		return 0
	}
	var v uint32
	d.err = binary.Read(d.r, d.bo, &v)
	return v
}

func (d *Decoder) readFloat() float32 {
	if d.err != nil {
		return 0
	}
	var v float32
	d.err = binary.Read(d.r, d.bo, &v)
	return v
}

func (d *Decoder) readBool() bool {
	return d.readUint() == 1
}

func (d *Decoder) decodeV1Header() (*Header, error) {
	data := struct {
		AdvanceDistance  uint32
		AdvanceMedia     uint32
		Collate          uint32
		CutMedia         uint32
		Duplex           uint32
		HorizDPI         uint32
		VertDPI          uint32
		BoundingBox      BoundingBox
		InsertSheet      uint32
		Jog              uint32
		LeadingEdge      uint32
		MarginLeft       uint32
		MarginBottom     uint32
		ManualFeed       uint32
		MediaPosition    uint32
		MediaWeight      uint32
		MirrorPrint      uint32
		NegativePrint    uint32
		NumCopies        uint32
		Orientation      uint32
		OutputFaceUp     uint32
		Width            uint32
		Length           uint32
		Separations      uint32
		TraySwitch       uint32
		Tumble           uint32
		CUPSWidth        uint32
		CUPSHeight       uint32
		CUPSMediaType    uint32
		CUPSBitsPerColor uint32
		CUPSBitsPerPixel uint32
		CUPSBytesPerLine uint32
		CUPSColorOrder   uint32
		CUPSColorSpace   uint32
		CUPSCompression  uint32
		CUPSRowCount     uint32
		CUPSRowFeed      uint32
		CUPSRowStep      uint32
	}{}

	h := Header{}
	h.MediaClass = d.readCString()
	h.MediaColor = d.readCString()
	h.MediaType = d.readCString()
	h.OutputType = d.readCString()

	// FIXME handle error
	err := binary.Read(d.r, d.bo, &data)
	if err != nil {
		return nil, err
	}
	h.AdvanceDistance = data.AdvanceDistance
	h.AdvanceMedia = int(data.AdvanceMedia)
	h.Collate = data.Collate == 1
	h.CutMedia = int(data.CutMedia)
	h.Duplex = data.Duplex == 1
	h.HorizDPI = data.HorizDPI
	h.VertDPI = data.VertDPI
	h.BoundingBox = data.BoundingBox
	h.InsertSheet = data.InsertSheet == 1
	h.Jog = int(data.Jog)
	h.LeadingEdge = int(data.LeadingEdge)
	h.MarginLeft = data.MarginLeft
	h.MarginBottom = data.MarginBottom
	h.ManualFeed = data.ManualFeed == 1
	h.MediaPosition = data.MediaPosition
	h.MediaWeight = data.MediaWeight
	h.MirrorPrint = data.MirrorPrint == 1
	h.NegativePrint = data.NegativePrint == 1
	h.NumCopies = data.NumCopies
	h.Orientation = int(data.Orientation)
	h.OutputFaceUp = data.OutputFaceUp == 1
	h.Width = data.Width
	h.Length = data.Length
	h.Separations = data.Separations == 1
	h.TraySwitch = data.TraySwitch == 1
	h.Tumble = data.Tumble == 1
	h.CUPSWidth = data.CUPSWidth
	h.CUPSHeight = data.CUPSHeight
	h.CUPSMediaType = data.CUPSMediaType
	h.CUPSBitsPerColor = data.CUPSBitsPerColor
	h.CUPSBitsPerPixel = data.CUPSBitsPerPixel
	h.CUPSBytesPerLine = data.CUPSBytesPerLine
	h.CUPSColorOrder = int(data.CUPSColorOrder)
	h.CUPSColorSpace = int(data.CUPSColorSpace)
	h.CUPSCompression = data.CUPSCompression
	h.CUPSRowCount = data.CUPSRowCount
	h.CUPSRowFeed = data.CUPSRowFeed
	h.CUPSRowStep = data.CUPSRowStep

	return &h, d.err
}

func (d *Decoder) decodeV2Header() (*Header, error) {
	h, err := d.decodeV1Header()
	if err != nil {
		return nil, err
	}

	data := struct {
		CUPSNumColors               uint32
		CUPSBorderlessScalingFactor float32
		CUPSPageSize                [2]float32
		CUPSImagingBBox             CUPSBoundingBox
		CUPSInteger                 [16]uint32
		CUPSReal                    [16]float32
	}{}

	err = binary.Read(d.r, d.bo, &data)
	if err != nil {
		return nil, err
	}
	h.CUPSNumColors = data.CUPSNumColors
	h.CUPSBorderlessScalingFactor = data.CUPSBorderlessScalingFactor
	h.CUPSPageSize = data.CUPSPageSize
	h.CUPSImagingBBox = data.CUPSImagingBBox
	h.CUPSInteger = data.CUPSInteger
	h.CUPSReal = data.CUPSReal

	for i := range h.CUPSString {
		h.CUPSString[i] = d.readCString()
	}
	h.CUPSMarkerType = d.readCString()
	h.CUPSRenderingIntent = d.readCString()
	h.CUPSPageSizeName = d.readCString()

	return h, d.err
}

func bytesPerColor(h *Header) (int, error) {
	switch h.CUPSColorOrder {
	case ChunkyPixels:
		return int(h.CUPSBitsPerPixel+7) / 8, nil
	case BandedPixels, PlanarPixels:
		return int(h.CUPSBitsPerColor+7) / 8, nil
	default:
		// The versions that we support only know these 3 color orders
		return 0, ErrInvalidFormat
	}
}
<commit_msg>raster: document that io.ReadLine returns io.EOF<commit_after>package raster

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"io/ioutil"
)

var (
	// ErrUnknownVersion is returned when encountering an unknown
	// magic byte sequence. It is indicative of input in a newer
	// format, or input that isn't a CUPS raster stream at all.
	ErrUnknownVersion = errors.New("unsupported file format or version")

	// ErrUnsupported is returned when encountering an unsupported
	// feature. This includes unsupported color spaces, color
	// orderings or bit depths.
	ErrUnsupported = errors.New("unsupported feature")

	// ErrBufferTooSmall is returned from ReadLine and ReadAll when
	// the buffer is smaller than Page.LineSize or Page.TotalSize
	// respectively.
	ErrBufferTooSmall = errors.New("buffer too small")

	// ErrInvalidFormat is returned when encountering values that
	// aren't possible in the supported versions of the format.
	ErrInvalidFormat = errors.New("error in the format")
)

const (
	syncV1BE = "RaSt"
	syncV1LE = "tSaR"

	syncV2BE = "RaS2"
	syncV2LE = "2SaR"

	syncV3BE = "RaS3"
	syncV3LE = "3SaR"
)

func parseMagic(b []byte) (version int, bo binary.ByteOrder, ok bool) {
	if len(b) != 4 {
		return 0, nil, false
	}
	switch string(b) {
	case syncV1BE:
		return 1, binary.BigEndian, true
	case syncV2BE:
		return 2, binary.BigEndian, true
	case syncV3BE:
		return 3, binary.BigEndian, true
	case syncV1LE:
		return 1, binary.LittleEndian, true
	case syncV2LE:
		return 2, binary.LittleEndian, true
	case syncV3LE:
		return 3, binary.LittleEndian, true
	default:
		return 0, nil, false
	}
}

type countingReader struct {
	r io.Reader
	n int
}

func (r *countingReader) Read(b []byte) (n int, err error) {
	n, err = r.r.Read(b)
	r.n += n
	return n, err
}

type Decoder struct {
	r       *countingReader
	bo      binary.ByteOrder
	err     error
	version int
	curPage *Page
}

func NewDecoder(r io.Reader) (*Decoder, error) {
	d := &Decoder{r: &countingReader{r: r}}
	magic := make([]byte, 4)
	_, err := io.ReadFull(r, magic)
	if err != nil {
		return nil, err
	}
	var ok bool
	d.version, d.bo, ok = parseMagic(magic)
	if !ok {
		return nil, ErrUnknownVersion
	}
	return d, nil
}

type Page struct {
	Header    *Header
	dec       *Decoder
	line      []byte
	color     []byte
	lineRep   int
	linesRead int
}

// NextPage returns the next page in the raster stream. After a call
// to NextPage, all previously returned pages from this decoder cannot
// be used to decode image data anymore. Their header data, however,
// remains valid.
func (d *Decoder) NextPage() (*Page, error) {
	if d.curPage != nil {
		if err := d.curPage.discard(); err != nil {
			return nil, err
		}
	}
	var err error
	var h *Header

	n := d.r.n
	switch d.version {
	case 1:
		h, err = d.decodeV1Header()
	case 2, 3:
		h, err = d.decodeV2Header()
	default:
		// can't happen, NewDecoder rejects unknown versions
		panic("impossible")
	}
	if err == io.EOF && d.r.n != n {
		return nil, io.ErrUnexpectedEOF
	}
	if err != nil {
		return nil, err
	}
	bpc, err := bytesPerColor(h)
	if err != nil {
		return nil, err
	}
	p := &Page{
		Header: h,
		dec:    d,
		line:   make([]byte, 0, h.CUPSBytesPerLine),
		color:  make([]byte, bpc),
	}
	d.curPage = p
	return p, nil
}

func (p *Page) discard() error {
	n := p.UnreadLines() * int(p.LineSize())
	r := io.LimitReader(p.dec.r, int64(n))
	_, err := io.Copy(ioutil.Discard, r)
	if err == io.EOF {
		return io.ErrUnexpectedEOF
	}
	return err
}

// ReadLine returns the next line of pixels in the image. It returns
// io.EOF if no more lines can be read.
func (p *Page) ReadLine(b []byte) error {
	if int64(len(b)) < int64(p.Header.CUPSBytesPerLine) {
		return ErrBufferTooSmall
	}
	if p.UnreadLines() == 0 {
		return io.EOF
	}
	p.linesRead++
	switch p.dec.version {
	case 1:
		return p.readRawLine(b)
	case 2:
		return p.readV2Line(b)
	case 3:
		return p.readRawLine(b)
	default:
		// can't happen, NewDecoder rejects unknown versions
		panic("impossible")
	}
}

func (p *Page) readV2Line(b []byte) (err error) {
	defer func() {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()

	if p.lineRep > 0 {
		p.lineRep--
		copy(b, p.line)
		return nil
	}

	var lineRep byte
	err = binary.Read(p.dec.r, p.dec.bo, &lineRep)
	if err != nil {
		return err
	}
	p.line = p.line[:0]
	// the count is stored as count - 1, but we're already reading the
	// first line, anyway.
	p.lineRep = int(lineRep)

	for len(p.line) < int(p.Header.CUPSBytesPerLine) {
		var n byte
		err := binary.Read(p.dec.r, p.dec.bo, &n)
		if err != nil {
			return err
		}
		if n <= 127 {
			// n repeating colors
			n := int(n + 1)
			_, err := io.ReadFull(p.dec.r, p.color)
			if err != nil {
				return err
			}

			for i := 0; i < n; i++ {
				p.line = append(p.line, p.color...)
			}
		} else {
			// n non-repeating colors
			n := 257 - int(n)
			for i := 0; i < n; i++ {
				_, err := io.ReadFull(p.dec.r, p.color)
				if err != nil {
					return err
				}
				p.line = append(p.line, p.color...)
			}
		}
	}
	copy(b, p.line)
	return nil
}

func (p *Page) readRawLine(b []byte) error {
	b = b[:p.Header.CUPSBytesPerLine]
	_, err := io.ReadFull(p.dec.r, b)
	return err
}

// UnreadLines returns the number of unread lines in the page.
func (p *Page) UnreadLines() int {
	return int(p.Header.CUPSHeight) - p.linesRead
}

// ReadAll reads the entire page into b. If ReadLine has been called
// previously, ReadAll will read the remainder of the page.
func (p *Page) ReadAll(b []byte) error {
	if len(b) < int(p.LineSize())*p.UnreadLines() {
		return ErrBufferTooSmall
	}
	n := p.UnreadLines()
	for i := uint32(0); i < uint32(n); i++ {
		start := i * p.Header.CUPSBytesPerLine
		end := start + p.Header.CUPSBytesPerLine
		err := p.ReadLine(b[start:end:end])
		if err == io.EOF {
			return io.ErrUnexpectedEOF
		}
		if err != nil {
			return err
		}
	}
	return nil
}

func cstring(b []byte) string {
	idx := bytes.IndexByte(b, 0)
	if idx < 0 {
		return ""
	}
	return string(b[:idx])
}

func (d *Decoder) readCString() string {
	if d.err != nil {
		return ""
	}
	b := make([]byte, 64)
	_, d.err = io.ReadFull(d.r, b)
	return cstring(b)
}

func (d *Decoder) readUint() uint32 {
	if d.err != nil {
		return 0
	}
	var v uint32
	d.err = binary.Read(d.r, d.bo, &v)
	return v
}

func (d *Decoder) readFloat() float32 {
	if d.err != nil {
		return 0
	}
	var v float32
	d.err = binary.Read(d.r, d.bo, &v)
	return v
}

func (d *Decoder) readBool() bool {
	return d.readUint() == 1
}

func (d *Decoder) decodeV1Header() (*Header, error) {
	data := struct {
		AdvanceDistance  uint32
		AdvanceMedia     uint32
		Collate          uint32
		CutMedia         uint32
		Duplex           uint32
		HorizDPI         uint32
		VertDPI          uint32
		BoundingBox      BoundingBox
		InsertSheet      uint32
		Jog              uint32
		LeadingEdge      uint32
		MarginLeft       uint32
		MarginBottom     uint32
		ManualFeed       uint32
		MediaPosition    uint32
		MediaWeight      uint32
		MirrorPrint      uint32
		NegativePrint    uint32
		NumCopies        uint32
		Orientation      uint32
		OutputFaceUp     uint32
		Width            uint32
		Length           uint32
		Separations      uint32
		TraySwitch       uint32
		Tumble           uint32
		CUPSWidth        uint32
		CUPSHeight       uint32
		CUPSMediaType    uint32
		CUPSBitsPerColor uint32
		CUPSBitsPerPixel uint32
		CUPSBytesPerLine uint32
		CUPSColorOrder   uint32
		CUPSColorSpace   uint32
		CUPSCompression  uint32
		CUPSRowCount     uint32
		CUPSRowFeed      uint32
		CUPSRowStep      uint32
	}{}

	h := Header{}
	h.MediaClass = d.readCString()
	h.MediaColor = d.readCString()
	h.MediaType = d.readCString()
	h.OutputType = d.readCString()

	// FIXME handle error
	err := binary.Read(d.r, d.bo, &data)
	if err != nil {
		return nil, err
	}
	h.AdvanceDistance = data.AdvanceDistance
	h.AdvanceMedia = int(data.AdvanceMedia)
	h.Collate = data.Collate == 1
	h.CutMedia = int(data.CutMedia)
	h.Duplex = data.Duplex == 1
	h.HorizDPI = data.HorizDPI
	h.VertDPI = data.VertDPI
	h.BoundingBox = data.BoundingBox
	h.InsertSheet = data.InsertSheet == 1
	h.Jog = int(data.Jog)
	h.LeadingEdge = int(data.LeadingEdge)
	h.MarginLeft = data.MarginLeft
	h.MarginBottom = data.MarginBottom
	h.ManualFeed = data.ManualFeed == 1
	h.MediaPosition = data.MediaPosition
	h.MediaWeight = data.MediaWeight
	h.MirrorPrint = data.MirrorPrint == 1
	h.NegativePrint = data.NegativePrint == 1
	h.NumCopies = data.NumCopies
	h.Orientation = int(data.Orientation)
	h.OutputFaceUp = data.OutputFaceUp == 1
	h.Width = data.Width
	h.Length = data.Length
	h.Separations = data.Separations == 1
	h.TraySwitch = data.TraySwitch == 1
	h.Tumble = data.Tumble == 1
	h.CUPSWidth = data.CUPSWidth
	h.CUPSHeight = data.CUPSHeight
	h.CUPSMediaType = data.CUPSMediaType
	h.CUPSBitsPerColor = data.CUPSBitsPerColor
	h.CUPSBitsPerPixel = data.CUPSBitsPerPixel
	h.CUPSBytesPerLine = data.CUPSBytesPerLine
	h.CUPSColorOrder = int(data.CUPSColorOrder)
	h.CUPSColorSpace = int(data.CUPSColorSpace)
	h.CUPSCompression = data.CUPSCompression
	h.CUPSRowCount = data.CUPSRowCount
	h.CUPSRowFeed = data.CUPSRowFeed
	h.CUPSRowStep = data.CUPSRowStep

	return &h, d.err
}

func (d *Decoder) decodeV2Header() (*Header, error) {
	h, err := d.decodeV1Header()
	if err != nil {
		return nil, err
	}

	data := struct {
		CUPSNumColors               uint32
		CUPSBorderlessScalingFactor float32
		CUPSPageSize                [2]float32
		CUPSImagingBBox             CUPSBoundingBox
		CUPSInteger                 [16]uint32
		CUPSReal                    [16]float32
	}{}

	err = binary.Read(d.r, d.bo, &data)
	if err != nil {
		return nil, err
	}
	h.CUPSNumColors = data.CUPSNumColors
	h.CUPSBorderlessScalingFactor = data.CUPSBorderlessScalingFactor
	h.CUPSPageSize = data.CUPSPageSize
	h.CUPSImagingBBox = data.CUPSImagingBBox
	h.CUPSInteger = data.CUPSInteger
	h.CUPSReal = data.CUPSReal

	for i := range h.CUPSString {
		h.CUPSString[i] = d.readCString()
	}
	h.CUPSMarkerType = d.readCString()
	h.CUPSRenderingIntent = d.readCString()
	h.CUPSPageSizeName = d.readCString()

	return h, d.err
}

func bytesPerColor(h *Header) (int, error) {
	switch h.CUPSColorOrder {
	case ChunkyPixels:
		return int(h.CUPSBitsPerPixel+7) / 8, nil
	case BandedPixels, PlanarPixels:
		return int(h.CUPSBitsPerColor+7) / 8, nil
	default:
		// The versions that we support only know these 3 color orders
		return 0, ErrInvalidFormat
	}
}
<|endoftext|>


<commit_before>package emil

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"time"
)

type positionKey string

// PositionEntry is an entry in the PositionDb
type PositionEntry struct {
	Position      *position
	Dtm           int
	PrevPositions map[positionKey]*Move
	NextPositions map[positionKey]*Move
}

// NewPositionEntry ceates a new *PositionEntry
func NewPositionEntry(p *position) *PositionEntry {
	return &PositionEntry{
		Position:      p,
		Dtm:           initial,
		PrevPositions: make(map[positionKey]*Move),
		NextPositions: make(map[positionKey]*Move)}
}

func (entry *PositionEntry) addMoveToNextPosition(next *position, m *Move) {
}

// PositionDb to query for mate in 1,2, etc.
type PositionDb struct {
	Positions map[positionKey]*PositionEntry
}

func (db *PositionDb) addPosition(p *position) {
	if _, ok := db.Positions[p.key()]; ok {
		panic("key exsists in db " + p.key())
	}
	entry := NewPositionEntry(p)
	db.retrogradeAnalysisStep0(entry)
	db.Positions[p.key()] = entry
}

func (db *PositionDb) AddPrevPositions() {
	for key, entry := range db.Positions {
		for nextKey, moveToNext := range entry.NextPositions {
			nextPosition := PositionFromKey(string(nextKey))
			nextEntry, ok := db.Positions[nextPosition.key()]
			if ok {
				nextEntry.PrevPositions[key] = moveToNext
			}
		}
	}
}

// generate all moves
func (db *PositionDb) retrogradeAnalysisStep0(entry *PositionEntry) {
	moves := GenerateMoves(entry.Position)
	other := otherPlayer(entry.Position.player)
	for _, move := range moves {
		nextBoard := entry.Position.board.DoMove(move)
		nextPosition := NewPosition(nextBoard, other)
		entry.NextPositions[nextPosition.key()] = move
	}
}

// NewPositionDB creates a new *PositionDB
func NewPositionDB() *PositionDb {
	return &PositionDb{
		Positions: make(map[positionKey]*PositionEntry)}
}

func (db *PositionDb) FillWithKRKPositions() {
	var err error

	for wk := A1; wk <= H8; wk++ {
		start := time.Now()
		for bk := A1; bk <= H8; bk++ {
			if squaresDistances[wk][bk] <= 1 {
				continue
			}
			for wr := A1; wr <= H8; wr++ {
				board := NewBoard()

				if err = board.Setup(WhiteKing, wk); err != nil {
					continue
				}
				if err = board.Setup(BlackKing, bk); err != nil {
					continue
				}
				if err = board.Setup(WhiteRock, wr); err != nil {
					continue
				}

				db.addPosition(NewPosition(board, WHITE))
				db.addPosition(NewPosition(board, BLACK))
			}
		}
		end := time.Now()
		if DEBUG {
			fmt.Printf("White king on %s, %v\n", BoardSquares[wk], end.Sub(start))
		}
	}

}

// SaveEndGameDb saves the an end game DB for KRK to file
func (db *PositionDb) SavePositionDb(file string) error {
	fmt.Println("WriteDataToFile: ", file)

	start := time.Now()
	fmt.Printf("json.MarshalIndent\n")
	b, err := json.MarshalIndent(db, "", "  ")
	if err != nil {
		return err
	}
	end := time.Now()
	fmt.Printf("json.MarshalIndent %v\n", end.Sub(start))

	start = time.Now()
	fmt.Printf("ioutil.WriteFile\n")
	err = ioutil.WriteFile(file, b, 0666)
	end = time.Now()
	fmt.Printf("ioutil.WriteFile %v, error=%v\n", end.Sub(start), err)
	return err
}
func LoadPositionDb(file string) (db *PositionDb, err error) {
	fmt.Println("LoadDataFromFile: ", file)

	start := time.Now()
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return db, err
	}
	end := time.Now()
	fmt.Printf("ioutil.ReadFile %v,b=%d, error=%v\n", end.Sub(start), len(b), err)

	data := NewPositionDB()
	start = time.Now()
	err = json.Unmarshal(b, data)
	if err != nil {
		return db, err
	}
	end = time.Now()
	fmt.Printf("json.Unmarshal%v\n", end.Sub(start))
	return data, err
}
<commit_msg>refactor addPositions<commit_after>package emil

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"time"
)

type positionKey string

// PositionEntry is an entry in the PositionDb
type PositionEntry struct {
	Position      *position
	Dtm           int
	PrevPositions map[positionKey]*Move
	NextPositions map[positionKey]*Move
}

// NewPositionEntry ceates a new *PositionEntry
func NewPositionEntry(p *position) *PositionEntry {
	return &PositionEntry{
		Position:      p,
		Dtm:           initial,
		PrevPositions: make(map[positionKey]*Move),
		NextPositions: make(map[positionKey]*Move)}
}

func (entry *PositionEntry) addMoveToNextPosition(next *position, m *Move) {
}

// PositionDb to query for mate in 1,2, etc.
type PositionDb struct {
	Positions map[positionKey]*PositionEntry
}

func (db *PositionDb) addPositions(board *Board) {
	db.addPosition(NewPosition(board, WHITE))
	db.addPosition(NewPosition(board, BLACK))
}

func (db *PositionDb) addPosition(p *position) {
	if _, ok := db.Positions[p.key()]; ok {
		panic("key exsists in db " + p.key())
	}
	entry := NewPositionEntry(p)
	db.retrogradeAnalysisStep0(entry)
	db.Positions[p.key()] = entry
}

func (db *PositionDb) AddPrevPositions() {
	for key, entry := range db.Positions {
		for nextKey, moveToNext := range entry.NextPositions {
			nextPosition := PositionFromKey(string(nextKey))
			nextEntry, ok := db.Positions[nextPosition.key()]
			if ok {
				nextEntry.PrevPositions[key] = moveToNext
			}
		}
	}
}

// generate all moves
func (db *PositionDb) retrogradeAnalysisStep0(entry *PositionEntry) {
	moves := GenerateMoves(entry.Position)
	other := otherPlayer(entry.Position.player)
	for _, move := range moves {
		nextBoard := entry.Position.board.DoMove(move)
		nextPosition := NewPosition(nextBoard, other)
		entry.NextPositions[nextPosition.key()] = move
	}
}

// NewPositionDB creates a new *PositionDB
func NewPositionDB() *PositionDb {
	return &PositionDb{
		Positions: make(map[positionKey]*PositionEntry)}
}

func (db *PositionDb) FillWithKRKPositions() {
	var err error

	for wk := A1; wk <= H8; wk++ {
		start := time.Now()
		for bk := A1; bk <= H8; bk++ {
			if squaresDistances[wk][bk] <= 1 {
				continue
			}
			for wr := A1; wr <= H8; wr++ {
				board := NewBoard()

				if err = board.Setup(WhiteKing, wk); err != nil {
					continue
				}
				if err = board.Setup(BlackKing, bk); err != nil {
					continue
				}
				if err = board.Setup(WhiteRock, wr); err != nil {
					continue
				}

				db.addPositions(board)
			}
		}
		end := time.Now()
		if DEBUG {
			fmt.Printf("White king on %s, %v\n", BoardSquares[wk], end.Sub(start))
		}
	}

}

// SaveEndGameDb saves the an end game DB for KRK to file
func (db *PositionDb) SavePositionDb(file string) error {
	fmt.Println("WriteDataToFile: ", file)

	start := time.Now()
	fmt.Printf("json.MarshalIndent\n")
	b, err := json.MarshalIndent(db, "", "  ")
	if err != nil {
		return err
	}
	end := time.Now()
	fmt.Printf("json.MarshalIndent %v\n", end.Sub(start))

	start = time.Now()
	fmt.Printf("ioutil.WriteFile\n")
	err = ioutil.WriteFile(file, b, 0666)
	end = time.Now()
	fmt.Printf("ioutil.WriteFile %v, error=%v\n", end.Sub(start), err)
	return err
}
func LoadPositionDb(file string) (db *PositionDb, err error) {
	fmt.Println("LoadDataFromFile: ", file)

	start := time.Now()
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return db, err
	}
	end := time.Now()
	fmt.Printf("ioutil.ReadFile %v,b=%d, error=%v\n", end.Sub(start), len(b), err)

	data := NewPositionDB()
	start = time.Now()
	err = json.Unmarshal(b, data)
	if err != nil {
		return db, err
	}
	end = time.Now()
	fmt.Printf("json.Unmarshal%v\n", end.Sub(start))
	return data, err
}
<|endoftext|>


<commit_before>package rational

import "math/big"

// Simplify simplifies the rational number by dividing it's numerator and
// denominator by the GCD.
func (ev *Rational) Simplify() {
	currentNumerator := ev.numerator
	currentDenominator := ev.denominator

	if currentNumerator < 0 && currentDenominator > 0 {
		currentNumerator *= -1
	} else if currentDenominator < 0 && currentNumerator >= 0 {
		currentDenominator *= -1
	}

	n := big.NewInt(currentNumerator)
	d := big.NewInt(currentDenominator)

	gcd := new(big.Int).GCD(nil, nil, n, d).Int64()

	if gcd > 1 {
		ev.numerator /= gcd
		ev.denominator /= gcd
	}
}

// Float64 returns the float64 representation of a rational number.
func (ev Rational) Float64() float64 {
	return float64(ev.numerator) / float64(ev.denominator)
}

// Get returns a value.
func (ev Rational) Get() (numerator, denominator int64) {
	return ev.numerator, ev.denominator
}

// GetNumerator returns a numerator.
func (ev Rational) GetNumerator() int64 {
	return ev.numerator
}

// GetDenominator returns a denominator.
func (ev Rational) GetDenominator() int64 {
	return ev.denominator
}

// IsNull determines whether the value is zero.
func (ev Rational) IsNull() (n bool) {
	if ev.numerator == 0 {
		n = true
	}
	return
}

// RationalsAreNull determines whether the slice of Rationals contains only zero values.
func RationalsAreNull(l []Rational) (isNull bool) {
	isNull = true
	for _, v := range l {
		if !v.IsNull() {
			isNull = false
		}
	}
	return
}

func solveNegatives(n, d *int64) {
	if *n < 0 && *d < 0 {
		*n *= -1
		*d *= -1
	}
}
<commit_msg>added module getter<commit_after>package rational

import "math/big"

// Simplify simplifies the rational number by dividing it's numerator and
// denominator by the GCD.
func (ev *Rational) Simplify() {
	currentNumerator := ev.numerator
	currentDenominator := ev.denominator

	if currentNumerator < 0 && currentDenominator > 0 {
		currentNumerator *= -1
	} else if currentDenominator < 0 && currentNumerator >= 0 {
		currentDenominator *= -1
	}

	n := big.NewInt(currentNumerator)
	d := big.NewInt(currentDenominator)

	gcd := new(big.Int).GCD(nil, nil, n, d).Int64()

	if gcd > 1 {
		ev.numerator /= gcd
		ev.denominator /= gcd
	}
}

// Float64 returns the float64 representation of a rational number.
func (ev Rational) Float64() float64 {
	return float64(ev.numerator) / float64(ev.denominator)
}

// Get returns a value.
func (ev Rational) Get() (numerator, denominator int64) {
	return ev.numerator, ev.denominator
}

// GetNumerator returns a numerator.
func (ev Rational) GetNumerator() int64 {
	return ev.numerator
}

// GetDenominator returns a denominator.
func (ev Rational) GetDenominator() int64 {
	return ev.denominator
}

// GetModule returns rational number's module.
func (ev Rational) GetModule() Rational {
	if ev.LessThanNum(0) {
		ev = ev.MultiplyByNum(-1)
	}
	return ev
}

// IsNull determines whether the value is zero.
func (ev Rational) IsNull() (n bool) {
	if ev.numerator == 0 {
		n = true
	}
	return
}

// RationalsAreNull determines whether the slice of Rationals contains only zero values.
func RationalsAreNull(l []Rational) (isNull bool) {
	isNull = true
	for _, v := range l {
		if !v.IsNull() {
			isNull = false
		}
	}
	return
}

func solveNegatives(n, d *int64) {
	if *n < 0 && *d < 0 {
		*n *= -1
		*d *= -1
	}
}
<|endoftext|>


<commit_before>package erasure

/*
#cgo CFLAGS: -Wall
#include "types.h"
#include "erasure_code.h"
*/
import "C"

import (
	"fmt"
	"unsafe"
)

func Hello() {
	m := 12
	k := 8
	sourceLength := 16

	source := make([]byte, k*sourceLength)
	destination := make([]byte, m*sourceLength)

	for i := range source {
		source[i] = 0x62
		destination[i] = 0x62
	}

	encodeMatrix := make([]byte, m*k)
	// decode_matrix := make([]byte, m*k)
	// invert_matrix := make([]byte, m*k)
	g_tbls := make([]byte, k*(m-k)*32)

	// fmt.Printf("Encode Matrix: %x\n", encode_matrix)

	// Generate encode matrix encode_matrix
	// The matrix generated by gf_gen_cauchy1_matrix
	// is always invertable.
	C.gf_gen_cauchy1_matrix((*C.uchar)(&encodeMatrix[0]), C.int(m), C.int(k))
	// The matrix generated by gf_gen_rs_matrix
	// is not always invertable.
	// C.gf_gen_rs_matrix((*C.uchar)(&encode_matrix[0]), C.int(m), C.int(k))

	// fmt.Printf("Encode Matrix: %x\n", encodeMatrix)

	// fmt.Printf("G Tables: %x\n", g_tbls)
	C.ec_init_tables(C.int(k), C.int(m-k), (*C.uchar)(&encodeMatrix[k*k]), (*C.uchar)(&g_tbls[0]))
	// fmt.Printf("G Tables: %x\n", g_tbls)

	// fmt.Printf("Source: %x\n", source)
	C.ec_encode_data(C.int(sourceLength), C.int(k), C.int(m-k), (*C.uchar)(&g_tbls[0]), (*C.uchar)(&source[0]), (*C.uchar)(&destination[k*sourceLength]))
	//fmt.Printf("Dest: %x\n", destination)

	decodeMatrix := make([]byte, m*k)
	decodeIndex := make([]int32, m)
	srcErrList := make([]int8, m-k)
	srcInErr := make([]int8, m)

	srcErrList[0] = 0
	srcErrList[1] = 2
	srcErrList[2] = 3
	srcErrList[3] = 4
	srcInErr[0] = 1
	srcInErr[2] = 1
	srcInErr[3] = 1
	srcInErr[4] = 1

	nErrs := 4
	nSrcErrs := 4

	C.gf_gen_decode_matrix((*C.uchar)(&encodeMatrix[0]), (*C.uchar)(&decodeMatrix[0]), (*C.uint)(unsafe.Pointer(&decodeIndex[0])), (*C.uchar)(unsafe.Pointer(&srcErrList[0])), (*C.uchar)(unsafe.Pointer(&srcInErr[0])), C.int(nErrs), C.int(nSrcErrs), C.int(k), C.int(m))
	fmt.Printf("Decode Matrix: %x\n", decodeMatrix)
	// fmt.Printf("Decode Index: %x\n", decodeIndex)

	g_tbls = make([]byte, k*(m-k)*32)

	C.ec_init_tables(C.int(k), C.int(nErrs), (*C.uchar)(&decodeMatrix[0]), (*C.uchar)(&g_tbls[0]))
	// fmt.Printf("G Tables: %x\n", g_tbls)

	recovered := make([]byte, m*sourceLength)
	C.ec_encode_data(C.int(sourceLength), C.int(k), C.int(m), (*C.uchar)(&g_tbls[0]), (*C.uchar)(&destination[0]), (*C.uchar)(&recovered[0]))
	// fmt.Printf("Recovered: %x\n", recovered)
}
<commit_msg>Got encode and decode working<commit_after>package erasure

/*
#cgo CFLAGS: -Wall
#include "types.h"
#include "erasure_code.h"
*/
import "C"

import (
	"fmt"
	"unsafe"
)

func Hello() {
	var m int32 = 12
	var k int32 = 8
	var sourceLength int32 = 16

	source := make([]byte, k*sourceLength)
	destination := make([]byte, m*sourceLength)

	for i := range source {
		source[i] = 0x62
		destination[i] = 0x62
	}

	encodeMatrix := make([]byte, m*k)
	// decode_matrix := make([]byte, m*k)
	// invert_matrix := make([]byte, m*k)
	g_tbls := make([]byte, k*(m-k)*32)

	// fmt.Printf("Encode Matrix: %x\n", encode_matrix)

	// Generate encode matrix encode_matrix
	// The matrix generated by gf_gen_cauchy1_matrix
	// is always invertable.
	C.gf_gen_cauchy1_matrix((*C.uchar)(&encodeMatrix[0]), C.int(m), C.int(k))
	// The matrix generated by gf_gen_rs_matrix
	// is not always invertable.
	// C.gf_gen_rs_matrix((*C.uchar)(&encode_matrix[0]), C.int(m), C.int(k))

	// fmt.Printf("Encode Matrix: %x\n", encodeMatrix)

	// fmt.Printf("G Tables: %x\n", g_tbls)
	C.ec_init_tables(C.int(k), C.int(m-k), (*C.uchar)(&encodeMatrix[k*k]), (*C.uchar)(&g_tbls[0]))
	// fmt.Printf("G Tables: %x\n", g_tbls)

	// fmt.Printf("Source: %x\n", source)
	C.ec_encode_data(C.int(sourceLength), C.int(k), C.int(m-k), (*C.uchar)(&g_tbls[0]), (*C.uchar)(&source[0]), (*C.uchar)(&destination[k*sourceLength]))
	//fmt.Printf("Dest: %x\n", destination)

	decodeMatrix := make([]byte, m*k)
	decodeIndex := make([]int32, m)
	srcErrList := make([]int8, m-k)
	srcInErr := make([]int8, m)

	srcErrList[0] = 0
	srcErrList[1] = 2
	srcErrList[2] = 3
	srcErrList[3] = 4
	srcInErr[0] = 1
	srcInErr[2] = 1
	srcInErr[3] = 1
	srcInErr[4] = 1

	nErrs := 4
	nSrcErrs := 4

	C.gf_gen_decode_matrix((*C.uchar)(&encodeMatrix[0]), (*C.uchar)(&decodeMatrix[0]), (*C.uint)(unsafe.Pointer(&decodeIndex[0])), (*C.uchar)(unsafe.Pointer(&srcErrList[0])), (*C.uchar)(unsafe.Pointer(&srcInErr[0])), C.int(nErrs), C.int(nSrcErrs), C.int(k), C.int(m))
	fmt.Printf("Decode Matrix: %x\n", decodeMatrix)
	// fmt.Printf("Decode Index: %x\n", decodeIndex)

	g_tbls = make([]byte, k*(m-k)*32)

	C.ec_init_tables(C.int(k), C.int(nErrs), (*C.uchar)(&decodeMatrix[0]), (*C.uchar)(&g_tbls[0]))
	// fmt.Printf("G Tables: %x\n", g_tbls)
	returned := []byte{}
	var i int32 = 0
	for i = 0; i <= k; i++ {
		returned = append(returned, destination[(decodeIndex[i]*sourceLength):(decodeIndex[i]+1)*sourceLength]...)
	}

	fmt.Printf("Returned: %x\n", returned)

	recovered := make([]byte, m*sourceLength)
	C.ec_encode_data(C.int(sourceLength), C.int(k), C.int(m), (*C.uchar)(&g_tbls[0]), (*C.uchar)(&returned[0]), (*C.uchar)(&recovered[0]))
	// fmt.Printf("Recovered: %x\n", recovered)
}
<|endoftext|>