<commit_before>package mackerel

// CheckStatus represents check monitoring status
type CheckStatus string

// CheckStatuses
const (
	CheckStatusOK       CheckStatus = "OK"
	CheckStatusWarning  CheckStatus = "WARNING"
	CheckStatusCritical CheckStatus = "CRITICAL"
	CheckStatusUnknown  CheckStatus = "UNKNOWN"
)

// CheckReport represents a report of check monitoring
type CheckReport struct {
	Source               CheckSource `json:"source"`
	Name                 string      `json:"name"`
	Status               CheckStatus `json:"status"`
	Message              string      `json:"message"`
	OccurredAt           int64       `json:"occurredAt"`
	NotificationInterval uint        `json:"notificationInterval,omitempty"`
	MaxCheckAttempts     uint        `json:"maxCheckAttempts,omitempty"`
}

// CheckSource represents interface to which each check source type must confirm to
type CheckSource interface {
	CheckType() string

	isCheck()
}

const checkTypeHost = "host"

// Ensure each check type conforms to the CheckSource interface.
var _ CheckSource = (*checkSourceHost)(nil)

// Ensure only checkSource types defined in this package can be assigned to the
// CheckSource interface.
func (cs *checkSourceHost) isCheck() {}

type checkSourceHost struct {
	Type   string `json:"type"`
	HostID string `json:"hostId"`
}

// CheckType is for satisfying CheckSource interface
func (cs *checkSourceHost) CheckType() string {
	return checkTypeHost
}

// NewCheckSourceHost returns new CheckSource which check type is "host"
func NewCheckSourceHost(hostID string) CheckSource {
	return &checkSourceHost{
		Type:   checkTypeHost,
		HostID: hostID,
	}
}

// CheckReports represents check reports for API
type CheckReports struct {
	Reports []*CheckReport `json:"reports"`
}

// ReportCheckMonitors reports check monitoring results
func (c *Client) ReportCheckMonitors(crs *CheckReports) error {
	resp, err := c.PostJSON("/api/v0/monitoring/checks/report", crs)
	defer closeResponse(resp)
	return err
}
<commit_msg>s/isCheck/isCheckSource/g<commit_after>package mackerel

// CheckStatus represents check monitoring status
type CheckStatus string

// CheckStatuses
const (
	CheckStatusOK       CheckStatus = "OK"
	CheckStatusWarning  CheckStatus = "WARNING"
	CheckStatusCritical CheckStatus = "CRITICAL"
	CheckStatusUnknown  CheckStatus = "UNKNOWN"
)

// CheckReport represents a report of check monitoring
type CheckReport struct {
	Source               CheckSource `json:"source"`
	Name                 string      `json:"name"`
	Status               CheckStatus `json:"status"`
	Message              string      `json:"message"`
	OccurredAt           int64       `json:"occurredAt"`
	NotificationInterval uint        `json:"notificationInterval,omitempty"`
	MaxCheckAttempts     uint        `json:"maxCheckAttempts,omitempty"`
}

// CheckSource represents interface to which each check source type must confirm to
type CheckSource interface {
	CheckType() string

	isCheckSource()
}

const checkTypeHost = "host"

// Ensure each check type conforms to the CheckSource interface.
var _ CheckSource = (*checkSourceHost)(nil)

// Ensure only checkSource types defined in this package can be assigned to the
// CheckSource interface.
func (cs *checkSourceHost) isCheckSource() {}

type checkSourceHost struct {
	Type   string `json:"type"`
	HostID string `json:"hostId"`
}

// CheckType is for satisfying CheckSource interface
func (cs *checkSourceHost) CheckType() string {
	return checkTypeHost
}

// NewCheckSourceHost returns new CheckSource which check type is "host"
func NewCheckSourceHost(hostID string) CheckSource {
	return &checkSourceHost{
		Type:   checkTypeHost,
		HostID: hostID,
	}
}

// CheckReports represents check reports for API
type CheckReports struct {
	Reports []*CheckReport `json:"reports"`
}

// ReportCheckMonitors reports check monitoring results
func (c *Client) ReportCheckMonitors(crs *CheckReports) error {
	resp, err := c.PostJSON("/api/v0/monitoring/checks/report", crs)
	defer closeResponse(resp)
	return err
}
<|endoftext|>


<commit_before>package sensu

import "fmt"

// GetChecks Return the list of checks
func (s *Sensu) GetChecks() ([]interface{}, error) {
	return s.Get("checks")
}

// GetCheck Return check info
func (s *Sensu) GetCheck(check string) ([]interface{}, error) {
	return s.Get(fmt.Sprintf("check/%s", check))
}

// RequestCheck Issues a check request
func (s *Sensu) RequestCheck(check string) ([]interface{}, error) {
	return s.Post(fmt.Sprintf("check/request"))
}
<commit_msg>reword comment<commit_after>package sensu

import "fmt"

// GetChecks Return the list of checks
func (s *Sensu) GetChecks() ([]interface{}, error) {
	return s.Get("checks")
}

// GetCheck Return check info for a specific check
func (s *Sensu) GetCheck(check string) ([]interface{}, error) {
	return s.Get(fmt.Sprintf("check/%s", check))
}

// RequestCheck Issues a check request
func (s *Sensu) RequestCheck(check string) ([]interface{}, error) {
	return s.Post(fmt.Sprintf("check/request"))
}
<|endoftext|>


<commit_before>//
// Copyright 2014, Sander van Harmelen
//
// 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 main

import (
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

func (cg *ChefGuard) executeChecks() (int, error) {
	if cfg.Tests.Foodcritic != "" {
		if errCode, err := runFoodcritic(cg.ChefOrg, cg.CookbookPath); err != nil {
			if errCode == http.StatusInternalServerError || !cg.continueAfterFailedCheck("foodcritic") {
				return errCode, err
			}
		}
	}
	if cfg.Tests.Rubocop != "" {
		if errCode, err := runRubocop(cg.CookbookPath); err != nil {
			if errCode == http.StatusInternalServerError || !cg.continueAfterFailedCheck("rubocop") {
				return errCode, err
			}
		}
	}
	return 0, nil
}

func (cg *ChefGuard) continueAfterFailedCheck(check string) bool {
	WARNING.Printf("%s errors when uploading cookbook '%s' for '%s'\n", strings.Title(check), cg.Cookbook.Name, cg.User)
	if getEffectiveConfig("Mode", cg.ChefOrg).(string) == "permissive" && cg.ForcedUpload {
		return true
	}
	return false
}

func runFoodcritic(org, cookbookPath string) (int, error) {
	args := getFoodcriticArgs(org, cookbookPath)
	cmd := exec.Command(cfg.Tests.Foodcritic, args...)

	cmd.Env = os.Environ()
	cmd.Env = append(cmd.Env, "RUBY_THREAD_VM_STACK_SIZE=2097152")

	output, err := cmd.CombinedOutput()
	if err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 3 {
				errText := strings.TrimSpace(strings.Replace(string(output), fmt.Sprintf("%s/", cookbookPath), "", -1))
				return http.StatusPreconditionFailed, fmt.Errorf("\n=== Foodcritic errors found ===\n%s\n===============================\n", errText)
			}
		}

		return http.StatusInternalServerError, fmt.Errorf("Failed to execute \"foodcritic %s\": %s - %s", strings.Join(cmd.Args, " "), output, err)
	}

	// This is still needed for Foodcritic > v9.x.x
	if strings.TrimSpace(string(output)) != "" {
		errText := strings.TrimSpace(strings.Replace(string(output), fmt.Sprintf("%s/", cookbookPath), "", -1))
		return http.StatusPreconditionFailed, fmt.Errorf("\n=== Foodcritic errors found ===\n%s\n===============================\n", errText)
	}

	return 0, nil
}

func getFoodcriticArgs(org, cookbookPath string) []string {
	excludes := cfg.Default.ExcludeFCs
	custExcludes := getEffectiveConfig("ExcludeFCs", org)
	if excludes != custExcludes {
		excludes = fmt.Sprintf("%s,%s", excludes, custExcludes)
	}
	args := []string{}
	if excludes != "" {
		args = append(args, "--tags", "~"+strings.Replace(excludes, ",", ",~", -1))
	}
	if cfg.Default.IncludeFCs != "" {
		args = append(args, "--include", cfg.Default.IncludeFCs)
	}
	return append(args, "--no-progress", "--cookbook-path", cookbookPath)
}

func runRubocop(cookbookPath string) (int, error) {
	cmd := exec.Command(cfg.Tests.Rubocop, cookbookPath)
	cmd.Env = []string{"HOME=" + cfg.Default.Tempdir}
	output, err := cmd.CombinedOutput()
	if err != nil {
		if strings.Contains(string(output), "offense") {
			errText := strings.TrimSpace(strings.Replace(string(output), fmt.Sprintf("%s/", cookbookPath), "", -1))
			return http.StatusPreconditionFailed, fmt.Errorf("\n=== Rubocop errors found ===\n%s\n============================\n", errText)
		}
		return http.StatusInternalServerError, fmt.Errorf("Failed to execute \"rubocop %s\": %s - %s", cookbookPath, output, err)
	}
	return 0, nil
}
<commit_msg>Properly exclude foodcritic checks<commit_after>//
// Copyright 2014, Sander van Harmelen
//
// 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 main

import (
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

func (cg *ChefGuard) executeChecks() (int, error) {
	if cfg.Tests.Foodcritic != "" {
		if errCode, err := runFoodcritic(cg.ChefOrg, cg.CookbookPath); err != nil {
			if errCode == http.StatusInternalServerError || !cg.continueAfterFailedCheck("foodcritic") {
				return errCode, err
			}
		}
	}
	if cfg.Tests.Rubocop != "" {
		if errCode, err := runRubocop(cg.CookbookPath); err != nil {
			if errCode == http.StatusInternalServerError || !cg.continueAfterFailedCheck("rubocop") {
				return errCode, err
			}
		}
	}
	return 0, nil
}

func (cg *ChefGuard) continueAfterFailedCheck(check string) bool {
	WARNING.Printf("%s errors when uploading cookbook '%s' for '%s'\n", strings.Title(check), cg.Cookbook.Name, cg.User)
	if getEffectiveConfig("Mode", cg.ChefOrg).(string) == "permissive" && cg.ForcedUpload {
		return true
	}
	return false
}

func runFoodcritic(org, cookbookPath string) (int, error) {
	args := getFoodcriticArgs(org, cookbookPath)
	cmd := exec.Command(cfg.Tests.Foodcritic, args...)

	cmd.Env = os.Environ()
	cmd.Env = append(cmd.Env, "RUBY_THREAD_VM_STACK_SIZE=2097152")

	output, err := cmd.CombinedOutput()
	if err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 3 {
				errText := strings.TrimSpace(strings.Replace(string(output), fmt.Sprintf("%s/", cookbookPath), "", -1))
				return http.StatusPreconditionFailed, fmt.Errorf("\n=== Foodcritic errors found ===\n%s\n===============================\n", errText)
			}
		}

		return http.StatusInternalServerError, fmt.Errorf("Failed to execute \"foodcritic %s\": %s - %s", strings.Join(cmd.Args, " "), output, err)
	}

	// This is still needed for Foodcritic > v9.x.x
	if strings.TrimSpace(string(output)) != "" {
		errText := strings.TrimSpace(strings.Replace(string(output), fmt.Sprintf("%s/", cookbookPath), "", -1))
		return http.StatusPreconditionFailed, fmt.Errorf("\n=== Foodcritic errors found ===\n%s\n===============================\n", errText)
	}

	return 0, nil
}

func getFoodcriticArgs(org, cookbookPath string) []string {
	excludes := cfg.Default.ExcludeFCs
	custExcludes := getEffectiveConfig("ExcludeFCs", org)
	if excludes != custExcludes {
		excludes = fmt.Sprintf("%s,%s", excludes, custExcludes)
	}
	args := []string{}
	for _, exclude := range strings.Split(excludes, ",") {
		args = append(args, "--tags", "~"+exclude)
	}
	if cfg.Default.IncludeFCs != "" {
		args = append(args, "--include", cfg.Default.IncludeFCs)
	}
	return append(args, "--no-progress", "--cookbook-path", cookbookPath)
}

func runRubocop(cookbookPath string) (int, error) {
	cmd := exec.Command(cfg.Tests.Rubocop, cookbookPath)
	cmd.Env = []string{"HOME=" + cfg.Default.Tempdir}
	output, err := cmd.CombinedOutput()
	if err != nil {
		if strings.Contains(string(output), "offense") {
			errText := strings.TrimSpace(strings.Replace(string(output), fmt.Sprintf("%s/", cookbookPath), "", -1))
			return http.StatusPreconditionFailed, fmt.Errorf("\n=== Rubocop errors found ===\n%s\n============================\n", errText)
		}
		return http.StatusInternalServerError, fmt.Errorf("Failed to execute \"rubocop %s\": %s - %s", cookbookPath, output, err)
	}
	return 0, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 - The Event Horizon 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 eventstore

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"testing"
	"time"

	eh "github.com/looplab/eventhorizon"
	"github.com/looplab/eventhorizon/mocks"
	"github.com/looplab/eventhorizon/uuid"
)

// AcceptanceTest is the acceptance test that all implementations of EventStore
// should pass. It should manually be called from a test case in each
// implementation:
//
//   func TestEventStore(t *testing.T) {
//       store := NewEventStore()
//       eventstore.AcceptanceTest(t, store, context.Background())
//   }
//
func AcceptanceTest(t *testing.T, store eh.EventStore, ctx context.Context) []eh.Event {
	savedEvents := []eh.Event{}

	type contextKey string
	ctx = context.WithValue(ctx, contextKey("testkey"), "testval")

	// Save no events.
	err := store.Save(ctx, []eh.Event{}, 0)
	eventStoreErr := &eh.EventStoreError{}
	if !errors.As(err, &eventStoreErr) || eventStoreErr.Err.Error() != "no events" {
		t.Error("there should be a event store error:", err)
	}

	// Save event, version 1.
	id := uuid.New()
	timestamp := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	event1 := eh.NewEvent(mocks.EventType, &mocks.EventData{Content: "event1"}, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 1))
	err = store.Save(ctx, []eh.Event{event1}, 0)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event1)
	// if val, ok := agg.Context.Value("testkey").(string); !ok || val != "testval" {
	// 	t.Error("the context should be correct:", agg.Context)
	// }

	// Try to save same event twice.
	err = store.Save(ctx, []eh.Event{event1}, 1)
	eventStoreErr = &eh.EventStoreError{}
	if !errors.As(err, &eventStoreErr) || eventStoreErr.Err.Error() != "invalid event version" {
		t.Error("there should be a event store error:", err)
	}

	// Save event, version 2, with metadata.
	event2 := eh.NewEvent(mocks.EventType, &mocks.EventData{Content: "event2"}, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 2),
		eh.WithMetadata(map[string]interface{}{"meta": "data", "num": 42.0}),
	)
	err = store.Save(ctx, []eh.Event{event2}, 1)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event2)

	// Save event without data, version 3.
	event3 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 3))
	err = store.Save(ctx, []eh.Event{event3}, 2)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event3)

	// Save multiple events, version 4,5 and 6.
	event4 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 4))
	event5 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 5))
	event6 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 6))
	err = store.Save(ctx, []eh.Event{event4, event5, event6}, 3)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event4, event5, event6)

	// Save event for another aggregate.
	id2 := uuid.New()
	event7 := eh.NewEvent(mocks.EventType, &mocks.EventData{Content: "event7"}, timestamp,
		eh.ForAggregate(mocks.AggregateType, id2, 1))
	err = store.Save(ctx, []eh.Event{event7}, 0)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event7)

	// Load events for non-existing aggregate.
	events, err := store.Load(ctx, uuid.New())
	eventStoreErr = &eh.EventStoreError{}
	if !errors.As(err, &eventStoreErr) || !errors.Is(err, eh.ErrAggregateNotFound) {
		t.Error("there should be a not found error:", err)
	}
	if len(events) != 0 {
		t.Error("there should be no loaded events:", eventsToString(events))
	}

	// Load events.
	events, err = store.Load(ctx, id)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	expectedEvents := []eh.Event{
		event1,                 // Version 1
		event2,                 // Version 2
		event3,                 // Version 3
		event4, event5, event6, // Version 4, 5 and 6
	}
	if len(events) != len(expectedEvents) {
		t.Errorf("incorrect number of loaded events: %d", len(events))
	}
	for i, event := range events {
		if err := eh.CompareEvents(event, expectedEvents[i],
			eh.IgnoreVersion(),
			eh.IgnorePositionMetadata(),
		); err != nil {
			t.Error("the event was incorrect:", err)
		}
		if event.Version() != i+1 {
			t.Error("the event version should be correct:", event, event.Version())
		}
	}

	// Load events for another aggregate.
	events, err = store.Load(ctx, id2)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	expectedEvents = []eh.Event{event7}
	if len(events) != len(expectedEvents) {
		t.Errorf("incorrect number of loaded events: %d", len(events))
	}
	for i, event := range events {
		if err := eh.CompareEvents(event, expectedEvents[i],
			eh.IgnoreVersion(),
			eh.IgnorePositionMetadata(),
		); err != nil {
			t.Error("the event was incorrect:", err)
		}
		if event.Version() != i+1 {
			t.Error("the event version should be correct:", event, event.Version())
		}
	}

	return savedEvents
}

func eventsToString(events []eh.Event) string {
	parts := make([]string, len(events))
	for i, e := range events {
		parts[i] = fmt.Sprintf("%s:%s (%s@%d)",
			e.AggregateType(), e.EventType(),
			e.AggregateID(), e.Version())
	}
	return strings.Join(parts, ", ")
}
<commit_msg>fix: Improve event store testing<commit_after>// Copyright (c) 2016 - The Event Horizon 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 eventstore

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"testing"
	"time"

	eh "github.com/looplab/eventhorizon"
	"github.com/looplab/eventhorizon/mocks"
	"github.com/looplab/eventhorizon/uuid"
)

// AcceptanceTest is the acceptance test that all implementations of EventStore
// should pass. It should manually be called from a test case in each
// implementation:
//
//   func TestEventStore(t *testing.T) {
//       store := NewEventStore()
//       eventstore.AcceptanceTest(t, store, context.Background())
//   }
//
func AcceptanceTest(t *testing.T, store eh.EventStore, ctx context.Context) []eh.Event {
	savedEvents := []eh.Event{}

	type contextKey string
	ctx = context.WithValue(ctx, contextKey("testkey"), "testval")

	// Save no events.
	err := store.Save(ctx, []eh.Event{}, 0)
	eventStoreErr := &eh.EventStoreError{}
	if !errors.As(err, &eventStoreErr) || eventStoreErr.Err.Error() != "no events" {
		t.Error("there should be a event store error:", err)
	}

	// Save event, version 1.
	id := uuid.New()
	timestamp := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	event1 := eh.NewEvent(mocks.EventType, &mocks.EventData{Content: "event1"}, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 1))
	err = store.Save(ctx, []eh.Event{event1}, 0)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event1)
	// if val, ok := agg.Context.Value("testkey").(string); !ok || val != "testval" {
	// 	t.Error("the context should be correct:", agg.Context)
	// }

	// Try to save same event twice.
	err = store.Save(ctx, []eh.Event{event1}, 1)
	eventStoreErr = &eh.EventStoreError{}
	if !errors.As(err, &eventStoreErr) || eventStoreErr.Err.Error() != "invalid event version" {
		t.Error("there should be a event store error:", err)
	}

	// Save event, version 2, with metadata.
	event2 := eh.NewEvent(mocks.EventType, &mocks.EventData{Content: "event2"}, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 2),
		eh.WithMetadata(map[string]interface{}{"meta": "data", "num": 42.0}),
	)
	err = store.Save(ctx, []eh.Event{event2}, 1)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event2)

	// Save event without data, version 3.
	event3 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 3))
	err = store.Save(ctx, []eh.Event{event3}, 2)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event3)

	// Save multiple events, version 4,5 and 6.
	event4 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 4))
	event5 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 5))
	event6 := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 6))
	err = store.Save(ctx, []eh.Event{event4, event5, event6}, 3)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event4, event5, event6)

	// Save event for different aggregate IDs.
	eventSameAggID := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 7))
	eventOtherAggID := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, uuid.New(), 8))
	err = store.Save(ctx, []eh.Event{eventSameAggID, eventOtherAggID}, 6)
	if !errors.As(err, &eventStoreErr) || eventStoreErr.Err.Error() != "event has different aggregate ID" {
		t.Error("there should be a event store error:", err)
	}

	// Save event of different aggregate types.
	eventSameAggType := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(mocks.AggregateType, id, 7))
	eventOtherAggType := eh.NewEvent(mocks.EventOtherType, nil, timestamp,
		eh.ForAggregate(eh.AggregateType("OtherAggregate"), id, 8))
	err = store.Save(ctx, []eh.Event{eventSameAggType, eventOtherAggType}, 6)
	if !errors.As(err, &eventStoreErr) || eventStoreErr.Err.Error() != "event has different aggregate type" {
		t.Error("there should be a event store error:", err)
	}

	// Save event for another aggregate.
	id2 := uuid.New()
	event7 := eh.NewEvent(mocks.EventType, &mocks.EventData{Content: "event7"}, timestamp,
		eh.ForAggregate(mocks.AggregateType, id2, 1))
	err = store.Save(ctx, []eh.Event{event7}, 0)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	savedEvents = append(savedEvents, event7)

	// Load events for non-existing aggregate.
	events, err := store.Load(ctx, uuid.New())
	eventStoreErr = &eh.EventStoreError{}
	if !errors.As(err, &eventStoreErr) || !errors.Is(err, eh.ErrAggregateNotFound) {
		t.Error("there should be a not found error:", err)
	}
	if len(events) != 0 {
		t.Error("there should be no loaded events:", eventsToString(events))
	}

	// Load events.
	events, err = store.Load(ctx, id)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	expectedEvents := []eh.Event{
		event1,                 // Version 1
		event2,                 // Version 2
		event3,                 // Version 3
		event4, event5, event6, // Version 4, 5 and 6
	}
	if len(events) != len(expectedEvents) {
		t.Errorf("incorrect number of loaded events: %d", len(events))
	}
	for i, event := range events {
		if err := eh.CompareEvents(event, expectedEvents[i],
			eh.IgnoreVersion(),
			eh.IgnorePositionMetadata(),
		); err != nil {
			t.Error("the event was incorrect:", err)
		}
		if event.Version() != i+1 {
			t.Error("the event version should be correct:", event, event.Version())
		}
	}

	// Load events for another aggregate.
	events, err = store.Load(ctx, id2)
	if err != nil {
		t.Error("there should be no error:", err)
	}
	expectedEvents = []eh.Event{event7}
	if len(events) != len(expectedEvents) {
		t.Errorf("incorrect number of loaded events: %d", len(events))
	}
	for i, event := range events {
		if err := eh.CompareEvents(event, expectedEvents[i],
			eh.IgnoreVersion(),
			eh.IgnorePositionMetadata(),
		); err != nil {
			t.Error("the event was incorrect:", err)
		}
		if event.Version() != i+1 {
			t.Error("the event version should be correct:", event, event.Version())
		}
	}

	return savedEvents
}

func eventsToString(events []eh.Event) string {
	parts := make([]string, len(events))
	for i, e := range events {
		parts[i] = fmt.Sprintf("%s:%s (%s@%d)",
			e.AggregateType(), e.EventType(),
			e.AggregateID(), e.Version())
	}
	return strings.Join(parts, ", ")
}
<|endoftext|>


<commit_before>package sqlz

import (
	"context"
	"database/sql"
	"fmt"
	"strings"

	"github.com/jmoiron/sqlx"
)

// UpdateStmt represents an UPDATE statement
type UpdateStmt struct {
	*Statement
	Table           string
	Updates         map[string]interface{}
	Conditions      []WhereCondition
	Return          []string
	execer          Ext
	SelectStmt      *SelectStmt
	SelectStmtAlias string
}

// Update creates a new UpdateStmt object for
// the specified table
func (db *DB) Update(table string) *UpdateStmt {
	return &UpdateStmt{
		Table:     table,
		Updates:   make(map[string]interface{}),
		execer:    db.DB,
		Statement: &Statement{db.ErrHandlers},
	}
}

// Update creates a new UpdateStmt object for
// the specified table
func (tx *Tx) Update(table string) *UpdateStmt {
	return &UpdateStmt{
		Table:     table,
		Updates:   make(map[string]interface{}),
		execer:    tx.Tx,
		Statement: &Statement{tx.ErrHandlers},
	}
}

// Set receives the name of a column and a new value. Multiple calls to Set
// can be chained together to modify multiple columns. Set can also be chained
// with calls to SetMap
func (stmt *UpdateStmt) Set(col string, value interface{}) *UpdateStmt {
	return stmt.SetIf(col, value, true)
}

// SetMap receives a map of columns and values. Multiple calls to both Set and
// SetMap can be chained to modify multiple columns.
func (stmt *UpdateStmt) SetMap(updates map[string]interface{}) *UpdateStmt {
	for col, value := range updates {
		stmt.Updates[col] = value
	}

	return stmt
}

// SetIf is the same as Set, but also accepts a boolean value and only does
// anything if that value is true. This is a convenience method so that
// conditional updates can be made without having to save the UpdateStmt into
// a variable and using if statements
func (stmt *UpdateStmt) SetIf(col string, value interface{}, b bool) *UpdateStmt {
	if b {
		stmt.Updates[col] = value
	}

	return stmt
}

// Where creates one or more WHERE conditions for the UPDATE statement.
// If multiple conditions are passed, they are considered AND conditions.
func (stmt *UpdateStmt) Where(conditions ...WhereCondition) *UpdateStmt {
	stmt.Conditions = append(stmt.Conditions, conditions...)
	return stmt
}

// Returning sets a RETURNING clause to receive values back from the
// database once executing the UPDATE statement. Note that GetRow or
// GetAll must be used to execute the query rather than Exec to get
// back the values.
func (stmt *UpdateStmt) Returning(cols ...string) *UpdateStmt {
	stmt.Return = append(stmt.Return, cols...)
	return stmt
}

// FromSelect allows creating update statements that takes values from the
// result of a select statement.
func (stmt *UpdateStmt) FromSelect(selStmt *SelectStmt, alias string) *UpdateStmt {
	stmt.SelectStmt = selStmt
	stmt.SelectStmtAlias = alias

	return stmt
}

// ToSQL generates the UPDATE statement's SQL and returns a list of
// bindings. It is used internally by Exec, GetRow and GetAll, but is
// exported if you wish to use it directly.
func (stmt *UpdateStmt) ToSQL(rebind bool) (asSQL string, bindings []interface{}) {
	var clauses = []string{fmt.Sprintf("UPDATE %s", stmt.Table)}

	var updates []string

	// sort updates by column for reproducibility
	for _, col := range sortKeys(stmt.Updates) {
		val := stmt.Updates[col]
		if fn, isFn := val.(UpdateFunction); isFn {
			var args []string

			for _, arg := range fn.Arguments {
				if indirect, isIndirect := arg.(IndirectValue); isIndirect {
					args = append(args, indirect.Reference)
					bindings = append(bindings, indirect.Bindings...)
				} else {
					args = append(args, "?")
					bindings = append(bindings, arg)
				}
			}

			updates = append(updates, col+" = "+fn.Name+"("+strings.Join(args, ", ")+")")
		} else if indirect, isIndirect := val.(IndirectValue); isIndirect {
			updates = append(updates, col+" = "+indirect.Reference)
			bindings = append(bindings, indirect.Bindings...)
		} else {
			updates = append(updates, col+" = ?")
			bindings = append(bindings, val)
		}
	}

	clauses = append(clauses, "SET "+strings.Join(updates, ", "))

	if stmt.SelectStmt != nil && stmt.SelectStmtAlias != "" {
		selectSQL, selectBindings := stmt.SelectStmt.ToSQL(false)
		selectSQL = "(" + selectSQL + ") AS " + stmt.SelectStmtAlias + " "

		clauses = append(clauses, "FROM ")
		clauses = append(clauses, selectSQL)
		bindings = append(bindings, selectBindings...)
	}

	if len(stmt.Conditions) > 0 {
		whereClause, whereBindings := parseConditions(stmt.Conditions)
		bindings = append(bindings, whereBindings...)
		clauses = append(clauses, fmt.Sprintf("WHERE %s", whereClause))
	}

	if len(stmt.Return) > 0 {
		clauses = append(clauses, "RETURNING "+strings.Join(stmt.Return, ", "))
	}

	asSQL = strings.Join(clauses, " ")

	if rebind {
		if db, ok := stmt.execer.(*sqlx.DB); ok {
			asSQL = db.Rebind(asSQL)
		} else if tx, ok := stmt.execer.(*sqlx.Tx); ok {
			asSQL = tx.Rebind(asSQL)
		}
	}

	return asSQL, bindings
}

// Exec executes the UPDATE statement, returning the standard
// sql.Result struct and an error if the query failed.
func (stmt *UpdateStmt) Exec() (res sql.Result, err error) {
	asSQL, bindings := stmt.ToSQL(true)

	res, err = stmt.execer.Exec(asSQL, bindings...)
	stmt.HandleError(err)

	return res, err
}

// ExecContext executes the UPDATE statement, returning the standard
// sql.Result struct and an error if the query failed.
func (stmt *UpdateStmt) ExecContext(ctx context.Context) (res sql.Result, err error) {
	asSQL, bindings := stmt.ToSQL(true)

	res, err = stmt.execer.ExecContext(ctx, asSQL, bindings...)
	stmt.HandleError(err)

	return res, err
}

// GetRow executes an UPDATE statement with a RETURNING clause
// expected to return one row, and loads the result into
// the provided variable (which may be a simple variable if
// only one column is returned, or a struct if multiple columns
// are returned)
func (stmt *UpdateStmt) GetRow(into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.Get(stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// GetRowContext executes an UPDATE statement with a RETURNING clause
// expected to return one row, and loads the result into
// the provided variable (which may be a simple variable if
// only one column is returned, or a struct if multiple columns
// are returned)
func (stmt *UpdateStmt) GetRowContext(ctx context.Context, into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.GetContext(ctx, stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// GetAll executes an UPDATE statement with a RETURNING clause
// expected to return multiple rows, and loads the result into
// the provided slice variable
func (stmt *UpdateStmt) GetAll(into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.Select(stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// GetAllContext executes an UPDATE statement with a RETURNING clause
// expected to return multiple rows, and loads the result into
// the provided slice variable
func (stmt *UpdateStmt) GetAllContext(ctx context.Context, into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.SelectContext(ctx, stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// UpdateFunction represents a function call in the context of
// updating a column's value. For example, PostgreSQL provides
// functions to append, prepend or remove items from array
// columns.
type UpdateFunction struct {
	Name      string
	Arguments []interface{}
}

// ArrayAppend is an UpdateFunction for calling PostgreSQL's
// array_append function during an update.
func ArrayAppend(name string, value interface{}) UpdateFunction {
	return UpdateFunction{
		Name:      "array_append",
		Arguments: []interface{}{Indirect(name), value},
	}
}

// ArrayPrepend is an UpdateFunction for calling PostgreSQL's
// array_prepend function during an update.
func ArrayPrepend(name string, value interface{}) UpdateFunction {
	return UpdateFunction{
		Name:      "array_prepend",
		Arguments: []interface{}{Indirect(name), value},
	}
}

// ArrayRemove is an UpdateFunction for calling PostgreSQL's
// array_remove function during an update.
func ArrayRemove(name string, value interface{}) UpdateFunction {
	return UpdateFunction{
		Name:      "array_remove",
		Arguments: []interface{}{Indirect(name), value},
	}
}
<commit_msg>Add support for "array_cat" function<commit_after>package sqlz

import (
	"context"
	"database/sql"
	"fmt"
	"strings"

	"github.com/jmoiron/sqlx"
)

// UpdateStmt represents an UPDATE statement
type UpdateStmt struct {
	*Statement
	Table           string
	Updates         map[string]interface{}
	Conditions      []WhereCondition
	Return          []string
	execer          Ext
	SelectStmt      *SelectStmt
	SelectStmtAlias string
}

// Update creates a new UpdateStmt object for
// the specified table
func (db *DB) Update(table string) *UpdateStmt {
	return &UpdateStmt{
		Table:     table,
		Updates:   make(map[string]interface{}),
		execer:    db.DB,
		Statement: &Statement{db.ErrHandlers},
	}
}

// Update creates a new UpdateStmt object for
// the specified table
func (tx *Tx) Update(table string) *UpdateStmt {
	return &UpdateStmt{
		Table:     table,
		Updates:   make(map[string]interface{}),
		execer:    tx.Tx,
		Statement: &Statement{tx.ErrHandlers},
	}
}

// Set receives the name of a column and a new value. Multiple calls to Set
// can be chained together to modify multiple columns. Set can also be chained
// with calls to SetMap
func (stmt *UpdateStmt) Set(col string, value interface{}) *UpdateStmt {
	return stmt.SetIf(col, value, true)
}

// SetMap receives a map of columns and values. Multiple calls to both Set and
// SetMap can be chained to modify multiple columns.
func (stmt *UpdateStmt) SetMap(updates map[string]interface{}) *UpdateStmt {
	for col, value := range updates {
		stmt.Updates[col] = value
	}

	return stmt
}

// SetIf is the same as Set, but also accepts a boolean value and only does
// anything if that value is true. This is a convenience method so that
// conditional updates can be made without having to save the UpdateStmt into
// a variable and using if statements
func (stmt *UpdateStmt) SetIf(col string, value interface{}, b bool) *UpdateStmt {
	if b {
		stmt.Updates[col] = value
	}

	return stmt
}

// Where creates one or more WHERE conditions for the UPDATE statement.
// If multiple conditions are passed, they are considered AND conditions.
func (stmt *UpdateStmt) Where(conditions ...WhereCondition) *UpdateStmt {
	stmt.Conditions = append(stmt.Conditions, conditions...)
	return stmt
}

// Returning sets a RETURNING clause to receive values back from the
// database once executing the UPDATE statement. Note that GetRow or
// GetAll must be used to execute the query rather than Exec to get
// back the values.
func (stmt *UpdateStmt) Returning(cols ...string) *UpdateStmt {
	stmt.Return = append(stmt.Return, cols...)
	return stmt
}

// FromSelect allows creating update statements that takes values from the
// result of a select statement.
func (stmt *UpdateStmt) FromSelect(selStmt *SelectStmt, alias string) *UpdateStmt {
	stmt.SelectStmt = selStmt
	stmt.SelectStmtAlias = alias

	return stmt
}

// ToSQL generates the UPDATE statement's SQL and returns a list of
// bindings. It is used internally by Exec, GetRow and GetAll, but is
// exported if you wish to use it directly.
func (stmt *UpdateStmt) ToSQL(rebind bool) (asSQL string, bindings []interface{}) {
	var clauses = []string{fmt.Sprintf("UPDATE %s", stmt.Table)}

	var updates []string

	// sort updates by column for reproducibility
	for _, col := range sortKeys(stmt.Updates) {
		val := stmt.Updates[col]
		if fn, isFn := val.(UpdateFunction); isFn {
			var args []string

			for _, arg := range fn.Arguments {
				if indirect, isIndirect := arg.(IndirectValue); isIndirect {
					args = append(args, indirect.Reference)
					bindings = append(bindings, indirect.Bindings...)
				} else {
					args = append(args, "?")
					bindings = append(bindings, arg)
				}
			}

			updates = append(updates, col+" = "+fn.Name+"("+strings.Join(args, ", ")+")")
		} else if indirect, isIndirect := val.(IndirectValue); isIndirect {
			updates = append(updates, col+" = "+indirect.Reference)
			bindings = append(bindings, indirect.Bindings...)
		} else {
			updates = append(updates, col+" = ?")
			bindings = append(bindings, val)
		}
	}

	clauses = append(clauses, "SET "+strings.Join(updates, ", "))

	if stmt.SelectStmt != nil && stmt.SelectStmtAlias != "" {
		selectSQL, selectBindings := stmt.SelectStmt.ToSQL(false)
		selectSQL = "(" + selectSQL + ") AS " + stmt.SelectStmtAlias + " "

		clauses = append(clauses, "FROM ")
		clauses = append(clauses, selectSQL)
		bindings = append(bindings, selectBindings...)
	}

	if len(stmt.Conditions) > 0 {
		whereClause, whereBindings := parseConditions(stmt.Conditions)
		bindings = append(bindings, whereBindings...)
		clauses = append(clauses, fmt.Sprintf("WHERE %s", whereClause))
	}

	if len(stmt.Return) > 0 {
		clauses = append(clauses, "RETURNING "+strings.Join(stmt.Return, ", "))
	}

	asSQL = strings.Join(clauses, " ")

	if rebind {
		if db, ok := stmt.execer.(*sqlx.DB); ok {
			asSQL = db.Rebind(asSQL)
		} else if tx, ok := stmt.execer.(*sqlx.Tx); ok {
			asSQL = tx.Rebind(asSQL)
		}
	}

	return asSQL, bindings
}

// Exec executes the UPDATE statement, returning the standard
// sql.Result struct and an error if the query failed.
func (stmt *UpdateStmt) Exec() (res sql.Result, err error) {
	asSQL, bindings := stmt.ToSQL(true)

	res, err = stmt.execer.Exec(asSQL, bindings...)
	stmt.HandleError(err)

	return res, err
}

// ExecContext executes the UPDATE statement, returning the standard
// sql.Result struct and an error if the query failed.
func (stmt *UpdateStmt) ExecContext(ctx context.Context) (res sql.Result, err error) {
	asSQL, bindings := stmt.ToSQL(true)

	res, err = stmt.execer.ExecContext(ctx, asSQL, bindings...)
	stmt.HandleError(err)

	return res, err
}

// GetRow executes an UPDATE statement with a RETURNING clause
// expected to return one row, and loads the result into
// the provided variable (which may be a simple variable if
// only one column is returned, or a struct if multiple columns
// are returned)
func (stmt *UpdateStmt) GetRow(into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.Get(stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// GetRowContext executes an UPDATE statement with a RETURNING clause
// expected to return one row, and loads the result into
// the provided variable (which may be a simple variable if
// only one column is returned, or a struct if multiple columns
// are returned)
func (stmt *UpdateStmt) GetRowContext(ctx context.Context, into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.GetContext(ctx, stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// GetAll executes an UPDATE statement with a RETURNING clause
// expected to return multiple rows, and loads the result into
// the provided slice variable
func (stmt *UpdateStmt) GetAll(into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.Select(stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// GetAllContext executes an UPDATE statement with a RETURNING clause
// expected to return multiple rows, and loads the result into
// the provided slice variable
func (stmt *UpdateStmt) GetAllContext(ctx context.Context, into interface{}) error {
	asSQL, bindings := stmt.ToSQL(true)

	err := sqlx.SelectContext(ctx, stmt.execer, into, asSQL, bindings...)
	stmt.HandleError(err)

	return err
}

// UpdateFunction represents a function call in the context of
// updating a column's value. For example, PostgreSQL provides
// functions to append, prepend or remove items from array
// columns.
type UpdateFunction struct {
	Name      string
	Arguments []interface{}
}

// ArrayAppend is an UpdateFunction for calling PostgreSQL's
// array_append function during an update.
func ArrayAppend(name string, value interface{}) UpdateFunction {
	return UpdateFunction{
		Name:      "array_append",
		Arguments: []interface{}{Indirect(name), value},
	}
}

// ArrayPrepend is an UpdateFunction for calling PostgreSQL's
// array_prepend function during an update.
func ArrayPrepend(name string, value interface{}) UpdateFunction {
	return UpdateFunction{
		Name:      "array_prepend",
		Arguments: []interface{}{Indirect(name), value},
	}
}

// ArrayRemove is an UpdateFunction for calling PostgreSQL's
// array_remove function during an update.
func ArrayRemove(name string, value interface{}) UpdateFunction {
	return UpdateFunction{
		Name:      "array_remove",
		Arguments: []interface{}{Indirect(name), value},
	}
}

// ArrayConcat is an UpdateFunction for calling PostgreSQL's
// array_cat function during an update.
func ArrayConcat(name string, value interface{}) UpdateFunction {
	return UpdateFunction{
		Name:      "array_cat",
		Arguments: []interface{}{Indirect(name), value},
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/dchest/uniuri"
	_ "github.com/go-sql-driver/mysql"
)

const (
	LENGTH     = 6
	PORT       = ":8080"
	DIRECTORY  = "/tmp/"
	UPADDRESS  = "http://localhost"
	dbUSERNAME = ""
	dbNAME     = ""
	dbPASSWORD = ""
	DATABASE   = dbUSERNAME + ":" + dbPASSWORD + "@/" + dbNAME + "?charset=utf8"
	MAXSIZE    = 10 * 1024 * 1024
)

type Result struct {
	URL  string `json:"url"`
	Name string `json:"name"`
	Hash string `json:"hash"`
	Size int64  `json:"size"`
}

type Response struct {
	Success     bool     `json:"success"`
	ErrorCode   int      `json:"errorcode,omitempty"`
	Description string   `json:"description,omitempty"`
	Files       []Result `json:"files,omitempty"`
}

func check(err error) {
	if err != nil {
		fmt.Println(err)
		return
	}
}

func generateName() string {
	name := uniuri.NewLen(LENGTH)
	db, err := sql.Open("mysql", DATABASE)
	check(err)
	query, err := db.Query("select id from files where id=?", name)
	if err != sql.ErrNoRows {
		for query.Next() {
			generateName()
		}
	}
	db.Close()

	return name
}
func respond(w http.ResponseWriter, output string, resp Response) {
	if resp.ErrorCode != 0 {
		resp.Files = []Result{}
		resp.Success = false
	} else {
		resp.Success = true
	}

	switch output {
	case "json":

		w.Header().Set("Content-Type", "application/json")
		err := json.NewEncoder(w).Encode(resp)

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	case "xml":
		x, err := xml.MarshalIndent(resp, "", "  ")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/xml")
		w.Write(x)

	case "html":
		w.Header().Set("Content-Type", "text/html")
		for _, file := range resp.Files {
			io.WriteString(w, ""+file.URL+"
")
		}

	case "gyazo", "text":
		w.Header().Set("Content-Type", "plain/text")
		for _, file := range resp.Files {
			io.WriteString(w, file.URL+"\n")
		}

	case "csv":
		w.Header().Set("Content-Type", "text/csv")
		io.WriteString(w, "name, url, hash, size\n")
		for _, file := range resp.Files {
			io.WriteString(w, file.Name+","+file.URL+","+file.Hash+","+strconv.FormatInt(file.Size, 10)+"\n")
		}

	default:
		w.Header().Set("Content-Type", "application/json")
		err := json.NewEncoder(w).Encode(resp)

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

	}

}
func grillHandler(w http.ResponseWriter, r *http.Request) {
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
	reader, err := r.MultipartReader()
	resp := Response{Files: []Result{}}
	output := r.FormValue("output")
	if err != nil {
		resp.ErrorCode = http.StatusInternalServerError
		resp.Description = err.Error()
		respond(w, output, resp)
		return
	}

	db, err := sql.Open("mysql", DATABASE)
	check(err)

	for {
		part, err := reader.NextPart()
		if err == io.EOF {
			break
		}

		if part.FileName() == "" {
			continue
		}

		s := generateName()
		extName := filepath.Ext(part.FileName())
		filename := s + extName
		dst, err := os.Create(DIRECTORY + filename)
		defer dst.Close()

		if err != nil {
			resp.ErrorCode = http.StatusInternalServerError
			resp.Description = err.Error()
			respond(w, output, resp)
			break
		}

		h := sha1.New()
		t := io.TeeReader(part, h)
		_, err = io.Copy(dst, t)

		if err != nil {
			resp.ErrorCode = http.StatusInternalServerError
			resp.Description = err.Error()
			respond(w, output, resp)
			break
		}
		hash := h.Sum(nil)
		sha1 := base64.URLEncoding.EncodeToString(hash)
		stat, _ := dst.Stat()
		size := stat.Size()
		if size > MAXSIZE {
			resp.ErrorCode = http.StatusRequestEntityTooLarge
			resp.Description = err.Error()
			break
		}

		originalname := part.FileName()
		err = db.QueryRow("select originalname, filename, size from files where hash=?", sha1).Scan(&originalname, &filename, &size)
		res := Result{
			URL:  UPADDRESS + "/" + filename,
			Name: originalname,
			Hash: sha1,
			Size: size,
		}
		if err == sql.ErrNoRows {
			query, err := db.Prepare("INSERT into files(hash, originalname, filename, size, date) values(?, ?, ?, ?, ?)")
			check(err)
			_, err = query.Exec(res.Hash, res.Name, filename, res.Size, time.Now().Format("2016-01-02"))
			check(err)
		}
		resp.Files = append(resp.Files, res)
	}
	respond(w, output, resp)
}

func main() {
	http.HandleFunc("/upload.php", uploadHandler)
	http.HandleFunc("/grill.php", grillHandler)
	err := http.ListenAndServe(PORT, nil)
	if err != nil {
		panic(err)
	}

}
<commit_msg>Add grill handler<commit_after>package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/dchest/uniuri"
	_ "github.com/go-sql-driver/mysql"
)

const (
	LENGTH         = 6
	PORT           = ":8080"
	DIRECTORY      = "/tmp/"
	GRILLDIRECTORY = ""
	UPADDRESS      = "http://localhost"
	dbUSERNAME     = ""
	dbNAME         = ""
	dbPASSWORD     = ""
	DATABASE       = dbUSERNAME + ":" + dbPASSWORD + "@/" + dbNAME + "?charset=utf8"
	MAXSIZE        = 10 * 1024 * 1024
)

type Result struct {
	URL  string `json:"url"`
	Name string `json:"name"`
	Hash string `json:"hash"`
	Size int64  `json:"size"`
}

type Response struct {
	Success     bool     `json:"success"`
	ErrorCode   int      `json:"errorcode,omitempty"`
	Description string   `json:"description,omitempty"`
	Files       []Result `json:"files,omitempty"`
}

func check(err error) {
	if err != nil {
		fmt.Println(err)
		return
	}
}

func generateName() string {
	name := uniuri.NewLen(LENGTH)
	db, err := sql.Open("mysql", DATABASE)
	check(err)
	query, err := db.Query("select id from files where id=?", name)
	if err != sql.ErrNoRows {
		for query.Next() {
			generateName()
		}
	}
	db.Close()

	return name
}
func respond(w http.ResponseWriter, output string, resp Response) {
	if resp.ErrorCode != 0 {
		resp.Files = []Result{}
		resp.Success = false
	} else {
		resp.Success = true
	}

	switch output {
	case "json":

		w.Header().Set("Content-Type", "application/json")
		err := json.NewEncoder(w).Encode(resp)

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	case "xml":
		x, err := xml.MarshalIndent(resp, "", "  ")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/xml")
		w.Write(x)

	case "html":
		w.Header().Set("Content-Type", "text/html")
		for _, file := range resp.Files {
			io.WriteString(w, ""+file.URL+"
")
		}

	case "gyazo", "text":
		w.Header().Set("Content-Type", "plain/text")
		for _, file := range resp.Files {
			io.WriteString(w, file.URL+"\n")
		}

	case "csv":
		w.Header().Set("Content-Type", "text/csv")
		io.WriteString(w, "name, url, hash, size\n")
		for _, file := range resp.Files {
			io.WriteString(w, file.Name+","+file.URL+","+file.Hash+","+strconv.FormatInt(file.Size, 10)+"\n")
		}

	default:
		w.Header().Set("Content-Type", "application/json")
		err := json.NewEncoder(w).Encode(resp)

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

	}

}
func grillHandler(w http.ResponseWriter, r *http.Request) {
	kawaii, err := ioutil.ReadDir(GRILLDIRECTORY)
	check(err)
	http.Redirect(w, r, GRILLDIRECTORY+kawaii[rand.Intn(len(kawaii))].Name(), 301)
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
	reader, err := r.MultipartReader()
	resp := Response{Files: []Result{}}
	output := r.FormValue("output")
	if err != nil {
		resp.ErrorCode = http.StatusInternalServerError
		resp.Description = err.Error()
		respond(w, output, resp)
		return
	}

	db, err := sql.Open("mysql", DATABASE)
	check(err)

	for {
		part, err := reader.NextPart()
		if err == io.EOF {
			break
		}

		if part.FileName() == "" {
			continue
		}

		s := generateName()
		extName := filepath.Ext(part.FileName())
		filename := s + extName
		dst, err := os.Create(DIRECTORY + filename)
		defer dst.Close()

		if err != nil {
			resp.ErrorCode = http.StatusInternalServerError
			resp.Description = err.Error()
			respond(w, output, resp)
			break
		}

		h := sha1.New()
		t := io.TeeReader(part, h)
		_, err = io.Copy(dst, t)

		if err != nil {
			resp.ErrorCode = http.StatusInternalServerError
			resp.Description = err.Error()
			respond(w, output, resp)
			break
		}
		hash := h.Sum(nil)
		sha1 := base64.URLEncoding.EncodeToString(hash)
		stat, _ := dst.Stat()
		size := stat.Size()
		if size > MAXSIZE {
			resp.ErrorCode = http.StatusRequestEntityTooLarge
			resp.Description = err.Error()
			break
		}

		originalname := part.FileName()
		err = db.QueryRow("select originalname, filename, size from files where hash=?", sha1).Scan(&originalname, &filename, &size)
		res := Result{
			URL:  UPADDRESS + "/" + filename,
			Name: originalname,
			Hash: sha1,
			Size: size,
		}
		if err == sql.ErrNoRows {
			query, err := db.Prepare("INSERT into files(hash, originalname, filename, size, date) values(?, ?, ?, ?, ?)")
			check(err)
			_, err = query.Exec(res.Hash, res.Name, filename, res.Size, time.Now().Format("2016-01-02"))
			check(err)
		}
		resp.Files = append(resp.Files, res)
	}
	respond(w, output, resp)
}

func main() {
	http.HandleFunc("/upload.php", uploadHandler)
	http.HandleFunc("/grill.php", grillHandler)
	err := http.ListenAndServe(PORT, nil)
	if err != nil {
		panic(err)
	}

}
<|endoftext|>


<commit_before>package tus

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"os"
)

type Metadata map[string]string

type Upload struct {
	stream io.ReadSeeker
	size   int64

	Fingerprint string
	Metadata    Metadata
}

// Size retuns the size of the upload body.
func (u *Upload) Size() int64 {
	return u.size
}

// EncodedMetadata encodes the upload metadata.
func (u *Upload) EncodedMetadata() string {
	var buffer bytes.Buffer

	for k, v := range u.Metadata {
		buffer.WriteString(fmt.Sprintf("%s %s;", k, b64encode(v)))
	}

	return buffer.String()
}

// NewUploadFromFile creates a new Upload from an os.File.
func NewUploadFromFile(f *os.File) (*Upload, error) {
	fi, err := f.Stat()

	if err != nil {
		return nil, err
	}

	metadata := map[string]string{
		"filename": fi.Name(),
	}

	fingerprint := fmt.Sprintf("%s-%d-%d", fi.Name(), fi.Size(), fi.ModTime())

	return NewUpload(f, fi.Size(), metadata, fingerprint), nil
}

// NewUploadFromBytes creates a new upload from a byte array.
func NewUploadFromBytes(b []byte) *Upload {
	buffer := bytes.NewReader(b)
	return NewUpload(buffer, buffer.Size(), nil, "")
}

// NewUpload creates a new upload from an io.Reader.
func NewUpload(reader io.Reader, size int64, metadata Metadata, fingerprint string) *Upload {
	stream, ok := reader.(io.ReadSeeker)

	if !ok {
		buf := new(bytes.Buffer)
		buf.ReadFrom(reader)
		stream = bytes.NewReader(buf.Bytes())
	}

	if metadata == nil {
		metadata = make(Metadata)
	}

	return &Upload{
		stream: stream,
		size:   size,

		Fingerprint: fingerprint,
		Metadata:    metadata,
	}
}

func b64encode(s string) string {
	return base64.StdEncoding.EncodeToString([]byte(s))
}
<commit_msg>Fix typo.<commit_after>package tus

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"os"
)

type Metadata map[string]string

type Upload struct {
	stream io.ReadSeeker
	size   int64

	Fingerprint string
	Metadata    Metadata
}

// Size returns the size of the upload body.
func (u *Upload) Size() int64 {
	return u.size
}

// EncodedMetadata encodes the upload metadata.
func (u *Upload) EncodedMetadata() string {
	var buffer bytes.Buffer

	for k, v := range u.Metadata {
		buffer.WriteString(fmt.Sprintf("%s %s;", k, b64encode(v)))
	}

	return buffer.String()
}

// NewUploadFromFile creates a new Upload from an os.File.
func NewUploadFromFile(f *os.File) (*Upload, error) {
	fi, err := f.Stat()

	if err != nil {
		return nil, err
	}

	metadata := map[string]string{
		"filename": fi.Name(),
	}

	fingerprint := fmt.Sprintf("%s-%d-%d", fi.Name(), fi.Size(), fi.ModTime())

	return NewUpload(f, fi.Size(), metadata, fingerprint), nil
}

// NewUploadFromBytes creates a new upload from a byte array.
func NewUploadFromBytes(b []byte) *Upload {
	buffer := bytes.NewReader(b)
	return NewUpload(buffer, buffer.Size(), nil, "")
}

// NewUpload creates a new upload from an io.Reader.
func NewUpload(reader io.Reader, size int64, metadata Metadata, fingerprint string) *Upload {
	stream, ok := reader.(io.ReadSeeker)

	if !ok {
		buf := new(bytes.Buffer)
		buf.ReadFrom(reader)
		stream = bytes.NewReader(buf.Bytes())
	}

	if metadata == nil {
		metadata = make(Metadata)
	}

	return &Upload{
		stream: stream,
		size:   size,

		Fingerprint: fingerprint,
		Metadata:    metadata,
	}
}

func b64encode(s string) string {
	return base64.StdEncoding.EncodeToString([]byte(s))
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Pani Networks
// 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.
package agent

import (
	"fmt"
	"net"
	"strings"
	"testing"

)

// TestAppendLineToFile writes data to fake file and ensures it's got written.
func TestAppendLineToFile(t *testing.T) {
	/*
	   Mocking framework comments

	   Framework is available via AgentHelperT structure
	   that must be initialized with mocking interfaces.

	   * new(AgentHelperT) returns uninitialized AgentHelperT
	   * AgentHelperT.Executor not used in this test so we initialize it with
	     default implementation
	   * AgentHelperT.OS initialized with FakeOS that implements
	     appendFile (used by appendLineToFile)
	   * Data written by appendLineToFile available via OS.fakeFile.content
	*/

	// Init fake helpe, &leasefiler
	fOS := &FakeOS{"", nil}
	helper := Helper{OS: fOS}
	agent := Agent{Helper: &helper}

	// when
	netif := NetIf{"eth0", "A", net.ParseIP("127.0.0.1")}
	lease := fmt.Sprintf("%s %s", netif.Mac, netif.Ip)
	_ = agent.Helper.appendLineToFile("stub", lease)

	// expect
	get := fOS.fakeFile.content
	if get != fmt.Sprintf("%s\n", lease) {
		t.Errorf("AppendLineToFile failed, expect %s\\n, got %q", lease, get)
	}
}

// TestIsLineInFile is checking that isLineInFile correctly detect presence of
// given line in the file.
func TestIsLineInFile(t *testing.T) {
	// Returning correct lease via FakeOS
	fOS := &FakeOS{"A 127.0.0.1", nil}
	agent := Agent{Helper: &Helper{OS: fOS}}

	// NetIf to make a lease from
	ip := net.ParseIP("127.0.0.1")
	netif := NetIf{"eth0", "A", ip}

	lease := fmt.Sprintf("%s %s", netif.Mac, netif.Ip)

	// we don't care for lease file name in this test so it's just "stub"
	out, err := agent.Helper.isLineInFile("stub", lease)

	// expect
	if err != nil {
		t.Error("IsLineInFile unkown error", err)
	}
	if out != true {
		t.Errorf("IsLineInFile failed, got %q, expect true", out)
	}

	// when

	// NetIf to make a lease from
	netif = NetIf{"eth0", "A", ip}

	// Returning wrong lease via FakeOS
	fOS = &FakeOS{"C 127.0.0.1", nil}
	agent.Helper.OS = fOS
	lease = fmt.Sprintf("%s %s", netif.Mac, netif.Ip)

	// we don't care for lease file name in this test so it's just "stub"
	out, err = agent.Helper.isLineInFile("stub", lease)

	// expect
	if err != nil {
		t.Error("IsLineInFile unknown error", err)
	}

	if out == true {
		t.Errorf("IsLineInFile failed, got %q, expect false", out)
	}
}

// TestDhcpPid is checking that DhcpPid is successfully detecting
// running DHCP server.
func TestDhcpPid(t *testing.T) {
	agent := Agent{Helper: &Helper{}}
	// when

	// DhcpPid is expecting pid in stdout
	E := &FakeExecutor{[]byte("12345"), nil, nil}
	agent.Helper.Executor = E
	out, err := agent.Helper.DhcpPid()
	// expect
	if err != nil {
		t.Error("DhcpPid() failed with", err)
	}
	if out != 12345 {
		t.Error("DhcpPid() returned wrong pid: expected 12345, got", out)
	}

	// when

	// Here testing that DhcpPid's sanity check - pid must be < 65535
	E = &FakeExecutor{[]byte("1234567"), nil, nil}
	agent.Helper.Executor = E
	out, err = agent.Helper.DhcpPid()
	// expect
	if err == nil {
		t.Error("DhcpPid() failed to detect error condition pid > 65535")
	}
}

// TestIsRouteExist is checking that isRouteExist detects correctly if given
// ip route already exist.
func TestIsRouteExist(t *testing.T) {
	agent := Agent{Helper: &Helper{}}
	// when

	// IsRouteExist treats non empty output as a success
	E := &FakeExecutor{[]byte("route exist"), nil, nil}
	agent.Helper.Executor = E
	ip := net.ParseIP("127.0.0.1")
	err := agent.Helper.isRouteExist(ip, "32")

	// expect
	if err != nil {
		t.Errorf("TestIsRouteExist failed with %q", err)
	}

	expect := "/sbin/ip ro show 127.0.0.1/32"
	got := *E.Commands
	if expect != got {
		t.Errorf("TestIsRouteExist returned unexpected command, expect %s, got %s", expect, got)
	}

	// when
	// for this test we want to fail isRouteExist by providing nil output
	E = &FakeExecutor{nil, nil, nil}
	agent.Helper.Executor = E
	err = agent.Helper.isRouteExist(ip, "32")

	// expect
	if err == nil {
		t.Error("TestIsRouteExist failed to detect 'No such route' condition")
	}
}

// TestCreateRoute is checking that createRoute generates correct OS commands
// to create ip routes for given endopoint.
func TestCreateRoute(t *testing.T) {
	agent := Agent{Helper: &Helper{}}
	// when

	// we only care for recorded commands, no need for fake output or errors
	E := &FakeExecutor{nil, nil, nil}
	agent.Helper.Executor = E
	ip := net.ParseIP("127.0.0.1")
	_ = agent.Helper.createRoute(ip, "0", "dev", "eth0")

	// expect
	expect := "/sbin/ip ro add 127.0.0.1/0 dev eth0"
	got := *E.Commands
	if expect != got {
		t.Errorf("TestIsRouteExist returned unexpected command, expect %s, got %s", expect, got)
	}
}

// TestCreateInterhostRoutes is checking that ensureInterHostRoutes generates
// correct commands to create IP routes to other romana hosts.
func TestCreateInterhostRoutes(t *testing.T) {
	agent := mockAgent()
	// when

	// we only care for recorded commands, no need for fake output or errors
	E := &FakeExecutor{nil, nil, nil}
	agent.Helper.Executor = E
	_ = agent.Helper.ensureInterHostRoutes()

	// expect
	expect := strings.Join([]string{"/sbin/ip ro show 10.65.0.0/16",
		"/sbin/ip ro add 10.65.0.0/16 via 192.168.0.12"}, "\n")
	got := *E.Commands
	if expect != got {
		t.Errorf("TestCreateInterhostRoutes returned unexpected command, expect %s, got %s", expect, got)
	}
}
<commit_msg>File comment for helpers_test.go<commit_after>// Copyright (c) 2015 Pani Networks
// 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.

// Tests cases for helpers
package agent

import (
	"fmt"
	"net"
	"strings"
	"testing"

)

// TestAppendLineToFile writes data to fake file and ensures it's got written.
func TestAppendLineToFile(t *testing.T) {
	/*
	   Mocking framework comments

	   Framework is available via AgentHelperT structure
	   that must be initialized with mocking interfaces.

	   * new(AgentHelperT) returns uninitialized AgentHelperT
	   * AgentHelperT.Executor not used in this test so we initialize it with
	     default implementation
	   * AgentHelperT.OS initialized with FakeOS that implements
	     appendFile (used by appendLineToFile)
	   * Data written by appendLineToFile available via OS.fakeFile.content
	*/

	// Init fake helpe, &leasefiler
	fOS := &FakeOS{"", nil}
	helper := Helper{OS: fOS}
	agent := Agent{Helper: &helper}

	// when
	netif := NetIf{"eth0", "A", net.ParseIP("127.0.0.1")}
	lease := fmt.Sprintf("%s %s", netif.Mac, netif.Ip)
	_ = agent.Helper.appendLineToFile("stub", lease)

	// expect
	get := fOS.fakeFile.content
	if get != fmt.Sprintf("%s\n", lease) {
		t.Errorf("AppendLineToFile failed, expect %s\\n, got %q", lease, get)
	}
}

// TestIsLineInFile is checking that isLineInFile correctly detect presence of
// given line in the file.
func TestIsLineInFile(t *testing.T) {
	// Returning correct lease via FakeOS
	fOS := &FakeOS{"A 127.0.0.1", nil}
	agent := Agent{Helper: &Helper{OS: fOS}}

	// NetIf to make a lease from
	ip := net.ParseIP("127.0.0.1")
	netif := NetIf{"eth0", "A", ip}

	lease := fmt.Sprintf("%s %s", netif.Mac, netif.Ip)

	// we don't care for lease file name in this test so it's just "stub"
	out, err := agent.Helper.isLineInFile("stub", lease)

	// expect
	if err != nil {
		t.Error("IsLineInFile unkown error", err)
	}
	if out != true {
		t.Errorf("IsLineInFile failed, got %q, expect true", out)
	}

	// when

	// NetIf to make a lease from
	netif = NetIf{"eth0", "A", ip}

	// Returning wrong lease via FakeOS
	fOS = &FakeOS{"C 127.0.0.1", nil}
	agent.Helper.OS = fOS
	lease = fmt.Sprintf("%s %s", netif.Mac, netif.Ip)

	// we don't care for lease file name in this test so it's just "stub"
	out, err = agent.Helper.isLineInFile("stub", lease)

	// expect
	if err != nil {
		t.Error("IsLineInFile unknown error", err)
	}

	if out == true {
		t.Errorf("IsLineInFile failed, got %q, expect false", out)
	}
}

// TestDhcpPid is checking that DhcpPid is successfully detecting
// running DHCP server.
func TestDhcpPid(t *testing.T) {
	agent := Agent{Helper: &Helper{}}
	// when

	// DhcpPid is expecting pid in stdout
	E := &FakeExecutor{[]byte("12345"), nil, nil}
	agent.Helper.Executor = E
	out, err := agent.Helper.DhcpPid()
	// expect
	if err != nil {
		t.Error("DhcpPid() failed with", err)
	}
	if out != 12345 {
		t.Error("DhcpPid() returned wrong pid: expected 12345, got", out)
	}

	// when

	// Here testing that DhcpPid's sanity check - pid must be < 65535
	E = &FakeExecutor{[]byte("1234567"), nil, nil}
	agent.Helper.Executor = E
	out, err = agent.Helper.DhcpPid()
	// expect
	if err == nil {
		t.Error("DhcpPid() failed to detect error condition pid > 65535")
	}
}

// TestIsRouteExist is checking that isRouteExist detects correctly if given
// ip route already exist.
func TestIsRouteExist(t *testing.T) {
	agent := Agent{Helper: &Helper{}}
	// when

	// IsRouteExist treats non empty output as a success
	E := &FakeExecutor{[]byte("route exist"), nil, nil}
	agent.Helper.Executor = E
	ip := net.ParseIP("127.0.0.1")
	err := agent.Helper.isRouteExist(ip, "32")

	// expect
	if err != nil {
		t.Errorf("TestIsRouteExist failed with %q", err)
	}

	expect := "/sbin/ip ro show 127.0.0.1/32"
	got := *E.Commands
	if expect != got {
		t.Errorf("TestIsRouteExist returned unexpected command, expect %s, got %s", expect, got)
	}

	// when
	// for this test we want to fail isRouteExist by providing nil output
	E = &FakeExecutor{nil, nil, nil}
	agent.Helper.Executor = E
	err = agent.Helper.isRouteExist(ip, "32")

	// expect
	if err == nil {
		t.Error("TestIsRouteExist failed to detect 'No such route' condition")
	}
}

// TestCreateRoute is checking that createRoute generates correct OS commands
// to create ip routes for given endopoint.
func TestCreateRoute(t *testing.T) {
	agent := Agent{Helper: &Helper{}}
	// when

	// we only care for recorded commands, no need for fake output or errors
	E := &FakeExecutor{nil, nil, nil}
	agent.Helper.Executor = E
	ip := net.ParseIP("127.0.0.1")
	_ = agent.Helper.createRoute(ip, "0", "dev", "eth0")

	// expect
	expect := "/sbin/ip ro add 127.0.0.1/0 dev eth0"
	got := *E.Commands
	if expect != got {
		t.Errorf("TestIsRouteExist returned unexpected command, expect %s, got %s", expect, got)
	}
}

// TestCreateInterhostRoutes is checking that ensureInterHostRoutes generates
// correct commands to create IP routes to other romana hosts.
func TestCreateInterhostRoutes(t *testing.T) {
	agent := mockAgent()
	// when

	// we only care for recorded commands, no need for fake output or errors
	E := &FakeExecutor{nil, nil, nil}
	agent.Helper.Executor = E
	_ = agent.Helper.ensureInterHostRoutes()

	// expect
	expect := strings.Join([]string{"/sbin/ip ro show 10.65.0.0/16",
		"/sbin/ip ro add 10.65.0.0/16 via 192.168.0.12"}, "\n")
	got := *E.Commands
	if expect != got {
		t.Errorf("TestCreateInterhostRoutes returned unexpected command, expect %s, got %s", expect, got)
	}
}
<|endoftext|>


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

// Package plist implements parsing of Apple plist files.
package plist

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"time"
)

func next(data []byte) (skip, tag, rest []byte) {
	i := bytes.IndexByte(data, '<')
	if i < 0 {
		return data, nil, nil
	}
	var j int
	if i+1 < len(data) && data[i+1] == '?' {
		j = bytes.Index(data[i:], []byte("?>"))
	} else {
		j = bytes.IndexByte(data[i:], '>')
	}
	if j < 0 {
		return data, nil, nil
	}
	j += i + 1
	return data[:i], data[i:j], data[j:]
}

func Unmarshal(data []byte, v interface{}) error {
	_, tag, data := next(data)
	if bytes.HasPrefix(tag, []byte("<?xml")) {
		_, tag, data = next(data)
	}
	if bytes.HasPrefix(tag, []byte("<!DOCTYPE")) {
		_, tag, data = next(data)
	}
	if !bytes.HasPrefix(tag, []byte("<plist")) {
		return fmt.Errorf("not a plist")
	}

	data, err := unmarshalValue(data, reflect.ValueOf(v))
	if err != nil {
		return err
	}
	_, tag, data = next(data)
	if !bytes.Equal(tag, []byte("</plist>")) {
		return fmt.Errorf("junk on end of plist")
	}
	return nil
}

func unmarshalValue(data []byte, v reflect.Value) (rest []byte, err error) {
	_, tag, data := next(data)
	if tag == nil {
		return nil, fmt.Errorf("unexpected end of data")
	}

	if v.Kind() == reflect.Ptr {
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}

	switch stag := string(tag); stag {
	case "<dict>":
		t := v.Type()
		if v.Kind() != reflect.Struct {
			return nil, fmt.Errorf("cannot unmarshal <dict> into non-struct %s", v.Type())
		}
	Dict:
		for {
			_, tag, data = next(data)
			if len(tag) == 0 {
				return nil, fmt.Errorf("eof inside <dict>")
			}
			if string(tag) == "</dict>" {
				break
			}
			if string(tag) != "<key>" {
				return nil, fmt.Errorf("unexpected tag %s inside <dict>", tag)
			}
			var body []byte
			body, tag, data = next(data)
			if len(tag) == 0 {
				return nil, fmt.Errorf("eof inside <dict>")
			}
			if string(tag) != "</key>" {
				return nil, fmt.Errorf("unexpected tag %s inside <dict>", tag)
			}
			name := string(body)
			var i int
			for i = 0; i < t.NumField(); i++ {
				f := t.Field(i)
				if f.Name == name || f.Tag.Get("plist") == name {
					data, err = unmarshalValue(data, v.Field(i))
					continue Dict
				}
			}
			data, err = skipValue(data)
			if err != nil {
				return nil, err
			}
		}
		return data, nil

	case "<array>":
		t := v.Type()
		if v.Kind() != reflect.Slice {
			return nil, fmt.Errorf("cannot unmarshal <array> into non-slice %s", v.Type())
		}
		for {
			_, tag, rest := next(data)
			if len(tag) == 0 {
				return nil, fmt.Errorf("eof inside <array>")
			}
			if string(tag) == "</array>" {
				data = rest
				break
			}
			elem := reflect.New(t.Elem()).Elem()
			data, err = unmarshalValue(data, elem)
			if err != nil {
				return nil, err
			}
			v.Set(reflect.Append(v, elem))
		}
		return data, nil

	case "<string>":
		if v.Kind() != reflect.String {
			return nil, fmt.Errorf("cannot unmarshal <string> into non-string %s", v.Type())
		}
		body, etag, data := next(data)
		if len(etag) == 0 {
			return nil, fmt.Errorf("eof inside <string>")
		}
		if string(etag) != "</string>" {
			return nil, fmt.Errorf("expected </string> but got %s", etag)
		}
		v.SetString(string(body)) // TODO: unescape
		return data, nil

	case "<integer>":
		if v.Kind() != reflect.Int {
			return nil, fmt.Errorf("cannot unmarshal <integer> into non-int %s", v.Type())
		}
		body, etag, data := next(data)
		if len(etag) == 0 {
			return nil, fmt.Errorf("eof inside <integer>")
		}
		if string(etag) != "</integer>" {
			return nil, fmt.Errorf("expected </integer> but got %s", etag)
		}
		i, err := strconv.Atoi(string(body))
		if err != nil {
			return nil, fmt.Errorf("non-integer in <integer> tag: %s", body)
		}
		v.SetInt(int64(i))
		return data, nil

	case "<true/>", "<false/>":
		if v.Kind() != reflect.Bool {
			return nil, fmt.Errorf("cannot unmarshal %s into non-bool %s", stag, v.Type())
		}
		v.SetBool(stag == "<true/>")
		return data, nil

	case "<date>":
		if v.Type() != reflect.TypeOf(time.Time{}) {
			return nil, fmt.Errorf("cannot unmarshal %s into %s (should be time.Time)", stag, v.Type())
		}
		body, etag, data := next(data)
		if len(etag) == 0 {
			return nil, fmt.Errorf("eof inside <date>")
		}
		if string(etag) != "</date>" {
			return nil, fmt.Errorf("expected </date> but got %s", etag)
		}
		t, err := time.Parse(time.RFC3339, string(body))
		if err != nil {
			return nil, fmt.Errorf("cannot unmarshal %s into %s: %v", stag, v.Type(), err)
		}
		v.Set(reflect.ValueOf(t))
		return data, nil
	}
	return nil, fmt.Errorf("unexpected tag %s", tag)
}

func skipValue(data []byte) (rest []byte, err error) {
	n := 0
	for {
		var tag []byte
		_, tag, data = next(data)
		if len(tag) == 0 {
			return nil, fmt.Errorf("unexpected eof")
		}
		if tag[1] == '/' {
			if n == 0 {
				return nil, fmt.Errorf("unexpected closing tag")
			}
			n--
			if n == 0 {
				break
			}
		} else if tag[len(tag)-2] == '/' {
			if n == 0 {
				break
			}
		} else {
			n++
		}
	}
	return data, nil
}
<commit_msg>Added support for importing a <dict> into a map<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package plist implements parsing of Apple plist files.
package plist

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"time"
)

func next(data []byte) (skip, tag, rest []byte) {
	i := bytes.IndexByte(data, '<')
	if i < 0 {
		return data, nil, nil
	}
	var j int
	if i+1 < len(data) && data[i+1] == '?' {
		j = bytes.Index(data[i:], []byte("?>"))
	} else {
		j = bytes.IndexByte(data[i:], '>')
	}
	if j < 0 {
		return data, nil, nil
	}
	j += i + 1
	return data[:i], data[i:j], data[j:]
}

func Unmarshal(data []byte, v interface{}) error {
	_, tag, data := next(data)
	if bytes.HasPrefix(tag, []byte("<?xml")) {
		_, tag, data = next(data)
	}
	if bytes.HasPrefix(tag, []byte("<!DOCTYPE")) {
		_, tag, data = next(data)
	}
	if !bytes.HasPrefix(tag, []byte("<plist")) {
		return fmt.Errorf("not a plist")
	}

	data, err := unmarshalValue(data, reflect.ValueOf(v))
	if err != nil {
		return err
	}
	_, tag, data = next(data)
	if !bytes.Equal(tag, []byte("</plist>")) {
		return fmt.Errorf("junk on end of plist")
	}
	return nil
}

func unmarshalValue(data []byte, v reflect.Value) (rest []byte, err error) {
	_, tag, data := next(data)
	if tag == nil {
		return nil, fmt.Errorf("unexpected end of data")
	}

	if v.Kind() == reflect.Ptr {
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}

	switch stag := string(tag); stag {
	case "<dict>":
		t := v.Type()
		if v.Kind() != reflect.Struct && v.Kind() != reflect.Map {
			return nil, fmt.Errorf("cannot unmarshal <dict> into non-struct/map %s", v.Type())
		}
		if v.Kind() == reflect.Map {
			v.Set(reflect.MakeMap(v.Type()))
		}
	Dict:
		for {
			_, tag, data = next(data)
			if len(tag) == 0 {
				return nil, fmt.Errorf("eof inside <dict>")
			}
			if string(tag) == "</dict>" {
				break
			}
			if string(tag) != "<key>" {
				return nil, fmt.Errorf("unexpected tag %s inside <dict>", tag)
			}
			var body []byte
			body, tag, data = next(data)
			if len(tag) == 0 {
				return nil, fmt.Errorf("eof inside <dict>")
			}
			if string(tag) != "</key>" {
				return nil, fmt.Errorf("unexpected tag %s inside <dict>", tag)
			}
			name := string(body)
			if v.Kind() == reflect.Struct {
				var i int
				for i = 0; i < t.NumField(); i++ {
					f := t.Field(i)
					if f.Name == name || f.Tag.Get("plist") == name {
						data, err = unmarshalValue(data, v.Field(i))
						continue Dict
					}
				}
			} else {
				value := reflect.New(t.Elem()).Elem()
				data, err = unmarshalValue(data, value)
				if err != nil {
					return nil, err
				}
				v.SetMapIndex(reflect.ValueOf(name), value)
				continue Dict
			}

			data, err = skipValue(data)
			if err != nil {
				return nil, err
			}
		}
		return data, nil

	case "<array>":
		t := v.Type()
		if v.Kind() != reflect.Slice {
			return nil, fmt.Errorf("cannot unmarshal <array> into non-slice %s", v.Type())
		}
		for {
			_, tag, rest := next(data)
			if len(tag) == 0 {
				return nil, fmt.Errorf("eof inside <array>")
			}
			if string(tag) == "</array>" {
				data = rest
				break
			}
			elem := reflect.New(t.Elem()).Elem()
			data, err = unmarshalValue(data, elem)
			if err != nil {
				return nil, err
			}
			v.Set(reflect.Append(v, elem))
		}
		return data, nil

	case "<string>":
		if v.Kind() != reflect.String {
			return nil, fmt.Errorf("cannot unmarshal <string> into non-string %s", v.Type())
		}
		body, etag, data := next(data)
		if len(etag) == 0 {
			return nil, fmt.Errorf("eof inside <string>")
		}
		if string(etag) != "</string>" {
			return nil, fmt.Errorf("expected </string> but got %s", etag)
		}
		v.SetString(string(body)) // TODO: unescape
		return data, nil

	case "<integer>":
		if v.Kind() != reflect.Int {
			return nil, fmt.Errorf("cannot unmarshal <integer> into non-int %s", v.Type())
		}
		body, etag, data := next(data)
		if len(etag) == 0 {
			return nil, fmt.Errorf("eof inside <integer>")
		}
		if string(etag) != "</integer>" {
			return nil, fmt.Errorf("expected </integer> but got %s", etag)
		}
		i, err := strconv.Atoi(string(body))
		if err != nil {
			return nil, fmt.Errorf("non-integer in <integer> tag: %s", body)
		}
		v.SetInt(int64(i))
		return data, nil

	case "<true/>", "<false/>":
		if v.Kind() != reflect.Bool {
			return nil, fmt.Errorf("cannot unmarshal %s into non-bool %s", stag, v.Type())
		}
		v.SetBool(stag == "<true/>")
		return data, nil

	case "<date>":
		if v.Type() != reflect.TypeOf(time.Time{}) {
			return nil, fmt.Errorf("cannot unmarshal %s into %s (should be time.Time)", stag, v.Type())
		}
		body, etag, data := next(data)
		if len(etag) == 0 {
			return nil, fmt.Errorf("eof inside <date>")
		}
		if string(etag) != "</date>" {
			return nil, fmt.Errorf("expected </date> but got %s", etag)
		}
		t, err := time.Parse(time.RFC3339, string(body))
		if err != nil {
			return nil, fmt.Errorf("cannot unmarshal %s into %s: %v", stag, v.Type(), err)
		}
		v.Set(reflect.ValueOf(t))
		return data, nil
	}
	return nil, fmt.Errorf("unexpected tag %s", tag)
}

func skipValue(data []byte) (rest []byte, err error) {
	n := 0
	for {
		var tag []byte
		_, tag, data = next(data)
		if len(tag) == 0 {
			return nil, fmt.Errorf("unexpected eof")
		}
		if tag[1] == '/' {
			if n == 0 {
				return nil, fmt.Errorf("unexpected closing tag")
			}
			n--
			if n == 0 {
				break
			}
		} else if tag[len(tag)-2] == '/' {
			if n == 0 {
				break
			}
		} else {
			n++
		}
	}
	return data, nil
}
<|endoftext|>


<commit_before>// Package promgrpc is an instrumentation package that allows capturing metrics of your gRPC based services, both the server and the client side.
// The main goal of version 4 was to make it modular without sacrificing the simplicity of use.
//
// It is still possible to integrate the package in just a few lines.
// However, if necessary, metrics can be added, removed or modified freely.
//
// Design
//
// The package does not introduce any new concepts to an already complicated environment.
// Instead, it focuses on providing implementations of interfaces exported by gRPC and Prometheus libraries.
//
// It causes no side effects nor has global state.
// Instead, it comes with handy one-liners to reduce integration overhead.
//
// The package achieved high modularity by using Inversion of Control.
// We can define three layers of abstraction, where each is configurable or if necessary replaceable.
//
// Collectors serve one purpose, storing metrics.
// These are types well known from Prometheus ecosystem, like counters, gauges, histograms or summaries.
// This package comes with a set of predefined functions that create a specific instances for each use case. For example:
//
//  func NewRequestsTotalCounterVec(Subsystem, ...CollectorOption) *prometheus.CounterVec
//
// Level higher consist of stats handlers. This layer is responsible for metrics collection.
// It is aware of a collector and knows how to use it to record event occurrences.
// Each implementation satisfies stats.Handler and prometheus.Collector interface and knows how to monitor a single dimension, e.g. a total number of received/sent requests:
//
//  func NewRequestsStatsHandler(Subsystem, *prometheus.GaugeVec, ...StatsHandlerOption) *RequestsStatsHandler
//
// Above all, there is a coordinator.
// StatsHandler combines multiple stats handlers into a single instance.
//
// Metrics
//
// The package comes with eighteen predefined metrics — nine for server and nine for client side:
//
//  grpc_client_connections
//  grpc_client_message_received_size_histogram_bytes
//  grpc_client_message_sent_size_histogram_bytes
//  grpc_client_messages_received_total
//  grpc_client_messages_sent_total
//  grpc_client_request_duration_histogram_seconds
//  grpc_client_requests_in_flight
//  grpc_client_requests_sent_total
//  grpc_client_responses_received_total
//  grpc_server_connections
//  grpc_server_message_received_size_histogram_bytes
//  grpc_server_message_sent_size_histogram_bytes
//  grpc_server_messages_received_total
//  grpc_server_messages_sent_total
//  grpc_server_request_duration_histogram_seconds
//  grpc_server_requests_in_flight
//  grpc_server_requests_received_total
//  grpc_server_responses_sent_total
//
// Configuration
//
// The package does not require any configuration whatsoever but makes it possible.
// It is beneficial for different reasons.
//
// Having all metrics enabled could not be desirable.
// Some, like histograms, can create significant overhead on the producer side.
// If performance is critical, it advisable to reduce the set of metrics.
// To do that, implement a custom version of coordinator constructor, ClientStatsHandler and ServerStatsHandler.
//
// Another good reason to change default settings is backward compatibility.
// Migration of Grafana dashboards is not an easy nor quick task.
// If the discrepancy is small and, e.g. the only necessary adjustment is changing the namespace, it is achievable by passing CollectorWithNamespace to a collector constructor.
// It is the same very known pattern from the gRPC package, with some enhancements.
// What makes it different is that both StatsHandlerOption and CollectorOption have a shareable variant, called ShareableCollectorOption and ShareableSt
package promgrpc<commit_msg>v4 - documentation, configuration section #2<commit_after>// Package promgrpc is an instrumentation package that allows capturing metrics of your gRPC based services, both the server and the client side.
// The main goal of version 4 was to make it modular without sacrificing the simplicity of use.
//
// It is still possible to integrate the package in just a few lines.
// However, if necessary, metrics can be added, removed or modified freely.
//
// Design
//
// The package does not introduce any new concepts to an already complicated environment.
// Instead, it focuses on providing implementations of interfaces exported by gRPC and Prometheus libraries.
//
// It causes no side effects nor has global state.
// Instead, it comes with handy one-liners to reduce integration overhead.
//
// The package achieved high modularity by using Inversion of Control.
// We can define three layers of abstraction, where each is configurable or if necessary replaceable.
//
// Collectors serve one purpose, storing metrics.
// These are types well known from Prometheus ecosystem, like counters, gauges, histograms or summaries.
// This package comes with a set of predefined functions that create a specific instances for each use case. For example:
//
//  func NewRequestsTotalCounterVec(Subsystem, ...CollectorOption) *prometheus.CounterVec
//
// Level higher consist of stats handlers. This layer is responsible for metrics collection.
// It is aware of a collector and knows how to use it to record event occurrences.
// Each implementation satisfies stats.Handler and prometheus.Collector interface and knows how to monitor a single dimension, e.g. a total number of received/sent requests:
//
//  func NewRequestsStatsHandler(Subsystem, *prometheus.GaugeVec, ...StatsHandlerOption) *RequestsStatsHandler
//
// Above all, there is a coordinator.
// StatsHandler combines multiple stats handlers into a single instance.
//
// Metrics
//
// The package comes with eighteen predefined metrics — nine for server and nine for client side:
//
//  grpc_client_connections
//  grpc_client_message_received_size_histogram_bytes
//  grpc_client_message_sent_size_histogram_bytes
//  grpc_client_messages_received_total
//  grpc_client_messages_sent_total
//  grpc_client_request_duration_histogram_seconds
//  grpc_client_requests_in_flight
//  grpc_client_requests_sent_total
//  grpc_client_responses_received_total
//  grpc_server_connections
//  grpc_server_message_received_size_histogram_bytes
//  grpc_server_message_sent_size_histogram_bytes
//  grpc_server_messages_received_total
//  grpc_server_messages_sent_total
//  grpc_server_request_duration_histogram_seconds
//  grpc_server_requests_in_flight
//  grpc_server_requests_received_total
//  grpc_server_responses_sent_total
//
// Configuration
//
// The package does not require any configuration whatsoever but makes it possible.
// It is beneficial for different reasons.
//
// Having all metrics enabled could not be desirable.
// Some, like histograms, can create significant overhead on the producer side.
// If performance is critical, it advisable to reduce the set of metrics.
// To do that, implement a custom version of coordinator constructor, ClientStatsHandler and ServerStatsHandler.
//
// Another good reason to change default settings is backward compatibility.
// Migration of Grafana dashboards is not an easy nor quick task.
// If the discrepancy is small and, e.g. the only necessary adjustment is changing the namespace, it is achievable by passing CollectorWithNamespace to a collector constructor.
// It is the same very known pattern from the gRPC package, with some enhancements.
// What makes it different is that both StatsHandlerOption and CollectorOption have a shareable variant, called ShareableCollectorOption and ShareableStatsHandlerOption respectively.
// Thanks to that, it is possible to pass options related to stats handlers and collectors to coordinator constructors.
// Constructors take care of moving options to the correct receivers.
//
// Mixing both strategies described above will give even greater freedom.
// However, if that is even not enough, it is possible to reimplement an entire stack for a given metric or metrics.
package promgrpc<|endoftext|>


<commit_before>// pipe command for playing gob encodings of functions.
// example usage:  pipe tone to aplay;
// ./player\[SYSV64\].elf < 1kSine.gob | aplay -fs16
//  note  player has the same default rate as aplay, but not the same default precision.
//  note  1kSine.gob is a procedural 1k cycles sine wave.
// or specifiy sample rate:
// ./player\[SYSV64\].elf -rate=16000 < 1kSine.gob | aplay -fs16 -r 16000
// or specifiy duration:
// ./player\[SYSV64\].elf -length=2 < 1kSine.gob | aplay -fs16
package main

import (
	"bufio"
	"flag"
	"os"
)

import signals "github.com/splace/signals"

func main() {
	help := flag.Bool("help", false, "display help/usage.")
	var sampleRate uint
	flag.UintVar(&sampleRate, "rate", 8000, "`samples` per unit.")
	var length float64
	flag.Float64Var(&length, "length", 1, "length in `units`")
	flag.Parse()
	if *help {
		flag.PrintDefaults()
		os.Exit(0)
	}
	m1 := signals.Modulated{}
	rr := bufio.NewReader(os.Stdin)
	if err := m1.Load(rr); err != nil {
		panic("unable to load."+err.Error())
	}
	signals.Encode(os.Stdout,m1,signals.X(length),uint32(sampleRate),2)
	os.Stdout.Close()
}

<commit_msg>bytes<commit_after>// command for piping from gob encodings of functions to PCM.
// example usage (to play a tone):-
// ./player\[SYSV64\].elf < gobs/1kSine.gob | aplay
// or
// cat gobs/1kSine.gob | ./player\[SYSV64\].elf | aplay
//  (1kSine.gob is a procedural 1k cycles sine wave.)
// to specifiy duration:
// ./player\[SYSV64\].elf -length=2 < 1kSine.gob | aplay
// to specifiy sample rate:
// ./player\[SYSV64\].elf -rate=16000 < 1kSine.gob | aplay
// (output s not a higher frequency, since player passes wave format and so includes rate.)
// to specifiy sample precision:
// ./player\[SYSV64\].elf -bytes=1 < 1kSine.gob | aplay
// (bytes can be one of: 1,2,3,4.)
package main

import (
	"bufio"
	"flag"
	"os"
)

import signals "github.com/splace/signals"

func main() {
	help := flag.Bool("help", false, "display help/usage.")
	var sampleRate uint
	flag.UintVar(&sampleRate, "rate", 8000, "`samples` per unit.")
	var samplePrecision uint
	flag.UintVar(&samplePrecision, "bytes", 2, "`bytes` per sample.")
	var length float64
	flag.Float64Var(&length, "length", 1, "length in `units`")
	flag.Parse()
	if *help {
		flag.PrintDefaults()
		os.Exit(0)
	}
	m1 := signals.Modulated{}
	rr := bufio.NewReader(os.Stdin)
	if err := m1.Load(rr); err != nil {
		panic("unable to load."+err.Error())
	}
	signals.Encode(os.Stdout,m1,signals.X(length),uint32(sampleRate),uint8(samplePrecision))
	os.Stdout.Close()
}

<|endoftext|>