<commit_before>package aws

import (
	"bytes"
	"fmt"
	"github.com/hashicorp/terraform/helper/validation"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/codebuild"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsCodeBuildWebhook() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsCodeBuildWebhookCreate,
		Read:   resourceAwsCodeBuildWebhookRead,
		Delete: resourceAwsCodeBuildWebhookDelete,
		Update: resourceAwsCodeBuildWebhookUpdate,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"project_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"branch_filter": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"filter_group"},
			},
			"filter_group": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"filter": {
							Type:     schema.TypeList,
							Optional: true,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"type": {
										Type:     schema.TypeString,
										Required: true,
										ValidateFunc: validation.StringInSlice([]string{
											codebuild.WebhookFilterTypeEvent,
											codebuild.WebhookFilterTypeActorAccountId,
											codebuild.WebhookFilterTypeBaseRef,
											codebuild.WebhookFilterTypeFilePath,
											codebuild.WebhookFilterTypeHeadRef,
										}, false),
									},
									"exclude_matched_pattern": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  false,
									},
									"pattern": {
										Type:     schema.TypeString,
										Required: true,
									},
								},
							},
						},
					},
				},
				ConflictsWith: []string{"branch_filter"},
			},
			"payload_url": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"secret": {
				Type:      schema.TypeString,
				Computed:  true,
				Sensitive: true,
			},
			"url": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsCodeBuildWebhookCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	input := &codebuild.CreateWebhookInput{
		ProjectName:  aws.String(d.Get("project_name").(string)),
		FilterGroups: expandWebhookFilterGroups(d),
	}

	// The CodeBuild API requires this to be non-empty if defined
	if v, ok := d.GetOk("branch_filter"); ok {
		input.BranchFilter = aws.String(v.(string))
	}

	log.Printf("[DEBUG] Creating CodeBuild Webhook: %s", input)
	resp, err := conn.CreateWebhook(input)

	if err != nil {
		return fmt.Errorf("error creating CodeBuild Webhook: %s", err)
	}

	// Secret is only returned on create, so capture it at the start
	d.Set("secret", resp.Webhook.Secret)
	d.SetId(d.Get("project_name").(string))

	return resourceAwsCodeBuildWebhookRead(d, meta)
}

func expandWebhookFilterGroups(d *schema.ResourceData) [][]*codebuild.WebhookFilter {
	configs := d.Get("filter_group").(*schema.Set).List()

	webhookFilters := make([][]*codebuild.WebhookFilter, 0)

	if len(configs) == 0 {
		return nil
	}

	for _, config := range configs {
		filters := expandWebhookFilterData(config.(map[string]interface{}))
		webhookFilters = append(webhookFilters, filters)
	}

	return webhookFilters
}

func expandWebhookFilterData(data map[string]interface{}) []*codebuild.WebhookFilter {
	filters := make([]*codebuild.WebhookFilter, 0)

	filterConfigs := data["filter"].([]interface{})

	for i, filterConfig := range filterConfigs {
		filter := filterConfig.(map[string]interface{})
		filters = append(filters, &codebuild.WebhookFilter{
			Type:                  aws.String(filter["type"].(string)),
			ExcludeMatchedPattern: aws.Bool(filter["exclude_matched_pattern"].(bool)),
		})
		if v := filter["pattern"]; v != nil {
			filters[i].Pattern = aws.String(v.(string))
		}
	}

	return filters
}

func resourceAwsCodeBuildWebhookRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	resp, err := conn.BatchGetProjects(&codebuild.BatchGetProjectsInput{
		Names: []*string{
			aws.String(d.Id()),
		},
	})

	if err != nil {
		return err
	}

	if len(resp.Projects) == 0 {
		log.Printf("[WARN] CodeBuild Project %q not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	project := resp.Projects[0]

	if project.Webhook == nil {
		log.Printf("[WARN] CodeBuild Project %q webhook not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	d.Set("branch_filter", project.Webhook.BranchFilter)
	d.Set("filter_group", flattenAwsCodeBuildWebhookFilterGroups(project.Webhook.FilterGroups))
	d.Set("payload_url", project.Webhook.PayloadUrl)
	d.Set("project_name", project.Name)
	d.Set("url", project.Webhook.Url)
	// The secret is never returned after creation, so don't set it here

	return nil
}

func resourceAwsCodeBuildWebhookUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	var err error
	filterGroups := expandWebhookFilterGroups(d)

	if len(filterGroups) >= 1 {
		_, err = conn.UpdateWebhook(&codebuild.UpdateWebhookInput{
			ProjectName:  aws.String(d.Id()),
			FilterGroups: filterGroups,
			RotateSecret: aws.Bool(false),
		})
	} else {
		_, err = conn.UpdateWebhook(&codebuild.UpdateWebhookInput{
			ProjectName:  aws.String(d.Id()),
			BranchFilter: aws.String(d.Get("branch_filter").(string)),
			RotateSecret: aws.Bool(false),
		})
	}

	if err != nil {
		return err
	}

	return resourceAwsCodeBuildWebhookRead(d, meta)
}

func resourceAwsCodeBuildWebhookDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	_, err := conn.DeleteWebhook(&codebuild.DeleteWebhookInput{
		ProjectName: aws.String(d.Id()),
	})

	if err != nil {
		if isAWSErr(err, codebuild.ErrCodeResourceNotFoundException, "") {
			return nil
		}
		return err
	}

	return nil
}

func flattenAwsCodeBuildWebhookFilterGroups(filterList [][]*codebuild.WebhookFilter) *schema.Set {
	filterSet := schema.Set{
		F: resourceAwsCodeBuildWebhookFilterHash,
	}

	for _, filters := range filterList {
		filterSet.Add(flattenAwsCodeBuildWebhookFilterData(filters))
	}
	return &filterSet
}

func resourceAwsCodeBuildWebhookFilterHash(v interface{}) int {
	var buf bytes.Buffer
	m := v.([]map[string]interface{})

	for _, f := range m {
		buf.WriteString(fmt.Sprintf("%v-", f["type"].(*string)))
		buf.WriteString(fmt.Sprintf("%v-", f["pattern"].(*string)))
		buf.WriteString(fmt.Sprintf("%q", f["exclude_matched_pattern"]))
	}

	return hashcode.String(buf.String())
}

func flattenAwsCodeBuildWebhookFilterData(filter []*codebuild.WebhookFilter) []map[string]interface{} {
	values := make([]map[string]interface{}, 0)

	for _, f := range filter {
		values = append(values, map[string]interface{}{
			"type":                    f.Type,
			"pattern":                 f.Pattern,
			"exclude_matched_pattern": f.ExcludeMatchedPattern,
		})
	}

	return values
}
<commit_msg>Fix flatten<commit_after>package aws

import (
	"bytes"
	"fmt"
	"github.com/hashicorp/terraform/helper/validation"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/codebuild"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsCodeBuildWebhook() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsCodeBuildWebhookCreate,
		Read:   resourceAwsCodeBuildWebhookRead,
		Delete: resourceAwsCodeBuildWebhookDelete,
		Update: resourceAwsCodeBuildWebhookUpdate,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"project_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"branch_filter": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"filter_group"},
			},
			"filter_group": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"filter": {
							Type:     schema.TypeList,
							Optional: true,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"type": {
										Type:     schema.TypeString,
										Required: true,
										ValidateFunc: validation.StringInSlice([]string{
											codebuild.WebhookFilterTypeEvent,
											codebuild.WebhookFilterTypeActorAccountId,
											codebuild.WebhookFilterTypeBaseRef,
											codebuild.WebhookFilterTypeFilePath,
											codebuild.WebhookFilterTypeHeadRef,
										}, false),
									},
									"exclude_matched_pattern": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  false,
									},
									"pattern": {
										Type:     schema.TypeString,
										Required: true,
									},
								},
							},
						},
					},
				},
				Set:           resourceAwsCodeBuildWebhookFilterHash,
				ConflictsWith: []string{"branch_filter"},
			},
			"payload_url": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"secret": {
				Type:      schema.TypeString,
				Computed:  true,
				Sensitive: true,
			},
			"url": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsCodeBuildWebhookCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	input := &codebuild.CreateWebhookInput{
		ProjectName:  aws.String(d.Get("project_name").(string)),
		FilterGroups: expandWebhookFilterGroups(d),
	}

	// The CodeBuild API requires this to be non-empty if defined
	if v, ok := d.GetOk("branch_filter"); ok {
		input.BranchFilter = aws.String(v.(string))
	}

	log.Printf("[DEBUG] Creating CodeBuild Webhook: %s", input)
	resp, err := conn.CreateWebhook(input)

	if err != nil {
		return fmt.Errorf("error creating CodeBuild Webhook: %s", err)
	}

	// Secret is only returned on create, so capture it at the start
	d.Set("secret", resp.Webhook.Secret)
	d.SetId(d.Get("project_name").(string))

	return resourceAwsCodeBuildWebhookRead(d, meta)
}

func expandWebhookFilterGroups(d *schema.ResourceData) [][]*codebuild.WebhookFilter {
	configs := d.Get("filter_group").(*schema.Set).List()

	webhookFilters := make([][]*codebuild.WebhookFilter, 0)

	if len(configs) == 0 {
		return nil
	}

	for _, config := range configs {
		filters := expandWebhookFilterData(config.(map[string]interface{}))
		webhookFilters = append(webhookFilters, filters)
	}

	return webhookFilters
}

func expandWebhookFilterData(data map[string]interface{}) []*codebuild.WebhookFilter {
	filters := make([]*codebuild.WebhookFilter, 0)

	filterConfigs := data["filter"].([]interface{})

	for i, filterConfig := range filterConfigs {
		filter := filterConfig.(map[string]interface{})
		filters = append(filters, &codebuild.WebhookFilter{
			Type:                  aws.String(filter["type"].(string)),
			ExcludeMatchedPattern: aws.Bool(filter["exclude_matched_pattern"].(bool)),
		})
		if v := filter["pattern"]; v != nil {
			filters[i].Pattern = aws.String(v.(string))
		}
	}

	return filters
}

func resourceAwsCodeBuildWebhookRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	resp, err := conn.BatchGetProjects(&codebuild.BatchGetProjectsInput{
		Names: []*string{
			aws.String(d.Id()),
		},
	})

	if err != nil {
		return err
	}

	if len(resp.Projects) == 0 {
		log.Printf("[WARN] CodeBuild Project %q not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	project := resp.Projects[0]

	if project.Webhook == nil {
		log.Printf("[WARN] CodeBuild Project %q webhook not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	d.Set("branch_filter", project.Webhook.BranchFilter)
	d.Set("filter_group", flattenAwsCodeBuildWebhookFilterGroups(project.Webhook.FilterGroups))
	d.Set("payload_url", project.Webhook.PayloadUrl)
	d.Set("project_name", project.Name)
	d.Set("url", project.Webhook.Url)
	// The secret is never returned after creation, so don't set it here

	return nil
}

func resourceAwsCodeBuildWebhookUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	var err error
	filterGroups := expandWebhookFilterGroups(d)

	if len(filterGroups) >= 1 {
		_, err = conn.UpdateWebhook(&codebuild.UpdateWebhookInput{
			ProjectName:  aws.String(d.Id()),
			FilterGroups: filterGroups,
			RotateSecret: aws.Bool(false),
		})
	} else {
		_, err = conn.UpdateWebhook(&codebuild.UpdateWebhookInput{
			ProjectName:  aws.String(d.Id()),
			BranchFilter: aws.String(d.Get("branch_filter").(string)),
			RotateSecret: aws.Bool(false),
		})
	}

	if err != nil {
		return err
	}

	return resourceAwsCodeBuildWebhookRead(d, meta)
}

func resourceAwsCodeBuildWebhookDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).codebuildconn

	_, err := conn.DeleteWebhook(&codebuild.DeleteWebhookInput{
		ProjectName: aws.String(d.Id()),
	})

	if err != nil {
		if isAWSErr(err, codebuild.ErrCodeResourceNotFoundException, "") {
			return nil
		}
		return err
	}

	return nil
}

func flattenAwsCodeBuildWebhookFilterGroups(filterList [][]*codebuild.WebhookFilter) *schema.Set {
	filterSet := schema.Set{
		F: resourceAwsCodeBuildWebhookFilterHash,
	}

	for _, filters := range filterList {
		filterSet.Add(flattenAwsCodeBuildWebhookFilterData(filters))
	}
	return &filterSet
}

func resourceAwsCodeBuildWebhookFilterHash(v interface{}) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})

	for _, g := range m {
		for _, f := range g.([]interface{}) {
			r := f.(map[string]interface{})
			buf.WriteString(fmt.Sprintf("%s-", r["type"].(string)))
			buf.WriteString(fmt.Sprintf("%s-", r["pattern"].(string)))
			buf.WriteString(fmt.Sprintf("%q", r["exclude_matched_pattern"]))
		}
	}

	return hashcode.String(buf.String())
}

func flattenAwsCodeBuildWebhookFilterData(filters []*codebuild.WebhookFilter) map[string]interface{} {
	values := map[string]interface{}{}
	ff := make([]interface{}, 0)

	for _, f := range filters {
		ff = append(ff, map[string]interface{}{
			"type":                    *f.Type,
			"pattern":                 *f.Pattern,
			"exclude_matched_pattern": *f.ExcludeMatchedPattern,
		})
	}

	values["filter"] = ff

	return values
}
<|endoftext|>


<commit_before>// Copyright 2014 The Cockroach 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. See the AUTHORS file
// for names of contributors.
//
// Author: Spencer Kimball (spencer.kimball@gmail.com)

package roachpb

import (
	"encoding/hex"
	"fmt"
	"reflect"
	"strings"
	"testing"

	"github.com/cockroachdb/cockroach/util/retry"
)

type testError struct{}

func (t *testError) Error() string             { return "test" }
func (t *testError) CanRetry() bool            { return true }
func (t *testError) ErrorIndex() (int32, bool) { return 99, true }
func (t *testError) SetErrorIndex(_ int32)     { panic("unsupported") }

// TestSetGoError verifies that a test error that
// implements retryable or indexed is converted properly into a generic error.
func TestSetGoErrorGeneric(t *testing.T) {
	br := &BatchResponse{}
	br.SetGoError(&testError{})
	err := br.GoError()
	if err.Error() != "test" {
		t.Fatalf("unexpected error: %s", err)
	}
	if !br.Error.Retryable {
		t.Error("expected generic error to be retryable")
	}
	if rErr, ok := br.Error.GoError().(retry.Retryable); !ok || !rErr.CanRetry() {
		t.Error("generated GoError is not retryable")
	}
}

// TestResponseHeaderNilError verifies that a nil error can be set
// and retrieved from a response header.
func TestSetGoErrorNil(t *testing.T) {
	br := &BatchResponse{}
	br.SetGoError(nil)
	if err := br.GoError(); err != nil {
		t.Errorf("expected nil error; got %s", err)
	}
}

type XX interface {
	Run()
}
type YY int

func (i YY) Run() {
	fmt.Println(i)
}

// TestCombinable tests the correct behaviour of some types that implement
// the Combinable interface, notably {Scan,DeleteRange}Response and
// ResponseHeader.
func TestCombinable(t *testing.T) {
	// Test that GetResponse doesn't have anything to do with Combinable.
	if _, ok := interface{}(&GetResponse{}).(Combinable); ok {
		t.Fatalf("GetResponse implements Combinable, so presumably all Response types will")
	}
	// Test that {Scan,DeleteRange}Response properly implement it.
	sr1 := &ScanResponse{
		ResponseHeader: ResponseHeader{Timestamp: MinTimestamp},
		Rows: []KeyValue{
			{Key: Key("A"), Value: MakeValueFromString("V")},
		},
	}

	if _, ok := interface{}(sr1).(Combinable); !ok {
		t.Fatalf("ScanResponse does not implement Combinable")
	}

	sr2 := &ScanResponse{
		ResponseHeader: ResponseHeader{Timestamp: MinTimestamp},
		Rows: []KeyValue{
			{Key: Key("B"), Value: MakeValueFromString("W")},
		},
	}
	sr2.Timestamp = MaxTimestamp

	wantedSR := &ScanResponse{
		ResponseHeader: ResponseHeader{Timestamp: MaxTimestamp},
		Rows:           append(append([]KeyValue(nil), sr1.Rows...), sr2.Rows...),
	}

	if err := sr1.Combine(sr2); err != nil {
		t.Fatal(err)
	}
	if err := sr1.Combine(&ScanResponse{}); err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(sr1, wantedSR) {
		t.Errorf("wanted %v, got %v", wantedSR, sr1)
	}

	dr1 := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 100}},
		NumDeleted:     5,
	}
	if _, ok := interface{}(dr1).(Combinable); !ok {
		t.Fatalf("DeleteRangeResponse does not implement Combinable")
	}
	dr2 := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 1}},
		NumDeleted:     12,
	}
	dr3 := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 111}},
		NumDeleted:     3,
	}
	wantedDR := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 111}},
		NumDeleted:     20,
	}
	if err := dr2.Combine(dr3); err != nil {
		t.Fatal(err)
	}
	if err := dr1.Combine(dr2); err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(dr1, wantedDR) {
		t.Errorf("wanted %v, got %v", wantedDR, dr1)
	}
}

func TestSetGoErrorCopy(t *testing.T) {
	br := &BatchResponse{}
	oErr := &Error{Message: "test123"}
	br.Error = oErr
	br.SetGoError(&testError{})
	if oErr.Message != "test123" {
		t.Fatalf("SetGoError did not create a new error")
	}
}

func TestBatchSplit(t *testing.T) {
	get := &GetRequest{}
	scan := &ScanRequest{}
	put := &PutRequest{}
	spl := &AdminSplitRequest{}
	dr := &DeleteRangeRequest{}
	bt := &BeginTransactionRequest{}
	et := &EndTransactionRequest{}
	rv := &ReverseScanRequest{}
	testCases := []struct {
		reqs  []Request
		sizes []int
	}{
		{[]Request{get, put}, []int{1, 1}},
		{[]Request{get, get, get, put, put, get, get}, []int{3, 2, 2}},
		{[]Request{get, scan, get, dr, rv, put, et}, []int{3, 1, 1, 1, 1}},
		{[]Request{spl, get, scan, spl, get}, []int{1, 2, 1, 1}},
		{[]Request{spl, spl, get, spl}, []int{1, 1, 1, 1}},
		{[]Request{bt, put, et}, []int{2, 1}},
	}

	for i, test := range testCases {
		ba := BatchRequest{}
		for _, args := range test.reqs {
			ba.Add(args)
		}
		var partLen []int
		var recombined []RequestUnion
		for _, part := range ba.Split() {
			recombined = append(recombined, part...)
			partLen = append(partLen, len(part))
		}
		if !reflect.DeepEqual(partLen, test.sizes) {
			t.Errorf("%d: expected chunks %v, got %v", i, test.sizes, partLen)
		}
		if !reflect.DeepEqual(recombined, ba.Requests) {
			t.Errorf("%d: started with:\n%+v\ngot back:\n%+v", i, ba.Requests, recombined)
		}
	}
}

func TestFlagsToStr(t *testing.T) {
	var ba BatchRequest
	ba.Add(&PutRequest{})
	ba.Add(&AdminSplitRequest{})
	exp := "AdWrAl"
	if act := flagsToStr(ba.flags()); act != exp {
		t.Fatalf("expected %s, got %s", exp, act)
	}
}

func TestBatchTraceID(t *testing.T) {
	var ba BatchRequest
	ba.Add(&ReverseScanRequest{})
	ba.Add(&IncrementRequest{})

	expID := "cRdWrRgRv@0.000000000,0"
	expName := expID[1:]
	if actID, actName := ba.TraceID(), ba.TraceName(); expID != actID || expName != actName {
		t.Fatalf("expected (%s,%s), got (%s, %s)", expID, expName, actID, actName)
	}

	uuidStr := "a53eef22-35f3-4c69-8e98-c563100e028c"
	bytes, err := hex.DecodeString(strings.Replace(uuidStr, "-", "", -1))
	if err != nil {
		t.Fatal(err)
	}
	ba.Txn = &Transaction{ID: bytes}
	expID = "t" + uuidStr
	expName = expID[:9]
	if actID, actName := ba.TraceID(), ba.TraceName(); expID != actID || expName != actName {
		t.Fatalf("expected (%s,%s), got (%s, %s)", expID, expName, actID, actName)
	}
}
<commit_msg>roachpb: remove detritus<commit_after>// Copyright 2014 The Cockroach 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. See the AUTHORS file
// for names of contributors.
//
// Author: Spencer Kimball (spencer.kimball@gmail.com)

package roachpb

import (
	"encoding/hex"
	"reflect"
	"strings"
	"testing"

	"github.com/cockroachdb/cockroach/util/retry"
)

type testError struct{}

func (t *testError) Error() string             { return "test" }
func (t *testError) CanRetry() bool            { return true }
func (t *testError) ErrorIndex() (int32, bool) { return 99, true }
func (t *testError) SetErrorIndex(_ int32)     { panic("unsupported") }

// TestSetGoError verifies that a test error that
// implements retryable or indexed is converted properly into a generic error.
func TestSetGoErrorGeneric(t *testing.T) {
	br := &BatchResponse{}
	br.SetGoError(&testError{})
	err := br.GoError()
	if err.Error() != "test" {
		t.Fatalf("unexpected error: %s", err)
	}
	if !br.Error.Retryable {
		t.Error("expected generic error to be retryable")
	}
	if rErr, ok := br.Error.GoError().(retry.Retryable); !ok || !rErr.CanRetry() {
		t.Error("generated GoError is not retryable")
	}
}

// TestResponseHeaderNilError verifies that a nil error can be set
// and retrieved from a response header.
func TestSetGoErrorNil(t *testing.T) {
	br := &BatchResponse{}
	br.SetGoError(nil)
	if err := br.GoError(); err != nil {
		t.Errorf("expected nil error; got %s", err)
	}
}

// TestCombinable tests the correct behaviour of some types that implement
// the Combinable interface, notably {Scan,DeleteRange}Response and
// ResponseHeader.
func TestCombinable(t *testing.T) {
	// Test that GetResponse doesn't have anything to do with Combinable.
	if _, ok := interface{}(&GetResponse{}).(Combinable); ok {
		t.Fatalf("GetResponse implements Combinable, so presumably all Response types will")
	}
	// Test that {Scan,DeleteRange}Response properly implement it.
	sr1 := &ScanResponse{
		ResponseHeader: ResponseHeader{Timestamp: MinTimestamp},
		Rows: []KeyValue{
			{Key: Key("A"), Value: MakeValueFromString("V")},
		},
	}

	if _, ok := interface{}(sr1).(Combinable); !ok {
		t.Fatalf("ScanResponse does not implement Combinable")
	}

	sr2 := &ScanResponse{
		ResponseHeader: ResponseHeader{Timestamp: MinTimestamp},
		Rows: []KeyValue{
			{Key: Key("B"), Value: MakeValueFromString("W")},
		},
	}
	sr2.Timestamp = MaxTimestamp

	wantedSR := &ScanResponse{
		ResponseHeader: ResponseHeader{Timestamp: MaxTimestamp},
		Rows:           append(append([]KeyValue(nil), sr1.Rows...), sr2.Rows...),
	}

	if err := sr1.Combine(sr2); err != nil {
		t.Fatal(err)
	}
	if err := sr1.Combine(&ScanResponse{}); err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(sr1, wantedSR) {
		t.Errorf("wanted %v, got %v", wantedSR, sr1)
	}

	dr1 := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 100}},
		NumDeleted:     5,
	}
	if _, ok := interface{}(dr1).(Combinable); !ok {
		t.Fatalf("DeleteRangeResponse does not implement Combinable")
	}
	dr2 := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 1}},
		NumDeleted:     12,
	}
	dr3 := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 111}},
		NumDeleted:     3,
	}
	wantedDR := &DeleteRangeResponse{
		ResponseHeader: ResponseHeader{Timestamp: Timestamp{Logical: 111}},
		NumDeleted:     20,
	}
	if err := dr2.Combine(dr3); err != nil {
		t.Fatal(err)
	}
	if err := dr1.Combine(dr2); err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(dr1, wantedDR) {
		t.Errorf("wanted %v, got %v", wantedDR, dr1)
	}
}

func TestSetGoErrorCopy(t *testing.T) {
	br := &BatchResponse{}
	oErr := &Error{Message: "test123"}
	br.Error = oErr
	br.SetGoError(&testError{})
	if oErr.Message != "test123" {
		t.Fatalf("SetGoError did not create a new error")
	}
}

func TestBatchSplit(t *testing.T) {
	get := &GetRequest{}
	scan := &ScanRequest{}
	put := &PutRequest{}
	spl := &AdminSplitRequest{}
	dr := &DeleteRangeRequest{}
	bt := &BeginTransactionRequest{}
	et := &EndTransactionRequest{}
	rv := &ReverseScanRequest{}
	testCases := []struct {
		reqs  []Request
		sizes []int
	}{
		{[]Request{get, put}, []int{1, 1}},
		{[]Request{get, get, get, put, put, get, get}, []int{3, 2, 2}},
		{[]Request{get, scan, get, dr, rv, put, et}, []int{3, 1, 1, 1, 1}},
		{[]Request{spl, get, scan, spl, get}, []int{1, 2, 1, 1}},
		{[]Request{spl, spl, get, spl}, []int{1, 1, 1, 1}},
		{[]Request{bt, put, et}, []int{2, 1}},
	}

	for i, test := range testCases {
		ba := BatchRequest{}
		for _, args := range test.reqs {
			ba.Add(args)
		}
		var partLen []int
		var recombined []RequestUnion
		for _, part := range ba.Split() {
			recombined = append(recombined, part...)
			partLen = append(partLen, len(part))
		}
		if !reflect.DeepEqual(partLen, test.sizes) {
			t.Errorf("%d: expected chunks %v, got %v", i, test.sizes, partLen)
		}
		if !reflect.DeepEqual(recombined, ba.Requests) {
			t.Errorf("%d: started with:\n%+v\ngot back:\n%+v", i, ba.Requests, recombined)
		}
	}
}

func TestFlagsToStr(t *testing.T) {
	var ba BatchRequest
	ba.Add(&PutRequest{})
	ba.Add(&AdminSplitRequest{})
	exp := "AdWrAl"
	if act := flagsToStr(ba.flags()); act != exp {
		t.Fatalf("expected %s, got %s", exp, act)
	}
}

func TestBatchTraceID(t *testing.T) {
	var ba BatchRequest
	ba.Add(&ReverseScanRequest{})
	ba.Add(&IncrementRequest{})

	expID := "cRdWrRgRv@0.000000000,0"
	expName := expID[1:]
	if actID, actName := ba.TraceID(), ba.TraceName(); expID != actID || expName != actName {
		t.Fatalf("expected (%s,%s), got (%s, %s)", expID, expName, actID, actName)
	}

	uuidStr := "a53eef22-35f3-4c69-8e98-c563100e028c"
	bytes, err := hex.DecodeString(strings.Replace(uuidStr, "-", "", -1))
	if err != nil {
		t.Fatal(err)
	}
	ba.Txn = &Transaction{ID: bytes}
	expID = "t" + uuidStr
	expName = expID[:9]
	if actID, actName := ba.TraceID(), ba.TraceName(); expID != actID || expName != actName {
		t.Fatalf("expected (%s,%s), got (%s, %s)", expID, expName, actID, actName)
	}
}
<|endoftext|>


<commit_before>package routefinder

import (
	"flag"
	"fmt"
	"testing"
)

func Example() {
	r, _ := NewRoutefinder("/shop/:item", "/shop/:item/rate", "/shop/:item/buy")

	fmt.Println(r.Lookup("/shop/gopher/rate"))
	// Output: /shop/:item/rate map[item:gopher]
}

func TestBasic(t *testing.T) {
	r, err := NewRoutefinder("/foo/:id/...", "/foo/:id", "/foo", "/bar/...", "/discard-trail/:foo/???")

	if err != nil {
		t.Fatal("Unexpected error creating routes", err)
	}

	tests := []struct {
		p  string
		t  string
		kv map[string]string
	}{
		{
			p:  "/",
			t:  "",
			kv: map[string]string{},
		},
		{
			p:  "/foo/foo/a",
			t:  "/foo/:id/a",
			kv: map[string]string{"id": "foo"},
		},
		{
			p:  "/foo",
			t:  "/foo",
			kv: map[string]string{},
		},
		{
			p:  "/fooo",
			t:  "",
			kv: map[string]string{},
		},
		{
			p:  "/bar/baz",
			t:  "/bar/baz",
			kv: map[string]string{},
		},
		{
			p:  "/bar/",
			t:  "/bar/",
			kv: map[string]string{},
		},
		/* Would love to get this case in, but it does look to cause some
		 * corner-cases that I'm too tired to reason about for now...
		        {
					p:  "/bar",
					t:  "/bar",
					kv: map[string]string{},
				},
		*/

		{
			p:  "/foo?abc=def",
			t:  "/foo",
			kv: map[string]string{},
		},

		// Discard ???-paths
		{
			p:  "/discard-trail/123",
			t:  "/discard-trail/:foo/???",
			kv: map[string]string{"foo": "123"},
		},
		{
			p:  "/discard-trail/123/",
			t:  "/discard-trail/:foo/???",
			kv: map[string]string{"foo": "123"},
		},
		{
			p:  "/discard-trail/123/a/b/c",
			t:  "/discard-trail/:foo/???",
			kv: map[string]string{"foo": "123"},
		},
	}

	for _, tt := range tests {
		templ, meta := r.Lookup(tt.p)

		if templ != tt.t {
			t.Errorf("Expected to get route `%s` from `%s`, got `%s`", tt.t, tt.p, templ)
		}

		for key, value := range tt.kv {
			if data, ok := meta[key]; !ok || data != value {
				t.Errorf("Expected to get `%+v`, got `%+v`", tt.kv, meta)
			}
		}

		for key, value := range meta {
			if data, ok := tt.kv[key]; !ok || data != value {
				t.Errorf("Unexpected `%+v`, should have `%+v`", meta, tt.kv)
			}
		}
	}
}

func TestPrecedence(t *testing.T) {
	r, _ := NewRoutefinder("/:a", "/:b")

	templ, _ := r.Lookup("/xxxxx")

	if templ != "/:a" {
		t.Errorf("Expected to get route /:a, got %s", templ)
	}
}

func TestStringer(t *testing.T) {
	r, _ := NewRoutefinder("/:a", "/:b")

	if r.String() != "/:a,/:b" {
		t.Errorf("Expected to get `/:a,/:b`, got %s", r.String())
	}
}

func TestSet(t *testing.T) {
	r, _ := NewRoutefinder()

	// Adding empty things shouldn't change a thing
	r.Set("")
	r.Set("")
	if r.String() != "" {
		t.Errorf("Expected ``, got `%s`", r.String())
	}

	r.Set("/a,/a/:id")
	if r.String() != "/a,/a/:id" {
		t.Errorf("Expected `/a,/a/:id`, got `%s`", r.String())
	}

	templ, params := r.Lookup("/a/123")
	if data, ok := params["id"]; templ != "/a/:id" && !ok && data == "123" {
		t.Errorf("Expected `/a/:id` and id=123, got `%s` and `%v`", templ, params)
	}

	r.Set("/foo/:bar")
	if r.String() != "/a,/a/:id,/foo/:bar" {
		t.Errorf("Expected `/a,/a/:id,/foo/:bar`, got `%s`", r.String())
	}
}

func ExampleRoutefinder_Set() {
	// Create a Routefinder and set it up as a Var-flag
	var routes Routefinder
	flag.Var(&routes, "routes", "comma-separated list of intervals")

	// Pretend the user added -routes "/u,/u/:id"
	flag.Set("routes", "/u,/u/:id")

	// Parse the flags and try it out with a small example
	flag.Parse()
	route, id := routes.Lookup("/u/123")
	fmt.Println(route, id)
	// Output: /u/:id map[id:123]
}

func BenchmarkLookupLast(b *testing.B) {
	r, _ := NewRoutefinder("/item/:id", "/item/:id/share/:network", "/item/:id/buy")

	for i := 0; i < b.N; i++ {
		r.Lookup("/item/123/buy")
	}
}

func BenchmarkLookupHitFirst(b *testing.B) {
	r, _ := NewRoutefinder("/item/:id", "/item/:id/share/:network", "/item/:id/buy")

	for i := 0; i < b.N; i++ {
		r.Lookup("/item/123")
	}
}

func BenchmarkLookupMiss(b *testing.B) {
	r, _ := NewRoutefinder("/item/:id", "/item/:id/share/:network", "/item/:id/buy", "/o")

	for i := 0; i < b.N; i++ {
		r.Lookup("/other")
	}
}
<commit_msg>Update example to tell about all the nifty features.<commit_after>package routefinder

import (
	"flag"
	"fmt"
	"testing"
)

func Example() {
	r, _ := NewRoutefinder(
		// Plain, static paths.
		"/",
		"/welcome",

		// Parse out a variable from the name.
		"/pay/:cardName",

		// Match all paths under /shop/:item/ and include the path as if the
		// rule for it was written out here.
		"/shop/:item/...",

		// The above rule doesn't catch `/shop/:item` (without the slash), so
		// we need to add that manually for now...
		"/shop/:item/...",

		// Match everything under /static, but ignore the trailing path.
		"/static/???",
	)

	// Plain path
	paths := []string{
		"/",
		"/returns-nothing",
		"/pay/visa",
		"/shop/gopher",
		"/shop/gopher/thumbnail",
		"/static/141029384.css",
	}

	for _, url := range paths {
		path, meta := r.Lookup(url)
		fmt.Printf("%s -> %s %+v\n", url, path, meta)
	}

	// / -> / map[]
	// /returns-nothing ->  map[]
	// /pay/visa -> /pay/:cardName map[cardName:visa]
	// /shop/gopher -> /shop/:item map[]
	// /shop/gopher/thumbnail -> /shop/:item/thumbnail map[item:gopher]
	// /static/141029384.css -> /static/??? map[]
}

func TestBasic(t *testing.T) {
	r, err := NewRoutefinder("/foo/:id/...", "/foo/:id", "/foo", "/bar/...", "/discard-trail/:foo/???")

	if err != nil {
		t.Fatal("Unexpected error creating routes", err)
	}

	tests := []struct {
		p  string
		t  string
		kv map[string]string
	}{
		{
			p:  "/",
			t:  "",
			kv: map[string]string{},
		},
		{
			p:  "/foo/foo/a",
			t:  "/foo/:id/a",
			kv: map[string]string{"id": "foo"},
		},
		{
			p:  "/foo",
			t:  "/foo",
			kv: map[string]string{},
		},
		{
			p:  "/fooo",
			t:  "",
			kv: map[string]string{},
		},
		{
			p:  "/bar/baz",
			t:  "/bar/baz",
			kv: map[string]string{},
		},
		{
			p:  "/bar/",
			t:  "/bar/",
			kv: map[string]string{},
		},
		/* Would love to get this case in, but it does look to cause some
		 * corner-cases that I'm too tired to reason about for now...
		        {
					p:  "/bar",
					t:  "/bar",
					kv: map[string]string{},
				},
		*/

		{
			p:  "/foo?abc=def",
			t:  "/foo",
			kv: map[string]string{},
		},

		// Discard ???-paths
		{
			p:  "/discard-trail/123",
			t:  "/discard-trail/:foo/???",
			kv: map[string]string{"foo": "123"},
		},
		{
			p:  "/discard-trail/123/",
			t:  "/discard-trail/:foo/???",
			kv: map[string]string{"foo": "123"},
		},
		{
			p:  "/discard-trail/123/a/b/c",
			t:  "/discard-trail/:foo/???",
			kv: map[string]string{"foo": "123"},
		},
	}

	for _, tt := range tests {
		templ, meta := r.Lookup(tt.p)

		if templ != tt.t {
			t.Errorf("Expected to get route `%s` from `%s`, got `%s`", tt.t, tt.p, templ)
		}

		for key, value := range tt.kv {
			if data, ok := meta[key]; !ok || data != value {
				t.Errorf("Expected to get `%+v`, got `%+v`", tt.kv, meta)
			}
		}

		for key, value := range meta {
			if data, ok := tt.kv[key]; !ok || data != value {
				t.Errorf("Unexpected `%+v`, should have `%+v`", meta, tt.kv)
			}
		}
	}
}

func TestPrecedence(t *testing.T) {
	r, _ := NewRoutefinder("/:a", "/:b")

	templ, _ := r.Lookup("/xxxxx")

	if templ != "/:a" {
		t.Errorf("Expected to get route /:a, got %s", templ)
	}
}

func TestStringer(t *testing.T) {
	r, _ := NewRoutefinder("/:a", "/:b")

	if r.String() != "/:a,/:b" {
		t.Errorf("Expected to get `/:a,/:b`, got %s", r.String())
	}
}

func TestSet(t *testing.T) {
	r, _ := NewRoutefinder()

	// Adding empty things shouldn't change a thing
	r.Set("")
	r.Set("")
	if r.String() != "" {
		t.Errorf("Expected ``, got `%s`", r.String())
	}

	r.Set("/a,/a/:id")
	if r.String() != "/a,/a/:id" {
		t.Errorf("Expected `/a,/a/:id`, got `%s`", r.String())
	}

	templ, params := r.Lookup("/a/123")
	if data, ok := params["id"]; templ != "/a/:id" && !ok && data == "123" {
		t.Errorf("Expected `/a/:id` and id=123, got `%s` and `%v`", templ, params)
	}

	r.Set("/foo/:bar")
	if r.String() != "/a,/a/:id,/foo/:bar" {
		t.Errorf("Expected `/a,/a/:id,/foo/:bar`, got `%s`", r.String())
	}
}

func ExampleRoutefinder_Set() {
	// Create a Routefinder and set it up as a Var-flag
	var routes Routefinder
	flag.Var(&routes, "routes", "comma-separated list of intervals")

	// Pretend the user added -routes "/u,/u/:id"
	flag.Set("routes", "/u,/u/:id")

	// Parse the flags and try it out with a small example
	flag.Parse()
	route, id := routes.Lookup("/u/123")
	fmt.Println(route, id)
	// Output: /u/:id map[id:123]
}

func BenchmarkLookupLast(b *testing.B) {
	r, _ := NewRoutefinder("/item/:id", "/item/:id/share/:network", "/item/:id/buy")

	for i := 0; i < b.N; i++ {
		r.Lookup("/item/123/buy")
	}
}

func BenchmarkLookupHitFirst(b *testing.B) {
	r, _ := NewRoutefinder("/item/:id", "/item/:id/share/:network", "/item/:id/buy")

	for i := 0; i < b.N; i++ {
		r.Lookup("/item/123")
	}
}

func BenchmarkLookupMiss(b *testing.B) {
	r, _ := NewRoutefinder("/item/:id", "/item/:id/share/:network", "/item/:id/buy", "/o")

	for i := 0; i < b.N; i++ {
		r.Lookup("/other")
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 The Jadep 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 jadeplib

import (
	"fmt"
	"io"
	"strconv"

	"github.com/bazelbuild/tools_jvm_autodeps/bazel"
)

// ask takes in a list of printable interfaces. It returns the
// input from the user indicating which interfaces is wanted.
// ask keeps asking the user for input until a valid input is given.
// If reading from stdin fails, returns an error.
func ask(in io.Reader, description string, options []bazel.Label) (int, error) {
	if len(options) == 1 {
		return 1, nil
	}
	fmt.Println()
	for i := len(options) - 1; i >= 0; i-- {
		fmt.Printf("[%v] %v\n", i+1, options[i])
	}
	fmt.Println("[0] None")

	fmt.Print(description)
	fmt.Printf("Enter a number to choose, or just Enter to select the default [%s]\n", options[0])
	for {
		var i string
		if _, err := fmt.Fscanln(in, &i); err != nil {
			if err == io.EOF {
				return -1, fmt.Errorf("Error reading stdin: %v", err)
			}
			return 1, nil
		}
		idx, err := strconv.Atoi(i)
		if err != nil {
			fmt.Println("Error occurred when converting input to integer. Please try again.")
			continue
		}
		if idx <= len(options) && idx >= 0 {
			return idx, nil
		}
		fmt.Println("Invalid index inputted. Please try again.")
	}
}

// SelectDepsToAdd asks the user to choose which deps to add to their rules to satisfy missing dependencies.
func SelectDepsToAdd(in io.Reader, missingDepsMap map[*bazel.Rule]map[ClassName][]bazel.Label) (map[*bazel.Rule][]bazel.Label, error) {
	depsToAdd := make(map[*bazel.Rule][]bazel.Label)
	for rule, classToRules := range missingDepsMap {
		addedDeps := make(map[bazel.Label]bool)
		for class, rules := range classToRules {
			if depAlreadySatisfied(addedDeps, rules) {
				continue
			}
			idx, err := ask(in, fmt.Sprintf("Choose a BUILD rule for %s to add to %s.\n", class, rule.Label()), rules)
			if err != nil {
				return nil, err
			}
			if idx != 0 {
				addedDeps[rules[idx-1]] = true
				depsToAdd[rule] = append(depsToAdd[rule], rules[(idx-1)])
			}
		}
	}
	return depsToAdd, nil
}

func depAlreadySatisfied(addedDeps map[bazel.Label]bool, rules []bazel.Label) bool {
	for _, rule := range rules {
		if _, ok := addedDeps[rule]; ok {
			return true
		}
	}
	return false
}
<commit_msg>When asking the user to choose a missing dependency to add, print the class name and suggested dependency in bold.<commit_after>// Copyright 2018 The Jadep 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 jadeplib

import (
	"fmt"
	"io"
	"strconv"

	"github.com/bazelbuild/tools_jvm_autodeps/bazel"
	"github.com/bazelbuild/tools_jvm_autodeps/color"
)

// ask takes in a list of printable interfaces. It returns the
// input from the user indicating which interfaces is wanted.
// ask keeps asking the user for input until a valid input is given.
// If reading from stdin fails, returns an error.
func ask(in io.Reader, description string, options []bazel.Label) (int, error) {
	if len(options) == 1 {
		return 1, nil
	}
	for i := len(options) - 1; i >= 0; i-- {
		fmt.Printf("[%v] %v\n", i+1, options[i])
	}
	fmt.Println("[0] None")

	fmt.Print(description)
	for {
		var i string
		if _, err := fmt.Fscanln(in, &i); err != nil {
			if err == io.EOF {
				return -1, fmt.Errorf("Error reading stdin: %v", err)
			}
			return 1, nil
		}
		idx, err := strconv.Atoi(i)
		if err != nil {
			fmt.Println("Error occurred when converting input to integer. Please try again.")
			continue
		}
		if idx <= len(options) && idx >= 0 {
			return idx, nil
		}
		fmt.Println("Invalid index inputted. Please try again.")
	}
}

// SelectDepsToAdd asks the user to choose which deps to add to their rules to satisfy missing dependencies.
func SelectDepsToAdd(in io.Reader, missingDepsMap map[*bazel.Rule]map[ClassName][]bazel.Label) (map[*bazel.Rule][]bazel.Label, error) {
	depsToAdd := make(map[*bazel.Rule][]bazel.Label)
	for rule, classToRules := range missingDepsMap {
		addedDeps := make(map[bazel.Label]bool)
		for class, rules := range classToRules {
			if depAlreadySatisfied(addedDeps, rules) {
				continue
			}
			fmt.Println()
			fmt.Printf("The BUILD rule %s is missing a dependency. Choose one of the options below:\n", rule.Label())
			description := fmt.Sprintf(`For class:  %s
Suggestion: %s
Hit Enter to accept, or a number to choose: `, color.Bold(string(class)), color.Bold(string(rules[0])))
			idx, err := ask(in, description, rules)
			if err != nil {
				return nil, err
			}
			if idx != 0 {
				addedDeps[rules[idx-1]] = true
				depsToAdd[rule] = append(depsToAdd[rule], rules[(idx-1)])
			}
		}
	}
	return depsToAdd, nil
}

func depAlreadySatisfied(addedDeps map[bazel.Label]bool, rules []bazel.Label) bool {
	for _, rule := range rules {
		if _, ok := addedDeps[rule]; ok {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package logd

import (
	"bytes"
	"errors"
	"testing"
)

func TestBasicLogging(t *testing.T) {
	var buff bytes.Buffer
	var dev = New("app.Debug", &buff)

	ctx := "3432"
	lvl := InfoLevel
	funcName := "CallRouters"
	funcMeta := "300:36"
	Message := "Initializing Routing Stats"

	// dev.SwitchMode(User)
	dev.Log(ctx, lvl, funcName, Message)
	testRes := basicFormatter(dev, ctx, funcName, funcMeta, Message, nil)

	if buff.String() != testRes {
		t.Fatalf("Invalid response with expected output: Expected %s got %s", testRes, buff.String())
	}

	t.Log("Basic Log format passed")
}

// Switch logLevel to DataTrace and send out some data to include in the trace lines
func TestDataTrace(t *testing.T) {
	var buff bytes.Buffer
	var dev = New("app.Debug", &buff)

	ctx := "go.4321"
	funcName := "Agg.WriteResponse"
	funcMeta := "30:3"
	Message := "Sending Response Body"

	/*
		   Turns bytes into:
			   0x000: 00 01 03 05 10 ...
	*/

	var bo = ByteFormatter([]byte(`Thunder routers`))
	dev.DataTrace(ctx, funcName, Message, bo)
	testRes := basicFormatter(dev, ctx, funcName, funcMeta, Message+bo.Format(), nil)

	if buff.String() != testRes {
		t.Fatalf("Invalid response with expected output: Expected %s got %s", testRes, buff.String())
	}

	//switch out level to a higher priority
	dev.SwitchLevel(ErrorLevel)

	// this log should be ignored as we have entered a high log
	dev.DataTracef("go.4321", "Agg.WriteResponse", "Response Written with Status: %d", nil, 200)
}

func TestErrorLevels(t *testing.T) {
	var buff bytes.Buffer
	var dev = New("app.Debug", &buff)
	dev.SwitchLevel(ErrorLevel)
	// all log levels below the current are ignored
	dev.Info("4021", "LoadConfig", "Configuratio Loaded")

	dev.Info("4021", "LoadConfig", "loading app.config file from disk")

	dev.Error("4021", "LoadConfig", "loading app.config file errored out", errors.New("File Not Found!"))
}
<commit_msg>fixed: test code check<commit_after>package logd

import (
	"bytes"
	"errors"
	"testing"
)

// TestBasicLogging tests the output response from using the log api
func TestBasicLogging(t *testing.T) {
	var buff bytes.Buffer
	var dev = New("app.Debug", &buff)

	ctx := "3432"
	lvl := InfoLevel
	funcName := "CallRouters#300:36"
	Message := "Initializing Routing Stats"

	// dev.SwitchMode(User)
	dev.Log(ctx, lvl, funcName, Message)
	testRes := basicFormatter(dev, ctx, funcName, Message, nil)

	if buff.String() != testRes {
		t.Fatalf("Invalid response with expected output: Expected %s got %s", testRes, buff.String())
	}

	t.Log("Basic Log format passed")
}

// Switch logLevel to DataTrace and send out some data to include in the trace lines
func TestDataTrace(t *testing.T) {
	var buff bytes.Buffer
	var dev = New("app.Debug", &buff)

	ctx := "go.4321"
	funcName := "Agg.WriteResponse"
	funcMeta := "30:3"
	Message := "Sending Response Body"

	/*
		   Turns bytes into:
			   0x000: 00 01 03 05 10 ...
	*/

	var bo = ByteFormatter([]byte(`Thunder routers`))
	dev.DataTrace(ctx, funcName, Message, bo)
	testRes := basicFormatter(dev, ctx, funcName, funcMeta, Message+bo.Format(), nil)

	if buff.String() != testRes {
		t.Fatalf("Invalid response with expected output: Expected %s got %s", testRes, buff.String())
	}

	//switch out level to a higher priority
	dev.SwitchLevel(ErrorLevel)

	// this log should be ignored as we have entered a high log
	dev.DataTracef("go.4321", "Agg.WriteResponse", "Response Written with Status: %d", nil, 200)
}

func TestErrorLevels(t *testing.T) {
	var buff bytes.Buffer
	var dev = New("app.Debug", &buff)
	dev.SwitchLevel(ErrorLevel)
	// all log levels below the current are ignored
	dev.Info("4021", "LoadConfig", "Configuratio Loaded")

	dev.Info("4021", "LoadConfig", "loading app.config file from disk")

	dev.Error("4021", "LoadConfig", "loading app.config file errored out", errors.New("File Not Found!"))
}
<|endoftext|>


<commit_before>package logger

import (
	"context"
	"fmt"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync"
	"time"

	dlog "github.com/micro/go-micro/v2/debug/log"
)

func init() {
	lvl, err := GetLevel(os.Getenv("MICRO_LOG_LEVEL"))
	if err != nil {
		lvl = InfoLevel
	}

	DefaultLogger = NewHelper(NewLogger(WithLevel(lvl)))
}

type defaultLogger struct {
	sync.RWMutex
	opts Options
}

// Init(opts...) should only overwrite provided options
func (l *defaultLogger) Init(opts ...Option) error {
	for _, o := range opts {
		o(&l.opts)
	}
	return nil
}

func (l *defaultLogger) String() string {
	return "default"
}

func (l *defaultLogger) Fields(fields map[string]interface{}) Logger {
	l.Lock()
	l.opts.Fields = copyFields(fields)
	l.Unlock()
	return l
}

func copyFields(src map[string]interface{}) map[string]interface{} {
	dst := make(map[string]interface{}, len(src))
	for k, v := range src {
		dst[k] = v
	}
	return dst
}

// logCallerfilePath returns a package/file:line description of the caller,
// preserving only the leaf directory name and file name.
func logCallerfilePath(loggingFilePath string) string {
	// To make sure we trim the path correctly on Windows too, we
	// counter-intuitively need to use '/' and *not* os.PathSeparator here,
	// because the path given originates from Go stdlib, specifically
	// runtime.Caller() which (as of Mar/17) returns forward slashes even on
	// Windows.
	//
	// See https://github.com/golang/go/issues/3335
	// and https://github.com/golang/go/issues/18151
	//
	// for discussion on the issue on Go side.
	idx := strings.LastIndexByte(loggingFilePath, '/')
	if idx == -1 {
		return loggingFilePath
	}
	idx = strings.LastIndexByte(loggingFilePath[:idx], '/')
	if idx == -1 {
		return loggingFilePath
	}
	return loggingFilePath[idx+1:]
}

func (l *defaultLogger) Log(level Level, v ...interface{}) {
	// TODO decide does we need to write message if log level not used?
	if !l.opts.Level.Enabled(level) {
		return
	}

	l.RLock()
	fields := copyFields(l.opts.Fields)
	l.RUnlock()

	fields["level"] = level.String()

	if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
		fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
	}

	rec := dlog.Record{
		Timestamp: time.Now(),
		Message:   fmt.Sprint(v...),
		Metadata:  make(map[string]string, len(fields)),
	}

	keys := make([]string, 0, len(fields))
	for k, v := range fields {
		keys = append(keys, k)
		rec.Metadata[k] = fmt.Sprintf("%v", v)
	}

	sort.Strings(keys)
	metadata := ""

	for _, k := range keys {
		metadata += fmt.Sprintf(" %s=%v", k, fields[k])
	}

	dlog.DefaultLog.Write(rec)

	t := rec.Timestamp.Format("2006-01-02 15:04:05")
	fmt.Printf("%s %s %v\n", t, metadata, rec.Message)
}

func (l *defaultLogger) Logf(level Level, format string, v ...interface{}) {
	//	 TODO decide does we need to write message if log level not used?
	if level < l.opts.Level {
		return
	}

	l.RLock()
	fields := copyFields(l.opts.Fields)
	l.RUnlock()

	fields["level"] = level.String()

	if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
		fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
	}

	rec := dlog.Record{
		Timestamp: time.Now(),
		Message:   fmt.Sprintf(format, v...),
		Metadata:  make(map[string]string, len(fields)),
	}

	keys := make([]string, 0, len(fields))
	for k, v := range fields {
		keys = append(keys, k)
		rec.Metadata[k] = fmt.Sprintf("%v", v)
	}

	sort.Strings(keys)
	metadata := ""

	for _, k := range keys {
		metadata += fmt.Sprintf(" %s=%v", k, fields[k])
	}

	dlog.DefaultLog.Write(rec)

	t := rec.Timestamp.Format("2006-01-02 15:04:05")
	fmt.Printf("%s %s %v\n", t, metadata, rec.Message)
}

func (n *defaultLogger) Options() Options {
	// not guard against options Context values
	n.RLock()
	opts := n.opts
	opts.Fields = copyFields(n.opts.Fields)
	n.RUnlock()
	return opts
}

// NewLogger builds a new logger based on options
func NewLogger(opts ...Option) Logger {
	// Default options
	options := Options{
		Level:           InfoLevel,
		Fields:          make(map[string]interface{}),
		Out:             os.Stderr,
		CallerSkipCount: 2,
		Context:         context.Background(),
	}

	l := &defaultLogger{opts: options}
	if err := l.Init(opts...); err != nil {
		l.Log(FatalLevel, err)
	}

	return l
}
<commit_msg>refactor(logger): fix the name of defaultLogger receiver (#1859)<commit_after>package logger

import (
	"context"
	"fmt"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync"
	"time"

	dlog "github.com/micro/go-micro/v2/debug/log"
)

func init() {
	lvl, err := GetLevel(os.Getenv("MICRO_LOG_LEVEL"))
	if err != nil {
		lvl = InfoLevel
	}

	DefaultLogger = NewHelper(NewLogger(WithLevel(lvl)))
}

type defaultLogger struct {
	sync.RWMutex
	opts Options
}

// Init(opts...) should only overwrite provided options
func (l *defaultLogger) Init(opts ...Option) error {
	for _, o := range opts {
		o(&l.opts)
	}
	return nil
}

func (l *defaultLogger) String() string {
	return "default"
}

func (l *defaultLogger) Fields(fields map[string]interface{}) Logger {
	l.Lock()
	l.opts.Fields = copyFields(fields)
	l.Unlock()
	return l
}

func copyFields(src map[string]interface{}) map[string]interface{} {
	dst := make(map[string]interface{}, len(src))
	for k, v := range src {
		dst[k] = v
	}
	return dst
}

// logCallerfilePath returns a package/file:line description of the caller,
// preserving only the leaf directory name and file name.
func logCallerfilePath(loggingFilePath string) string {
	// To make sure we trim the path correctly on Windows too, we
	// counter-intuitively need to use '/' and *not* os.PathSeparator here,
	// because the path given originates from Go stdlib, specifically
	// runtime.Caller() which (as of Mar/17) returns forward slashes even on
	// Windows.
	//
	// See https://github.com/golang/go/issues/3335
	// and https://github.com/golang/go/issues/18151
	//
	// for discussion on the issue on Go side.
	idx := strings.LastIndexByte(loggingFilePath, '/')
	if idx == -1 {
		return loggingFilePath
	}
	idx = strings.LastIndexByte(loggingFilePath[:idx], '/')
	if idx == -1 {
		return loggingFilePath
	}
	return loggingFilePath[idx+1:]
}

func (l *defaultLogger) Log(level Level, v ...interface{}) {
	// TODO decide does we need to write message if log level not used?
	if !l.opts.Level.Enabled(level) {
		return
	}

	l.RLock()
	fields := copyFields(l.opts.Fields)
	l.RUnlock()

	fields["level"] = level.String()

	if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
		fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
	}

	rec := dlog.Record{
		Timestamp: time.Now(),
		Message:   fmt.Sprint(v...),
		Metadata:  make(map[string]string, len(fields)),
	}

	keys := make([]string, 0, len(fields))
	for k, v := range fields {
		keys = append(keys, k)
		rec.Metadata[k] = fmt.Sprintf("%v", v)
	}

	sort.Strings(keys)
	metadata := ""

	for _, k := range keys {
		metadata += fmt.Sprintf(" %s=%v", k, fields[k])
	}

	dlog.DefaultLog.Write(rec)

	t := rec.Timestamp.Format("2006-01-02 15:04:05")
	fmt.Printf("%s %s %v\n", t, metadata, rec.Message)
}

func (l *defaultLogger) Logf(level Level, format string, v ...interface{}) {
	//	 TODO decide does we need to write message if log level not used?
	if level < l.opts.Level {
		return
	}

	l.RLock()
	fields := copyFields(l.opts.Fields)
	l.RUnlock()

	fields["level"] = level.String()

	if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
		fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
	}

	rec := dlog.Record{
		Timestamp: time.Now(),
		Message:   fmt.Sprintf(format, v...),
		Metadata:  make(map[string]string, len(fields)),
	}

	keys := make([]string, 0, len(fields))
	for k, v := range fields {
		keys = append(keys, k)
		rec.Metadata[k] = fmt.Sprintf("%v", v)
	}

	sort.Strings(keys)
	metadata := ""

	for _, k := range keys {
		metadata += fmt.Sprintf(" %s=%v", k, fields[k])
	}

	dlog.DefaultLog.Write(rec)

	t := rec.Timestamp.Format("2006-01-02 15:04:05")
	fmt.Printf("%s %s %v\n", t, metadata, rec.Message)
}

func (l *defaultLogger) Options() Options {
	// not guard against options Context values
	l.RLock()
	opts := l.opts
	opts.Fields = copyFields(l.opts.Fields)
	l.RUnlock()
	return opts
}

// NewLogger builds a new logger based on options
func NewLogger(opts ...Option) Logger {
	// Default options
	options := Options{
		Level:           InfoLevel,
		Fields:          make(map[string]interface{}),
		Out:             os.Stderr,
		CallerSkipCount: 2,
		Context:         context.Background(),
	}

	l := &defaultLogger{opts: options}
	if err := l.Init(opts...); err != nil {
		l.Log(FatalLevel, err)
	}

	return l
}
<|endoftext|>


<commit_before>/*
 * This is the main core of the yaag package
 */
package yaag

import (
	"encoding/json"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
)

const TEMPLATE = `<!DOCTYPE html>

    <title> API Documentation </title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">

    <link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css">

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">

            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1">
                Toggle navigation

            </button>
            {{.Title}}

            <form class="navbar-form navbar-left" role="search">

                    <input type="text" class="form-control" placeholder="Search">

                <button type="submit" class="btn btn-default">Find</button>
            </form>

Base URL => {{.BaseLink}}

    {{ range $key, $value := .array }}

 {{$value.HttpVerb}}
        {{$value.Path}}

    {{ range $wrapperKey, $wrapperValue := $value.HtmlValues }}

 Example {{add $wrapperKey 1}}

            {{ if $wrapperValue.RequestHeader }}

 Request Headers

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.RequestHeader }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.PostForm }}

 Post Form

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.PostForm }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.RequestUrlParams }}

 URL Params

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.RequestUrlParams }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.RequestBody }}

 Request Body

{{ $wrapperValue.RequestBody }}

            {{ end }}

 Response Code

{{ $wrapperValue.ResponseCode }}

            {{ if $wrapperValue.ResponseHeader }}

 Response Headers

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.ResponseHeader }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.ResponseBody }}

 Response Body

{{ $wrapperValue.ResponseBody }}

            {{ end }}

    {{ end}}
    {{ end}}

    Developed by Gophers at betacraft Inc

`

var CommonHeaders = []string{
	"Accept",
	"Accept-Encoding",
	"Accept-Language",
	"Cache-Control",
	"Content-Length",
	"Content-Type",
	"Origin",
	"User-Agent",
	"X-Forwarded-For",
}

var count int

type APICall struct {
	Id int

	CurrentPath string
	MethodType  string

	PostForm map[string]string

	RequestHeader        map[string]string
	CommonRequestHeaders map[string]string
	ResponseHeader       map[string]string
	RequestUrlParams     map[string]string

	RequestBody  string
	ResponseBody string
	ResponseCode int
}

type PathSpec struct {
	HttpVerb   string
	Path       string
	HtmlValues []APICall
}

type ApiCallValue struct {
	BaseLink string
	Path     []PathSpec
}

type Config struct {
	On       bool
	DocTitle string
	DocPath  string
}

var ApiCallValueInstance = &ApiCallValue{}
var config *Config = &Config{On: false, DocPath: "apidoc.html", DocTitle: "YAAG"}

func IsOn() bool {
	return config.On
}

func Init(conf *Config) {
	filePath, err := filepath.Abs(conf.DocPath + ".json")
	dataFile, err := os.Open(filePath)
	defer dataFile.Close()

	if err == nil {
		json.NewDecoder(io.Reader(dataFile)).Decode(ApiCallValueInstance)
	}
	config = conf
}

func add(x, y int) int {
	return x + y
}

func mult(x, y int) int {
	return (x + 1) * y
}

func GenerateHtml(htmlValue *APICall) {
	shouldAddPathSpec := true
	log.Printf("PathSpec : %v", ApiCallValueInstance.Path)
	for k, pathSpec := range ApiCallValueInstance.Path {
		if pathSpec.Path == htmlValue.CurrentPath && pathSpec.HttpVerb == htmlValue.MethodType {
			shouldAddPathSpec = false
			shouldAdd := true
			// for _, value := range pathSpec.HtmlValues {
			// 	if value.RequestBody == htmlValue.RequestBody {
			// 		shouldAdd = false
			// 	}
			// }
			if shouldAdd {
				htmlValue.Id = count
				count += 1
				deleteCommonHeaders(htmlValue)
				ApiCallValueInstance.Path[k].HtmlValues = append(pathSpec.HtmlValues, *htmlValue)
			}
		}
	}

	if shouldAddPathSpec {
		pathSpec := PathSpec{
			HttpVerb: htmlValue.MethodType,
			Path:     htmlValue.CurrentPath,
		}
		htmlValue.Id = count
		count += 1
		deleteCommonHeaders(htmlValue)
		pathSpec.HtmlValues = append(pathSpec.HtmlValues, *htmlValue)
		ApiCallValueInstance.Path = append(ApiCallValueInstance.Path, pathSpec)
	}
	funcs := template.FuncMap{"add": add, "mult": mult}
	t := template.New("API Documentation").Funcs(funcs)
	filePath, err := filepath.Abs(config.DocPath)
	htmlString := TEMPLATE

	t, err = t.Parse(htmlString)
	if err != nil {
		log.Println(err)
		return
	}
	homeHtmlFile, err := os.Create(filePath)
	defer homeHtmlFile.Close()

	data, err := json.Marshal(ApiCallValueInstance)
	if err != nil {
		log.Println(err)
		return
	}

	if ioutil.WriteFile(filePath+".json", data, os.O_CREATE) != nil {
		log.Println(err)
		return
	}

	_, err := dataFile.Write(data)
	if err != nil {
		log.Println(err)
		return
	}
	homeWriter := io.Writer(homeHtmlFile)
	t.Execute(homeWriter, map[string]interface{}{"array": ApiCallValueInstance.Path,
		"BaseLink": ApiCallValueInstance.BaseLink, "Title": config.DocTitle})
}

func deleteCommonHeaders(call *APICall) {
	delete(call.RequestHeader, "Accept")
	delete(call.RequestHeader, "Accept-Encoding")
	delete(call.RequestHeader, "Accept-Language")
	delete(call.RequestHeader, "Cache-Control")
	delete(call.RequestHeader, "Connection")
	delete(call.RequestHeader, "Cookie")
	delete(call.RequestHeader, "Origin")
	delete(call.RequestHeader, "User-Agent")
}
<commit_msg>Fix errors from previous commit<commit_after>/*
 * This is the main core of the yaag package
 */
package yaag

import (
	"encoding/json"
	"html/template"
	"io"
	"log"
	"os"
	"path/filepath"
)

const TEMPLATE = `<!DOCTYPE html>

    <title> API Documentation </title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">

    <link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css">

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">

            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1">
                Toggle navigation

            </button>
            {{.Title}}

            <form class="navbar-form navbar-left" role="search">

                    <input type="text" class="form-control" placeholder="Search">

                <button type="submit" class="btn btn-default">Find</button>
            </form>

Base URL => {{.BaseLink}}

    {{ range $key, $value := .array }}

 {{$value.HttpVerb}}
        {{$value.Path}}

    {{ range $wrapperKey, $wrapperValue := $value.HtmlValues }}

 Example {{add $wrapperKey 1}}

            {{ if $wrapperValue.RequestHeader }}

 Request Headers

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.RequestHeader }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.PostForm }}

 Post Form

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.PostForm }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.RequestUrlParams }}

 URL Params

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.RequestUrlParams }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.RequestBody }}

 Request Body

{{ $wrapperValue.RequestBody }}

            {{ end }}

 Response Code

{{ $wrapperValue.ResponseCode }}

            {{ if $wrapperValue.ResponseHeader }}

 Response Headers

                    Key
                    Value

                {{ range $key, $value := $wrapperValue.ResponseHeader }}

                    {{ $key }}
                     {{ $value }}

                {{ end }}

            {{ end }}

            {{ if $wrapperValue.ResponseBody }}

 Response Body

{{ $wrapperValue.ResponseBody }}

            {{ end }}

    {{ end}}
    {{ end}}

    Developed by Gophers at betacraft Inc

`

var CommonHeaders = []string{
	"Accept",
	"Accept-Encoding",
	"Accept-Language",
	"Cache-Control",
	"Content-Length",
	"Content-Type",
	"Origin",
	"User-Agent",
	"X-Forwarded-For",
}

var count int

type APICall struct {
	Id int

	CurrentPath string
	MethodType  string

	PostForm map[string]string

	RequestHeader        map[string]string
	CommonRequestHeaders map[string]string
	ResponseHeader       map[string]string
	RequestUrlParams     map[string]string

	RequestBody  string
	ResponseBody string
	ResponseCode int
}

type PathSpec struct {
	HttpVerb   string
	Path       string
	HtmlValues []APICall
}

type ApiCallValue struct {
	BaseLink string
	Path     []PathSpec
}

type Config struct {
	On       bool
	DocTitle string
	DocPath  string
}

var ApiCallValueInstance = &ApiCallValue{}
var config *Config = &Config{On: false, DocPath: "apidoc.html", DocTitle: "YAAG"}

func IsOn() bool {
	return config.On
}

func Init(conf *Config) {
	filePath, err := filepath.Abs(conf.DocPath + ".json")
	dataFile, err := os.Open(filePath)
	defer dataFile.Close()

	if err == nil {
		json.NewDecoder(io.Reader(dataFile)).Decode(ApiCallValueInstance)
	}
	config = conf
}

func add(x, y int) int {
	return x + y
}

func mult(x, y int) int {
	return (x + 1) * y
}

func GenerateHtml(htmlValue *APICall) {
	shouldAddPathSpec := true
	log.Printf("PathSpec : %v", ApiCallValueInstance.Path)
	for k, pathSpec := range ApiCallValueInstance.Path {
		if pathSpec.Path == htmlValue.CurrentPath && pathSpec.HttpVerb == htmlValue.MethodType {
			shouldAddPathSpec = false
			shouldAdd := true
			// for _, value := range pathSpec.HtmlValues {
			// 	if value.RequestBody == htmlValue.RequestBody {
			// 		shouldAdd = false
			// 	}
			// }
			if shouldAdd {
				htmlValue.Id = count
				count += 1
				deleteCommonHeaders(htmlValue)
				ApiCallValueInstance.Path[k].HtmlValues = append(pathSpec.HtmlValues, *htmlValue)
			}
		}
	}

	if shouldAddPathSpec {
		pathSpec := PathSpec{
			HttpVerb: htmlValue.MethodType,
			Path:     htmlValue.CurrentPath,
		}
		htmlValue.Id = count
		count += 1
		deleteCommonHeaders(htmlValue)
		pathSpec.HtmlValues = append(pathSpec.HtmlValues, *htmlValue)
		ApiCallValueInstance.Path = append(ApiCallValueInstance.Path, pathSpec)
	}
	funcs := template.FuncMap{"add": add, "mult": mult}
	t := template.New("API Documentation").Funcs(funcs)
	filePath, err := filepath.Abs(config.DocPath)
	htmlString := TEMPLATE

	t, err = t.Parse(htmlString)
	if err != nil {
		log.Println(err)
		return
	}
	homeHtmlFile, err := os.Create(filePath)
	defer homeHtmlFile.Close()

	dataFile, err := os.Create(filePath + ".json")
	if err != nil {
		log.Println(err)
		return
	}
	defer dataFile.Close()

	data, err := json.Marshal(ApiCallValueInstance)
	if err != nil {
		log.Println(err)
		return
	}

	_, err = dataFile.Write(data)
	if err != nil {
		log.Println(err)
		return
	}
	homeWriter := io.Writer(homeHtmlFile)
	t.Execute(homeWriter, map[string]interface{}{"array": ApiCallValueInstance.Path,
		"BaseLink": ApiCallValueInstance.BaseLink, "Title": config.DocTitle})
}

func deleteCommonHeaders(call *APICall) {
	delete(call.RequestHeader, "Accept")
	delete(call.RequestHeader, "Accept-Encoding")
	delete(call.RequestHeader, "Accept-Language")
	delete(call.RequestHeader, "Cache-Control")
	delete(call.RequestHeader, "Connection")
	delete(call.RequestHeader, "Cookie")
	delete(call.RequestHeader, "Origin")
	delete(call.RequestHeader, "User-Agent")
}
<|endoftext|>


<commit_before>// Copyright 2013, Cong Ding. All rights reserved.
//
// 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.
//
// author: Cong Ding <dinggnu@gmail.com>
//
package logging

import (
	"bytes"
	"fmt"
	"sync/atomic"
	"time"
)

// watcher watches the logger.queue channel, and writes the logs to output
func (logger *Logger) watcher() {
	var buf bytes.Buffer
	for {
		timeout := time.After(time.Second / 10)

		for i := 0; i < bufSize; i++ {
			select {
			case msg := <-logger.queue:
				fmt.Fprintln(&buf, msg)
			case req := <-logger.request:
				logger.flushReq(&buf, &req)
			case <-timeout:
				break
			case <-logger.flush:
				logger.flushBuf(&buf)
				logger.flush <- true
				break
			case <-logger.quit:
				// If quit signal received, cleans the channel
				// and writes all of them to io.Writer.
				for {
					select {
					case msg := <-logger.queue:
						fmt.Fprintln(&buf, msg)
					case req := <-logger.request:
						logger.flushReq(&buf, &req)
					case <-logger.flush:
						// do nothing
					default:
						logger.flushBuf(&buf)
						logger.quit <- true
						return
					}
				}
			}

		}
		logger.flushBuf(&buf)
	}
}

// flushBuf flushes the content of buffer to out and reset the buffer
func (logger *Logger) flushBuf(b *bytes.Buffer) {
	if len(b.Bytes()) > 0 {
		logger.out.Write(b.Bytes())
		b.Reset()
	}
}

// flushReq handles the request and writes the result to writer
func (logger *Logger) flushReq(b *bytes.Buffer, req *request) {
	if req.format == "" {
		msg := fmt.Sprint(req.v...)
		msg = logger.genLog(req.level, msg)
		fmt.Fprintln(b, msg)
	} else {
		msg := fmt.Sprintf(req.format, req.v...)
		msg = logger.genLog(req.level, msg)
		fmt.Fprintln(b, msg)
	}
}

// flushMsg is to print log to file, stdout, or others.
func (logger *Logger) flushMsg(message string) {
	if logger.sync {
		logger.wlock.Lock()
		defer logger.wlock.Unlock()
		fmt.Fprintln(logger.out, message)
	} else {
		logger.queue <- message
	}
}

// log records log v... with level `level'.
func (logger *Logger) log(level Level, v ...interface{}) {
	if int32(level) >= atomic.LoadInt32((*int32)(&logger.level)) {
		if logger.runtime || logger.sync {
			message := fmt.Sprint(v...)
			message = logger.genLog(level, message)
			logger.flushMsg(message)
		} else {
			r := new(request)
			r.level = level
			r.v = v
			logger.request <- *r
		}
	}
}

// logf records log v... with level `level'.
func (logger *Logger) logf(level Level, format string, v ...interface{}) {
	if int32(level) >= atomic.LoadInt32((*int32)(&logger.level)) {
		if logger.runtime || logger.sync {
			message := fmt.Sprintf(format, v...)
			message = logger.genLog(level, message)
			logger.flushMsg(message)
		} else {
			r := new(request)
			r.level = level
			r.format = format
			r.v = v
			logger.request <- *r
		}
	}
}
<commit_msg>fix wrong use in break<commit_after>// Copyright 2013, Cong Ding. All rights reserved.
//
// 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.
//
// author: Cong Ding <dinggnu@gmail.com>
//
package logging

import (
	"bytes"
	"fmt"
	"sync/atomic"
	"time"
)

// watcher watches the logger.queue channel, and writes the logs to output
func (logger *Logger) watcher() {
	var buf bytes.Buffer
	for {
		timeout := time.After(time.Second / 10)

		for i := 0; i < bufSize; i++ {
			select {
			case msg := <-logger.queue:
				fmt.Fprintln(&buf, msg)
			case req := <-logger.request:
				logger.flushReq(&buf, &req)
			case <-timeout:
				i = bufSize
			case <-logger.flush:
				logger.flushBuf(&buf)
				logger.flush <- true
				i = bufSize
			case <-logger.quit:
				// If quit signal received, cleans the channel
				// and writes all of them to io.Writer.
				for {
					select {
					case msg := <-logger.queue:
						fmt.Fprintln(&buf, msg)
					case req := <-logger.request:
						logger.flushReq(&buf, &req)
					case <-logger.flush:
						// do nothing
					default:
						logger.flushBuf(&buf)
						logger.quit <- true
						return
					}
				}
			}
		}
		logger.flushBuf(&buf)
	}
}

// flushBuf flushes the content of buffer to out and reset the buffer
func (logger *Logger) flushBuf(b *bytes.Buffer) {
	if len(b.Bytes()) > 0 {
		logger.out.Write(b.Bytes())
		b.Reset()
	}
}

// flushReq handles the request and writes the result to writer
func (logger *Logger) flushReq(b *bytes.Buffer, req *request) {
	if req.format == "" {
		msg := fmt.Sprint(req.v...)
		msg = logger.genLog(req.level, msg)
		fmt.Fprintln(b, msg)
	} else {
		msg := fmt.Sprintf(req.format, req.v...)
		msg = logger.genLog(req.level, msg)
		fmt.Fprintln(b, msg)
	}
}

// flushMsg is to print log to file, stdout, or others.
func (logger *Logger) flushMsg(message string) {
	if logger.sync {
		logger.wlock.Lock()
		defer logger.wlock.Unlock()
		fmt.Fprintln(logger.out, message)
	} else {
		logger.queue <- message
	}
}

// log records log v... with level `level'.
func (logger *Logger) log(level Level, v ...interface{}) {
	if int32(level) >= atomic.LoadInt32((*int32)(&logger.level)) {
		if logger.runtime || logger.sync {
			message := fmt.Sprint(v...)
			message = logger.genLog(level, message)
			logger.flushMsg(message)
		} else {
			r := new(request)
			r.level = level
			r.v = v
			logger.request <- *r
		}
	}
}

// logf records log v... with level `level'.
func (logger *Logger) logf(level Level, format string, v ...interface{}) {
	if int32(level) >= atomic.LoadInt32((*int32)(&logger.level)) {
		if logger.runtime || logger.sync {
			message := fmt.Sprintf(format, v...)
			message = logger.genLog(level, message)
			logger.flushMsg(message)
		} else {
			r := new(request)
			r.level = level
			r.format = format
			r.v = v
			logger.request <- *r
		}
	}
}
<|endoftext|>


<commit_before>package controllers

import (
	dbpkg "github.com/qb0C80aE/clay/db"
	"github.com/qb0C80aE/clay/helper"

	"encoding/json"
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"net/http"
)

func BindJson(c *gin.Context, container interface{}) error {
	return c.Bind(container)
}

func OutputJsonError(c *gin.Context, code int, err error) {
	c.JSON(code, gin.H{"error": err.Error()})
}

func OutputSingleJsonResult(c *gin.Context, code int, result interface{}, fields map[string]interface{}) {
	if fields == nil {
		c.JSON(code, result)
	} else {
		fieldMap, err := helper.FieldToMap(result, fields)
		if err != nil {
			OutputJsonError(c, http.StatusBadRequest, err)
			return
		}

		if _, ok := c.GetQuery("pretty"); ok {
			c.IndentedJSON(code, fieldMap)
		} else {
			c.JSON(code, fieldMap)
		}
	}
}

func OutputMultiJsonResult(c *gin.Context, code int, result []interface{}, fields map[string]interface{}) {
	if fields == nil {
		c.JSON(code, result)
	} else {
		if _, ok := c.GetQuery("stream"); ok {
			enc := json.NewEncoder(c.Writer)
			c.Status(code)

			for _, item := range result {
				fieldMap, err := helper.FieldToMap(item, fields)

				if err != nil {
					OutputJsonError(c, http.StatusBadRequest, err)
					return
				}

				if err := enc.Encode(fieldMap); err != nil {
					OutputJsonError(c, http.StatusBadRequest, err)
					return
				}
			}
		} else {
			fieldMaps := []map[string]interface{}{}

			for _, item := range result {
				fieldMap, err := helper.FieldToMap(item, fields)

				if err != nil {
					OutputJsonError(c, http.StatusBadRequest, err)
					return
				}

				fieldMaps = append(fieldMaps, fieldMap)
			}

			if _, ok := c.GetQuery("pretty"); ok {
				c.IndentedJSON(code, fieldMaps)
			} else {
				c.JSON(code, fieldMaps)
			}
		}
	}
}

func OutputTextResult(c *gin.Context, code int, result interface{}, _ map[string]interface{}) {
	text := result.(string)
	c.String(code, text)
}

func OutputNothing(c *gin.Context, code int, _ interface{}, _ map[string]interface{}) {
	c.Writer.WriteHeader(code)
}

func processSingleGet(c *gin.Context,
	model interface{},
	actualLogic func(*gorm.DB, string, string) (interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {

	id := c.Params.ByName("id")
	db := dbpkg.DBInstance(c)
	db = dbpkg.SetPreloads(c.Query("preloads"), db)
	fields := helper.ParseFields(c.DefaultQuery("fields", "*"))
	queryFields := helper.QueryFields(model, fields)

	result, err := actualLogic(db, id, queryFields)
	if err != nil {
		errorOutputFunction(c, http.StatusNotFound, errors.New("item with id#"+id+" not found"))
		return
	}

	resultOutputFunction(c, http.StatusOK, result, fields)
}

func processMultiGet(c *gin.Context,
	model interface{},
	actualLogic func(*gorm.DB, string) ([]interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, []interface{}, map[string]interface{})) {

	db := dbpkg.DBInstance(c)
	db = dbpkg.SetPreloads(c.Query("preloads"), db)
	db = dbpkg.SortRecords(c.Query("sort"), db)
	db = dbpkg.FilterFields(c, model, db)
	fields := helper.ParseFields(c.DefaultQuery("fields", "*"))
	queryFields := helper.QueryFields(model, fields)

	result, err := actualLogic(db, queryFields)
	if err != nil {
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	resultOutputFunction(c, http.StatusOK, result, fields)
}

func processCreate(c *gin.Context,
	container interface{},
	binderFunction func(*gin.Context, interface{}) error,
	actualLogic func(*gorm.DB, interface{}) (interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {
	if err := binderFunction(c, container); err != nil {
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db := dbpkg.DBInstance(c)

	db = db.Begin()
	result, err := actualLogic(db, container)
	if err != nil {
		db.Rollback()
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db.Commit()

	resultOutputFunction(c, http.StatusCreated, result, nil)
}

func processUpdate(c *gin.Context,
	container interface{},
	binderFunction func(*gin.Context, interface{}) error,
	actualLogic func(*gorm.DB, string, interface{}) (interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {
	id := c.Params.ByName("id")

	if err := binderFunction(c, container); err != nil {
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db := dbpkg.DBInstance(c)

	db = db.Begin()
	result, err := actualLogic(db, id, container)
	if err != nil {
		db.Rollback()
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db.Commit()

	resultOutputFunction(c, http.StatusOK, result, nil)
}

func processDelete(c *gin.Context,
	actualLogic func(*gorm.DB, string) error,
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {
	id := c.Params.ByName("id")

	db := dbpkg.DBInstance(c)

	db = db.Begin()
	err := actualLogic(db, id)
	if err != nil {
		db.Rollback()
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db.Commit()

	resultOutputFunction(c, http.StatusNoContent, nil, nil)
}
<commit_msg>Implement BindText<commit_after>package controllers

import (
	dbpkg "github.com/qb0C80aE/clay/db"
	"github.com/qb0C80aE/clay/helper"

	"encoding/json"
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"net/http"
	"bytes"
	"io/ioutil"
)

func BindJson(c *gin.Context, container interface{}) error {
	return c.Bind(container)
}

func BindText(c *gin.Context, container interface{}) error {
	buffer := container.(*bytes.Buffer)
	file, _, err := c.Request.FormFile("file")
	data, _ := ioutil.ReadAll(file)
	buffer.Write(data)
	return err
}

func OutputJsonError(c *gin.Context, code int, err error) {
	c.JSON(code, gin.H{"error": err.Error()})
}

func OutputSingleJsonResult(c *gin.Context, code int, result interface{}, fields map[string]interface{}) {
	if fields == nil {
		c.JSON(code, result)
	} else {
		fieldMap, err := helper.FieldToMap(result, fields)
		if err != nil {
			OutputJsonError(c, http.StatusBadRequest, err)
			return
		}

		if _, ok := c.GetQuery("pretty"); ok {
			c.IndentedJSON(code, fieldMap)
		} else {
			c.JSON(code, fieldMap)
		}
	}
}

func OutputMultiJsonResult(c *gin.Context, code int, result []interface{}, fields map[string]interface{}) {
	if fields == nil {
		c.JSON(code, result)
	} else {
		if _, ok := c.GetQuery("stream"); ok {
			enc := json.NewEncoder(c.Writer)
			c.Status(code)

			for _, item := range result {
				fieldMap, err := helper.FieldToMap(item, fields)

				if err != nil {
					OutputJsonError(c, http.StatusBadRequest, err)
					return
				}

				if err := enc.Encode(fieldMap); err != nil {
					OutputJsonError(c, http.StatusBadRequest, err)
					return
				}
			}
		} else {
			fieldMaps := []map[string]interface{}{}

			for _, item := range result {
				fieldMap, err := helper.FieldToMap(item, fields)

				if err != nil {
					OutputJsonError(c, http.StatusBadRequest, err)
					return
				}

				fieldMaps = append(fieldMaps, fieldMap)
			}

			if _, ok := c.GetQuery("pretty"); ok {
				c.IndentedJSON(code, fieldMaps)
			} else {
				c.JSON(code, fieldMaps)
			}
		}
	}
}

func OutputTextResult(c *gin.Context, code int, result interface{}, _ map[string]interface{}) {
	text := result.(string)
	c.String(code, text)
}

func OutputNothing(c *gin.Context, code int, _ interface{}, _ map[string]interface{}) {
	c.Writer.WriteHeader(code)
}

func processSingleGet(c *gin.Context,
	model interface{},
	actualLogic func(*gorm.DB, string, string) (interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {

	id := c.Params.ByName("id")
	db := dbpkg.DBInstance(c)
	db = dbpkg.SetPreloads(c.Query("preloads"), db)
	fields := helper.ParseFields(c.DefaultQuery("fields", "*"))
	queryFields := helper.QueryFields(model, fields)

	result, err := actualLogic(db, id, queryFields)
	if err != nil {
		errorOutputFunction(c, http.StatusNotFound, errors.New("item with id#"+id+" not found"))
		return
	}

	resultOutputFunction(c, http.StatusOK, result, fields)
}

func processMultiGet(c *gin.Context,
	model interface{},
	actualLogic func(*gorm.DB, string) ([]interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, []interface{}, map[string]interface{})) {

	db := dbpkg.DBInstance(c)
	db = dbpkg.SetPreloads(c.Query("preloads"), db)
	db = dbpkg.SortRecords(c.Query("sort"), db)
	db = dbpkg.FilterFields(c, model, db)
	fields := helper.ParseFields(c.DefaultQuery("fields", "*"))
	queryFields := helper.QueryFields(model, fields)

	result, err := actualLogic(db, queryFields)
	if err != nil {
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	resultOutputFunction(c, http.StatusOK, result, fields)
}

func processCreate(c *gin.Context,
	container interface{},
	binderFunction func(*gin.Context, interface{}) error,
	actualLogic func(*gorm.DB, interface{}) (interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {
	if err := binderFunction(c, container); err != nil {
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db := dbpkg.DBInstance(c)

	db = db.Begin()
	result, err := actualLogic(db, container)
	if err != nil {
		db.Rollback()
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db.Commit()

	resultOutputFunction(c, http.StatusCreated, result, nil)
}

func processUpdate(c *gin.Context,
	container interface{},
	binderFunction func(*gin.Context, interface{}) error,
	actualLogic func(*gorm.DB, string, interface{}) (interface{}, error),
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {
	id := c.Params.ByName("id")

	if err := binderFunction(c, container); err != nil {
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db := dbpkg.DBInstance(c)

	db = db.Begin()
	result, err := actualLogic(db, id, container)
	if err != nil {
		db.Rollback()
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db.Commit()

	resultOutputFunction(c, http.StatusOK, result, nil)
}

func processDelete(c *gin.Context,
	actualLogic func(*gorm.DB, string) error,
	errorOutputFunction func(*gin.Context, int, error),
	resultOutputFunction func(*gin.Context, int, interface{}, map[string]interface{})) {
	id := c.Params.ByName("id")

	db := dbpkg.DBInstance(c)

	db = db.Begin()
	err := actualLogic(db, id)
	if err != nil {
		db.Rollback()
		errorOutputFunction(c, http.StatusBadRequest, err)
		return
	}

	db.Commit()

	resultOutputFunction(c, http.StatusNoContent, nil, nil)
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"
	"os"
	"path"
	"reflect"
	"runtime"
	"strconv"
	"testing"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/rlp"
)

//var Logger logpkg.LogSystem

//var Log = logpkg.NewLogger("TEST")

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	//Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.DebugLevel)
	//logpkg.AddLogSystem(Logger)

	ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")

	db, err := ethdb.NewMemDatabase()
	if err != nil {
		panic("Could not create mem-db, failing")
	}
	ethutil.Config.Db = db
}

func loadChain(fn string, t *testing.T) (types.Blocks, error) {
	fh, err := os.OpenFile(path.Join("..", "_data", fn), os.O_RDONLY, os.ModePerm)
	if err != nil {
		return nil, err
	}
	defer fh.Close()

	var chain types.Blocks
	if err := rlp.Decode(fh, &chain); err != nil {
		return nil, err
	}

	return chain, nil
}

func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
	err := chainMan.InsertChain(chain)
	done <- true
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}
}

func TestChainInsertions(t *testing.T) {
	chain1, err := loadChain("valid1", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}
	fmt.Println(len(chain1))

	chain2, err := loadChain("valid2", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	var eventMux event.TypeMux
	chainMan := NewChainManager(&eventMux)
	txPool := NewTxPool(chainMan, &eventMux)
	blockMan := NewBlockManager(txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)

	const max = 2
	done := make(chan bool, max)

	go insertChain(done, chainMan, chain1, t)
	go insertChain(done, chainMan, chain2, t)

	for i := 0; i < max; i++ {
		<-done
	}

	if reflect.DeepEqual(chain2[len(chain2)-1], chainMan.CurrentBlock()) {
		t.Error("chain2 is canonical and shouldn't be")
	}

	if !reflect.DeepEqual(chain1[len(chain1)-1], chainMan.CurrentBlock()) {
		t.Error("chain1 isn't canonical and should be")
	}
}

func TestChainMultipleInsertions(t *testing.T) {
	const max = 4
	chains := make([]types.Blocks, max)
	var longest int
	for i := 0; i < max; i++ {
		var err error
		name := "valid" + strconv.Itoa(i+1)
		chains[i], err = loadChain(name, t)
		if len(chains[i]) >= len(chains[longest]) {
			longest = i
		}
		fmt.Println("loaded", name, "with a length of", len(chains[i]))
		if err != nil {
			fmt.Println(err)
			t.FailNow()
		}
	}

	var eventMux event.TypeMux
	chainMan := NewChainManager(&eventMux)
	txPool := NewTxPool(chainMan, &eventMux)
	blockMan := NewBlockManager(txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)
	done := make(chan bool, max)
	for i, chain := range chains {
		var i int = i
		go func() {
			insertChain(done, chainMan, chain, t)
			fmt.Println(i, "done")
		}()
	}

	for i := 0; i < max; i++ {
		<-done
	}

	if !reflect.DeepEqual(chains[longest][len(chains[longest])-1], chainMan.CurrentBlock()) {
		t.Error("Invalid canonical chain")
	}
}
<commit_msg>Fixed tests<commit_after>package core

import (
	"fmt"
	"os"
	"path"
	"reflect"
	"runtime"
	"strconv"
	"testing"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/rlp"
)

//var Logger logpkg.LogSystem

//var Log = logpkg.NewLogger("TEST")

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	//Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.DebugLevel)
	//logpkg.AddLogSystem(Logger)

	ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")

}

func reset() {
	db, err := ethdb.NewMemDatabase()
	if err != nil {
		panic("Could not create mem-db, failing")
	}
	ethutil.Config.Db = db
}

func loadChain(fn string, t *testing.T) (types.Blocks, error) {
	fh, err := os.OpenFile(path.Join("..", "_data", fn), os.O_RDONLY, os.ModePerm)
	if err != nil {
		return nil, err
	}
	defer fh.Close()

	var chain types.Blocks
	if err := rlp.Decode(fh, &chain); err != nil {
		return nil, err
	}

	return chain, nil
}

func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
	err := chainMan.InsertChain(chain)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}
	done <- true
}

func TestChainInsertions(t *testing.T) {
	reset()

	chain1, err := loadChain("valid1", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	chain2, err := loadChain("valid2", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	var eventMux event.TypeMux
	chainMan := NewChainManager(&eventMux)
	txPool := NewTxPool(chainMan, &eventMux)
	blockMan := NewBlockManager(txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)

	const max = 2
	done := make(chan bool, max)

	go insertChain(done, chainMan, chain1, t)
	go insertChain(done, chainMan, chain2, t)

	for i := 0; i < max; i++ {
		<-done
	}

	if reflect.DeepEqual(chain2[len(chain2)-1], chainMan.CurrentBlock()) {
		t.Error("chain2 is canonical and shouldn't be")
	}

	if !reflect.DeepEqual(chain1[len(chain1)-1], chainMan.CurrentBlock()) {
		t.Error("chain1 isn't canonical and should be")
	}
}

func TestChainMultipleInsertions(t *testing.T) {
	reset()

	const max = 4
	chains := make([]types.Blocks, max)
	var longest int
	for i := 0; i < max; i++ {
		var err error
		name := "valid" + strconv.Itoa(i+1)
		chains[i], err = loadChain(name, t)
		if len(chains[i]) >= len(chains[longest]) {
			longest = i
		}
		fmt.Println("loaded", name, "with a length of", len(chains[i]))
		if err != nil {
			fmt.Println(err)
			t.FailNow()
		}
	}
	var eventMux event.TypeMux
	chainMan := NewChainManager(&eventMux)
	txPool := NewTxPool(chainMan, &eventMux)
	blockMan := NewBlockManager(txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)
	done := make(chan bool, max)
	for i, chain := range chains {
		// XXX the go routine would otherwise reference the same (chain[3]) variable and fail
		i := i
		chain := chain
		go func() {
			insertChain(done, chainMan, chain, t)
			fmt.Println(i, "done")
		}()
	}

	for i := 0; i < max; i++ {
		<-done
	}

	if !reflect.DeepEqual(chains[longest][len(chains[longest])-1], chainMan.CurrentBlock()) {
		t.Error("Invalid canonical chain")
	}
}
<|endoftext|>


<commit_before>package core

import (
	"bytes"
	"fmt"
	"os"
	"path"
	"runtime"
	"strconv"
	"testing"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/rlp"
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")
}

func loadChain(fn string, t *testing.T) (types.Blocks, error) {
	fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm)
	if err != nil {
		return nil, err
	}
	defer fh.Close()

	var chain types.Blocks
	if err := rlp.Decode(fh, &chain); err != nil {
		return nil, err
	}

	return chain, nil
}

func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
	err := chainMan.InsertChain(chain)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}
	done <- true
}

func TestChainInsertions(t *testing.T) {
	db, _ := ethdb.NewMemDatabase()

	chain1, err := loadChain("valid1", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	chain2, err := loadChain("valid2", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	var eventMux event.TypeMux
	chainMan := NewChainManager(db, &eventMux)
	txPool := NewTxPool(&eventMux)
	blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)

	const max = 2
	done := make(chan bool, max)

	go insertChain(done, chainMan, chain1, t)
	go insertChain(done, chainMan, chain2, t)

	for i := 0; i < max; i++ {
		<-done
	}

	if bytes.Equal(chain2[len(chain2)-1].Hash(), chainMan.CurrentBlock().Hash()) {
		t.Error("chain2 is canonical and shouldn't be")
	}

	if !bytes.Equal(chain1[len(chain1)-1].Hash(), chainMan.CurrentBlock().Hash()) {
		t.Error("chain1 isn't canonical and should be")
	}
}

func TestChainMultipleInsertions(t *testing.T) {
	db, _ := ethdb.NewMemDatabase()

	const max = 4
	chains := make([]types.Blocks, max)
	var longest int
	for i := 0; i < max; i++ {
		var err error
		name := "valid" + strconv.Itoa(i+1)
		chains[i], err = loadChain(name, t)
		if len(chains[i]) >= len(chains[longest]) {
			longest = i
		}
		fmt.Println("loaded", name, "with a length of", len(chains[i]))
		if err != nil {
			fmt.Println(err)
			t.FailNow()
		}
	}
	var eventMux event.TypeMux
	chainMan := NewChainManager(db, &eventMux)
	txPool := NewTxPool(&eventMux)
	blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)
	done := make(chan bool, max)
	for i, chain := range chains {
		// XXX the go routine would otherwise reference the same (chain[3]) variable and fail
		i := i
		chain := chain
		go func() {
			insertChain(done, chainMan, chain, t)
			fmt.Println(i, "done")
		}()
	}

	for i := 0; i < max; i++ {
		<-done
	}

	if !bytes.Equal(chains[longest][len(chains[longest])-1].Hash(), chainMan.CurrentBlock().Hash()) {
		t.Error("Invalid canonical chain")
	}
}

func TestGetAncestors(t *testing.T) {
	db, _ := ethdb.NewMemDatabase()
	var eventMux event.TypeMux
	chainMan := NewChainManager(db, &eventMux)
	chain, err := loadChain("valid1", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	for _, block := range chain {
		chainMan.write(block)
	}

	ancestors := chainMan.GetAncestors(chain[len(chain)-1], 4)
	fmt.Println(ancestors)
}
<commit_msg>skipping for travis<commit_after>package core

import (
	"bytes"
	"fmt"
	"os"
	"path"
	"runtime"
	"strconv"
	"testing"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/rlp"
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")
}

func loadChain(fn string, t *testing.T) (types.Blocks, error) {
	fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm)
	if err != nil {
		return nil, err
	}
	defer fh.Close()

	var chain types.Blocks
	if err := rlp.Decode(fh, &chain); err != nil {
		return nil, err
	}

	return chain, nil
}

func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
	err := chainMan.InsertChain(chain)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}
	done <- true
}

func TestChainInsertions(t *testing.T) {
	t.Skip() // travil fails.

	db, _ := ethdb.NewMemDatabase()

	chain1, err := loadChain("valid1", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	chain2, err := loadChain("valid2", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	var eventMux event.TypeMux
	chainMan := NewChainManager(db, &eventMux)
	txPool := NewTxPool(&eventMux)
	blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)

	const max = 2
	done := make(chan bool, max)

	go insertChain(done, chainMan, chain1, t)
	go insertChain(done, chainMan, chain2, t)

	for i := 0; i < max; i++ {
		<-done
	}

	if bytes.Equal(chain2[len(chain2)-1].Hash(), chainMan.CurrentBlock().Hash()) {
		t.Error("chain2 is canonical and shouldn't be")
	}

	if !bytes.Equal(chain1[len(chain1)-1].Hash(), chainMan.CurrentBlock().Hash()) {
		t.Error("chain1 isn't canonical and should be")
	}
}

func TestChainMultipleInsertions(t *testing.T) {
	t.Skip() // travil fails.

	db, _ := ethdb.NewMemDatabase()

	const max = 4
	chains := make([]types.Blocks, max)
	var longest int
	for i := 0; i < max; i++ {
		var err error
		name := "valid" + strconv.Itoa(i+1)
		chains[i], err = loadChain(name, t)
		if len(chains[i]) >= len(chains[longest]) {
			longest = i
		}
		fmt.Println("loaded", name, "with a length of", len(chains[i]))
		if err != nil {
			fmt.Println(err)
			t.FailNow()
		}
	}
	var eventMux event.TypeMux
	chainMan := NewChainManager(db, &eventMux)
	txPool := NewTxPool(&eventMux)
	blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux)
	chainMan.SetProcessor(blockMan)
	done := make(chan bool, max)
	for i, chain := range chains {
		// XXX the go routine would otherwise reference the same (chain[3]) variable and fail
		i := i
		chain := chain
		go func() {
			insertChain(done, chainMan, chain, t)
			fmt.Println(i, "done")
		}()
	}

	for i := 0; i < max; i++ {
		<-done
	}

	if !bytes.Equal(chains[longest][len(chains[longest])-1].Hash(), chainMan.CurrentBlock().Hash()) {
		t.Error("Invalid canonical chain")
	}
}

func TestGetAncestors(t *testing.T) {
	db, _ := ethdb.NewMemDatabase()
	var eventMux event.TypeMux
	chainMan := NewChainManager(db, &eventMux)
	chain, err := loadChain("valid1", t)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	for _, block := range chain {
		chainMan.write(block)
	}

	ancestors := chainMan.GetAncestors(chain[len(chain)-1], 4)
	fmt.Println(ancestors)
}
<|endoftext|>