<commit_before>package transactions

import (
	"errors"
	"reflect"
	"testing"

	"github.com/shopspring/decimal"

	"github.com/luistm/go-bank-cli/elib/testkit"
	"github.com/luistm/go-bank-cli/lib/categories"

	"github.com/luistm/go-bank-cli/lib"

	"github.com/luistm/go-bank-cli/lib/customerrors"
	"github.com/luistm/go-bank-cli/lib/sellers"
	"github.com/stretchr/testify/mock"
)

type testMock struct {
	mock.Mock
}

func (m *testMock) GetAll() ([]*Transaction, error) {
	args := m.Called()
	return args.Get(0).([]*Transaction), args.Error(1)
}

func (m *testMock) Create(s string) (lib.Identifier, error) {
	args := m.Called(s)
	return args.Get(0).(lib.Identifier), args.Error(1)
}

func TestUnitInteractorTransactionsLoadDataFromRecords(t *testing.T) {

	testCasesRepository := []struct {
		name       string
		output     error
		withMock   bool
		mockOutput []interface{}
	}{
		{
			name:       "Returns error if repository is not defined",
			output:     customerrors.ErrRepositoryUndefined,
			withMock:   false,
			mockOutput: nil,
		},
		{
			name:       "Returns error on repository error",
			output:     &customerrors.ErrRepository{Msg: "Test Error"},
			withMock:   true,
			mockOutput: []interface{}{[]*Transaction{}, errors.New("Test Error")},
		},
	}

	for _, tc := range testCasesRepository {
		t.Log(tc.name)
		i := Interactor{}
		var m *testMock
		if tc.withMock {
			m = new(testMock)
			i.transactionsRepository = m
			m.On("GetAll").Return(tc.mockOutput...)
		}

		err := i.LoadDataFromRecords()

		if tc.withMock {
			m.AssertExpectations(t)
		}
		if !reflect.DeepEqual(tc.output, err) {
			t.Errorf("Expected '%v', got '%v'", tc.output, err)
		}
	}

	c := categories.New("Test Category")
	t1 := &Transaction{seller: sellers.New("d1", "d1"), category: c}
	t2 := &Transaction{seller: sellers.New("d2", "d2"), category: c}
	i := Interactor{}
	tm := new(testMock)
	i.transactionsRepository = tm
	tm.On("GetAll").Return([]*Transaction{t1, t2}, nil)

	testCasesIdentifierRepositorySave := []struct {
		name       string
		output     error
		withMock   bool
		mockInput  lib.Identifier
		mockOutput error
	}{
		{
			name:       "Returns error if entity repository is not defined",
			output:     customerrors.ErrInteractorUndefined,
			withMock:   false,
			mockInput:  nil,
			mockOutput: nil,
		},
		{
			name:       "Returns error if entity save method returns fail",
			output:     &customerrors.ErrInteractor{Msg: "Test Error"},
			withMock:   true,
			mockInput:  t1.seller,
			mockOutput: errors.New("Test Error"),
		},
	}

	for _, tc := range testCasesIdentifierRepositorySave {
		t.Log(tc.name)
		var im *lib.RepositoryMock
		if tc.withMock {
			im = new(lib.RepositoryMock)
			im.On("Save", tc.mockInput).Return(tc.mockOutput)
			i.sellersRepository = im
		}

		err := i.LoadDataFromRecords()

		if tc.withMock {
			im.AssertExpectations(t)
		}
		if !reflect.DeepEqual(tc.output, err) {
			t.Errorf("Expected '%v', got '%v'", tc.output, err)
		}
	}

}

type repositoryMock struct {
	mock.Mock
}

func (m *repositoryMock) GetAll() ([]*Transaction, error) {
	args := m.Called()
	return args.Get(0).([]*Transaction), args.Error(1)
}

func TestUnitReport(t *testing.T) {

	testCases := []struct {
		name       string
		output     error
		withMock   bool
		mockOutput []interface{}
	}{
		{
			name:   "Returns error if repository is undefined",
			output: customerrors.ErrRepositoryUndefined,
		},
		{
			name:       "Returns error if repository returns error",
			output:     &customerrors.ErrRepository{Msg: "Test Error"},
			withMock:   true,
			mockOutput: []interface{}{[]*Transaction{}, errors.New("Test Error")},
		},
		{
			name:       "Returns nil if success",
			output:     nil,
			withMock:   true,
			mockOutput: []interface{}{[]*Transaction{&Transaction{}}, nil},
		},
	}

	for _, tc := range testCases {
		t.Log(tc.name)
		i := Interactor{}
		var m *repositoryMock
		if tc.withMock {
			m = new(repositoryMock)
			m.On("GetAll").Return(tc.mockOutput...)
			i.transactionsRepository = m

			sellersMock := new(lib.RepositoryMock)
			sellersMock.On("GetAll").Return([]lib.Identifier{}, nil)
			i.sellersRepository = sellersMock
		}

		err := i.ReportFromRecords()

		if tc.withMock {
			m.AssertExpectations(t)
		}
		testkit.AssertEqual(t, tc.output, err)
	}

	trMock := new(repositoryMock)
	trMock.On("GetAll").Return([]*Transaction{&Transaction{seller: sellers.New("sellerSlug", "")}}, nil)

	testCasesSellerWithPrettyName := []struct {
		name       string
		output     error
		withMock   bool
		mockOutput []interface{}
	}{
		{
			name:   "Returns error if repository is undefined",
			output: customerrors.ErrRepositoryUndefined,
		},
		{
			name:       "Seller repository returns error",
			output:     &customerrors.ErrRepository{Msg: "Test error"},
			withMock:   true,
			mockOutput: []interface{}{[]lib.Identifier{}, errors.New("Test error")},
		},
		{
			name:     "Seller from transaction has no pretty name",
			output:   nil,
			withMock: true,
			mockOutput: []interface{}{
				[]lib.Identifier{sellers.New("sellerSlug", "sellerName")},
				nil,
			},
		},
	}

	for _, tc := range testCasesSellerWithPrettyName {
		t.Log(tc.name)
		i := Interactor{}
		i.transactionsRepository = trMock
		var m *lib.RepositoryMock
		if tc.withMock {
			m = new(lib.RepositoryMock)
			m.On("GetAll").Return(tc.mockOutput...)
			i.sellersRepository = m
		}

		err := i.ReportFromRecords()

		if tc.withMock {
			m.AssertExpectations(t)
		}
		testkit.AssertEqual(t, tc.output, err)
	}

}

func TestUnitMergeTransactionsWithSameSeller(t *testing.T) {

	decimalOne, _ := decimal.NewFromString("1")
	decimalTwo, _ := decimal.NewFromString("2")

	testCases := []struct {
		name   string
		input  []*Transaction
		output []*Transaction
	}{
		{
			name:   "Input slice is empty",
			input:  []*Transaction{},
			output: []*Transaction{},
		},
		{
			name:   "Input slice has one item, whitout seller",
			input:  []*Transaction{&Transaction{}},
			output: []*Transaction{},
		},
		{
			name:   "Input slice has one item, with seller",
			input:  []*Transaction{&Transaction{seller: sellers.New("SellerSlug", "SellerName")}},
			output: []*Transaction{&Transaction{seller: sellers.New("SellerSlug", "SellerName")}},
		},
		{
			name: "Input slice has two items, same seller",
			input: []*Transaction{
				&Transaction{value: &decimalOne, seller: sellers.New("SellerSlug", "SellerName")},
				&Transaction{value: &decimalOne, seller: sellers.New("SellerSlug", "SellerName")},
			},
			output: []*Transaction{&Transaction{value: &decimalTwo, seller: sellers.New("SellerSlug", "SellerName")}},
		},
	}

	for _, tc := range testCases {
		t.Log(tc.name)

		got, _ := mergeTransactions(tc.input)

		testkit.AssertEqual(t, tc.output, got)
	}
}
<commit_msg>Removes unused mock method<commit_after>package transactions

import (
	"errors"
	"reflect"
	"testing"

	"github.com/shopspring/decimal"

	"github.com/luistm/go-bank-cli/elib/testkit"
	"github.com/luistm/go-bank-cli/lib/categories"

	"github.com/luistm/go-bank-cli/lib"

	"github.com/luistm/go-bank-cli/lib/customerrors"
	"github.com/luistm/go-bank-cli/lib/sellers"
	"github.com/stretchr/testify/mock"
)

type testMock struct {
	mock.Mock
}

func (m *testMock) GetAll() ([]*Transaction, error) {
	args := m.Called()
	return args.Get(0).([]*Transaction), args.Error(1)
}

func TestUnitInteractorTransactionsLoadDataFromRecords(t *testing.T) {

	testCasesRepository := []struct {
		name       string
		output     error
		withMock   bool
		mockOutput []interface{}
	}{
		{
			name:       "Returns error if repository is not defined",
			output:     customerrors.ErrRepositoryUndefined,
			withMock:   false,
			mockOutput: nil,
		},
		{
			name:       "Returns error on repository error",
			output:     &customerrors.ErrRepository{Msg: "Test Error"},
			withMock:   true,
			mockOutput: []interface{}{[]*Transaction{}, errors.New("Test Error")},
		},
	}

	for _, tc := range testCasesRepository {
		t.Log(tc.name)
		i := Interactor{}
		var m *testMock
		if tc.withMock {
			m = new(testMock)
			i.transactionsRepository = m
			m.On("GetAll").Return(tc.mockOutput...)
		}

		err := i.LoadDataFromRecords()

		if tc.withMock {
			m.AssertExpectations(t)
		}
		if !reflect.DeepEqual(tc.output, err) {
			t.Errorf("Expected '%v', got '%v'", tc.output, err)
		}
	}

	c := categories.New("Test Category")
	t1 := &Transaction{seller: sellers.New("d1", "d1"), category: c}
	t2 := &Transaction{seller: sellers.New("d2", "d2"), category: c}
	i := Interactor{}
	tm := new(testMock)
	i.transactionsRepository = tm
	tm.On("GetAll").Return([]*Transaction{t1, t2}, nil)

	testCasesIdentifierRepositorySave := []struct {
		name       string
		output     error
		withMock   bool
		mockInput  lib.Identifier
		mockOutput error
	}{
		{
			name:       "Returns error if entity repository is not defined",
			output:     customerrors.ErrInteractorUndefined,
			withMock:   false,
			mockInput:  nil,
			mockOutput: nil,
		},
		{
			name:       "Returns error if entity save method returns fail",
			output:     &customerrors.ErrInteractor{Msg: "Test Error"},
			withMock:   true,
			mockInput:  t1.seller,
			mockOutput: errors.New("Test Error"),
		},
	}

	for _, tc := range testCasesIdentifierRepositorySave {
		t.Log(tc.name)
		var im *lib.RepositoryMock
		if tc.withMock {
			im = new(lib.RepositoryMock)
			im.On("Save", tc.mockInput).Return(tc.mockOutput)
			i.sellersRepository = im
		}

		err := i.LoadDataFromRecords()

		if tc.withMock {
			im.AssertExpectations(t)
		}
		if !reflect.DeepEqual(tc.output, err) {
			t.Errorf("Expected '%v', got '%v'", tc.output, err)
		}
	}

}

type repositoryMock struct {
	mock.Mock
}

func (m *repositoryMock) GetAll() ([]*Transaction, error) {
	args := m.Called()
	return args.Get(0).([]*Transaction), args.Error(1)
}

func TestUnitReport(t *testing.T) {

	testCases := []struct {
		name       string
		output     error
		withMock   bool
		mockOutput []interface{}
	}{
		{
			name:   "Returns error if repository is undefined",
			output: customerrors.ErrRepositoryUndefined,
		},
		{
			name:       "Returns error if repository returns error",
			output:     &customerrors.ErrRepository{Msg: "Test Error"},
			withMock:   true,
			mockOutput: []interface{}{[]*Transaction{}, errors.New("Test Error")},
		},
		{
			name:       "Returns nil if success",
			output:     nil,
			withMock:   true,
			mockOutput: []interface{}{[]*Transaction{&Transaction{}}, nil},
		},
	}

	for _, tc := range testCases {
		t.Log(tc.name)
		i := Interactor{}
		var m *repositoryMock
		if tc.withMock {
			m = new(repositoryMock)
			m.On("GetAll").Return(tc.mockOutput...)
			i.transactionsRepository = m

			sellersMock := new(lib.RepositoryMock)
			sellersMock.On("GetAll").Return([]lib.Identifier{}, nil)
			i.sellersRepository = sellersMock
		}

		err := i.ReportFromRecords()

		if tc.withMock {
			m.AssertExpectations(t)
		}
		testkit.AssertEqual(t, tc.output, err)
	}

	trMock := new(repositoryMock)
	trMock.On("GetAll").Return([]*Transaction{&Transaction{seller: sellers.New("sellerSlug", "")}}, nil)

	testCasesSellerWithPrettyName := []struct {
		name       string
		output     error
		withMock   bool
		mockOutput []interface{}
	}{
		{
			name:   "Returns error if repository is undefined",
			output: customerrors.ErrRepositoryUndefined,
		},
		{
			name:       "Seller repository returns error",
			output:     &customerrors.ErrRepository{Msg: "Test error"},
			withMock:   true,
			mockOutput: []interface{}{[]lib.Identifier{}, errors.New("Test error")},
		},
		{
			name:     "Seller from transaction has no pretty name",
			output:   nil,
			withMock: true,
			mockOutput: []interface{}{
				[]lib.Identifier{sellers.New("sellerSlug", "sellerName")},
				nil,
			},
		},
	}

	for _, tc := range testCasesSellerWithPrettyName {
		t.Log(tc.name)
		i := Interactor{}
		i.transactionsRepository = trMock
		var m *lib.RepositoryMock
		if tc.withMock {
			m = new(lib.RepositoryMock)
			m.On("GetAll").Return(tc.mockOutput...)
			i.sellersRepository = m
		}

		err := i.ReportFromRecords()

		if tc.withMock {
			m.AssertExpectations(t)
		}
		testkit.AssertEqual(t, tc.output, err)
	}

}

func TestUnitMergeTransactionsWithSameSeller(t *testing.T) {

	decimalOne, _ := decimal.NewFromString("1")
	decimalTwo, _ := decimal.NewFromString("2")

	testCases := []struct {
		name   string
		input  []*Transaction
		output []*Transaction
	}{
		{
			name:   "Input slice is empty",
			input:  []*Transaction{},
			output: []*Transaction{},
		},
		{
			name:   "Input slice has one item, whitout seller",
			input:  []*Transaction{&Transaction{}},
			output: []*Transaction{},
		},
		{
			name:   "Input slice has one item, with seller",
			input:  []*Transaction{&Transaction{seller: sellers.New("SellerSlug", "SellerName")}},
			output: []*Transaction{&Transaction{seller: sellers.New("SellerSlug", "SellerName")}},
		},
		{
			name: "Input slice has two items, same seller",
			input: []*Transaction{
				&Transaction{value: &decimalOne, seller: sellers.New("SellerSlug", "SellerName")},
				&Transaction{value: &decimalOne, seller: sellers.New("SellerSlug", "SellerName")},
			},
			output: []*Transaction{&Transaction{value: &decimalTwo, seller: sellers.New("SellerSlug", "SellerName")}},
		},
	}

	for _, tc := range testCases {
		t.Log(tc.name)

		got, _ := mergeTransactions(tc.input)

		testkit.AssertEqual(t, tc.output, got)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	machinery "github.com/RichardKnop/machinery/v1"
	"github.com/RichardKnop/machinery/v1/config"
	"github.com/RichardKnop/machinery/v1/log"
	"github.com/RichardKnop/machinery/v1/tasks"
	"github.com/urfave/cli"

	exampletasks "github.com/RichardKnop/machinery/example/tasks"
)

var (
	app               *cli.App
	configPath        string
	broker            string
	defaultQueue      string
	resultBackend     string
	amqpExchange      string
	amqpExchangeType  string
	amqpBindingKey    string
	amqpPrefetchCount int64
)

func init() {
	// Initialise a CLI app
	app = cli.NewApp()
	app.Name = "machinery"
	app.Usage = "machinery worker and send example tasks with machinery send"
	app.Author = "Richard Knop"
	app.Email = "risoknop@gmail.com"
	app.Version = "0.0.0"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "c",
			Value:       "example/config.yml",
			Destination: &configPath,
			Usage:       "Path to a configuration file",
		},
		cli.StringFlag{
			Name:        "b",
			Value:       "amqp://guest:guest@localhost:5672/",
			Destination: &broker,
			Usage:       "Broker URL",
		},
		cli.StringFlag{
			Name:        "q",
			Value:       "machinery_tasks",
			Destination: &defaultQueue,
			Usage:       "Ephemeral AMQP/Redis queue name",
		},
		cli.StringFlag{
			Name:        "r",
			Value:       "amqp://guest:guest@localhost:5672/",
			Destination: &resultBackend,
			Usage:       "Result backend",
		},
		cli.StringFlag{
			Name:        "e",
			Value:       "machinery_exchange",
			Destination: &amqpExchange,
			Usage:       "Durable, non-auto-deleted AMQP exchange name",
		},
		cli.StringFlag{
			Name:        "t",
			Value:       "direct",
			Destination: &amqpExchangeType,
			Usage:       "Exchange type - direct|fanout|topic|x-custom",
		},
		cli.StringFlag{
			Name:        "k",
			Value:       "machinery_task",
			Destination: &amqpBindingKey,
			Usage:       "AMQP binding key",
		},
		cli.Int64Flag{
			Name:        "p",
			Value:       int64(3),
			Destination: &amqpPrefetchCount,
			Usage:       "AMQP prefetch count",
		},
	}
}

func main() {
	// Set the CLI app commands
	app.Commands = []cli.Command{
		{
			Name:  "worker",
			Usage: "launch machinery worker",
			Action: func(c *cli.Context) error {
				return worker()
			},
		},
		{
			Name:  "send",
			Usage: "send example tasks ",
			Action: func(c *cli.Context) error {
				return send()
			},
		},
	}

	// Run the CLI app
	if err := app.Run(os.Args); err != nil {
		log.FATAL.Print(err)
	}
}

func startServer() (*machinery.Server, error) {
	cnf := config.Config{
		Broker:        broker,
		DefaultQueue:  defaultQueue,
		ResultBackend: resultBackend,
		AMQP: &config.AMQPConfig{
			Exchange:      amqpExchange,
			ExchangeType:  amqpExchangeType,
			BindingKey:    amqpBindingKey,
			PrefetchCount: int(amqpPrefetchCount),
		},
	}

	// If present, the config file takes priority over cli flags
	data, err := config.ReadFromFile(configPath)
	if err != nil {
		log.ERROR.Printf("Could not load config from file: %s", err.Error())
	} else {
		if err = config.ParseYAMLConfig(&data, &cnf); err != nil {
			return nil, fmt.Errorf("Could not parse config file: %s", err.Error())
		}
	}

	// Create server instance
	server, err := machinery.NewServer(&cnf)
	if err != nil {
		return nil, fmt.Errorf("Could not initialize server: %s", err.Error())
	}

	// Register tasks
	tasks := map[string]interface{}{
		"add":        exampletasks.Add,
		"multiply":   exampletasks.Multiply,
		"panic_task": exampletasks.PanicTask,
	}
	server.RegisterTasks(tasks)

	return server, nil
}

func worker() error {
	server, err := startServer()
	if err != nil {
		return err
	}

	// The second argument is a consumer tag
	// Ideally, each worker should have a unique tag (worker1, worker2 etc)
	worker := server.NewWorker("machinery_worker")

	if err := worker.Launch(); err != nil {
		return fmt.Errorf("Could not launch worker: %s", err.Error())
	}

	return nil
}

func send() error {
	server, err := startServer()
	if err != nil {
		return err
	}

	var task0, task1, task2, task3, task4, task5 tasks.Signature

	var initTasks = func() {
		task0 = tasks.Signature{
			Name: "add",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 1,
				},
				{
					Type:  "int64",
					Value: 1,
				},
			},
		}

		task1 = tasks.Signature{
			Name: "add",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 2,
				},
				{
					Type:  "int64",
					Value: 2,
				},
			},
		}

		task2 = tasks.Signature{
			Name: "add",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 5,
				},
				{
					Type:  "int64",
					Value: 6,
				},
			},
		}

		task3 = tasks.Signature{
			Name: "multiply",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 4,
				},
			},
		}

		task4 = tasks.Signature{
			Name: "multiply",
		}

		task5 = tasks.Signature{
			Name: "panic_task",
		}
	}

	/*
	 * First, let's try sending a single task
	 */
	initTasks()
	log.INFO.Println("Single task:")

	asyncResult, err := server.SendTask(&task0)
	if err != nil {
		return fmt.Errorf("Could not send task: %s", err.Error())
	}

	results, err := asyncResult.Get()
	if err != nil {
		return fmt.Errorf("Getting task result failed with error: %s", err.Error())
	}
	log.INFO.Printf("1 + 1 = %v\n", results[0].Interface())

	/*
	 * Now let's explore ways of sending multiple tasks
	 */

	// Now let's try a parallel execution
	initTasks()
	log.INFO.Println("Group of tasks (parallel execution):")

	group := tasks.NewGroup(&task0, &task1, &task2)
	asyncResults, err := server.SendGroup(group)
	if err != nil {
		return fmt.Errorf("Could not send group: %s", err.Error())
	}

	for _, asyncResult := range asyncResults {
		results, err = asyncResult.Get()
		if err != nil {
			return fmt.Errorf("Getting task result failed with error: %s", err.Error())
		}
		log.INFO.Printf(
			"%v + %v = %v\n",
			asyncResult.Signature.Args[0].Value,
			asyncResult.Signature.Args[1].Value,
			results[0].Interface(),
		)
	}

	// Now let's try a group with a chord
	initTasks()
	log.INFO.Println("Group of tasks with a callback (chord):")

	group = tasks.NewGroup(&task0, &task1, &task2)
	chord := tasks.NewChord(group, &task4)
	chordAsyncResult, err := server.SendChord(chord)
	if err != nil {
		return fmt.Errorf("Could not send chord: %s", err.Error())
	}

	results, err = chordAsyncResult.Get()
	if err != nil {
		return fmt.Errorf("Getting chord result failed with error: %s", err.Error())
	}
	log.INFO.Printf("(1 + 1) * (2 + 2) * (5 + 6) = %v\n", results[0].Interface())

	// Now let's try chaining task results
	initTasks()
	log.INFO.Println("Chain of tasks:")

	chain := tasks.NewChain(&task0, &task1, &task2, &task3)
	chainAsyncResult, err := server.SendChain(chain)
	if err != nil {
		return fmt.Errorf("Could not send chain: %s", err.Error())
	}

	results, err = chainAsyncResult.Get()
	if err != nil {
		return fmt.Errorf("Getting chain result failed with error: %s", err.Error())
	}
	log.INFO.Printf("(((1 + 1) + (2 + 2)) + (5 + 6)) * 4 = %v\n", results[0].Interface())

	// Let's try a task which throws panic to make sure stack trace is not lost
	initTasks()
	asyncResult, err = server.SendTask(&task5)
	if err != nil {
		return fmt.Errorf("Could not send task: %s", err.Error())
	}

	return nil
}
<commit_msg>Small improvement to example executable.<commit_after>package main

import (
	"fmt"
	"os"

	machinery "github.com/RichardKnop/machinery/v1"
	"github.com/RichardKnop/machinery/v1/config"
	"github.com/RichardKnop/machinery/v1/log"
	"github.com/RichardKnop/machinery/v1/tasks"
	"github.com/urfave/cli"

	exampletasks "github.com/RichardKnop/machinery/example/tasks"
)

var (
	app               *cli.App
	configPath        string
	broker            string
	defaultQueue      string
	resultBackend     string
	amqpExchange      string
	amqpExchangeType  string
	amqpBindingKey    string
	amqpPrefetchCount int64
)

func init() {
	// Initialise a CLI app
	app = cli.NewApp()
	app.Name = "machinery"
	app.Usage = "machinery worker and send example tasks with machinery send"
	app.Author = "Richard Knop"
	app.Email = "risoknop@gmail.com"
	app.Version = "0.0.0"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "c",
			Value:       "config.yml",
			Destination: &configPath,
			Usage:       "Path to a configuration file",
		},
		cli.StringFlag{
			Name:        "b",
			Value:       "amqp://guest:guest@localhost:5672/",
			Destination: &broker,
			Usage:       "Broker URL",
		},
		cli.StringFlag{
			Name:        "q",
			Value:       "machinery_tasks",
			Destination: &defaultQueue,
			Usage:       "Ephemeral AMQP/Redis queue name",
		},
		cli.StringFlag{
			Name:        "r",
			Value:       "amqp://guest:guest@localhost:5672/",
			Destination: &resultBackend,
			Usage:       "Result backend",
		},
		cli.StringFlag{
			Name:        "e",
			Value:       "machinery_exchange",
			Destination: &amqpExchange,
			Usage:       "Durable, non-auto-deleted AMQP exchange name",
		},
		cli.StringFlag{
			Name:        "t",
			Value:       "direct",
			Destination: &amqpExchangeType,
			Usage:       "Exchange type - direct|fanout|topic|x-custom",
		},
		cli.StringFlag{
			Name:        "k",
			Value:       "machinery_task",
			Destination: &amqpBindingKey,
			Usage:       "AMQP binding key",
		},
		cli.Int64Flag{
			Name:        "p",
			Value:       int64(3),
			Destination: &amqpPrefetchCount,
			Usage:       "AMQP prefetch count",
		},
	}
}

func main() {
	// Set the CLI app commands
	app.Commands = []cli.Command{
		{
			Name:  "worker",
			Usage: "launch machinery worker",
			Action: func(c *cli.Context) error {
				return worker()
			},
		},
		{
			Name:  "send",
			Usage: "send example tasks ",
			Action: func(c *cli.Context) error {
				return send()
			},
		},
	}

	// Run the CLI app
	if err := app.Run(os.Args); err != nil {
		log.FATAL.Print(err)
	}
}

func startServer() (*machinery.Server, error) {
	cnf := config.Config{
		Broker:        broker,
		DefaultQueue:  defaultQueue,
		ResultBackend: resultBackend,
		AMQP: &config.AMQPConfig{
			Exchange:      amqpExchange,
			ExchangeType:  amqpExchangeType,
			BindingKey:    amqpBindingKey,
			PrefetchCount: int(amqpPrefetchCount),
		},
	}

	// If present, the config file takes priority over cli flags
	data, err := config.ReadFromFile(configPath)
	if err != nil {
		log.WARNING.Printf("Could not load config from file: %s", err.Error())
	} else {
		if err = config.ParseYAMLConfig(&data, &cnf); err != nil {
			return nil, fmt.Errorf("Could not parse config file: %s", err.Error())
		}
	}

	// Create server instance
	server, err := machinery.NewServer(&cnf)
	if err != nil {
		return nil, fmt.Errorf("Could not initialize server: %s", err.Error())
	}

	// Register tasks
	tasks := map[string]interface{}{
		"add":        exampletasks.Add,
		"multiply":   exampletasks.Multiply,
		"panic_task": exampletasks.PanicTask,
	}
	server.RegisterTasks(tasks)

	return server, nil
}

func worker() error {
	server, err := startServer()
	if err != nil {
		return err
	}

	// The second argument is a consumer tag
	// Ideally, each worker should have a unique tag (worker1, worker2 etc)
	worker := server.NewWorker("machinery_worker")

	if err := worker.Launch(); err != nil {
		return fmt.Errorf("Could not launch worker: %s", err.Error())
	}

	return nil
}

func send() error {
	server, err := startServer()
	if err != nil {
		return err
	}

	var task0, task1, task2, task3, task4, task5 tasks.Signature

	var initTasks = func() {
		task0 = tasks.Signature{
			Name: "add",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 1,
				},
				{
					Type:  "int64",
					Value: 1,
				},
			},
		}

		task1 = tasks.Signature{
			Name: "add",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 2,
				},
				{
					Type:  "int64",
					Value: 2,
				},
			},
		}

		task2 = tasks.Signature{
			Name: "add",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 5,
				},
				{
					Type:  "int64",
					Value: 6,
				},
			},
		}

		task3 = tasks.Signature{
			Name: "multiply",
			Args: []tasks.Arg{
				{
					Type:  "int64",
					Value: 4,
				},
			},
		}

		task4 = tasks.Signature{
			Name: "multiply",
		}

		task5 = tasks.Signature{
			Name: "panic_task",
		}
	}

	/*
	 * First, let's try sending a single task
	 */
	initTasks()
	log.INFO.Println("Single task:")

	asyncResult, err := server.SendTask(&task0)
	if err != nil {
		return fmt.Errorf("Could not send task: %s", err.Error())
	}

	results, err := asyncResult.Get()
	if err != nil {
		return fmt.Errorf("Getting task result failed with error: %s", err.Error())
	}
	log.INFO.Printf("1 + 1 = %v\n", results[0].Interface())

	/*
	 * Now let's explore ways of sending multiple tasks
	 */

	// Now let's try a parallel execution
	initTasks()
	log.INFO.Println("Group of tasks (parallel execution):")

	group := tasks.NewGroup(&task0, &task1, &task2)
	asyncResults, err := server.SendGroup(group)
	if err != nil {
		return fmt.Errorf("Could not send group: %s", err.Error())
	}

	for _, asyncResult := range asyncResults {
		results, err = asyncResult.Get()
		if err != nil {
			return fmt.Errorf("Getting task result failed with error: %s", err.Error())
		}
		log.INFO.Printf(
			"%v + %v = %v\n",
			asyncResult.Signature.Args[0].Value,
			asyncResult.Signature.Args[1].Value,
			results[0].Interface(),
		)
	}

	// Now let's try a group with a chord
	initTasks()
	log.INFO.Println("Group of tasks with a callback (chord):")

	group = tasks.NewGroup(&task0, &task1, &task2)
	chord := tasks.NewChord(group, &task4)
	chordAsyncResult, err := server.SendChord(chord)
	if err != nil {
		return fmt.Errorf("Could not send chord: %s", err.Error())
	}

	results, err = chordAsyncResult.Get()
	if err != nil {
		return fmt.Errorf("Getting chord result failed with error: %s", err.Error())
	}
	log.INFO.Printf("(1 + 1) * (2 + 2) * (5 + 6) = %v\n", results[0].Interface())

	// Now let's try chaining task results
	initTasks()
	log.INFO.Println("Chain of tasks:")

	chain := tasks.NewChain(&task0, &task1, &task2, &task3)
	chainAsyncResult, err := server.SendChain(chain)
	if err != nil {
		return fmt.Errorf("Could not send chain: %s", err.Error())
	}

	results, err = chainAsyncResult.Get()
	if err != nil {
		return fmt.Errorf("Getting chain result failed with error: %s", err.Error())
	}
	log.INFO.Printf("(((1 + 1) + (2 + 2)) + (5 + 6)) * 4 = %v\n", results[0].Interface())

	// Let's try a task which throws panic to make sure stack trace is not lost
	initTasks()
	asyncResult, err = server.SendTask(&task5)
	if err != nil {
		return fmt.Errorf("Could not send task: %s", err.Error())
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Davis Webb
// Copyright 2015 Luke Shumaker
// Copyright 2015 Guntas Grewal

package store

import (
	"github.com/jinzhu/gorm"
	he "httpentity"
	"httpentity/util" // heutil
	"io"
	"jsonpatch"
	"periwinkle/util" // putil
	"strings"
)

var _ he.Entity = &Group{}
var _ he.NetEntity = &Group{}
var dirGroups he.Entity = newDirGroups()

// Model /////////////////////////////////////////////////////////////

type Group struct {
	Id        string         `json:"group_id"`
	Addresses []GroupAddress `json:"addresses"`
}

func (o Group) dbSchema(db *gorm.DB) error {
	return db.CreateTable(&o).Error
}

func (o Group) dbSeed(db *gorm.DB) error {
	errs := []error{}
	errHelper(&errs, db.Create(&Group{"test", []GroupAddress{{0,"test","twilio","add_twilio_phone_number", "test_user"}}}).Error)
	return errorList(errs)
}

type GroupAddress struct {
	Id      int64  `json:"group_address_id"`
	GroupId string `json:"group_id"`
	Medium  string `json:"medium"`
	Address string `json:"address"`
	UserId 	string `json:"user_id"`
}

func (o GroupAddress) dbSchema(db *gorm.DB) error {
	return db.CreateTable(&o).
		AddForeignKey("group_id", "groups(id)", "RESTRICT", "RESTRICT").
		AddForeignKey("medium", "media(id)", "RESTRICT", "RESTRICT").
		AddUniqueIndex("uniqueness_idx", "medium", "address").
		Error
}

func GetGroupById(db *gorm.DB, id string) *Group {
	var o Group
	if result := db.First(&o, "id = ?", id); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetUsersInGroup(db *gorm.DB, groupId string) *[]User {
	groupAddresses := GetGroupAddressByGroupId(db, groupId)
	var users []User
	for _, groupAddr := range *groupAddresses {
		users = append(users, *GetUserById(db, groupAddr.UserId))
	}

	/*             No longer using this as it is super innificient but keep it just in case
	err := db.Joins("inner join user_addresses on user_addresses.user_id = users.id").Joins(
	"inner join subscriptions on subscriptions.address_id = user_addresses.id").Where(
	"subscriptions.group_id = ?", groupId).Find(&users)
	*/
	return &users
}

func GetGroupAddressByGroupId(db *gorm.DB, groupId string) *[]GroupAddress {
        var o []GroupAddress
        if result := db.Where("group_id =?", groupId).Find(&o); result.Error != nil {
                if result.RecordNotFound() {
                        return nil
                }
                panic(result.Error)
        }
        return &o
}

func GetGroupByAddress(db *gorm.DB, address string) *Group {
	var o Group
	if result := db.Joins("inner join groups on group_addresses.group_id = groups.id").Where("group_addresses.address = ?", address).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetGroupAddressesByMediumAndGroupId(db *gorm.DB, medium string, groupId string) *[]GroupAddress {
	var o []GroupAddress
	if result := db.Where("medium =? and group_id =?", medium, groupId).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetGroupByUserId(db *gorm.DB, id string) *Group {
	var o Group
	if result := db.Where("user_id", id).First(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetGroupsByUserId(db *gorm.DB, id string) *[]Group {
	var o []Group
	if result := db.Where("user_id", id).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetGroupAddressesByMedium(db *gorm.DB, medium string) *[]GroupAddress {
	var o []GroupAddress
	if result := db.Where("medium =?", medium).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func NewGroup(db *gorm.DB, name string) *Group {
	o := Group{Id: name}
	if err := db.Create(&o).Error; err != nil {
		panic(err)
	}
	return &o
}

func NewGroupAddress(db *gorm.DB, id int64, group_id string, medium string, address string, user_id string) *GroupAddress {
	o := GroupAddress{
		Id      	:id,
		GroupId 	:group_id,
		Medium  	:medium,
		Address 	:address,
		UserId 		:user_id,
	}
	if err := db.Create(&o).Error; err != nil {
		panic(err)
	}
	return &o
}

func (o *Group) Save(db *gorm.DB) {
	if err := db.Save(o).Error; err != nil {
		panic(err)
	}
}

func (o *Group) Subentity(name string, req he.Request) he.Entity {
	panic("TODO: API: (*Group).Subentity()")
}

func (o *Group) Methods() map[string]func(he.Request) he.Response {
	return map[string]func(he.Request) he.Response{
		"GET": func(req he.Request) he.Response {
			return he.StatusOK(o)
		},
		"PUT": func(req he.Request) he.Response {
			db := req.Things["db"].(*gorm.DB)
			sess := req.Things["session"].(*Session)
			users := GetUsersInGroup(db, o.Id)
			flag := false
			for _, user := range *users {
				if sess.UserId == user.Id {
					flag = true
					break
				}
			}
			if !flag {
				return he.StatusForbidden(heutil.NetString("Unauthorized user"))
			}

			var new_group Group
			err := safeDecodeJSON(req.Entity, &new_group)
			if err != nil {
				return err.Response()
			}
			if o.Id != new_group.Id {
				return he.StatusConflict(heutil.NetString("Cannot change group id"))
			}
			*o = new_group
			o.Save(db)
			return he.StatusOK(o)
		},
		"PATCH": func(req he.Request) he.Response {
			db := req.Things["db"].(*gorm.DB)
			sess := req.Things["session"].(*Session)
			users := GetUsersInGroup(db, o.Id)
			flag := false
			for _, user := range *users {
				if sess.UserId == user.Id {
					flag = true
					break
				}
			}
			if !flag {
				return he.StatusForbidden(heutil.NetString("Unauthorized user"))
			}

			patch, ok := req.Entity.(jsonpatch.Patch)
			if !ok {
				return putil.HTTPErrorf(415, "PATCH request must have a patch media type").Response()
			}
			var new_group Group
			err := patch.Apply(o, &new_group)
			if err != nil {
				return putil.HTTPErrorf(409, "%v", err).Response()
			}
			if o.Id != new_group.Id {
				return he.StatusConflict(heutil.NetString("Cannot change user id"))
			}
			*o = new_group
			o.Save(db)
			return he.StatusOK(o)
		},
		"DELETE": func(req he.Request) he.Response {
                        db := req.Things["db"].(*gorm.DB)
                        db.Delete(o)
                        return he.StatusGone(heutil.NetString("Group has been deleted"))
		},
	}
}

// View //////////////////////////////////////////////////////////////

func (o *Group) Encoders() map[string]func(io.Writer) error {
	return defaultEncoders(o)
}

// Directory ("Controller") //////////////////////////////////////////

type t_dirGroups struct {
	methods map[string]func(he.Request) he.Response
}

func newDirGroups() t_dirGroups {
	r := t_dirGroups{}
	r.methods = map[string]func(he.Request) he.Response{
		"GET": func(req he.Request) he.Response {
			return he.StatusNoContent()
			/*
			db := req.Things["db"].(*gorm.DB)
			type getfmt struct {
				UserId string `json:"userid"`
			}
			var entity getfmt
			httperr := safeDecodeJSON(req.Entity, &entity)
			if httperr != nil {
                                return httperr.Response()
			}
			entity.UserId = strings.ToLower(entity.UserId)
			groups := GetGroupsByUserId(db, entity.UserId)
			return he.StatusOK(groups)
			*/
		},
		"POST": func(req he.Request) he.Response {
			db := req.Things["db"].(*gorm.DB)
			type postfmt struct {
				Groupname string `json:"groupname"`
			}
			var entity postfmt
			httperr := safeDecodeJSON(req.Entity, &entity)
			if httperr != nil {
				return httperr.Response()
			}

			entity.Groupname = strings.ToLower(entity.Groupname)

			group := NewGroup(db, entity.Groupname)
			if group == nil {
				return he.StatusConflict(heutil.NetString("a group with that name already exists"))
			} else {
				return he.StatusCreated(r, entity.Groupname, req)
			}
		},
	}
	return r
}

func (d t_dirGroups) Methods() map[string]func(he.Request) he.Response {
	return d.methods
}

func (d t_dirGroups) Subentity(name string, req he.Request) he.Entity {
        name = strings.ToLower(name)
        sess := req.Things["session"].(*Session)
        if sess == nil && req.Method == "POST" {
                group, ok := req.Things["group"].(Group)
                if !ok {
                        return nil
                }
                if group.Id == name {
                        return &group
                }
                return nil
        }
        db := req.Things["db"].(*gorm.DB)
	return GetGroupById(db, name)
}
<commit_msg>we are returning groups<commit_after>// Copyright 2015 Davis Webb
// Copyright 2015 Luke Shumaker
// Copyright 2015 Guntas Grewal

package store

import (
	"github.com/jinzhu/gorm"
	he "httpentity"
	"httpentity/util" // heutil
	"io"
	"jsonpatch"
	"periwinkle/util" // putil
	"strings"
)

var _ he.Entity = &Group{}
var _ he.NetEntity = &Group{}
var dirGroups he.Entity = newDirGroups()

// Model /////////////////////////////////////////////////////////////

type Group struct {
	Id        string         `json:"group_id"`
	Addresses []GroupAddress `json:"addresses"`
}

func (o Group) dbSchema(db *gorm.DB) error {
	return db.CreateTable(&o).Error
}

func (o Group) dbSeed(db *gorm.DB) error {
	errs := []error{}
	errHelper(&errs, db.Create(&Group{"test", []GroupAddress{{0,"test","twilio","add_twilio_phone_number", "test_user"}}}).Error)
	return errorList(errs)
}

type GroupAddress struct {
	Id      int64  `json:"group_address_id"`
	GroupId string `json:"group_id"`
	Medium  string `json:"medium"`
	Address string `json:"address"`
	UserId 	string `json:"user_id"`
}

func (o GroupAddress) dbSchema(db *gorm.DB) error {
	return db.CreateTable(&o).
		AddForeignKey("group_id", "groups(id)", "RESTRICT", "RESTRICT").
		AddForeignKey("medium", "media(id)", "RESTRICT", "RESTRICT").
		AddUniqueIndex("uniqueness_idx", "medium", "address").
		Error
}

func GetGroupById(db *gorm.DB, id string) *Group {
	var o Group
	if result := db.First(&o, "id = ?", id); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetUsersInGroup(db *gorm.DB, groupId string) *[]User {
	groupAddresses := GetGroupAddressByGroupId(db, groupId)
	var users []User
	for _, groupAddr := range *groupAddresses {
		users = append(users, *GetUserById(db, groupAddr.UserId))
	}

	/*             No longer using this as it is super innificient but keep it just in case
	err := db.Joins("inner join user_addresses on user_addresses.user_id = users.id").Joins(
	"inner join subscriptions on subscriptions.address_id = user_addresses.id").Where(
	"subscriptions.group_id = ?", groupId).Find(&users)
	*/
	return &users
}

func GetGroupAddressByGroupId(db *gorm.DB, groupId string) *[]GroupAddress {
        var o []GroupAddress
        if result := db.Where("group_id =?", groupId).Find(&o); result.Error != nil {
                if result.RecordNotFound() {
                        return nil
                }
                panic(result.Error)
        }
        return &o
}

func GetGroupByAddress(db *gorm.DB, address string) *Group {
	var o Group
	if result := db.Joins("inner join groups on group_addresses.group_id = groups.id").Where("group_addresses.address = ?", address).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetGroupAddressesByMediumAndGroupId(db *gorm.DB, medium string, groupId string) *[]GroupAddress {
	var o []GroupAddress
	if result := db.Where("medium =? and group_id =?", medium, groupId).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetGroupByUserId(db *gorm.DB, id string) *Group {
	var o Group
	if result := db.Where("user_id", id).First(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func GetGroupsByUserId(db *gorm.DB, id string) *[]Group {
	var o []GroupAddress
	if result := db.Where("user_id", id).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}

	g := make([]Group, len(o))
	for i, group := range o {
		a := GetGroupById(db, group.GroupId)
		if a != nil {
			g[i] = *a
		}
	}
	return &g
}

func GetGroupAddressesByMedium(db *gorm.DB, medium string) *[]GroupAddress {
	var o []GroupAddress
	if result := db.Where("medium =?", medium).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		panic(result.Error)
	}
	return &o
}

func NewGroup(db *gorm.DB, name string) *Group {
	o := Group{Id: name}
	if err := db.Create(&o).Error; err != nil {
		panic(err)
	}
	return &o
}

func NewGroupAddress(db *gorm.DB, id int64, group_id string, medium string, address string, user_id string) *GroupAddress {
	o := GroupAddress{
		Id      	:id,
		GroupId 	:group_id,
		Medium  	:medium,
		Address 	:address,
		UserId 		:user_id,
	}
	if err := db.Create(&o).Error; err != nil {
		panic(err)
	}
	return &o
}

func (o *Group) Save(db *gorm.DB) {
	if err := db.Save(o).Error; err != nil {
		panic(err)
	}
}

func (o *Group) Subentity(name string, req he.Request) he.Entity {
	panic("TODO: API: (*Group).Subentity()")
}

func (o *Group) Methods() map[string]func(he.Request) he.Response {
	return map[string]func(he.Request) he.Response{
		"GET": func(req he.Request) he.Response {
			return he.StatusOK(o)
		},
		"PUT": func(req he.Request) he.Response {
			db := req.Things["db"].(*gorm.DB)
			sess := req.Things["session"].(*Session)
			users := GetUsersInGroup(db, o.Id)
			flag := false
			for _, user := range *users {
				if sess.UserId == user.Id {
					flag = true
					break
				}
			}
			if !flag {
				return he.StatusForbidden(heutil.NetString("Unauthorized user"))
			}

			var new_group Group
			err := safeDecodeJSON(req.Entity, &new_group)
			if err != nil {
				return err.Response()
			}
			if o.Id != new_group.Id {
				return he.StatusConflict(heutil.NetString("Cannot change group id"))
			}
			*o = new_group
			o.Save(db)
			return he.StatusOK(o)
		},
		"PATCH": func(req he.Request) he.Response {
			db := req.Things["db"].(*gorm.DB)
			sess := req.Things["session"].(*Session)
			users := GetUsersInGroup(db, o.Id)
			flag := false
			for _, user := range *users {
				if sess.UserId == user.Id {
					flag = true
					break
				}
			}
			if !flag {
				return he.StatusForbidden(heutil.NetString("Unauthorized user"))
			}

			patch, ok := req.Entity.(jsonpatch.Patch)
			if !ok {
				return putil.HTTPErrorf(415, "PATCH request must have a patch media type").Response()
			}
			var new_group Group
			err := patch.Apply(o, &new_group)
			if err != nil {
				return putil.HTTPErrorf(409, "%v", err).Response()
			}
			if o.Id != new_group.Id {
				return he.StatusConflict(heutil.NetString("Cannot change user id"))
			}
			*o = new_group
			o.Save(db)
			return he.StatusOK(o)
		},
		"DELETE": func(req he.Request) he.Response {
                        db := req.Things["db"].(*gorm.DB)
                        db.Delete(o)
                        return he.StatusGone(heutil.NetString("Group has been deleted"))
		},
	}
}

// View //////////////////////////////////////////////////////////////

func (o *Group) Encoders() map[string]func(io.Writer) error {
	return defaultEncoders(o)
}

// Directory ("Controller") //////////////////////////////////////////

type t_dirGroups struct {
	methods map[string]func(he.Request) he.Response
}

func newDirGroups() t_dirGroups {
	r := t_dirGroups{}
	r.methods = map[string]func(he.Request) he.Response{
		"GET": func(req he.Request) he.Response {
			//return he.StatusNoContent()

			db := req.Things["db"].(*gorm.DB)
			type getfmt struct {
				UserId string `json:"userid"`
			}
			var entity getfmt
			entity.UserId = strings.ToLower(entity.UserId)
			groups := GetGroupsByUserId(db, entity.UserId)
			generic := make([]interface{}, len(*groups))
			for i, group := range *groups {
				generic[i] = group.Id
			}

			return he.StatusOK(heutil.NetList(generic))

		},
		"POST": func(req he.Request) he.Response {
			db := req.Things["db"].(*gorm.DB)
			type postfmt struct {
				Groupname string `json:"groupname"`
			}
			var entity postfmt
			httperr := safeDecodeJSON(req.Entity, &entity)
			if httperr != nil {
				return httperr.Response()
			}

			entity.Groupname = strings.ToLower(entity.Groupname)

			group := NewGroup(db, entity.Groupname)
			if group == nil {
				return he.StatusConflict(heutil.NetString("a group with that name already exists"))
			} else {
				return he.StatusCreated(r, entity.Groupname, req)
			}
		},
	}
	return r
}

func (d t_dirGroups) Methods() map[string]func(he.Request) he.Response {
	return d.methods
}

func (d t_dirGroups) Subentity(name string, req he.Request) he.Entity {
        name = strings.ToLower(name)
        sess := req.Things["session"].(*Session)
        if sess == nil && req.Method == "POST" {
                group, ok := req.Things["group"].(Group)
                if !ok {
                        return nil
                }
                if group.Id == name {
                        return &group
                }
                return nil
        }
        db := req.Things["db"].(*gorm.DB)
	return GetGroupById(db, name)
}
<|endoftext|>


<commit_before>// Copyright 2011 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 spdy is an incomplete implementation of the SPDY protocol.
//
// The implementation follows draft 2 of the spec:
// https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft2
package spdy

import (
	"bytes"
	"compress/zlib"
	"encoding/binary"
	"http"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"
)

// Version is the protocol version number that this package implements.
const Version = 2

// ControlFrameType stores the type field in a control frame header.
type ControlFrameType uint16

// Control frame type constants
const (
	TypeSynStream    ControlFrameType = 0x0001
	TypeSynReply     = 0x0002
	TypeRstStream    = 0x0003
	TypeSettings     = 0x0004
	TypeNoop         = 0x0005
	TypePing         = 0x0006
	TypeGoaway       = 0x0007
	TypeHeaders      = 0x0008
	TypeWindowUpdate = 0x0009
)

func (t ControlFrameType) String() string {
	switch t {
	case TypeSynStream:
		return "SYN_STREAM"
	case TypeSynReply:
		return "SYN_REPLY"
	case TypeRstStream:
		return "RST_STREAM"
	case TypeSettings:
		return "SETTINGS"
	case TypeNoop:
		return "NOOP"
	case TypePing:
		return "PING"
	case TypeGoaway:
		return "GOAWAY"
	case TypeHeaders:
		return "HEADERS"
	case TypeWindowUpdate:
		return "WINDOW_UPDATE"
	}
	return "Type(" + strconv.Itoa(int(t)) + ")"
}

type FrameFlags uint8

// Stream frame flags
const (
	FlagFin            FrameFlags = 0x01
	FlagUnidirectional = 0x02
)

// SETTINGS frame flags
const (
	FlagClearPreviouslyPersistedSettings = 0x01
)

// MaxDataLength is the maximum number of bytes that can be stored in one frame.
const MaxDataLength = 1<<24 - 1

// A Frame is a framed message as sent between clients and servers.
// There are two types of frames: control frames and data frames.
type Frame struct {
	Header [4]byte
	Flags  FrameFlags
	Data   []byte
}

// ControlFrame creates a control frame with the given information.
func ControlFrame(t ControlFrameType, f FrameFlags, data []byte) Frame {
	return Frame{
		Header: [4]byte{
			(Version&0xff00)>>8 | 0x80,
			(Version & 0x00ff),
			byte((t & 0xff00) >> 8),
			byte((t & 0x00ff) >> 0),
		},
		Flags: f,
		Data:  data,
	}
}

// DataFrame creates a data frame with the given information.
func DataFrame(streamId uint32, f FrameFlags, data []byte) Frame {
	return Frame{
		Header: [4]byte{
			byte(streamId & 0x7f000000 >> 24),
			byte(streamId & 0x00ff0000 >> 16),
			byte(streamId & 0x0000ff00 >> 8),
			byte(streamId & 0x000000ff >> 0),
		},
		Flags: f,
		Data:  data,
	}
}

// ReadFrame reads an entire frame into memory.
func ReadFrame(r io.Reader) (f Frame, err os.Error) {
	_, err = io.ReadFull(r, f.Header[:])
	if err != nil {
		return
	}
	err = binary.Read(r, binary.BigEndian, &f.Flags)
	if err != nil {
		return
	}
	var lengthField [3]byte
	_, err = io.ReadFull(r, lengthField[:])
	if err != nil {
		if err == os.EOF {
			err = io.ErrUnexpectedEOF
		}
		return
	}
	var length uint32
	length |= uint32(lengthField[0]) << 16
	length |= uint32(lengthField[1]) << 8
	length |= uint32(lengthField[2]) << 0
	if length > 0 {
		f.Data = make([]byte, int(length))
		_, err = io.ReadFull(r, f.Data)
		if err == os.EOF {
			err = io.ErrUnexpectedEOF
		}
	} else {
		f.Data = []byte{}
	}
	return
}

// IsControl returns whether the frame holds a control frame.
func (f Frame) IsControl() bool {
	return f.Header[0]&0x80 != 0
}

// Type obtains the type field if the frame is a control frame, otherwise it returns zero.
func (f Frame) Type() ControlFrameType {
	if !f.IsControl() {
		return 0
	}
	return (ControlFrameType(f.Header[2])<<8 | ControlFrameType(f.Header[3]))
}

// StreamId returns the stream ID field if the frame is a data frame, otherwise it returns zero.
func (f Frame) StreamId() (id uint32) {
	if f.IsControl() {
		return 0
	}
	id |= uint32(f.Header[0]) << 24
	id |= uint32(f.Header[1]) << 16
	id |= uint32(f.Header[2]) << 8
	id |= uint32(f.Header[3]) << 0
	return
}

// WriteTo writes the frame in the SPDY format.
func (f Frame) WriteTo(w io.Writer) (n int64, err os.Error) {
	var nn int
	// Header
	nn, err = w.Write(f.Header[:])
	n += int64(nn)
	if err != nil {
		return
	}
	// Flags
	nn, err = w.Write([]byte{byte(f.Flags)})
	n += int64(nn)
	if err != nil {
		return
	}
	// Length
	nn, err = w.Write([]byte{
		byte(len(f.Data) & 0x00ff0000 >> 16),
		byte(len(f.Data) & 0x0000ff00 >> 8),
		byte(len(f.Data) & 0x000000ff),
	})
	n += int64(nn)
	if err != nil {
		return
	}
	// Data
	if len(f.Data) > 0 {
		nn, err = w.Write(f.Data)
		n += int64(nn)
	}
	return
}

// headerDictionary is the dictionary sent to the zlib compressor/decompressor.
// Even though the specification states there is no null byte at the end, Chrome sends it.
const headerDictionary = "optionsgetheadpostputdeletetrace" +
	"acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" +
	"if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" +
	"max-forwardsproxy-authorizationrangerefererteuser-agent" +
	"100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" +
	"accept-rangesageetaglocationproxy-authenticatepublicretry-after" +
	"servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" +
	"connectiondatetrailertransfer-encodingupgradeviawarning" +
	"content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" +
	"MondayTuesdayWednesdayThursdayFridaySaturdaySunday" +
	"JanFebMarAprMayJunJulAugSepOctNovDec" +
	"chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" +
	"charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00"

// hrSource is a reader that passes through reads from another reader.
// When the underlying reader reaches EOF, Read will block until another reader is added via change.
type hrSource struct {
	r io.Reader
	m sync.RWMutex
	c *sync.Cond
}

func (src *hrSource) Read(p []byte) (n int, err os.Error) {
	src.m.RLock()
	for src.r == nil {
		src.c.Wait()
	}
	n, err = src.r.Read(p)
	src.m.RUnlock()
	if err == os.EOF {
		src.change(nil)
		err = nil
	}
	return
}

func (src *hrSource) change(r io.Reader) {
	src.m.Lock()
	defer src.m.Unlock()
	src.r = r
	src.c.Broadcast()
}

// A HeaderReader reads zlib-compressed headers.
type HeaderReader struct {
	source       hrSource
	decompressor io.ReadCloser
}

// NewHeaderReader creates a HeaderReader with the initial dictionary.
func NewHeaderReader() (hr *HeaderReader) {
	hr = new(HeaderReader)
	hr.source.c = sync.NewCond(hr.source.m.RLocker())
	return
}

// ReadHeader reads a set of headers from a reader.
func (hr *HeaderReader) ReadHeader(r io.Reader) (h http.Header, err os.Error) {
	hr.source.change(r)
	h, err = hr.read()
	return
}

// Decode reads a set of headers from a block of bytes.
func (hr *HeaderReader) Decode(data []byte) (h http.Header, err os.Error) {
	hr.source.change(bytes.NewBuffer(data))
	h, err = hr.read()
	return
}

func (hr *HeaderReader) read() (h http.Header, err os.Error) {
	var count uint16
	if hr.decompressor == nil {
		hr.decompressor, err = zlib.NewReaderDict(&hr.source, []byte(headerDictionary))
		if err != nil {
			return
		}
	}
	err = binary.Read(hr.decompressor, binary.BigEndian, &count)
	if err != nil {
		return
	}
	h = make(http.Header, int(count))
	for i := 0; i < int(count); i++ {
		var name, value string
		name, err = readHeaderString(hr.decompressor)
		if err != nil {
			return
		}
		value, err = readHeaderString(hr.decompressor)
		if err != nil {
			return
		}
		valueList := strings.Split(string(value), "\x00", -1)
		for _, v := range valueList {
			h.Add(name, v)
		}
	}
	return
}

func readHeaderString(r io.Reader) (s string, err os.Error) {
	var length uint16
	err = binary.Read(r, binary.BigEndian, &length)
	if err != nil {
		return
	}
	data := make([]byte, int(length))
	_, err = io.ReadFull(r, data)
	if err != nil {
		return
	}
	return string(data), nil
}

// HeaderWriter will write zlib-compressed headers on different streams.
type HeaderWriter struct {
	compressor *zlib.Writer
	buffer     *bytes.Buffer
}

// NewHeaderWriter creates a HeaderWriter ready to compress headers.
func NewHeaderWriter(level int) (hw *HeaderWriter) {
	hw = &HeaderWriter{buffer: new(bytes.Buffer)}
	hw.compressor, _ = zlib.NewWriterDict(hw.buffer, level, []byte(headerDictionary))
	return
}

// WriteHeader writes a header block directly to an output.
func (hw *HeaderWriter) WriteHeader(w io.Writer, h http.Header) (err os.Error) {
	hw.write(h)
	_, err = io.Copy(w, hw.buffer)
	hw.buffer.Reset()
	return
}

// Encode returns a compressed header block.
func (hw *HeaderWriter) Encode(h http.Header) (data []byte) {
	hw.write(h)
	data = make([]byte, hw.buffer.Len())
	hw.buffer.Read(data)
	return
}

func (hw *HeaderWriter) write(h http.Header) {
	binary.Write(hw.compressor, binary.BigEndian, uint16(len(h)))
	for k, vals := range h {
		k = strings.ToLower(k)
		binary.Write(hw.compressor, binary.BigEndian, uint16(len(k)))
		binary.Write(hw.compressor, binary.BigEndian, []byte(k))
		v := strings.Join(vals, "\x00")
		binary.Write(hw.compressor, binary.BigEndian, uint16(len(v)))
		binary.Write(hw.compressor, binary.BigEndian, []byte(v))
	}
	hw.compressor.Flush()
}
<commit_msg>http/spdy: add type to FlagClearPreviouslyPersistedSettings constant<commit_after>// Copyright 2011 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 spdy is an incomplete implementation of the SPDY protocol.
//
// The implementation follows draft 2 of the spec:
// https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft2
package spdy

import (
	"bytes"
	"compress/zlib"
	"encoding/binary"
	"http"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"
)

// Version is the protocol version number that this package implements.
const Version = 2

// ControlFrameType stores the type field in a control frame header.
type ControlFrameType uint16

// Control frame type constants
const (
	TypeSynStream    ControlFrameType = 0x0001
	TypeSynReply     = 0x0002
	TypeRstStream    = 0x0003
	TypeSettings     = 0x0004
	TypeNoop         = 0x0005
	TypePing         = 0x0006
	TypeGoaway       = 0x0007
	TypeHeaders      = 0x0008
	TypeWindowUpdate = 0x0009
)

func (t ControlFrameType) String() string {
	switch t {
	case TypeSynStream:
		return "SYN_STREAM"
	case TypeSynReply:
		return "SYN_REPLY"
	case TypeRstStream:
		return "RST_STREAM"
	case TypeSettings:
		return "SETTINGS"
	case TypeNoop:
		return "NOOP"
	case TypePing:
		return "PING"
	case TypeGoaway:
		return "GOAWAY"
	case TypeHeaders:
		return "HEADERS"
	case TypeWindowUpdate:
		return "WINDOW_UPDATE"
	}
	return "Type(" + strconv.Itoa(int(t)) + ")"
}

type FrameFlags uint8

// Stream frame flags
const (
	FlagFin            FrameFlags = 0x01
	FlagUnidirectional = 0x02
)

// SETTINGS frame flags
const (
	FlagClearPreviouslyPersistedSettings FrameFlags = 0x01
)

// MaxDataLength is the maximum number of bytes that can be stored in one frame.
const MaxDataLength = 1<<24 - 1

// A Frame is a framed message as sent between clients and servers.
// There are two types of frames: control frames and data frames.
type Frame struct {
	Header [4]byte
	Flags  FrameFlags
	Data   []byte
}

// ControlFrame creates a control frame with the given information.
func ControlFrame(t ControlFrameType, f FrameFlags, data []byte) Frame {
	return Frame{
		Header: [4]byte{
			(Version&0xff00)>>8 | 0x80,
			(Version & 0x00ff),
			byte((t & 0xff00) >> 8),
			byte((t & 0x00ff) >> 0),
		},
		Flags: f,
		Data:  data,
	}
}

// DataFrame creates a data frame with the given information.
func DataFrame(streamId uint32, f FrameFlags, data []byte) Frame {
	return Frame{
		Header: [4]byte{
			byte(streamId & 0x7f000000 >> 24),
			byte(streamId & 0x00ff0000 >> 16),
			byte(streamId & 0x0000ff00 >> 8),
			byte(streamId & 0x000000ff >> 0),
		},
		Flags: f,
		Data:  data,
	}
}

// ReadFrame reads an entire frame into memory.
func ReadFrame(r io.Reader) (f Frame, err os.Error) {
	_, err = io.ReadFull(r, f.Header[:])
	if err != nil {
		return
	}
	err = binary.Read(r, binary.BigEndian, &f.Flags)
	if err != nil {
		return
	}
	var lengthField [3]byte
	_, err = io.ReadFull(r, lengthField[:])
	if err != nil {
		if err == os.EOF {
			err = io.ErrUnexpectedEOF
		}
		return
	}
	var length uint32
	length |= uint32(lengthField[0]) << 16
	length |= uint32(lengthField[1]) << 8
	length |= uint32(lengthField[2]) << 0
	if length > 0 {
		f.Data = make([]byte, int(length))
		_, err = io.ReadFull(r, f.Data)
		if err == os.EOF {
			err = io.ErrUnexpectedEOF
		}
	} else {
		f.Data = []byte{}
	}
	return
}

// IsControl returns whether the frame holds a control frame.
func (f Frame) IsControl() bool {
	return f.Header[0]&0x80 != 0
}

// Type obtains the type field if the frame is a control frame, otherwise it returns zero.
func (f Frame) Type() ControlFrameType {
	if !f.IsControl() {
		return 0
	}
	return (ControlFrameType(f.Header[2])<<8 | ControlFrameType(f.Header[3]))
}

// StreamId returns the stream ID field if the frame is a data frame, otherwise it returns zero.
func (f Frame) StreamId() (id uint32) {
	if f.IsControl() {
		return 0
	}
	id |= uint32(f.Header[0]) << 24
	id |= uint32(f.Header[1]) << 16
	id |= uint32(f.Header[2]) << 8
	id |= uint32(f.Header[3]) << 0
	return
}

// WriteTo writes the frame in the SPDY format.
func (f Frame) WriteTo(w io.Writer) (n int64, err os.Error) {
	var nn int
	// Header
	nn, err = w.Write(f.Header[:])
	n += int64(nn)
	if err != nil {
		return
	}
	// Flags
	nn, err = w.Write([]byte{byte(f.Flags)})
	n += int64(nn)
	if err != nil {
		return
	}
	// Length
	nn, err = w.Write([]byte{
		byte(len(f.Data) & 0x00ff0000 >> 16),
		byte(len(f.Data) & 0x0000ff00 >> 8),
		byte(len(f.Data) & 0x000000ff),
	})
	n += int64(nn)
	if err != nil {
		return
	}
	// Data
	if len(f.Data) > 0 {
		nn, err = w.Write(f.Data)
		n += int64(nn)
	}
	return
}

// headerDictionary is the dictionary sent to the zlib compressor/decompressor.
// Even though the specification states there is no null byte at the end, Chrome sends it.
const headerDictionary = "optionsgetheadpostputdeletetrace" +
	"acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" +
	"if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" +
	"max-forwardsproxy-authorizationrangerefererteuser-agent" +
	"100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" +
	"accept-rangesageetaglocationproxy-authenticatepublicretry-after" +
	"servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" +
	"connectiondatetrailertransfer-encodingupgradeviawarning" +
	"content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" +
	"MondayTuesdayWednesdayThursdayFridaySaturdaySunday" +
	"JanFebMarAprMayJunJulAugSepOctNovDec" +
	"chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" +
	"charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00"

// hrSource is a reader that passes through reads from another reader.
// When the underlying reader reaches EOF, Read will block until another reader is added via change.
type hrSource struct {
	r io.Reader
	m sync.RWMutex
	c *sync.Cond
}

func (src *hrSource) Read(p []byte) (n int, err os.Error) {
	src.m.RLock()
	for src.r == nil {
		src.c.Wait()
	}
	n, err = src.r.Read(p)
	src.m.RUnlock()
	if err == os.EOF {
		src.change(nil)
		err = nil
	}
	return
}

func (src *hrSource) change(r io.Reader) {
	src.m.Lock()
	defer src.m.Unlock()
	src.r = r
	src.c.Broadcast()
}

// A HeaderReader reads zlib-compressed headers.
type HeaderReader struct {
	source       hrSource
	decompressor io.ReadCloser
}

// NewHeaderReader creates a HeaderReader with the initial dictionary.
func NewHeaderReader() (hr *HeaderReader) {
	hr = new(HeaderReader)
	hr.source.c = sync.NewCond(hr.source.m.RLocker())
	return
}

// ReadHeader reads a set of headers from a reader.
func (hr *HeaderReader) ReadHeader(r io.Reader) (h http.Header, err os.Error) {
	hr.source.change(r)
	h, err = hr.read()
	return
}

// Decode reads a set of headers from a block of bytes.
func (hr *HeaderReader) Decode(data []byte) (h http.Header, err os.Error) {
	hr.source.change(bytes.NewBuffer(data))
	h, err = hr.read()
	return
}

func (hr *HeaderReader) read() (h http.Header, err os.Error) {
	var count uint16
	if hr.decompressor == nil {
		hr.decompressor, err = zlib.NewReaderDict(&hr.source, []byte(headerDictionary))
		if err != nil {
			return
		}
	}
	err = binary.Read(hr.decompressor, binary.BigEndian, &count)
	if err != nil {
		return
	}
	h = make(http.Header, int(count))
	for i := 0; i < int(count); i++ {
		var name, value string
		name, err = readHeaderString(hr.decompressor)
		if err != nil {
			return
		}
		value, err = readHeaderString(hr.decompressor)
		if err != nil {
			return
		}
		valueList := strings.Split(string(value), "\x00", -1)
		for _, v := range valueList {
			h.Add(name, v)
		}
	}
	return
}

func readHeaderString(r io.Reader) (s string, err os.Error) {
	var length uint16
	err = binary.Read(r, binary.BigEndian, &length)
	if err != nil {
		return
	}
	data := make([]byte, int(length))
	_, err = io.ReadFull(r, data)
	if err != nil {
		return
	}
	return string(data), nil
}

// HeaderWriter will write zlib-compressed headers on different streams.
type HeaderWriter struct {
	compressor *zlib.Writer
	buffer     *bytes.Buffer
}

// NewHeaderWriter creates a HeaderWriter ready to compress headers.
func NewHeaderWriter(level int) (hw *HeaderWriter) {
	hw = &HeaderWriter{buffer: new(bytes.Buffer)}
	hw.compressor, _ = zlib.NewWriterDict(hw.buffer, level, []byte(headerDictionary))
	return
}

// WriteHeader writes a header block directly to an output.
func (hw *HeaderWriter) WriteHeader(w io.Writer, h http.Header) (err os.Error) {
	hw.write(h)
	_, err = io.Copy(w, hw.buffer)
	hw.buffer.Reset()
	return
}

// Encode returns a compressed header block.
func (hw *HeaderWriter) Encode(h http.Header) (data []byte) {
	hw.write(h)
	data = make([]byte, hw.buffer.Len())
	hw.buffer.Read(data)
	return
}

func (hw *HeaderWriter) write(h http.Header) {
	binary.Write(hw.compressor, binary.BigEndian, uint16(len(h)))
	for k, vals := range h {
		k = strings.ToLower(k)
		binary.Write(hw.compressor, binary.BigEndian, uint16(len(k)))
		binary.Write(hw.compressor, binary.BigEndian, []byte(k))
		v := strings.Join(vals, "\x00")
		binary.Write(hw.compressor, binary.BigEndian, uint16(len(v)))
		binary.Write(hw.compressor, binary.BigEndian, []byte(v))
	}
	hw.compressor.Flush()
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"encoding/json"
	"reflect"
	"sort"
	"strings"
)

func diffStringMap(pathPrefix string, oldV, newV map[string]interface{}) PatchOperations {
	ops := make([]PatchOperation, 0, 0)

	pathPrefix = strings.TrimRight(pathPrefix, "/")

	// This is suboptimal for adding whole new map from scratch
	// or deleting the whole map, but it's actually intention.
	// There may be some other map items managed outside of TF
	// and we don't want to touch these.

	for k, _ := range oldV {
		if _, ok := newV[k]; ok {
			continue
		}
		ops = append(ops, &RemoveOperation{Path: pathPrefix + "/" + k})
	}

	for k, v := range newV {
		newValue := v.(string)

		if oldValue, ok := oldV[k].(string); ok {
			if oldValue == newValue {
				continue
			}

			ops = append(ops, &ReplaceOperation{
				Path:  pathPrefix + "/" + k,
				Value: newValue,
			})
			continue
		}

		ops = append(ops, &AddOperation{
			Path:  pathPrefix + "/" + k,
			Value: newValue,
		})
	}

	return ops
}

type PatchOperations []PatchOperation

func (po PatchOperations) MarshalJSON() ([]byte, error) {
	var v []PatchOperation = po
	return json.Marshal(v)
}

func (po PatchOperations) Equal(ops []PatchOperation) bool {
	var v []PatchOperation = po

	sort.Slice(v, sortByPathAsc(ops))
	sort.Slice(ops, sortByPathAsc(ops))

	return reflect.DeepEqual(v, ops)
}

func sortByPathAsc(ops []PatchOperation) func(i, j int) bool {
	return func(i, j int) bool {
		return ops[i].GetPath() < ops[j].GetPath()
	}
}

type PatchOperation interface {
	MarshalJSON() ([]byte, error)
	GetPath() string
}

type ReplaceOperation struct {
	Path  string      `json:"path"`
	Value interface{} `json:"value"`
	Op    string      `json:"op"`
}

func (o *ReplaceOperation) GetPath() string {
	return o.Path
}

func (o *ReplaceOperation) MarshalJSON() ([]byte, error) {
	o.Op = "replace"
	return json.Marshal(*o)
}

func (o *ReplaceOperation) String() string {
	b, _ := o.MarshalJSON()
	return string(b)
}

type AddOperation struct {
	Path  string      `json:"path"`
	Value interface{} `json:"value"`
	Op    string      `json:"op"`
}

func (o *AddOperation) GetPath() string {
	return o.Path
}

func (o *AddOperation) MarshalJSON() ([]byte, error) {
	o.Op = "add"
	return json.Marshal(*o)
}

func (o *AddOperation) String() string {
	b, _ := o.MarshalJSON()
	return string(b)
}

type RemoveOperation struct {
	Path string `json:"path"`
	Op   string `json:"op"`
}

func (o *RemoveOperation) GetPath() string {
	return o.Path
}

func (o *RemoveOperation) MarshalJSON() ([]byte, error) {
	o.Op = "remove"
	return json.Marshal(*o)
}

func (o *RemoveOperation) String() string {
	b, _ := o.MarshalJSON()
	return string(b)
}
<commit_msg>provider/kubernetes: Fix sorting of the PatchOperations (#13117)<commit_after>package kubernetes

import (
	"encoding/json"
	"reflect"
	"sort"
	"strings"
)

func diffStringMap(pathPrefix string, oldV, newV map[string]interface{}) PatchOperations {
	ops := make([]PatchOperation, 0, 0)

	pathPrefix = strings.TrimRight(pathPrefix, "/")

	// This is suboptimal for adding whole new map from scratch
	// or deleting the whole map, but it's actually intention.
	// There may be some other map items managed outside of TF
	// and we don't want to touch these.

	for k, _ := range oldV {
		if _, ok := newV[k]; ok {
			continue
		}
		ops = append(ops, &RemoveOperation{Path: pathPrefix + "/" + k})
	}

	for k, v := range newV {
		newValue := v.(string)

		if oldValue, ok := oldV[k].(string); ok {
			if oldValue == newValue {
				continue
			}

			ops = append(ops, &ReplaceOperation{
				Path:  pathPrefix + "/" + k,
				Value: newValue,
			})
			continue
		}

		ops = append(ops, &AddOperation{
			Path:  pathPrefix + "/" + k,
			Value: newValue,
		})
	}

	return ops
}

type PatchOperations []PatchOperation

func (po PatchOperations) MarshalJSON() ([]byte, error) {
	var v []PatchOperation = po
	return json.Marshal(v)
}

func (po PatchOperations) Equal(ops []PatchOperation) bool {
	var v []PatchOperation = po

	sort.Slice(v, sortByPathAsc(v))
	sort.Slice(ops, sortByPathAsc(ops))

	return reflect.DeepEqual(v, ops)
}

func sortByPathAsc(ops []PatchOperation) func(i, j int) bool {
	return func(i, j int) bool {
		return ops[i].GetPath() < ops[j].GetPath()
	}
}

type PatchOperation interface {
	MarshalJSON() ([]byte, error)
	GetPath() string
}

type ReplaceOperation struct {
	Path  string      `json:"path"`
	Value interface{} `json:"value"`
	Op    string      `json:"op"`
}

func (o *ReplaceOperation) GetPath() string {
	return o.Path
}

func (o *ReplaceOperation) MarshalJSON() ([]byte, error) {
	o.Op = "replace"
	return json.Marshal(*o)
}

func (o *ReplaceOperation) String() string {
	b, _ := o.MarshalJSON()
	return string(b)
}

type AddOperation struct {
	Path  string      `json:"path"`
	Value interface{} `json:"value"`
	Op    string      `json:"op"`
}

func (o *AddOperation) GetPath() string {
	return o.Path
}

func (o *AddOperation) MarshalJSON() ([]byte, error) {
	o.Op = "add"
	return json.Marshal(*o)
}

func (o *AddOperation) String() string {
	b, _ := o.MarshalJSON()
	return string(b)
}

type RemoveOperation struct {
	Path string `json:"path"`
	Op   string `json:"op"`
}

func (o *RemoveOperation) GetPath() string {
	return o.Path
}

func (o *RemoveOperation) MarshalJSON() ([]byte, error) {
	o.Op = "remove"
	return json.Marshal(*o)
}

func (o *RemoveOperation) String() string {
	b, _ := o.MarshalJSON()
	return string(b)
}
<|endoftext|>


<commit_before>// +build !darwin,!windows

package util

import (
	"bufio"
	"fmt"
	"image"
	"io"
	"math"
	"os/exec"
	"strings"
	"time"

	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/goserial"
)

var ledPath = config.String("/dev/tty.ledmatrix", "led.tty")

var cmdWriteBuffer byte = 1
var cmdSwapBuffers byte = 2

// Attempts this first, then falls back to half.
const baudRate = 230400

// From https://diarmuid.ie/blog/post/pwm-exponential-led-fading-on-arduino-or-other-platforms
var R = (255 * math.Log10(2)) / (math.Log10(255))
var ledAdjust = make(map[uint8]uint8)

func init() {
	for i := 0; i < 256; i++ {
		ledAdjust[uint8(i)] = uint8(math.Pow(2, (float64(i)/R)) - 1)
	}
}

func GetLEDConnectionAtRate(baudRate int) (io.ReadWriteCloser, error) {

	log.Infof("Connecting to LED using baud rate: %d", baudRate)

	c := &serial.Config{Name: ledPath, Baud: baudRate}
	s, err := serial.OpenPort(c)
	if err != nil {
		return nil, err
	}

	init := make(chan string)
	failed := make(chan error)
	go func() {
		reader := bufio.NewReader(s)
		str, err := reader.ReadString('\n')
		if err != nil {
			failed <- err
		} else {
			init <- str
		}
	}()

	select {
	case err := <-failed:
		log.Infof("Failed reading init string from LED matrix: %s", err)
		return nil, err
	case initStr := <-init:
		log.Infof("Read init string from LED matrix: %s", initStr)

		if !strings.Contains(initStr, "LED") {
			return nil, fmt.Errorf("Bad init string... '%s'", initStr)
		}

		return s, nil
	case <-time.After(time.Second * 3):
		log.Warningf("Timeout waiting for LED matrix init string.")
		s.Close()
		return nil, fmt.Errorf("Bad init string..")
	}

}

func GetLEDConnection() (io.ReadWriteCloser, error) {

	resetLedMatrix, err := exec.LookPath("reset-led-matrix")
	if err != nil {
		return nil, err
	}

	for _, d := range []int{1, 2, 4} {
		for _, baud := range []int{baudRate, baudRate / 2} {

			cmd := exec.Command(resetLedMatrix)
			_, err = cmd.Output()

			s, err := GetLEDConnectionAtRate(baud)
			if err == nil {
				return s, nil
			}

			log.Warningf("Connection to LED matrix failed at %d. Sleeping for %d seconds.", baud, d)

			time.Sleep(time.Second * time.Duration(d))
		}
	}

	log.Errorf("failed to connect to LED matrix - falling back to mock a matrix connection.")
	return newMockMatrix(), nil
}

func ConvertImage(image *image.RGBA) []byte {

	var frame [768]byte

	for inPos, outPos := 0, 0; inPos < len(image.Pix); inPos = inPos + 4 {

		outPos = inPos / 4 * 3

		frame[outPos] = ledAdjust[image.Pix[inPos]]
		frame[outPos+1] = ledAdjust[image.Pix[inPos+1]]
		frame[outPos+2] = ledAdjust[image.Pix[inPos+2]]
	}

	rows := split(frame[:], 16*3)

	var orderedRows [][]byte
	for i := 0; i < 8; i++ {
		orderedRows = append(orderedRows, rows[i+8])
		orderedRows = append(orderedRows, rows[i])
	}

	var finalFrame []byte

	for _, line := range orderedRows {
		for i, j := 0, len(line)-1; i < j; i, j = i+1, j-1 {
			line[i], line[j] = line[j], line[i]
		}

		finalFrame = append(finalFrame, line...)
	}

	return finalFrame
}

// Write an image into the led matrix
func WriteLEDMatrix(image *image.RGBA, s io.ReadWriteCloser) {

	//spew.Dump("writing image", image)

	finalFrame := ConvertImage(image)

	_, err := s.Write([]byte{cmdWriteBuffer})
	if err != nil {
		log.Fatalf("Failed writing write buffer command: %s", err)
	}

	_, err = s.Write(finalFrame[:])
	if err != nil {
		log.Fatalf("Failed writing frame: %s", err)
	}

	_, err = s.Write([]byte{cmdSwapBuffers})
	if err != nil {
		log.Fatalf("Failed writing swap buffer command: %s", err)
	}

	//log.Println("Wrote frame", n)
	buf := make([]byte, 1)
	_, err = s.Read(buf)
	if err != nil {
		log.Infof("Failed to read char after sending frame : %s", err)
	}
	if buf[0] != byte('F') {
		log.Infof("Expected an 'F', got '%q'", buf[0])
	}
}

func split(a []byte, size int) [][]byte {
	var out [][]byte
	var i = 0
	for i < len(a) {
		out = append(out, a[i:i+size])
		i += size
	}

	return out
}

// Simple RLE on zero values....
/*
func compress(frame []byte) []byte {
	compressed := make([]byte, 0)
	for i := 0; i < len(frame); i++ {

		val := frame[i]
		if val == 0 {

			count := 0
			for j := i + 1; j < len(frame) && frame[j] == val; j++ {
				count++
			}

			compressed = append(compressed, val, byte(count))
			i += count
		} else {
			compressed = append(compressed, val)
		}
	}
	//spew.Dump("from", frame, compressed)
	return compressed
}*/
<commit_msg>Allow build on osx, change to tarm/serial<commit_after>package util

import (
	"bufio"
	"errors"
	"fmt"
	"image"
	"io"
	"math"
	"os/exec"
	"runtime"
	"strings"
	"time"

	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/goserial"
)

var ledPath = config.String("/dev/tty.ledmatrix", "led.tty")

var cmdWriteBuffer byte = 1
var cmdSwapBuffers byte = 2

// Attempts this first, then falls back to half.
const baudRate = 230400

// From https://diarmuid.ie/blog/post/pwm-exponential-led-fading-on-arduino-or-other-platforms
var R = (255 * math.Log10(2)) / (math.Log10(255))
var ledAdjust = make(map[uint8]uint8)

func init() {
	for i := 0; i < 256; i++ {
		ledAdjust[uint8(i)] = uint8(math.Pow(2, (float64(i)/R)) - 1)
	}
}

func GetLEDConnectionAtRate(baudRate int) (io.ReadWriteCloser, error) {

	log.Infof("Connecting to LED using baud rate: %d", baudRate)

	c := &serial.Config{Name: ledPath, Baud: baudRate}
	s, err := serial.OpenPort(c)
	if err != nil {
		return nil, err
	}

	init := make(chan string)
	failed := make(chan error)
	go func() {
		reader := bufio.NewReader(s)
		str, err := reader.ReadString('\n')
		if err != nil {
			failed <- err
		} else {
			init <- str
		}
	}()

	select {
	case err := <-failed:
		log.Infof("Failed reading init string from LED matrix: %s", err)
		return nil, err
	case initStr := <-init:
		log.Infof("Read init string from LED matrix: %s", initStr)

		if !strings.Contains(initStr, "LED") {
			return nil, fmt.Errorf("Bad init string... '%s'", initStr)
		}

		return s, nil
	case <-time.After(time.Second * 3):
		log.Warningf("Timeout waiting for LED matrix init string.")
		s.Close()
		return nil, fmt.Errorf("Bad init string..")
	}

}

func GetLEDConnection() (io.ReadWriteCloser, error) {

	if runtime.GOOS == "linux" {
		return getLEDConnectionLinux()
	}

	return newMockMatrix(), nil
}

func getLEDConnectionLinux() (io.ReadWriteCloser, error) {

	resetLedMatrix, resetErr := exec.LookPath("reset-led-matrix")
	if resetErr != nil {
		log.Errorf("Could not find reset led matrix command: %s", resetErr)
	}

	for _, d := range []int{1, 2, 4} {
		for _, baud := range []int{baudRate, baudRate / 2} {

			if resetErr == nil {
				cmd := exec.Command(resetLedMatrix)
				_, _ = cmd.Output()
			}

			s, err := GetLEDConnectionAtRate(baud)
			if err == nil {
				return s, nil
			}

			log.Warningf("Connection to LED matrix failed at %d. Sleeping for %d seconds.", baud, d)

			time.Sleep(time.Second * time.Duration(d))
		}
	}

	return nil, errors.New("failed to connect to LED matrix - falling back to mock a matrix connection.")
}

func ConvertImage(image *image.RGBA) []byte {

	var frame [768]byte

	for inPos, outPos := 0, 0; inPos < len(image.Pix); inPos = inPos + 4 {

		outPos = inPos / 4 * 3

		frame[outPos] = ledAdjust[image.Pix[inPos]]
		frame[outPos+1] = ledAdjust[image.Pix[inPos+1]]
		frame[outPos+2] = ledAdjust[image.Pix[inPos+2]]
	}

	rows := split(frame[:], 16*3)

	var orderedRows [][]byte
	for i := 0; i < 8; i++ {
		orderedRows = append(orderedRows, rows[i+8])
		orderedRows = append(orderedRows, rows[i])
	}

	var finalFrame []byte

	for _, line := range orderedRows {
		for i, j := 0, len(line)-1; i < j; i, j = i+1, j-1 {
			line[i], line[j] = line[j], line[i]
		}

		finalFrame = append(finalFrame, line...)
	}

	return finalFrame
}

// Write an image into the led matrix
func WriteLEDMatrix(image *image.RGBA, s io.ReadWriteCloser) {

	//spew.Dump("writing image", image)

	finalFrame := ConvertImage(image)

	_, err := s.Write([]byte{cmdWriteBuffer})
	if err != nil {
		log.Fatalf("Failed writing write buffer command: %s", err)
	}

	_, err = s.Write(finalFrame[:])
	if err != nil {
		log.Fatalf("Failed writing frame: %s", err)
	}

	_, err = s.Write([]byte{cmdSwapBuffers})
	if err != nil {
		log.Fatalf("Failed writing swap buffer command: %s", err)
	}

	//log.Println("Wrote frame", n)
	buf := make([]byte, 1)
	_, err = s.Read(buf)
	if err != nil {
		log.Infof("Failed to read char after sending frame : %s", err)
	}
	if buf[0] != byte('F') {
		log.Infof("Expected an 'F', got '%q'", buf[0])
	}
}

func split(a []byte, size int) [][]byte {
	var out [][]byte
	var i = 0
	for i < len(a) {
		out = append(out, a[i:i+size])
		i += size
	}

	return out
}

// Simple RLE on zero values....
/*
func compress(frame []byte) []byte {
	compressed := make([]byte, 0)
	for i := 0; i < len(frame); i++ {

		val := frame[i]
		if val == 0 {

			count := 0
			for j := i + 1; j < len(frame) && frame[j] == val; j++ {
				count++
			}

			compressed = append(compressed, val, byte(count))
			i += count
		} else {
			compressed = append(compressed, val)
		}
	}
	//spew.Dump("from", frame, compressed)
	return compressed
}*/
<|endoftext|>


<commit_before>package of10

import (
	"net"

	. "github.com/oshothebig/goflow/openflow"
)

type ActionType uint16

const (
	OFPAT_OUTPUT ActionType = iota
	OFPAT_SET_VLAN_VID
	OFPAT_SET_VLAN_PCP
	OFPAT_SET_STRIP_VLAN
	OFPAT_SET_DL_SRC
	OFPAT_SET_DL_DST
	OFPAT_SET_NW_SRC
	OFPAT_SET_NW_DST
	OFPAT_SET_NW_TOS
	OFPAT_SET_TP_SRC
	OFPAT_SET_TP_DST
	OFPAT_ENQUEUE
	OFPAT_VENDOR ActionType = 0xffff
)

var ActionTypes = struct {
	Output        ActionType
	SetVlanId     ActionType
	SetVlanPcp    ActionType
	StripVlan     ActionType
	SetEtherSrc   ActionType
	SetEtherDst   ActionType
	SetIpSrc      ActionType
	SetIpDst      ActionType
	SetIpTos      ActionType
	SetNetworkSrc ActionType
	SetNetworkDst ActionType
	Enqueue       ActionType
	Vendor        ActionType
}{
	OFPAT_OUTPUT,
	OFPAT_SET_VLAN_VID,
	OFPAT_SET_VLAN_PCP,
	OFPAT_SET_STRIP_VLAN,
	OFPAT_SET_DL_SRC,
	OFPAT_SET_DL_DST,
	OFPAT_SET_NW_SRC,
	OFPAT_SET_NW_DST,
	OFPAT_SET_NW_TOS,
	OFPAT_SET_TP_SRC,
	OFPAT_SET_TP_DST,
	OFPAT_ENQUEUE,
	OFPAT_VENDOR,
}

type Action interface {
	Packetizable
	GetType() ActionType
}

type ActionHeader struct {
	Type   ActionType
	Length uint16
}

func (header *ActionHeader) GetType() ActionType {
	return header.Type
}

type SendOutPort struct {
	ActionHeader
	Port      PortNumber
	MaxLength uint16
}

type Enqueue struct {
	ActionHeader
	Port    PortNumber
	pad     [6]uint8
	QueueId uint32
}

type SetVlanVid struct {
	ActionHeader
	VlanId VlanId
	pad    [2]uint32
}

type SetVlanPcp struct {
	ActionHeader
	VlanPcp VlanPriority
	pad     [3]uint8
}

type SetEtherAddress struct {
	ActionHeader
	EtherAddress net.HardwareAddr
	pad          [6]uint8
}

type SetIpAddress struct {
	ActionHeader
	IpAddress net.IP
}

type SetIpTos struct {
	ActionHeader
	IpTos Dscp
	pad   [3]uint8
}
<commit_msg>Define SetTransportPort and VendorHeader struct<commit_after>package of10

import (
	"net"

	. "github.com/oshothebig/goflow/openflow"
)

type ActionType uint16

const (
	OFPAT_OUTPUT ActionType = iota
	OFPAT_SET_VLAN_VID
	OFPAT_SET_VLAN_PCP
	OFPAT_SET_STRIP_VLAN
	OFPAT_SET_DL_SRC
	OFPAT_SET_DL_DST
	OFPAT_SET_NW_SRC
	OFPAT_SET_NW_DST
	OFPAT_SET_NW_TOS
	OFPAT_SET_TP_SRC
	OFPAT_SET_TP_DST
	OFPAT_ENQUEUE
	OFPAT_VENDOR ActionType = 0xffff
)

var ActionTypes = struct {
	Output        ActionType
	SetVlanId     ActionType
	SetVlanPcp    ActionType
	StripVlan     ActionType
	SetEtherSrc   ActionType
	SetEtherDst   ActionType
	SetIpSrc      ActionType
	SetIpDst      ActionType
	SetIpTos      ActionType
	SetNetworkSrc ActionType
	SetNetworkDst ActionType
	Enqueue       ActionType
	Vendor        ActionType
}{
	OFPAT_OUTPUT,
	OFPAT_SET_VLAN_VID,
	OFPAT_SET_VLAN_PCP,
	OFPAT_SET_STRIP_VLAN,
	OFPAT_SET_DL_SRC,
	OFPAT_SET_DL_DST,
	OFPAT_SET_NW_SRC,
	OFPAT_SET_NW_DST,
	OFPAT_SET_NW_TOS,
	OFPAT_SET_TP_SRC,
	OFPAT_SET_TP_DST,
	OFPAT_ENQUEUE,
	OFPAT_VENDOR,
}

type Action interface {
	Packetizable
	GetType() ActionType
}

type ActionHeader struct {
	Type   ActionType
	Length uint16
}

func (header *ActionHeader) GetType() ActionType {
	return header.Type
}

type SendOutPort struct {
	ActionHeader
	Port      PortNumber
	MaxLength uint16
}

type Enqueue struct {
	ActionHeader
	Port    PortNumber
	pad     [6]uint8
	QueueId uint32
}

type SetVlanVid struct {
	ActionHeader
	VlanId VlanId
	pad    [2]uint32
}

type SetVlanPcp struct {
	ActionHeader
	VlanPcp VlanPriority
	pad     [3]uint8
}

type SetEtherAddress struct {
	ActionHeader
	EtherAddress net.HardwareAddr
	pad          [6]uint8
}

type SetIpAddress struct {
	ActionHeader
	IpAddress net.IP
}

type SetIpTos struct {
	ActionHeader
	IpTos Dscp
	pad   [3]uint8
}

type SetTransportPort struct {
	ActionHeader
	TransportPort NetworkPort
	pad           [2]uint8
}

type VendorHeader struct {
	ActionHeader
	Vendor VendorId
}

type VendorId uint32
<|endoftext|>