<commit_before>package github

import (
	"github.com/google/go-github/github"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathLogin(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields: map[string]*framework.FieldSchema{
			"token": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "GitHub personal API token",
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.WriteOperation: b.pathLogin,
		},
	}
}

func (b *backend) pathLogin(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	// Get all our stored state
	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}
	if config.Org == "" {
		return logical.ErrorResponse(
			"configure the github credential backend first"), nil
	}

	client, err := b.Client(data.Get("token").(string))
	if err != nil {
		return nil, err
	}

	// Get the user
	user, _, err := client.Users.Get("")
	if err != nil {
		return nil, err
	}

	// Verify that the user is part of the organization
	var org *github.Organization
	orgs, _, err := client.Organizations.List("", nil)
	if err != nil {
		return nil, err
	}

	for _, o := range orgs {
		if *o.Login == config.Org {
			org = &o
			break
		}
	}
	if org == nil {
		return logical.ErrorResponse("user is not part of required org"), nil
	}

	// Get the teams that this user is part of to determine the policies
	var teamNames []string
	teams, _, err := client.Organizations.ListUserTeams(nil)
	if err != nil {
		return nil, err
	}
	for _, t := range teams {
		// We only care about teams that are part of the organization we use
		if *t.Organization.ID != *org.ID {
			continue
		}

		// Append the names AND slug so we can get the policies
                // Slug is needed for teamnames with whitespaces
		teamNames = append(teamNames, *t.Name)
                if *t.Name != *t.Slug {
                        teamNames = append(teamNames, *t.Slug)
                }
	}

	policiesList, err := b.Map.Policies(req.Storage, teamNames...)
	if err != nil {
		return nil, err
	}

	return &logical.Response{
		Auth: &logical.Auth{
			Policies: policiesList,
			Metadata: map[string]string{
				"username": *user.Login,
				"org":      *org.Login,
			},
			DisplayName: *user.Login,
		},
	}, nil
}
<commit_msg>fix bug #488<commit_after>package github

import (
	"github.com/google/go-github/github"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathLogin(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields: map[string]*framework.FieldSchema{
			"token": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "GitHub personal API token",
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.WriteOperation: b.pathLogin,
		},
	}
}

func (b *backend) pathLogin(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	// Get all our stored state
	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}
	if config.Org == "" {
		return logical.ErrorResponse(
			"configure the github credential backend first"), nil
	}

	client, err := b.Client(data.Get("token").(string))
	if err != nil {
		return nil, err
	}

	// Get the user
	user, _, err := client.Users.Get("")
	if err != nil {
		return nil, err
	}

	// Verify that the user is part of the organization
	var org *github.Organization

	orgOpt := &github.ListOptions{
		PerPage: 100,
	}

	var allOrgs []github.Organization
	for {
		orgs, resp, err := client.Organizations.List("", orgOpt)
		if err != nil {
			return nil, err
		}
		allOrgs = append(allOrgs, orgs...)
		if resp.NextPage == 0 {
			break
		}
		orgOpt.Page = resp.NextPage
	}

	for _, o := range allOrgs {
		if *o.Login == config.Org {
			org = &o
			break
		}
	}
	if org == nil {
		return logical.ErrorResponse("user is not part of required org"), nil
	}

	// Get the teams that this user is part of to determine the policies
	var teamNames []string

	teamOpt := &github.ListOptions{
		PerPage: 100,
	}

	var allTeams []github.Team
	for {
		teams, resp, err := client.Organizations.ListUserTeams(teamOpt)
		if err != nil {
			return nil, err
		}
		allTeams = append(allTeams, teams...)
		if resp.NextPage == 0 {
			break
		}
		teamOpt.Page = resp.NextPage
	}

	for _, t := range allTeams {
		// We only care about teams that are part of the organization we use
		if *t.Organization.ID != *org.ID {
			continue
		}

		// Append the names so we can get the policies
		teamNames = append(teamNames, *t.Name)
	}

	policiesList, err := b.Map.Policies(req.Storage, teamNames...)
	if err != nil {
		return nil, err
	}

	return &logical.Response{
		Auth: &logical.Auth{
			Policies: policiesList,
			Metadata: map[string]string{
				"username": *user.Login,
				"org":      *org.Login,
			},
			DisplayName: *user.Login,
		},
	}, nil
}

<|endoftext|>


<commit_before>package reporter

import (
	"os"
	"strconv"

	"github.com/olekukonko/tablewriter"
)

const defaultStyle = "\x1b[0m"
const boldStyle = "\x1b[1m"
const redColor = "\x1b[91m"
const greenColor = "\x1b[32m"
const yellowColor = "\x1b[33m"
const cyanColor = "\x1b[36m"
const grayColor = "\x1b[90m"
const magentaColor = "\033[35m"
const lightGrayColor = "\x1b[37m"
const tick = "\u2705"
const cross = "\u274c"
const skipped = "\u23ed"

// DefaultReporter collects all the test summaries
type DefaultReporter struct {
	testSummaries []*TestSummary
}

// NewDefaultReporter returns the pointer of DefaultReporter
func NewDefaultReporter() *DefaultReporter {
	return &DefaultReporter{}
}

// SuiteWillBegin prints banner and total benchmarks to be run
func (r *DefaultReporter) SuiteWillBegin(suiteSummary *SuiteSummary) {
	writer.PrintBanner(writer.Colorize(boldStyle, "%s", suiteSummary.Suite.Title), "=")
	writer.Println(0, writer.Colorize(lightGrayColor, "Will run %d of %d", suiteSummary.NumberOfTotalTests, suiteSummary.Suite.Totals()))
}

// TestWillRun prints each test status
func (r *DefaultReporter) TestWillRun(testSummary *TestSummary) {
	if testSummary.Validation {
		writer.Println(0, writer.Colorize(cyanColor, "[PL%d] [%s] %s", testSummary.Benchmark.ProfileLevel, testSummary.Benchmark.Category, testSummary.Benchmark.Title))
		writer.Println(0, writer.Colorize(grayColor, "%s", testSummary.Benchmark.Description))
		if testSummary.Test {
			writer.Println(0, writer.Colorize(greenColor, "Passed"))
		} else {
			writer.Println(0, writer.Colorize(redColor, "Failed"))
			writer.Println(0, writer.Colorize(lightGrayColor, "Remediation: %s", testSummary.Benchmark.Remediation))

		}
		writer.PrintBanner(writer.Colorize(grayColor, "Completed in %v", testSummary.RunTime), "-")
		return
	}

	writer.PrintBanner(writer.Colorize(magentaColor, "PreRun-Validation Error %s: %v", testSummary.Benchmark.Title, testSummary.ValidationError), "-")
	r.testSummaries = append(r.testSummaries, testSummary)
}

// SuiteDidEnd prints end result summary of benchmark suite
func (r *DefaultReporter) SuiteDidEnd(suiteSummary *SuiteSummary) {
	writer.Print(0, writer.Colorize(greenColor, "%d Passed | ", suiteSummary.NumberOfPassedTests))
	writer.Print(0, writer.Colorize(redColor, "%d Failed | ", suiteSummary.NumberOfFailedTests))
	writer.Print(0, writer.Colorize(yellowColor, "%d Skipped | ", suiteSummary.NumberOfSkippedTests))
	writer.Print(0, writer.Colorize(magentaColor, "%d Errors | ", suiteSummary.NumberOfFailedValidations))
	writer.PrintNewLine()
	writer.PrintBanner(writer.Colorize(grayColor, "Completed in %v", suiteSummary.RunTime), "=")
}

// FullSummary prints end result of all the tests at one place.
func (r *DefaultReporter) FullSummary(finalSummary *FinalSummary) {
	data := [][]string{}
	counter := 0

	for val, key := range finalSummary.TestResult {
		counter++
		var status string
		var symbol string
		if key.Error {
			status = writer.Colorize(magentaColor, "Error")
			symbol = cross
		} else if key.Passed {
			status = writer.Colorize(greenColor, "Passed")
			symbol = tick
		} else if key.Failed {
			status = writer.Colorize(redColor, "Failed")
			symbol = cross
		} else {
			status = writer.Colorize(yellowColor, "Skipped")
			symbol = skipped
		}
		testName := val.Title + " " + symbol
		result := []string{strconv.Itoa(counter), strconv.Itoa(val.ProfileLevel), testName, status}
		data = append(data, result)
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"No.", "PLevel", "Test", "Result"})
	table.SetAutoWrapText(false)

	for _, v := range data {
		table.Append(v)
	}
	table.Render() // Send output
}
<commit_msg>color changes<commit_after>package reporter

import (
	"fmt"
	"os"
	"strconv"

	"github.com/olekukonko/tablewriter"
)

const defaultStyle = "\x1b[0m"
const boldStyle = "\x1b[1m"
const redColor = "\x1b[91m"
const greenColor = "\x1b[32m"
const yellowColor = "\x1b[33m"
const cyanColor = "\x1b[36m"
const grayColor = "\x1b[90m"
const magentaColor = "\033[35m"
const lightGrayColor = "\x1b[37m"
const lilac = "\033[38;2;200;162;200m"
const tick = "\u2705"
const cross = "\u274c"
const skipped = "\u23ed"

// DefaultReporter collects all the test summaries
type DefaultReporter struct {
	testSummaries []*TestSummary
}

// NewDefaultReporter returns the pointer of DefaultReporter
func NewDefaultReporter() *DefaultReporter {
	return &DefaultReporter{}
}

// SuiteWillBegin prints banner and total benchmarks to be run
func (r *DefaultReporter) SuiteWillBegin(suiteSummary *SuiteSummary) {
	writer.PrintBanner(writer.Colorize(boldStyle, "%s", suiteSummary.Suite.Title), "=")
	writer.Println(0, writer.Colorize(lightGrayColor, "Will run %d of %d", suiteSummary.NumberOfTotalTests, suiteSummary.Suite.Totals()))
}

// TestWillRun prints each test status
func (r *DefaultReporter) TestWillRun(testSummary *TestSummary) {
	if testSummary.Validation {
		writer.Print(0, writer.Colorize(cyanColor, "[PL%d] [%s] ", testSummary.Benchmark.ProfileLevel, testSummary.Benchmark.Category))
		writer.Println(0, testSummary.Benchmark.Title)
		writer.Println(0, writer.Colorize(grayColor, "%s", testSummary.Benchmark.Description))
		if testSummary.Test {
			passed := "Passed " + tick
			writer.Println(0, writer.Colorize(greenColor, passed))
		} else {
			failed := "Failed " + cross
			writer.Println(0, writer.Colorize(redColor, failed))
			writer.Print(0, writer.Colorize(lilac, "Remediation: "))
			writer.Println(0, writer.Colorize(lightGrayColor, testSummary.Benchmark.Remediation))

		}
		writer.PrintBanner(writer.Colorize(grayColor, "Completed in %v", testSummary.RunTime), "-")
		return
	}
	preRunfmt := writer.Colorize(magentaColor, "[PreRun-Validation Error]")
	errormsg := writer.Colorize(redColor, testSummary.ValidationError.Error())
	bannerText := fmt.Sprintf("%s %s: %s %s", preRunfmt, testSummary.Benchmark.Title, errormsg, cross)
	writer.PrintBanner(bannerText, "-")
	r.testSummaries = append(r.testSummaries, testSummary)
}

// SuiteDidEnd prints end result summary of benchmark suite
func (r *DefaultReporter) SuiteDidEnd(suiteSummary *SuiteSummary) {
	writer.Print(0, writer.Colorize(greenColor, "%d Passed | ", suiteSummary.NumberOfPassedTests))
	writer.Print(0, writer.Colorize(redColor, "%d Failed | ", suiteSummary.NumberOfFailedTests))
	writer.Print(0, writer.Colorize(yellowColor, "%d Skipped | ", suiteSummary.NumberOfSkippedTests))
	writer.Print(0, writer.Colorize(magentaColor, "%d Errors | ", suiteSummary.NumberOfFailedValidations))
	writer.PrintNewLine()
	writer.PrintBanner(writer.Colorize(grayColor, "Completed in %v", suiteSummary.RunTime), "=")
}

// FullSummary prints end result of all the tests at one place.
func (r *DefaultReporter) FullSummary(finalSummary *FinalSummary) {
	data := [][]string{}
	counter := 0

	for val, key := range finalSummary.TestResult {
		counter++
		var status string
		var symbol string
		if key.Error {
			status = writer.Colorize(magentaColor, "Error")
			symbol = cross
		} else if key.Passed {
			status = writer.Colorize(greenColor, "Passed")
			symbol = tick
		} else if key.Failed {
			status = writer.Colorize(redColor, "Failed")
			symbol = cross
		} else {
			status = writer.Colorize(yellowColor, "Skipped")
			symbol = skipped
		}
		testName := val.Title + " " + symbol
		result := []string{strconv.Itoa(counter), strconv.Itoa(val.ProfileLevel), testName, status}
		data = append(data, result)
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"No.", "PLevel", "Test", "Result"})
	table.SetAutoWrapText(false)

	for _, v := range data {
		table.Append(v)
	}
	table.Render() // Send output
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"socialapi/workers/common/runner"
	"socialapi/workers/email/sender"

	"github.com/sendgrid/sendgrid-go"
)

var (
	Name = "MailSender"
)

func main() {
	r := runner.New(Name)
	if err := r.Init(); err != nil {
		fmt.Println(err)
		return
	}

	// if err := bongo.B.PublishEvent("send", &sender.Mail{Body: "foo"}); err != nil {
	// 	fmt.Println(err.Error())
	// }

	sg := sendgrid.NewSendGridClient(r.Conf.Email.Username, r.Conf.Email.Password)

	constructor := sender.New(r.Log, sg)
	r.SetContext(constructor)
	r.Register(sender.Mail{}).On("send").Handle((*sender.Controller).Send)
	r.Listen()
	r.Wait()
}
<commit_msg>mailsender: unnecessary comment is removed<commit_after>package main

import (
	"fmt"
	"socialapi/workers/common/runner"
	"socialapi/workers/email/sender"

	"github.com/sendgrid/sendgrid-go"
)

var (
	Name = "MailSender"
)

func main() {
	r := runner.New(Name)
	if err := r.Init(); err != nil {
		fmt.Println(err)
		return
	}

	sg := sendgrid.NewSendGridClient(r.Conf.Email.Username, r.Conf.Email.Password)

	constructor := sender.New(r.Log, sg)
	r.SetContext(constructor)
	r.Register(sender.Mail{}).On("send").Handle((*sender.Controller).Send)
	r.Listen()
	r.Wait()
}
<|endoftext|>


<commit_before>/*                          _       _
 *__      _____  __ ___   ___  __ _| |_ ___
 *\ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
 * \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
 *  \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
 *
 * Copyright © 2016 - 2018 Weaviate. All rights reserved.
 * LICENSE: https://github.com/creativesoftwarefdn/weaviate/blob/develop/LICENSE.md
 * AUTHOR: Bob van Luijt (bob@kub.design)
 * See www.creativesoftwarefdn.org for details
 * Contact: @CreativeSofwFdn / bob@kub.design
 */

package graphqlapi

import (
	"fmt"
	"github.com/creativesoftwarefdn/weaviate/models"
	"github.com/creativesoftwarefdn/weaviate/schema"
	"github.com/graphql-go/graphql"
)

// Build the dynamically generated ConvertedFetch Actions part of the schema
func (g *GraphQL) genActionClassFieldsFromSchema(convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Object, error) {
	actionClassFields := graphql.Fields{}

	for _, class := range g.databaseSchema.ActionSchema.Schema.Classes {
		singleActionClassField, singleActionClassObject := genSingleActionClassField(class, convertedFetchActionsAndThings)
		actionClassFields[class.Class] = singleActionClassField
		// this line assigns the created class to a Hashmap which is used in thunks to handle cyclical relationships (Classes with other Classes as properties)
		(*convertedFetchActionsAndThings)[class.Class] = singleActionClassObject
	}

	localConvertedFetchActions := graphql.ObjectConfig{
		Name:        "WeaviateLocalConvertedFetchActionsObj",
		Fields:      actionClassFields,
		Description: "Fetch Actions on the internal Weaviate",
	}

	return graphql.NewObject(localConvertedFetchActions), nil
}

func genSingleActionClassField(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Field, *graphql.Object) {
	singleActionClassPropertyFields := graphql.ObjectConfig{
		Name: class.Class,
		Fields: (graphql.FieldsThunk)(func() graphql.Fields {
			singleActionClassPropertyFields, err := genSingleActionClassPropertyFields(class, convertedFetchActionsAndThings)

			if err != nil {
				panic("Failed to generate single Action Class property fields")
			}

			return singleActionClassPropertyFields
		}),
		Description: "Type of fetch on the internal Weaviate",
	}

	singleActionClassPropertyFieldsObj := graphql.NewObject(singleActionClassPropertyFields)
	singleActionClassPropertyFieldsField := &graphql.Field{
		Type:        graphql.NewList(singleActionClassPropertyFieldsObj),
		Description: class.Description,
		Args: graphql.FieldConfigArgument{
			"_certainty": &graphql.ArgumentConfig{
				Description: "How certain about these values?",
				Type:        graphql.Float,
			},
			"_limit": &graphql.ArgumentConfig{
				Description: "define the max returned values",
				Type:        graphql.Int,
			},
			"_skip": &graphql.ArgumentConfig{
				Description: "define the amount of values to skip",
				Type:        graphql.Int,
			},
		},
		Resolve: func(p graphql.ResolveParams) (interface{}, error) {
			return nil, fmt.Errorf("Not supported")
		},
	}
	return singleActionClassPropertyFieldsField, singleActionClassPropertyFieldsObj
}

func genSingleActionClassPropertyFields(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (graphql.Fields, error) {
	singleActionClassPropertyFields := graphql.Fields{}

	for _, property := range class.Properties {
		propertyType, err := schema.GetPropertyDataType(class, property.Name)

		if err != nil {
			return nil, err
		}

		if *propertyType == schema.DataTypeCRef {
			numberOfDataTypes := len(property.AtDataType)
			dataTypeClasses := make([]*graphql.Object, numberOfDataTypes)

			for index, dataType := range property.AtDataType {
				thingOrActionType, ok := (*convertedFetchActionsAndThings)[dataType]

				if !ok {
					return nil, fmt.Errorf("No such thing/action class '%s'", property.AtDataType[index])
				}

				dataTypeClasses[index] = thingOrActionType
			}

			dataTypeUnionConf := graphql.UnionConfig{
				Name:  fmt.Sprintf("%s%s%s", class.Class, property.Name, "Obj"),
				Types: dataTypeClasses,
				ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
					return nil
				},
				Description: property.Description,
			}

			multipleClassDataTypesUnion := graphql.NewUnion(dataTypeUnionConf)

			singleActionClassPropertyFields[property.Name] = &graphql.Field{
				Type:        multipleClassDataTypesUnion,
				Description: property.Description,
				Resolve: func(p graphql.ResolveParams) (interface{}, error) {
					return nil, fmt.Errorf("Not supported")
				},
			}
		} else {
			convertedDataType, err := handleConvertedFetchNonObjectDataTypes(*propertyType, property)

			if err != nil {
				return nil, err
			}

			singleActionClassPropertyFields[property.Name] = convertedDataType
		}
	}

	return singleActionClassPropertyFields, nil
}

// Build the dynamically generated ConvertedFetch Things part of the schema
func (g *GraphQL) genThingClassFieldsFromSchema(convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Object, error) {
	thingClassFields := graphql.Fields{}

	for _, class := range g.databaseSchema.ThingSchema.Schema.Classes {
		singleThingClassField, singleThingClassObject := genSingleThingClassField(class, convertedFetchActionsAndThings)
		thingClassFields[class.Class] = singleThingClassField
		// this line assigns the created class to a Hashmap which is used in thunks to handle cyclical relationships (Classes with other Classes as properties)
		(*convertedFetchActionsAndThings)[class.Class] = singleThingClassObject
	}

	localConvertedFetchThings := graphql.ObjectConfig{
		Name:        "WeaviateLocalConvertedFetchThingsObj",
		Fields:      thingClassFields,
		Description: "Fetch Things on the internal Weaviate",
	}

	return graphql.NewObject(localConvertedFetchThings), nil
}

func genSingleThingClassField(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Field, *graphql.Object) {
	singleThingClassPropertyFieldsObj := graphql.ObjectConfig{
		Name: class.Class,
		Fields: (graphql.FieldsThunk)(func() graphql.Fields {
			singleThingClassPropertyFields, err := genSingleThingClassPropertyFields(class, convertedFetchActionsAndThings)
			if err != nil {
				panic(fmt.Errorf("Failed to assemble single Thing Class field for Class %s", class.Class))
			}
			return singleThingClassPropertyFields
		}),
		Description: "Type of fetch on the internal Weaviate",
	}

	thingClassPropertyFieldsObject := graphql.NewObject(singleThingClassPropertyFieldsObj)
	thingClassPropertyFieldsField := &graphql.Field{
		Type:        graphql.NewList(thingClassPropertyFieldsObject),
		Description: class.Description,
		Args: graphql.FieldConfigArgument{
			"_certainty": &graphql.ArgumentConfig{
				Description: "How certain about these values?",
				Type:        graphql.Float,
			},
			"_limit": &graphql.ArgumentConfig{
				Description: "define the max returned values",
				Type:        graphql.Int,
			},
			"_skip": &graphql.ArgumentConfig{
				Description: "define the amount of values to skip",
				Type:        graphql.Int,
			},
		},
		Resolve: func(p graphql.ResolveParams) (interface{}, error) {
			return nil, fmt.Errorf("Not supported")
		},
	}
	return thingClassPropertyFieldsField, thingClassPropertyFieldsObject
}

func genSingleThingClassPropertyFields(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (graphql.Fields, error) {
	singleThingClassPropertyFields := graphql.Fields{}

	for _, property := range class.Properties {

		propertyType, err := schema.GetPropertyDataType(class, property.Name)

		if err != nil {
			return nil, err
		}

		if *propertyType == schema.DataTypeCRef {
			numberOfDataTypes := len(property.AtDataType)
			dataTypeClasses := make([]*graphql.Object, numberOfDataTypes)

			for index, dataType := range property.AtDataType {
				thingOrActionType, ok := (*convertedFetchActionsAndThings)[dataType]

				if !ok {
					return nil, fmt.Errorf("No such thing/action class '%s'", property.AtDataType[index])
				}

				dataTypeClasses[index] = thingOrActionType
			}

			dataTypeUnionConf := graphql.UnionConfig{
				Name:  fmt.Sprintf("%s%s%s", class.Class, property.Name, "Obj"),
				Types: dataTypeClasses,
				ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
					return nil
				},
				Description: property.Description,
			}

			multipleClassDataTypesUnion := graphql.NewUnion(dataTypeUnionConf)

			singleThingClassPropertyFields[property.Name] = &graphql.Field{
				Type:        multipleClassDataTypesUnion,
				Description: property.Description,
				Resolve: func(p graphql.ResolveParams) (interface{}, error) {
					return nil, fmt.Errorf("Not supported")
				},
			}
		} else {
			convertedDataType, err := handleConvertedFetchNonObjectDataTypes(*propertyType, property)

			if err != nil {
				return nil, err
			}

			singleThingClassPropertyFields[property.Name] = convertedDataType
		}
	}
	return singleThingClassPropertyFields, nil
}

func handleConvertedFetchNonObjectDataTypes(dataType schema.DataType, property *models.SemanticSchemaClassProperty) (*graphql.Field, error) {

	switch dataType {

	case schema.DataTypeString:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.String,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil

	case schema.DataTypeInt:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.Int,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil

	case schema.DataTypeNumber:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.Float,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil

	case schema.DataTypeBoolean:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.Boolean,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil

	case schema.DataTypeDate:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.String, // String since no graphql date datatype exists
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil

	default:
		return nil, fmt.Errorf(schema.ErrorNoSuchDatatype)
	}
}
<commit_msg>Remove whitespace<commit_after>/*                          _       _
 *__      _____  __ ___   ___  __ _| |_ ___
 *\ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
 * \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
 *  \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
 *
 * Copyright © 2016 - 2018 Weaviate. All rights reserved.
 * LICENSE: https://github.com/creativesoftwarefdn/weaviate/blob/develop/LICENSE.md
 * AUTHOR: Bob van Luijt (bob@kub.design)
 * See www.creativesoftwarefdn.org for details
 * Contact: @CreativeSofwFdn / bob@kub.design
 */

package graphqlapi

import (
	"fmt"
	"github.com/creativesoftwarefdn/weaviate/models"
	"github.com/creativesoftwarefdn/weaviate/schema"
	"github.com/graphql-go/graphql"
)

// Build the dynamically generated ConvertedFetch Actions part of the schema
func (g *GraphQL) genActionClassFieldsFromSchema(convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Object, error) {
	actionClassFields := graphql.Fields{}

	for _, class := range g.databaseSchema.ActionSchema.Schema.Classes {
		singleActionClassField, singleActionClassObject := genSingleActionClassField(class, convertedFetchActionsAndThings)
		actionClassFields[class.Class] = singleActionClassField
		// this line assigns the created class to a Hashmap which is used in thunks to handle cyclical relationships (Classes with other Classes as properties)
		(*convertedFetchActionsAndThings)[class.Class] = singleActionClassObject
	}

	localConvertedFetchActions := graphql.ObjectConfig{
		Name:        "WeaviateLocalConvertedFetchActionsObj",
		Fields:      actionClassFields,
		Description: "Fetch Actions on the internal Weaviate",
	}

	return graphql.NewObject(localConvertedFetchActions), nil
}

func genSingleActionClassField(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Field, *graphql.Object) {
	singleActionClassPropertyFields := graphql.ObjectConfig{
		Name: class.Class,
		Fields: (graphql.FieldsThunk)(func() graphql.Fields {
			singleActionClassPropertyFields, err := genSingleActionClassPropertyFields(class, convertedFetchActionsAndThings)

			if err != nil {
				panic("Failed to generate single Action Class property fields")
			}

			return singleActionClassPropertyFields
		}),
		Description: "Type of fetch on the internal Weaviate",
	}

	singleActionClassPropertyFieldsObj := graphql.NewObject(singleActionClassPropertyFields)
	singleActionClassPropertyFieldsField := &graphql.Field{
		Type:        graphql.NewList(singleActionClassPropertyFieldsObj),
		Description: class.Description,
		Args: graphql.FieldConfigArgument{
			"_certainty": &graphql.ArgumentConfig{
				Description: "How certain about these values?",
				Type:        graphql.Float,
			},
			"_limit": &graphql.ArgumentConfig{
				Description: "define the max returned values",
				Type:        graphql.Int,
			},
			"_skip": &graphql.ArgumentConfig{
				Description: "define the amount of values to skip",
				Type:        graphql.Int,
			},
		},
		Resolve: func(p graphql.ResolveParams) (interface{}, error) {
			return nil, fmt.Errorf("Not supported")
		},
	}
	return singleActionClassPropertyFieldsField, singleActionClassPropertyFieldsObj
}

func genSingleActionClassPropertyFields(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (graphql.Fields, error) {
	singleActionClassPropertyFields := graphql.Fields{}

	for _, property := range class.Properties {
		propertyType, err := schema.GetPropertyDataType(class, property.Name)

		if err != nil {
			return nil, err
		}

		if *propertyType == schema.DataTypeCRef {
			numberOfDataTypes := len(property.AtDataType)
			dataTypeClasses := make([]*graphql.Object, numberOfDataTypes)

			for index, dataType := range property.AtDataType {
				thingOrActionType, ok := (*convertedFetchActionsAndThings)[dataType]

				if !ok {
					return nil, fmt.Errorf("No such thing/action class '%s'", property.AtDataType[index])
				}

				dataTypeClasses[index] = thingOrActionType
			}

			dataTypeUnionConf := graphql.UnionConfig{
				Name:  fmt.Sprintf("%s%s%s", class.Class, property.Name, "Obj"),
				Types: dataTypeClasses,
				ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
					return nil
				},
				Description: property.Description,
			}

			multipleClassDataTypesUnion := graphql.NewUnion(dataTypeUnionConf)

			singleActionClassPropertyFields[property.Name] = &graphql.Field{
				Type:        multipleClassDataTypesUnion,
				Description: property.Description,
				Resolve: func(p graphql.ResolveParams) (interface{}, error) {
					return nil, fmt.Errorf("Not supported")
				},
			}
		} else {
			convertedDataType, err := handleConvertedFetchNonObjectDataTypes(*propertyType, property)

			if err != nil {
				return nil, err
			}

			singleActionClassPropertyFields[property.Name] = convertedDataType
		}
	}

	return singleActionClassPropertyFields, nil
}

// Build the dynamically generated ConvertedFetch Things part of the schema
func (g *GraphQL) genThingClassFieldsFromSchema(convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Object, error) {
	thingClassFields := graphql.Fields{}

	for _, class := range g.databaseSchema.ThingSchema.Schema.Classes {
		singleThingClassField, singleThingClassObject := genSingleThingClassField(class, convertedFetchActionsAndThings)
		thingClassFields[class.Class] = singleThingClassField
		// this line assigns the created class to a Hashmap which is used in thunks to handle cyclical relationships (Classes with other Classes as properties)
		(*convertedFetchActionsAndThings)[class.Class] = singleThingClassObject
	}

	localConvertedFetchThings := graphql.ObjectConfig{
		Name:        "WeaviateLocalConvertedFetchThingsObj",
		Fields:      thingClassFields,
		Description: "Fetch Things on the internal Weaviate",
	}

	return graphql.NewObject(localConvertedFetchThings), nil
}

func genSingleThingClassField(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (*graphql.Field, *graphql.Object) {
	singleThingClassPropertyFieldsObj := graphql.ObjectConfig{
		Name: class.Class,
		Fields: (graphql.FieldsThunk)(func() graphql.Fields {
			singleThingClassPropertyFields, err := genSingleThingClassPropertyFields(class, convertedFetchActionsAndThings)
			if err != nil {
				panic(fmt.Errorf("Failed to assemble single Thing Class field for Class %s", class.Class))
			}
			return singleThingClassPropertyFields
		}),
		Description: "Type of fetch on the internal Weaviate",
	}

	thingClassPropertyFieldsObject := graphql.NewObject(singleThingClassPropertyFieldsObj)
	thingClassPropertyFieldsField := &graphql.Field{
		Type:        graphql.NewList(thingClassPropertyFieldsObject),
		Description: class.Description,
		Args: graphql.FieldConfigArgument{
			"_certainty": &graphql.ArgumentConfig{
				Description: "How certain about these values?",
				Type:        graphql.Float,
			},
			"_limit": &graphql.ArgumentConfig{
				Description: "define the max returned values",
				Type:        graphql.Int,
			},
			"_skip": &graphql.ArgumentConfig{
				Description: "define the amount of values to skip",
				Type:        graphql.Int,
			},
		},
		Resolve: func(p graphql.ResolveParams) (interface{}, error) {
			return nil, fmt.Errorf("Not supported")
		},
	}
	return thingClassPropertyFieldsField, thingClassPropertyFieldsObject
}

func genSingleThingClassPropertyFields(class *models.SemanticSchemaClass, convertedFetchActionsAndThings *map[string]*graphql.Object) (graphql.Fields, error) {
	singleThingClassPropertyFields := graphql.Fields{}

	for _, property := range class.Properties {

		propertyType, err := schema.GetPropertyDataType(class, property.Name)

		if err != nil {
			return nil, err
		}

		if *propertyType == schema.DataTypeCRef {
			numberOfDataTypes := len(property.AtDataType)
			dataTypeClasses := make([]*graphql.Object, numberOfDataTypes)

			for index, dataType := range property.AtDataType {
				thingOrActionType, ok := (*convertedFetchActionsAndThings)[dataType]

				if !ok {
					return nil, fmt.Errorf("No such thing/action class '%s'", property.AtDataType[index])
				}

				dataTypeClasses[index] = thingOrActionType
			}

			dataTypeUnionConf := graphql.UnionConfig{
				Name:  fmt.Sprintf("%s%s%s", class.Class, property.Name, "Obj"),
				Types: dataTypeClasses,
				ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
					return nil
				},
				Description: property.Description,
			}

			multipleClassDataTypesUnion := graphql.NewUnion(dataTypeUnionConf)

			singleThingClassPropertyFields[property.Name] = &graphql.Field{
				Type:        multipleClassDataTypesUnion,
				Description: property.Description,
				Resolve: func(p graphql.ResolveParams) (interface{}, error) {
					return nil, fmt.Errorf("Not supported")
				},
			}
		} else {
			convertedDataType, err := handleConvertedFetchNonObjectDataTypes(*propertyType, property)

			if err != nil {
				return nil, err
			}

			singleThingClassPropertyFields[property.Name] = convertedDataType
		}
	}
	return singleThingClassPropertyFields, nil
}

func handleConvertedFetchNonObjectDataTypes(dataType schema.DataType, property *models.SemanticSchemaClassProperty) (*graphql.Field, error) {
	switch dataType {
	case schema.DataTypeString:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.String,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil
	case schema.DataTypeInt:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.Int,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil
	case schema.DataTypeNumber:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.Float,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil
	case schema.DataTypeBoolean:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.Boolean,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil
	case schema.DataTypeDate:
		return &graphql.Field{
			Description: property.Description,
			Type:        graphql.String, // String since no graphql date datatype exists
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return nil, fmt.Errorf("Not supported")
			},
		}, nil
	default:
		return nil, fmt.Errorf(schema.ErrorNoSuchDatatype)
	}
}
<|endoftext|>


<commit_before>package githubprovider

import (
	"os"
	"testing"

	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
)

func TestGithubAddAndRemoveUser(t *testing.T) {
	orgClient := github.NewClient(
		oauth2.NewClient(
			oauth2.NoContext,
			oauth2.StaticTokenSource(
				&oauth2.Token{
					AccessToken: os.Getenv("GITHUB_ORG_ACCESS_TOKEN"),
				},
			),
		),
	)
	userClient := github.NewClient(
		oauth2.NewClient(
			oauth2.NoContext,
			oauth2.StaticTokenSource(
				&oauth2.Token{
					AccessToken: os.Getenv("GITHUB_USER_ACCESS_TOKEN"),
				},
			),
		),
	)

	org := "organizasyon"
	user := "mehmetalikoding"
	teamNames := []string{"team"}
	role := "member"
	active := "active"

	teamIDs, err := GetTeamIDs(orgClient, org, teamNames)

	optAddOrgMembership := &github.OrganizationAddTeamMembershipOptions{
		Role: role,
	}

	for _, teamID := range teamIDs {
		_, _, err := orgClient.Organizations.AddTeamMembership(teamID, user, optAddOrgMembership)
		if err != nil {
			t.Fatalf("Error while adding user to team ", err)
		}
	}

	// When you try to add a user to a team twice,
	// it doesn't return any error
	for _, teamID := range teamIDs {
		_, _, err := orgClient.Organizations.AddTeamMembership(teamID, user, optAddOrgMembership)
		if err != nil {
			t.Fatalf("Error while adding user to team ", err)
		}
	}

	membership := &github.Membership{
		// state should be active to add the user into organization
		State: &active,

		// Role is the required for the membership
		Role: &role,
	}

	_, _, err = userClient.Organizations.EditOrgMembership("", org, membership)
	if err != nil {
		t.Fatalf("Error while adding user to organization ", err)
	}

	// When you try to add a user to an organization twice,
	// it doesn't return any error
	_, _, err = userClient.Organizations.EditOrgMembership("", org, membership)
	if err != nil {
		t.Fatalf("Error while adding user to organization ", err)
	}

	// You can remove a member from organization
	_, err = orgClient.Organizations.RemoveMember(org, user)
	if err != nil {
		t.Fatalf("Error while removing user from organization and teams of the organization ", err)
	}

}
<commit_msg>test: fails are replaced with fatalf<commit_after>package githubprovider

import (
	"os"
	"testing"

	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
)

func TestGithubAddAndRemoveUser(t *testing.T) {
	orgClient := github.NewClient(
		oauth2.NewClient(
			oauth2.NoContext,
			oauth2.StaticTokenSource(
				&oauth2.Token{
					AccessToken: os.Getenv("GITHUB_ORG_ACCESS_TOKEN"),
				},
			),
		),
	)
	userClient := github.NewClient(
		oauth2.NewClient(
			oauth2.NoContext,
			oauth2.StaticTokenSource(
				&oauth2.Token{
					AccessToken: os.Getenv("GITHUB_USER_ACCESS_TOKEN"),
				},
			),
		),
	)

	org := "organizasyon"
	user := "mehmetalikoding"
	teamNames := []string{"team"}
	role := "member"
	active := "active"

	teamIDs, err := GetTeamIDs(orgClient, org, teamNames)

	optAddOrgMembership := &github.OrganizationAddTeamMembershipOptions{
		Role: role,
	}

	for _, teamID := range teamIDs {
		_, _, err := orgClient.Organizations.AddTeamMembership(teamID, user, optAddOrgMembership)
		if err != nil {
			t.Fatalf("Error while adding user to team: %+v ", err)
		}
	}

	// When you try to add a user to a team twice,
	// it doesn't return any error
	for _, teamID := range teamIDs {
		_, _, err := orgClient.Organizations.AddTeamMembership(teamID, user, optAddOrgMembership)
		if err != nil {
			t.Fatalf("Error while adding user to team: %+v ", err)
		}
	}

	membership := &github.Membership{
		// state should be active to add the user into organization
		State: &active,

		// Role is the required for the membership
		Role: &role,
	}

	_, _, err = userClient.Organizations.EditOrgMembership("", org, membership)
	if err != nil {
		t.Fatalf("Error while adding user to organization: %+v ", err)
	}

	// When you try to add a user to an organization twice,
	// it doesn't return any error
	_, _, err = userClient.Organizations.EditOrgMembership("", org, membership)
	if err != nil {
		t.Fatalf("Error while adding user to organization: %+v ", err)
	}

	// You can remove a member from organization
	_, err = orgClient.Organizations.RemoveMember(org, user)
	if err != nil {
		t.Fatalf("Error while removing user from organization and teams of the organization: %+v", err)
	}

}
<|endoftext|>


<commit_before>package release

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

// newTestDownload creates a new Download instance for testing purposes and
// returns its pointer.
func newTestDownload() *Download {
	return &Download{
		url:          "https://example.com/1.0.0/app.dmg",
		filetype:     "application/octet-stream",
		length:       100000,
		dsaSignature: "MC4CFQCeqQ/MxlFt2H3rQfCPimChDPibCgIVAJhZmHcU8ZHylc7EjvbkVr3ardLp",
	}
}

func TestNewDownload(t *testing.T) {
	d := NewDownload("https://example.com/1.0.0/app.dmg", "application/octet-stream", 100000, "test")
	assert.IsType(t, Download{}, *d)
	assert.Equal(t, "https://example.com/1.0.0/app.dmg", d.url)
	assert.Equal(t, "application/octet-stream", d.filetype)
	assert.Equal(t, 100000, d.length)
	assert.Equal(t, "test", d.dsaSignature)
}

func TestDownload_Url(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.url, d.Url())
}

func TestDownload_SetUrl(t *testing.T) {
	d := newTestDownload()
	d.SetUrl("https://example.com/2.0.0/app.dmg")
	assert.Equal(t, "https://example.com/2.0.0/app.dmg", d.url)
}

func TestDownload_Filetype(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.filetype, d.Filetype())
}

func TestDownload_SetFiletype(t *testing.T) {
	d := newTestDownload()
	d.SetFiletype("application/x-bzip2; charset=binary")
	assert.Equal(t, "application/x-bzip2; charset=binary", d.filetype)
}

func TestDownload_Length(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.length, d.Length())
}

func TestDownload_SetLength(t *testing.T) {
	d := newTestDownload()
	d.SetLength(200000)
	assert.Equal(t, 200000, d.length)
}

func TestDownload_DsaSignature(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.dsaSignature, d.DsaSignature())
}

func TestDownload_SetDsaSignature(t *testing.T) {
	d := newTestDownload()
	d.SetDsaSignature("test")
	assert.Equal(t, "test", d.dsaSignature)
}
<commit_msg>Add release Download.md5 tests<commit_after>package release

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

// newTestDownload creates a new Download instance for testing purposes and
// returns its pointer.
func newTestDownload() *Download {
	return &Download{
		url:          "https://example.com/1.0.0/app.dmg",
		filetype:     "application/octet-stream",
		length:       100000,
		dsaSignature: "MC4CFQCeqQ/MxlFt2H3rQfCPimChDPibCgIVAJhZmHcU8ZHylc7EjvbkVr3ardLp",
		md5:          "098f6bcd4621d373cade4e832627b4f6",
	}
}

func TestNewDownload(t *testing.T) {
	d := NewDownload(
		"https://example.com/1.0.0/app.dmg",
		"application/octet-stream",
		100000,
		"MC4CFQCeqQ/MxlFt2H3rQfCPimChDPibCgIVAJhZmHcU8ZHylc7EjvbkVr3ardLp",
		"098f6bcd4621d373cade4e832627b4f6",
	)

	assert.IsType(t, Download{}, *d)
	assert.Equal(t, "https://example.com/1.0.0/app.dmg", d.url)
	assert.Equal(t, "application/octet-stream", d.filetype)
	assert.Equal(t, 100000, d.length)
	assert.Equal(t, "MC4CFQCeqQ/MxlFt2H3rQfCPimChDPibCgIVAJhZmHcU8ZHylc7EjvbkVr3ardLp", d.dsaSignature)
	assert.Equal(t, "098f6bcd4621d373cade4e832627b4f6", d.md5)
}

func TestDownload_Url(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.url, d.Url())
}

func TestDownload_SetUrl(t *testing.T) {
	d := newTestDownload()
	d.SetUrl("https://example.com/2.0.0/app.dmg")
	assert.Equal(t, "https://example.com/2.0.0/app.dmg", d.url)
}

func TestDownload_Filetype(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.filetype, d.Filetype())
}

func TestDownload_SetFiletype(t *testing.T) {
	d := newTestDownload()
	d.SetFiletype("application/x-bzip2; charset=binary")
	assert.Equal(t, "application/x-bzip2; charset=binary", d.filetype)
}

func TestDownload_Length(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.length, d.Length())
}

func TestDownload_SetLength(t *testing.T) {
	d := newTestDownload()
	d.SetLength(200000)
	assert.Equal(t, 200000, d.length)
}

func TestDownload_DsaSignature(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.dsaSignature, d.DsaSignature())
}

func TestDownload_SetDsaSignature(t *testing.T) {
	d := newTestDownload()
	d.SetDsaSignature("test")
	assert.Equal(t, "test", d.dsaSignature)
}

func TestDownload_Md5(t *testing.T) {
	d := newTestDownload()
	assert.Equal(t, d.md5, d.Md5())
}

func TestDownload_SetMd5(t *testing.T) {
	d := newTestDownload()
	d.SetMd5("test")
	assert.Equal(t, "test", d.md5)
}
<|endoftext|>


<commit_before>package sortutil

import (
	"errors"
	"sort"
	"strings"
)

func Int64Sorted(int64s []int64) []int64 {
	ints := Int64sToInts(int64s)
	sort.Ints(ints)
	return IntsToInt64s(ints)
}

func Int64sToInts(int64s []int64) []int {
	ints := []int{}
	for _, x := range int64s {
		ints = append(ints, int(x))
	}
	return ints
}

func IntsToInt64s(ints []int) []int64 {
	int64s := []int64{}
	for _, x := range ints {
		int64s = append(int64s, int64(x))
	}
	return int64s
}

// For now, use only for slices < 100 in length for performance.
// To do: more scalable implementation that uses sorting/searching.
func InArrayStringCaseInsensitive(haystack []string, needle string) (string, error) {
	needleLower := strings.ToLower(strings.TrimSpace(needle))
	for _, canonical := range haystack {
		canonicalLower := strings.ToLower(canonical)
		if canonicalLower == needleLower {
			return canonical, nil
		}
	}
	return "", errors.New("String not found")
}

// Uint16Slice attaches the methods of Interface to []uint16, sorting in increasing order.
type Uint16Slice []uint16

func (p Uint16Slice) Len() int           { return len(p) }
func (p Uint16Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Uint16Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p Uint16Slice) Sort() { sort.Sort(p) }

func Uint16s(a []uint16) { sort.Sort(Uint16Slice(a)) }
<commit_msg>add sortutil.Int64s<commit_after>package sortutil

import (
	"errors"
	"sort"
	"strings"
)

func Int64Sorted(int64s []int64) []int64 {
	ints := Int64sToInts(int64s)
	sort.Ints(ints)
	return IntsToInt64s(ints)
}

func Int64sToInts(int64s []int64) []int {
	ints := []int{}
	for _, x := range int64s {
		ints = append(ints, int(x))
	}
	return ints
}

func IntsToInt64s(ints []int) []int64 {
	int64s := []int64{}
	for _, x := range ints {
		int64s = append(int64s, int64(x))
	}
	return int64s
}

// For now, use only for slices < 100 in length for performance.
// To do: more scalable implementation that uses sorting/searching.
func InArrayStringCaseInsensitive(haystack []string, needle string) (string, error) {
	needleLower := strings.ToLower(strings.TrimSpace(needle))
	for _, canonical := range haystack {
		canonicalLower := strings.ToLower(canonical)
		if canonicalLower == needleLower {
			return canonical, nil
		}
	}
	return "", errors.New("String not found")
}

func Int64s(a []int64) { sort.Sort(Int64Slice(a)) }

// Int64Slice attaches the methods of Interface to []iint64, sorting in increasing order.
type Int64Slice []int64

func (p Int64Slice) Len() int           { return len(p) }
func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p Int64Slice) Sort() { sort.Sort(p) }

// Uint16Slice attaches the methods of Interface to []uint16, sorting in increasing order.
type Uint16Slice []uint16

func (p Uint16Slice) Len() int           { return len(p) }
func (p Uint16Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Uint16Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p Uint16Slice) Sort() { sort.Sort(p) }

func Uint16s(a []uint16) { sort.Sort(Uint16Slice(a)) }
<|endoftext|>


<commit_before>package clock

import (
	"runtime"
	"sort"
	"sync"
	"time"
)

// Clock represents an interface to the functions in the standard library time
// package. Two implementations are available in the clock package. The first
// is a real-time clock which simply wraps the time package's functions. The
// second is a mock clock which will only make forward progress when
// programmatically adjusted.
type Clock interface {
	After(d time.Duration) <-chan time.Time
	AfterFunc(d time.Duration, f func()) *Timer
	Now() time.Time
	Sleep(d time.Duration)
	Tick(d time.Duration) <-chan time.Time
	Ticker(d time.Duration) *Ticker
	Timer(d time.Duration) *Timer
}

// New returns an instance of a real-time clock.
func New() Clock {
	return &clock{}
}

// clock implements a real-time clock by simply wrapping the time package functions.
type clock struct{}

func (c *clock) After(d time.Duration) <-chan time.Time { return time.After(d) }

func (c *clock) AfterFunc(d time.Duration, f func()) *Timer {
	return &Timer{timer: time.AfterFunc(d, f)}
}

func (c *clock) Now() time.Time { return time.Now() }

func (c *clock) Sleep(d time.Duration) { time.Sleep(d) }

func (c *clock) Tick(d time.Duration) <-chan time.Time { return time.Tick(d) }

func (c *clock) Ticker(d time.Duration) *Ticker {
	t := time.NewTicker(d)
	return &Ticker{C: t.C, ticker: t}
}

func (c *clock) Timer(d time.Duration) *Timer {
	t := time.NewTimer(d)
	return &Timer{C: t.C, timer: t}
}

// Mock represents a mock clock that only moves forward programmically.
// It can be preferable to a real-time clock when testing time-based functionality.
type Mock struct {
	mu     sync.Mutex
	now    time.Time   // current time
	timers clockTimers // tickers & timers
}

// NewMock returns an instance of a mock clock.
// The current time of the mock clock on initialization is the Unix epoch.
func NewMock() *Mock {
	return &Mock{now: time.Unix(0, 0)}
}

// Add moves the current time of the mock clock forward by the duration.
// This should only be called from a single goroutine at a time.
func (m *Mock) Add(d time.Duration) {
	// Calculate the final current time.
	t := m.now.Add(d)

	// Continue to execute timers until there are no more before the new time.
	for {
		if !m.runNextTimer(t) {
			break
		}
	}

	// Ensure that we end with the new time.
	m.mu.Lock()
	m.now = t
	m.mu.Unlock()

	// Give a small buffer to make sure the other goroutines get handled.
	gosched()
}

// runNextTimer executes the next timer in chronological order and moves the
// current time to the timer's next tick time. The next time is not executed if
// it's next time if after the max time. Returns true if a timer is executed.
func (m *Mock) runNextTimer(max time.Time) bool {
	m.mu.Lock()

	// Sort timers by time.
	sort.Sort(m.timers)

	// If we have no more timers then exit.
	if len(m.timers) == 0 {
		m.mu.Unlock()
		return false
	}

	// Retrieve next timer. Exit if next tick is after new time.
	t := m.timers[0]
	if t.Next().After(max) {
		m.mu.Unlock()
		return false
	}

	// Move "now" forward and unlock clock.
	m.now = t.Next()
	m.mu.Unlock()

	// Execute timer.
	t.Tick(m.now)
	return true
}

// After waits for the duration to elapse and then sends the current time on the returned channel.
func (m *Mock) After(d time.Duration) <-chan time.Time {
	return m.Timer(d).C
}

// AfterFunc waits for the duration to elapse and then executes a function.
// A Timer is returned that can be stopped.
func (m *Mock) AfterFunc(d time.Duration, f func()) *Timer {
	t := m.Timer(d)
	t.C = nil
	t.fn = f
	return t
}

// Now returns the current wall time on the mock clock.
func (m *Mock) Now() time.Time {
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.now
}

// Sleep pauses the goroutine for the given duration on the mock clock.
// The clock must be moved forward in a separate goroutine.
func (m *Mock) Sleep(d time.Duration) {
	<-m.After(d)
}

// Tick is a convenience function for Ticker().
// It will return a ticker channel that cannot be stopped.
func (m *Mock) Tick(d time.Duration) <-chan time.Time {
	return m.Ticker(d).C
}

// Ticker creates a new instance of Ticker.
func (m *Mock) Ticker(d time.Duration) *Ticker {
	m.mu.Lock()
	defer m.mu.Unlock()
	ch := make(chan time.Time)
	t := &Ticker{
		C:    ch,
		c:    ch,
		mock: m,
		d:    d,
		next: m.now.Add(d),
	}
	m.timers = append(m.timers, (*internalTicker)(t))
	return t
}

// Timer creates a new instance of Timer.
func (m *Mock) Timer(d time.Duration) *Timer {
	m.mu.Lock()
	defer m.mu.Unlock()
	ch := make(chan time.Time)
	t := &Timer{
		C:    ch,
		c:    ch,
		mock: m,
		next: m.now.Add(d),
	}
	m.timers = append(m.timers, (*internalTimer)(t))
	return t
}

func (m *Mock) removeClockTimer(t clockTimer) {
	m.mu.Lock()
	defer m.mu.Unlock()
	for i, timer := range m.timers {
		if timer == t {
			copy(m.timers[i:], m.timers[i+1:])
			m.timers[len(m.timers)-1] = nil
			m.timers = m.timers[:len(m.timers)-1]
			break
		}
	}
	sort.Sort(m.timers)
}

// clockTimer represents an object with an associated start time.
type clockTimer interface {
	Next() time.Time
	Tick(time.Time)
}

// clockTimers represents a list of sortable timers.
type clockTimers []clockTimer

func (a clockTimers) Len() int           { return len(a) }
func (a clockTimers) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a clockTimers) Less(i, j int) bool { return a[i].Next().Before(a[j].Next()) }

// Timer represents a single event.
// The current time will be sent on C, unless the timer was created by AfterFunc.
type Timer struct {
	C     <-chan time.Time
	c     chan time.Time
	timer *time.Timer // realtime impl, if set
	next  time.Time   // next tick time
	mock  *Mock       // mock clock, if set
	fn    func()      // AfterFunc function, if set
}

// Stop turns off the ticker.
func (t *Timer) Stop() {
	if t.timer != nil {
		t.timer.Stop()
	} else {
		t.mock.removeClockTimer((*internalTimer)(t))
	}
}

type internalTimer Timer

func (t *internalTimer) Next() time.Time { return t.next }
func (t *internalTimer) Tick(now time.Time) {
	if t.fn != nil {
		t.fn()
	} else {
		t.c <- now
	}
	t.mock.removeClockTimer((*internalTimer)(t))
	gosched()
}

// Ticker holds a channel that receives "ticks" at regular intervals.
type Ticker struct {
	C      <-chan time.Time
	c      chan time.Time
	ticker *time.Ticker  // realtime impl, if set
	next   time.Time     // next tick time
	mock   *Mock         // mock clock, if set
	d      time.Duration // time between ticks
}

// Stop turns off the ticker.
func (t *Ticker) Stop() {
	if t.ticker != nil {
		t.ticker.Stop()
	} else {
		t.mock.removeClockTimer((*internalTicker)(t))
	}
}

type internalTicker Ticker

func (t *internalTicker) Next() time.Time { return t.next }
func (t *internalTicker) Tick(now time.Time) {
	select {
	case t.c <- now:
	case <-time.After(1 * time.Millisecond):
	}
	t.next = now.Add(t.d)
	gosched()
}

// Sleep momentarily so that other goroutines can process.
func gosched() { runtime.Gosched() }
<commit_msg>add clock.Wait<commit_after>package clock

import (
	"runtime"
	"sort"
	"sync"
	"time"
)

// Clock represents an interface to the functions in the standard library time
// package. Two implementations are available in the clock package. The first
// is a real-time clock which simply wraps the time package's functions. The
// second is a mock clock which will only make forward progress when
// programmatically adjusted.
type Clock interface {
	After(d time.Duration) <-chan time.Time
	AfterFunc(d time.Duration, f func()) *Timer
	Now() time.Time
	Sleep(d time.Duration)
	Tick(d time.Duration) <-chan time.Time
	Ticker(d time.Duration) *Ticker
	Timer(d time.Duration) *Timer
}

// New returns an instance of a real-time clock.
func New() Clock {
	return &clock{}
}

// clock implements a real-time clock by simply wrapping the time package functions.
type clock struct{}

func (c *clock) After(d time.Duration) <-chan time.Time { return time.After(d) }

func (c *clock) AfterFunc(d time.Duration, f func()) *Timer {
	return &Timer{timer: time.AfterFunc(d, f)}
}

func (c *clock) Now() time.Time { return time.Now() }

func (c *clock) Sleep(d time.Duration) { time.Sleep(d) }

func (c *clock) Tick(d time.Duration) <-chan time.Time { return time.Tick(d) }

func (c *clock) Ticker(d time.Duration) *Ticker {
	t := time.NewTicker(d)
	return &Ticker{C: t.C, ticker: t}
}

func (c *clock) Timer(d time.Duration) *Timer {
	t := time.NewTimer(d)
	return &Timer{C: t.C, timer: t}
}

// Mock represents a mock clock that only moves forward programmically.
// It can be preferable to a real-time clock when testing time-based functionality.
type Mock struct {
	mu     sync.Mutex
	now    time.Time   // current time
	timers clockTimers // tickers & timers

	calls      Calls
	waiting    []waiting
	callsMutex sync.Mutex
}

// NewMock returns an instance of a mock clock.
// The current time of the mock clock on initialization is the Unix epoch.
func NewMock() *Mock {
	return &Mock{now: time.Unix(0, 0)}
}

// Add moves the current time of the mock clock forward by the duration.
// This should only be called from a single goroutine at a time.
func (m *Mock) Add(d time.Duration) {
	// Calculate the final current time.
	t := m.now.Add(d)

	// Continue to execute timers until there are no more before the new time.
	for {
		if !m.runNextTimer(t) {
			break
		}
	}

	// Ensure that we end with the new time.
	m.mu.Lock()
	m.now = t
	m.mu.Unlock()

	// Give a small buffer to make sure the other goroutines get handled.
	gosched()
}

// runNextTimer executes the next timer in chronological order and moves the
// current time to the timer's next tick time. The next time is not executed if
// it's next time if after the max time. Returns true if a timer is executed.
func (m *Mock) runNextTimer(max time.Time) bool {
	m.mu.Lock()

	// Sort timers by time.
	sort.Sort(m.timers)

	// If we have no more timers then exit.
	if len(m.timers) == 0 {
		m.mu.Unlock()
		return false
	}

	// Retrieve next timer. Exit if next tick is after new time.
	t := m.timers[0]
	if t.Next().After(max) {
		m.mu.Unlock()
		return false
	}

	// Move "now" forward and unlock clock.
	m.now = t.Next()
	m.mu.Unlock()

	// Execute timer.
	t.Tick(m.now)
	return true
}

// After waits for the duration to elapse and then sends the current time on the returned channel.
func (m *Mock) After(d time.Duration) <-chan time.Time {
	defer m.inc(&m.calls.After)
	return m.Timer(d).C
}

// AfterFunc waits for the duration to elapse and then executes a function.
// A Timer is returned that can be stopped.
func (m *Mock) AfterFunc(d time.Duration, f func()) *Timer {
	defer m.inc(&m.calls.AfterFunc)
	t := m.Timer(d)
	t.C = nil
	t.fn = f
	return t
}

// Now returns the current wall time on the mock clock.
func (m *Mock) Now() time.Time {
	defer m.inc(&m.calls.Now)
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.now
}

// Sleep pauses the goroutine for the given duration on the mock clock.
// The clock must be moved forward in a separate goroutine.
func (m *Mock) Sleep(d time.Duration) {
	defer m.inc(&m.calls.Sleep)
	<-m.After(d)
}

// Tick is a convenience function for Ticker().
// It will return a ticker channel that cannot be stopped.
func (m *Mock) Tick(d time.Duration) <-chan time.Time {
	defer m.inc(&m.calls.Tick)
	return m.Ticker(d).C
}

// Ticker creates a new instance of Ticker.
func (m *Mock) Ticker(d time.Duration) *Ticker {
	defer m.inc(&m.calls.Ticker)
	m.mu.Lock()
	defer m.mu.Unlock()
	ch := make(chan time.Time)
	t := &Ticker{
		C:    ch,
		c:    ch,
		mock: m,
		d:    d,
		next: m.now.Add(d),
	}
	m.timers = append(m.timers, (*internalTicker)(t))
	return t
}

// Timer creates a new instance of Timer.
func (m *Mock) Timer(d time.Duration) *Timer {
	defer m.inc(&m.calls.Timer)
	m.mu.Lock()
	defer m.mu.Unlock()
	ch := make(chan time.Time)
	t := &Timer{
		C:    ch,
		c:    ch,
		mock: m,
		next: m.now.Add(d),
	}
	m.timers = append(m.timers, (*internalTimer)(t))
	return t
}

func (m *Mock) removeClockTimer(t clockTimer) {
	m.mu.Lock()
	defer m.mu.Unlock()
	for i, timer := range m.timers {
		if timer == t {
			copy(m.timers[i:], m.timers[i+1:])
			m.timers[len(m.timers)-1] = nil
			m.timers = m.timers[:len(m.timers)-1]
			break
		}
	}
	sort.Sort(m.timers)
}

func (m *Mock) inc(addr *uint32) {
	m.callsMutex.Lock()
	defer m.callsMutex.Unlock()
	*addr++
	var newWaiting []waiting
	for _, w := range m.waiting {
		if m.calls.atLeast(w.expected) {
			close(w.done)
			continue
		}
		newWaiting = append(newWaiting, w)
	}
	m.waiting = newWaiting
}

// Wait waits for at least the relevant calls before returning. The expected
// Calls are always over the lifetime of the Mock. Values in the Calls struct
// are used as the minimum number of calls, this allows you to wait for only
// the calls you care about.
func (m *Mock) Wait(s Calls) {
	m.callsMutex.Lock()
	if m.calls.atLeast(s) {
		m.callsMutex.Unlock()
		return
	}
	done := make(chan struct{})
	m.waiting = append(m.waiting, waiting{expected: s, done: done})
	m.callsMutex.Unlock()
	<-done
}

// clockTimer represents an object with an associated start time.
type clockTimer interface {
	Next() time.Time
	Tick(time.Time)
}

// clockTimers represents a list of sortable timers.
type clockTimers []clockTimer

func (a clockTimers) Len() int           { return len(a) }
func (a clockTimers) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a clockTimers) Less(i, j int) bool { return a[i].Next().Before(a[j].Next()) }

// Timer represents a single event.
// The current time will be sent on C, unless the timer was created by AfterFunc.
type Timer struct {
	C     <-chan time.Time
	c     chan time.Time
	timer *time.Timer // realtime impl, if set
	next  time.Time   // next tick time
	mock  *Mock       // mock clock, if set
	fn    func()      // AfterFunc function, if set
}

// Stop turns off the ticker.
func (t *Timer) Stop() {
	if t.timer != nil {
		t.timer.Stop()
	} else {
		t.mock.removeClockTimer((*internalTimer)(t))
	}
}

type internalTimer Timer

func (t *internalTimer) Next() time.Time { return t.next }
func (t *internalTimer) Tick(now time.Time) {
	if t.fn != nil {
		t.fn()
	} else {
		t.c <- now
	}
	t.mock.removeClockTimer((*internalTimer)(t))
	gosched()
}

// Ticker holds a channel that receives "ticks" at regular intervals.
type Ticker struct {
	C      <-chan time.Time
	c      chan time.Time
	ticker *time.Ticker  // realtime impl, if set
	next   time.Time     // next tick time
	mock   *Mock         // mock clock, if set
	d      time.Duration // time between ticks
}

// Stop turns off the ticker.
func (t *Ticker) Stop() {
	if t.ticker != nil {
		t.ticker.Stop()
	} else {
		t.mock.removeClockTimer((*internalTicker)(t))
	}
}

type internalTicker Ticker

func (t *internalTicker) Next() time.Time { return t.next }
func (t *internalTicker) Tick(now time.Time) {
	select {
	case t.c <- now:
	case <-time.After(1 * time.Millisecond):
	}
	t.next = now.Add(t.d)
	gosched()
}

// Sleep momentarily so that other goroutines can process.
func gosched() { runtime.Gosched() }

// Calls keeps track of the count of calls for each of the methods on the Clock
// interface.
type Calls struct {
	After     uint32
	AfterFunc uint32
	Now       uint32
	Sleep     uint32
	Tick      uint32
	Ticker    uint32
	Timer     uint32
}

// atLeast returns true if at least the number of calls in o have been made.
func (c Calls) atLeast(o Calls) bool {
	if c.After < o.After {
		return false
	}
	if c.AfterFunc < o.AfterFunc {
		return false
	}
	if c.Now < o.Now {
		return false
	}
	if c.Sleep < o.Sleep {
		return false
	}
	if c.Tick < o.Tick {
		return false
	}
	if c.Ticker < o.Ticker {
		return false
	}
	if c.Timer < o.Timer {
		return false
	}
	return true
}

type waiting struct {
	expected Calls
	done     chan struct{}
}
<|endoftext|>


<commit_before>package rpc

import (
	"io"

	"github.com/ugorji/go/codec"
)

type decoder interface {
	Decode(interface{}) error
}

// TODO rename this interface to EncodeAndSend
type encoder interface {
	Encode(interface{}) <-chan error
}

type decoderWrapper struct {
	*codec.Decoder
	fieldNumber int
}

func newDecoderWrapper() *decoderWrapper {
	return &decoderWrapper{
		Decoder:     codec.NewDecoderBytes([]byte{}, newCodecMsgpackHandle()),
		fieldNumber: 0,
	}
}

func (dw *decoderWrapper) Decode(i interface{}) error {
	defer func() {
		dw.fieldNumber++
	}()

	err := dw.Decoder.Decode(i)
	if err != nil {
		return newRPCMessageFieldDecodeError(dw.fieldNumber, err)
	}
	return nil
}

func newCodecMsgpackHandle() codec.Handle {
	return &codec.MsgpackHandle{
		WriteExt:    true,
		RawToString: true,
	}
}

type writeBundle struct {
	bytes []byte
	ch    chan error
}

type framedMsgpackEncoder struct {
	handle   codec.Handle
	writer   io.Writer
	writeCh  chan writeBundle
	doneCh   chan struct{}
	closedCh chan struct{}
}

func newFramedMsgpackEncoder(writer io.Writer) *framedMsgpackEncoder {
	e := &framedMsgpackEncoder{
		handle:   newCodecMsgpackHandle(),
		writer:   writer,
		writeCh:  make(chan writeBundle),
		doneCh:   make(chan struct{}),
		closedCh: make(chan struct{}),
	}
	go e.writerLoop()
	return e
}

func (e *framedMsgpackEncoder) encodeToBytes(enc *codec.Encoder, i interface{}) (v []byte, err error) {
	enc.ResetBytes(&v)
	err = enc.Encode(i)
	return v, err
}

func (e *framedMsgpackEncoder) encodeFrame(i interface{}) ([]byte, error) {
	enc := codec.NewEncoderBytes(&[]byte{}, e.handle)
	content, err := e.encodeToBytes(enc, i)
	if err != nil {
		return nil, err
	}
	length, err := e.encodeToBytes(enc, len(content))
	if err != nil {
		return nil, err
	}
	return append(length, content...), nil
}

func (e *framedMsgpackEncoder) Encode(i interface{}) <-chan error {
	bytes, err := e.encodeFrame(i)
	ch := make(chan error, 1)
	if err != nil {
		ch <- err
		return ch
	}
	select {
	case <-e.doneCh:
		ch <- io.EOF
	case e.writeCh <- writeBundle{bytes, ch}:
	}
	return ch
}

func (e *framedMsgpackEncoder) writerLoop() {
	for {
		select {
		case <-e.doneCh:
			close(e.closedCh)
			return
		case write := <-e.writeCh:
			_, err := e.writer.Write(write.bytes)
			write.ch <- err
		}
	}
}

func (e *framedMsgpackEncoder) Close() <-chan struct{} {
	close(e.doneCh)
	return e.closedCh
}
<commit_msg>Make the write channel buffered to prevent starvation<commit_after>package rpc

import (
	"io"

	"github.com/ugorji/go/codec"
)

type decoder interface {
	Decode(interface{}) error
}

// TODO rename this interface to EncodeAndSend
type encoder interface {
	Encode(interface{}) <-chan error
}

type decoderWrapper struct {
	*codec.Decoder
	fieldNumber int
}

func newDecoderWrapper() *decoderWrapper {
	return &decoderWrapper{
		Decoder:     codec.NewDecoderBytes([]byte{}, newCodecMsgpackHandle()),
		fieldNumber: 0,
	}
}

func (dw *decoderWrapper) Decode(i interface{}) error {
	defer func() {
		dw.fieldNumber++
	}()

	err := dw.Decoder.Decode(i)
	if err != nil {
		return newRPCMessageFieldDecodeError(dw.fieldNumber, err)
	}
	return nil
}

func newCodecMsgpackHandle() codec.Handle {
	return &codec.MsgpackHandle{
		WriteExt:    true,
		RawToString: true,
	}
}

type writeBundle struct {
	bytes []byte
	ch    chan error
}

type framedMsgpackEncoder struct {
	handle   codec.Handle
	writer   io.Writer
	writeCh  chan writeBundle
	doneCh   chan struct{}
	closedCh chan struct{}
}

func newFramedMsgpackEncoder(writer io.Writer) *framedMsgpackEncoder {
	e := &framedMsgpackEncoder{
		handle:   newCodecMsgpackHandle(),
		writer:   writer,
		writeCh:  make(chan writeBundle, 128),
		doneCh:   make(chan struct{}),
		closedCh: make(chan struct{}),
	}
	go e.writerLoop()
	return e
}

func (e *framedMsgpackEncoder) encodeToBytes(enc *codec.Encoder, i interface{}) (v []byte, err error) {
	enc.ResetBytes(&v)
	err = enc.Encode(i)
	return v, err
}

func (e *framedMsgpackEncoder) encodeFrame(i interface{}) ([]byte, error) {
	enc := codec.NewEncoderBytes(&[]byte{}, e.handle)
	content, err := e.encodeToBytes(enc, i)
	if err != nil {
		return nil, err
	}
	length, err := e.encodeToBytes(enc, len(content))
	if err != nil {
		return nil, err
	}
	return append(length, content...), nil
}

func (e *framedMsgpackEncoder) Encode(i interface{}) <-chan error {
	bytes, err := e.encodeFrame(i)
	ch := make(chan error, 1)
	if err != nil {
		ch <- err
		return ch
	}
	select {
	case <-e.doneCh:
		ch <- io.EOF
	case e.writeCh <- writeBundle{bytes, ch}:
	}
	return ch
}

func (e *framedMsgpackEncoder) writerLoop() {
	for {
		select {
		case <-e.doneCh:
			close(e.closedCh)
			return
		case write := <-e.writeCh:
			_, err := e.writer.Write(write.bytes)
			write.ch <- err
		}
	}
}

func (e *framedMsgpackEncoder) Close() <-chan struct{} {
	close(e.doneCh)
	return e.closedCh
}
<|endoftext|>


<commit_before>package geolite2v2_test

import (
	"bytes"
	"log"
	_ "net/http/pprof"
	"sort"
	"testing"

	"github.com/Pallinder/go-randomdata"
	"github.com/stretchr/testify/assert"

	"github.com/m-lab/annotation-service/api"
	"github.com/m-lab/annotation-service/geolite2"
	"github.com/m-lab/annotation-service/geolite2v2"
	"github.com/m-lab/annotation-service/geoloader"
)

// TestCompareAnnotations tests if the new implementation annotates the same way as the old
// implementation
func TestCompareAnnotations(t *testing.T) {
	if testing.Short() {
		log.Println("Skipping test that relies on mlab-testing bucket")
		return
	}
	oldAnnotators := loadOld(t)
	newAnnotators := loadNew(t)

	// sort the annotators to be able to compare their resuults
	sort.Slice(oldAnnotators, createSorterFor(oldAnnotators))
	sort.Slice(newAnnotators, createSorterFor(newAnnotators))

	// we need minimum 200 IP hits per annotator
	minimumHitCountPerAnnotator := 200

	// get each annotator
	for idx, oldAnn := range oldAnnotators {
		newAnn := newAnnotators[idx]
		notFoundCount, v4HitCount, v6HitCount := 0, 0, 0
		ipV4 := true

		// annotate v4 and v6 IP addresses and compare the resuults
		for (v4HitCount + v6HitCount) < minimumHitCountPerAnnotator {
			var oldResp, newResp api.GeoData
			var oldErr, newErr error

			var address string
			if ipV4 {
				address = randomdata.IpV4Address()
			} else {
				address = randomdata.IpV6Address()
			}

			// the error should be the same if there's any
			oldErr = oldAnn.Annotate(address, &oldResp)
			newErr = newAnn.Annotate(address, &newResp)
			if oldErr != nil {
				notFoundCount++
				assert.EqualError(t, newErr, oldErr.Error())
				continue
			}
			// the content should be the same if there's any
			assertSameGeoData(t, &oldResp, &newResp)

			if ipV4 {
				v4HitCount++
			} else {
				v6HitCount++
			}
			ipV4 = !ipV4

			if v4HitCount%100 == 0 || v6HitCount%100 == 0 {
				log.Printf("Not found count: %d, v4 hit count: %d, v6 hit count %d", notFoundCount, v4HitCount, v6HitCount)
			}
		}

		log.Printf("annotator[%d] - Not found count: %d, v4 hit count: %d, v6 hit count %d", idx, notFoundCount, v4HitCount, v6HitCount)
	}
}

func assertSameGeoData(t *testing.T, old, new *api.GeoData) {
	assert.Equal(t, old.Geo.AreaCode, new.Geo.AreaCode)
	assert.Equal(t, old.Geo.City, new.Geo.City)
	assert.Equal(t, old.Geo.ContinentCode, new.Geo.ContinentCode)
	assert.Equal(t, old.Geo.CountryCode, new.Geo.CountryCode)
	assert.Equal(t, old.Geo.CountryCode3, new.Geo.CountryCode3)
	assert.Equal(t, old.Geo.CountryName, new.Geo.CountryName)
	assert.Equal(t, old.Geo.Latitude, new.Geo.Latitude)
	assert.Equal(t, old.Geo.Longitude, new.Geo.Longitude)
	assert.Equal(t, old.Geo.MetroCode, new.Geo.MetroCode)
	assert.Equal(t, old.Geo.PostalCode, new.Geo.PostalCode)
	assert.Equal(t, old.Geo.Region, new.Geo.Region)
}

// TestCompareOldNewContent loads all the data with the old and the new implementation and check if contents are the same
func TestCompareOldNewContent(t *testing.T) {
	if testing.Short() {
		log.Println("Skipping test that relies on mlab-testing bucket")
		return
	}
	oldAnnotators := loadOld(t)
	newAnnotators := loadNew(t)

	// assert if we have the same number of annotators
	assert.Equal(t, len(oldAnnotators), len(newAnnotators))

	// sort the annotators to make sure we can compare the list items by index
	sort.Slice(oldAnnotators, createSorterFor(oldAnnotators))
	sort.Slice(newAnnotators, createSorterFor(newAnnotators))

	// assert full content
	for idx, oldAnn := range oldAnnotators {
		newAnn := newAnnotators[idx]
		oldDataset := oldAnn.(*geolite2.GeoDataset)
		newDataset := newAnn.(*geolite2v2.GeoDataset)
		assertSameDataset(t, oldDataset, newDataset)
	}
}

// assertSameDataset asserts if the annotators datasets are the same
func assertSameDataset(t *testing.T, oldDataset *geolite2.GeoDataset, newDataset *geolite2v2.GeoDataset) {
	assert.NotNil(t, oldDataset)
	assert.NotNil(t, newDataset)

	assert.True(t, oldDataset.Start.Equal(newDataset.Start))
	assertSameLocations(t, oldDataset.LocationNodes, newDataset.LocationNodes)
	assertSameIPNodes(t, oldDataset.IP4Nodes, newDataset.IP4Nodes)
	assertSameIPNodes(t, oldDataset.IP6Nodes, newDataset.IP6Nodes)
}

// assertSameLocations asserts if LocationNodes are the same
func assertSameLocations(t *testing.T, oldLocationNodes []geolite2.LocationNode, newLocationNodes []geolite2v2.LocationNode) {
	assert.Equal(t, len(oldLocationNodes), len(newLocationNodes))
	for idx, oldVal := range oldLocationNodes {
		newVal := newLocationNodes[idx]
		assert.Equal(t, oldVal.CityName, newVal.CityName)
		assert.Equal(t, oldVal.ContinentCode, newVal.ContinentCode)
		assert.Equal(t, oldVal.CountryCode, newVal.CountryCode)
		assert.Equal(t, oldVal.CountryName, newVal.CountryName)
		assert.Equal(t, oldVal.GeonameID, newVal.GeonameID)
		assert.Equal(t, oldVal.MetroCode, newVal.MetroCode)
		assert.Equal(t, oldVal.RegionCode, newVal.RegionCode)
		assert.Equal(t, oldVal.RegionName, newVal.RegionName)
	}
}

// assertSameIPNodes asserts if IPNodes are the same (note that the new version merges nodes if possible, so the comparison is a bit complex)
func assertSameIPNodes(t *testing.T, oldIPNodes []geolite2.IPNode, newIPNodes []geolite2v2.GeoIPNode) {
	oldIdx := 0
	// iterate over the new nodes
	for newIdx, newNode := range newIPNodes {
		oldNode := oldIPNodes[oldIdx]

		// in the beginning of every iteration the actual oldNode should be in the beginning of the newNode
		assert.True(t, newNode.IPAddressLow.Equal(oldNode.IPAddressLow))

		// we keep getting the next nodes until an oldNode reaches the end of the actual new node
		for ; bytes.Compare(oldNode.IPAddressHigh, newNode.IPAddressHigh) <= 0; oldNode = oldIPNodes[oldIdx] {
			// oldNode should be within the neNode
			assert.True(t, bytes.Compare(oldNode.IPAddressLow, newNode.IPAddressLow) >= 0)

			// all data should match
			assert.Equal(t, oldNode.Latitude, newNode.Latitude, "latitude at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)
			assert.Equal(t, oldNode.Longitude, newNode.Longitude, "longitude at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)
			assert.Equal(t, oldNode.PostalCode, newNode.PostalCode, "postal code at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)
			assert.Equal(t, oldNode.LocationIndex, newNode.LocationIndex, "locationindex at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)

			oldIdx++

			// if we reach the end of the old nodes double check that we!re in the end of the new nodes as well and exit
			if oldIdx == len(oldIPNodes) {
				assert.Equal(t, len(newIPNodes)-1, newIdx)
				assert.True(t, oldNode.IPAddressHigh.Equal(newNode.IPAddressHigh))
				break
			}
		}
	}
}

// createSorterFor returns a sorter function for the specified annotator list
func createSorterFor(forList []api.Annotator) func(int, int) bool {
	return func(firstIdx, nextIdx int) bool {
		return forList[firstIdx].AnnotatorDate().Before(forList[nextIdx].AnnotatorDate())
	}
}

// loadOld loads only data from march with the old loader
func loadOld(t *testing.T) []api.Annotator {
	year, month, day := "2018", "03", "01"
	geoloader.UseSpecificGeolite2DateForTesting(&year, &month, &day)
	g2loader := geoloader.Geolite2Loader(geolite2.LoadGeolite2)
	err := g2loader.UpdateCache()
	assert.Nil(t, err)
	return g2loader.Fetch()
}

// loadNew loads only data from march with the new loader
func loadNew(t *testing.T) []api.Annotator {
	year, month, day := "2018", "03", "01"
	geoloader.UseSpecificGeolite2DateForTesting(&year, &month, &day)
	g2loader := geoloader.Geolite2Loader(geolite2v2.LoadG2)
	err := g2loader.UpdateCache()
	assert.Nil(t, err)
	return g2loader.Fetch()
}
<commit_msg>speed up comparison test<commit_after>package geolite2v2_test

import (
	"bytes"
	"log"
	"net"
	_ "net/http/pprof"
	"sort"
	"sync"
	"testing"

	"github.com/Pallinder/go-randomdata"
	"github.com/stretchr/testify/assert"

	"github.com/m-lab/annotation-service/api"
	"github.com/m-lab/annotation-service/geolite2"
	"github.com/m-lab/annotation-service/geolite2v2"
	"github.com/m-lab/annotation-service/geoloader"
)

// TestCompareAnnotations tests if the new implementation annotates the same way as the old
// implementation
func TestCompareV4Annotations(t *testing.T) {
	if testing.Short() {
		log.Println("Skipping test that relies on mlab-testing bucket")
		return
	}
	oldAnnotators, newAnnotators := oldAndNew(t)

	// we need minimum 200 IP hits per annotator
	minimumHitCountPerAnnotator := 10000

	// get each annotator
	for idx, oldAnn := range oldAnnotators {
		newAnn := newAnnotators[idx]
		notFoundCount, v4HitCount := 0, 0

		// annotate v4 and v6 IP addresses and compare the resuults
		// TODO - hit rate is only about 1 in 10K.  WHY???
		for v4HitCount < minimumHitCountPerAnnotator {
			var oldResp, newResp api.GeoData
			var oldErr, newErr error

			var address string
			address = randomdata.IpV4Address()

			// the error should be the same if there's any
			oldErr = oldAnn.Annotate(address, &oldResp)
			newErr = newAnn.Annotate(address, &newResp)
			if oldErr != nil || newErr != nil {
				notFoundCount++
				if notFoundCount%1000 == 0 {
					log.Println("Not found:", address)
				}
				assert.EqualError(t, newErr, oldErr.Error())
				continue
			}
			// the content should be the same if there's any
			assertSameGeoData(t, &oldResp, &newResp)

			v4HitCount++

			if v4HitCount%2000 == 0 {
				log.Printf("Not found count: %d, v4 hit count: %d", notFoundCount, v4HitCount)
			}
		}

		log.Printf("annotator[%d] - Not found count: %d, v4 hit count: %d", idx, notFoundCount, v4HitCount)
	}

	// Now do the ipv6, which needs a slightly different strategy.
	for idx, oldAnn := range oldAnnotators {
		newAnn := newAnnotators[idx]
		notFoundCount, v6HitCount := 0, 0

		// annotate v4 and v6 IP addresses and compare the resuults
		// TODO - hit rate is only about 1 in 10K.  WHY???
		for v6HitCount < minimumHitCountPerAnnotator {
			var oldResp, newResp api.GeoData
			var oldErr, newErr error

			var address net.IP
			if v6HitCount%2 == 0 {
				_, address = randomValidIPv6(oldAnn)
			} else {
				_, address = randomValidIPv6(newAnn)
			}

			// the error should be the same if there's any
			oldErr = oldAnn.Annotate(address.String(), &oldResp)
			newErr = newAnn.Annotate(address.String(), &newResp)
			if oldErr != nil || newErr != nil {
				notFoundCount++
				if notFoundCount%1000 == 0 {
					log.Println("Not found:", address)
				}
				assert.EqualError(t, newErr, oldErr.Error())
				continue
			}
			// the content should be the same if there's any
			assertSameGeoData(t, &oldResp, &newResp)

			v6HitCount++

			if v6HitCount%2000 == 0 {
				log.Printf("Not found count: %d, v6 hit count: %d", notFoundCount, v6HitCount)
			}
		}

		log.Printf("annotator[%d] - Not found count: %d, v6 hit count: %d", idx, notFoundCount, v6HitCount)
	}
}

func assertSameGeoData(t *testing.T, old, new *api.GeoData) {
	assert.Equal(t, old.Geo.AreaCode, new.Geo.AreaCode)
	assert.Equal(t, old.Geo.City, new.Geo.City)
	assert.Equal(t, old.Geo.ContinentCode, new.Geo.ContinentCode)
	assert.Equal(t, old.Geo.CountryCode, new.Geo.CountryCode)
	assert.Equal(t, old.Geo.CountryCode3, new.Geo.CountryCode3)
	assert.Equal(t, old.Geo.CountryName, new.Geo.CountryName)
	assert.Equal(t, old.Geo.Latitude, new.Geo.Latitude)
	assert.Equal(t, old.Geo.Longitude, new.Geo.Longitude)
	assert.Equal(t, old.Geo.MetroCode, new.Geo.MetroCode)
	assert.Equal(t, old.Geo.PostalCode, new.Geo.PostalCode)
	assert.Equal(t, old.Geo.Region, new.Geo.Region)
}

// TestCompareOldNewContent loads all the data with the old and the new implementation and check if contents are the same
func TestCompareOldNewContent(t *testing.T) {
	if testing.Short() {
		log.Println("Skipping test that relies on mlab-testing bucket")
		return
	}
	oldAnnotators, newAnnotators := oldAndNew(t)

	// assert if we have the same number of annotators
	assert.Equal(t, len(oldAnnotators), len(newAnnotators))

	// sort the annotators to make sure we can compare the list items by index
	sort.Slice(oldAnnotators, createSorterFor(oldAnnotators))
	sort.Slice(newAnnotators, createSorterFor(newAnnotators))

	// assert full content
	for idx, oldAnn := range oldAnnotators {
		newAnn := newAnnotators[idx]
		oldDataset := oldAnn.(*geolite2.GeoDataset)
		newDataset := newAnn.(*geolite2v2.GeoDataset)
		assertSameDataset(t, oldDataset, newDataset)
	}
}

// assertSameDataset asserts if the annotators datasets are the same
func assertSameDataset(t *testing.T, oldDataset *geolite2.GeoDataset, newDataset *geolite2v2.GeoDataset) {
	assert.NotNil(t, oldDataset)
	assert.NotNil(t, newDataset)

	assert.True(t, oldDataset.Start.Equal(newDataset.Start))
	assertSameLocations(t, oldDataset.LocationNodes, newDataset.LocationNodes)
	assertSameIPNodes(t, oldDataset.IP4Nodes, newDataset.IP4Nodes)
	assertSameIPNodes(t, oldDataset.IP6Nodes, newDataset.IP6Nodes)
}

// assertSameLocations asserts if LocationNodes are the same
func assertSameLocations(t *testing.T, oldLocationNodes []geolite2.LocationNode, newLocationNodes []geolite2v2.LocationNode) {
	assert.Equal(t, len(oldLocationNodes), len(newLocationNodes))
	for idx, oldVal := range oldLocationNodes {
		newVal := newLocationNodes[idx]
		assert.Equal(t, oldVal.CityName, newVal.CityName)
		assert.Equal(t, oldVal.ContinentCode, newVal.ContinentCode)
		assert.Equal(t, oldVal.CountryCode, newVal.CountryCode)
		assert.Equal(t, oldVal.CountryName, newVal.CountryName)
		assert.Equal(t, oldVal.GeonameID, newVal.GeonameID)
		assert.Equal(t, oldVal.MetroCode, newVal.MetroCode)
		assert.Equal(t, oldVal.RegionCode, newVal.RegionCode)
		assert.Equal(t, oldVal.RegionName, newVal.RegionName)
	}
}

// assertSameIPNodes asserts if IPNodes are the same (note that the new version merges nodes if possible, so the comparison is a bit complex)
func assertSameIPNodes(t *testing.T, oldIPNodes []geolite2.IPNode, newIPNodes []geolite2v2.GeoIPNode) {
	oldIdx := 0
	// iterate over the new nodes
	for newIdx, newNode := range newIPNodes {
		oldNode := oldIPNodes[oldIdx]

		// in the beginning of every iteration the actual oldNode should be in the beginning of the newNode
		assert.True(t, newNode.IPAddressLow.Equal(oldNode.IPAddressLow))

		// we keep getting the next nodes until an oldNode reaches the end of the actual new node
		for ; bytes.Compare(oldNode.IPAddressHigh, newNode.IPAddressHigh) <= 0; oldNode = oldIPNodes[oldIdx] {
			// oldNode should be within the neNode
			assert.True(t, bytes.Compare(oldNode.IPAddressLow, newNode.IPAddressLow) >= 0)

			// all data should match
			assert.Equal(t, oldNode.Latitude, newNode.Latitude, "latitude at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)
			assert.Equal(t, oldNode.Longitude, newNode.Longitude, "longitude at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)
			assert.Equal(t, oldNode.PostalCode, newNode.PostalCode, "postal code at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)
			assert.Equal(t, oldNode.LocationIndex, newNode.LocationIndex, "locationindex at oldIdx=%d, newIdx=%d, oldNode=%v, newNode=%v", oldIdx, newIdx, oldNode, newNode)

			oldIdx++

			// if we reach the end of the old nodes double check that we!re in the end of the new nodes as well and exit
			if oldIdx == len(oldIPNodes) {
				assert.Equal(t, len(newIPNodes)-1, newIdx)
				assert.True(t, oldNode.IPAddressHigh.Equal(newNode.IPAddressHigh))
				break
			}
		}
	}
}

// createSorterFor returns a sorter function for the specified annotator list
func createSorterFor(forList []api.Annotator) func(int, int) bool {
	return func(firstIdx, nextIdx int) bool {
		return forList[firstIdx].AnnotatorDate().Before(forList[nextIdx].AnnotatorDate())
	}
}

// loadOld loads only data from march with the old loader
// TODO preload these only once
func loadOld(t *testing.T) []api.Annotator {
	year, month, day := "2018", "03", "01"
	geoloader.UseSpecificGeolite2DateForTesting(&year, &month, &day)
	g2loader := geoloader.Geolite2Loader(geolite2.LoadGeolite2)
	err := g2loader.UpdateCache()
	assert.Nil(t, err)
	return g2loader.Fetch()
}

// loadNew loads only data from march with the new loader
// TODO preload these only once
func loadNew(t *testing.T) []api.Annotator {
	year, month, day := "2018", "03", "01"
	geoloader.UseSpecificGeolite2DateForTesting(&year, &month, &day)
	g2loader := geoloader.Geolite2Loader(geolite2v2.LoadG2)
	err := g2loader.UpdateCache()
	assert.Nil(t, err)
	return g2loader.Fetch()
}

func oldAndNew(t *testing.T) ([]api.Annotator, []api.Annotator) {
	var oldAnnotators []api.Annotator
	var newAnnotators []api.Annotator
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		oldAnnotators = loadOld(t)
		wg.Done()
	}()

	go func() {
		newAnnotators = loadNew(t)
		wg.Done()
	}()

	wg.Wait()
	// sort the annotators to be able to compare their resuults
	sort.Slice(oldAnnotators, createSorterFor(oldAnnotators))
	sort.Slice(newAnnotators, createSorterFor(newAnnotators))
	return oldAnnotators, newAnnotators
}
<|endoftext|>


<commit_before>package loadbalancer

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"

	"github.com/FrenchBen/oracle-sdk-go/bmc"

	"github.com/Sirupsen/logrus"
)

// LoadBalancer represents the listener's configuration: https://docs.us-phoenix-1.oraclecloud.com/api/#/en/loadbalancer/20170115/LoadBalancer/
type LoadBalancer struct {
	// A mapping of strings to BackendSet objects
	BackendSets map[string]BackendSet `json:"backendSets,omitempty"`
	// A user-friendly name
	DisplayName string `json:"displayName"`
	// A mapping of strings to Certificate objects
	Certificates map[string]Certificate `json:"certificates,omitempty"`
	// The OCID of the compartment containing the load balancer
	CompartmentID string `json:"compartmentId"`
	// The OCID of the load balancer
	ID string `json:"id"`
	// An array of IP addresses
	IPAddresses []IP `json:"ipAddresses"`
	// Whether the load balancer has a VCN-local (private) IP address
	Private bool `json:"isPrivate"`
	// The current state of the instance.
	// CREATING | ACTIVE
	// FAILED | DELETING | DELETED
	LifeCycleState string `json:"lifecycleState"`
	// A mapping of strings to Listener objects
	Listeners []Listener `json:"listeners"`
	// A template that determines the total pre-provisioned bandwidth
	ShapeName string `json:"shapeName"` // HTTP or TCP
	// An array of subnet OCIDs
	SubnetIDs []string `json:"subnetIds"`
	// The date and time the instance was created (RFC3339)
	TimeCreated string `json:"timeCreated"`
}

// IP is a load balancer IP address
type IP struct {
	Address string `json:"ipAddress"`
	Public  bool   `json:"isPublic"`
}

// GetLoadBalancer gets the specified load balancer's configuration information
func (c *Client) GetLoadBalancer(loadBalancerID string) (LoadBalancer, *bmc.Error) {
	loadBalancer := LoadBalancer{}
	loadBalancerID = url.PathEscape(loadBalancerID)
	resp, err := c.Request("GET", fmt.Sprintf("/loadBalancers/%s", loadBalancerID), nil)
	if err != nil {
		logrus.Error(err)
		bmcError := bmc.Error{Code: string(resp.StatusCode), Message: err.Error()}
		return loadBalancer, &bmcError
	}
	logrus.Debug("StatusCode: ", resp.StatusCode)
	if resp.StatusCode != 200 {
		return loadBalancer, bmc.NewError(*resp)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	logrus.Debug("Body: ", string(body))
	if err != nil {
		logrus.Fatalf("Could not read JSON response: %s", err)
	}

	if err = json.Unmarshal(body, &loadBalancer); err != nil {
		logrus.Fatalf("Unmarshal impossible: %s", err)
	}
	return loadBalancer, nil
}

// ListLoadBalancers lists all load balancers in the specified compartment
func (c *Client) ListLoadBalancers() ([]LoadBalancer, *bmc.Error) {
	loadBalancers := []LoadBalancer{}
	resp, err := c.Request("GET", fmt.Sprintf("/loadBalancers"), nil)
	if err != nil {
		logrus.Error(err)
		bmcError := bmc.Error{Code: string(resp.StatusCode), Message: err.Error()}
		return loadBalancers, &bmcError
	}
	logrus.Debug("StatusCode: ", resp.StatusCode)
	if resp.StatusCode != 200 {
		return loadBalancers, bmc.NewError(*resp)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	logrus.Debug("Body: ", string(body))
	if err != nil {
		logrus.Fatalf("Could not read JSON response: %s", err)
	}

	if err = json.Unmarshal(body, &loadBalancers); err != nil {
		logrus.Fatalf("Unmarshal impossible: %s", err)
	}
	return loadBalancers, nil
}
<commit_msg>Listeners on LB are maps as well<commit_after>package loadbalancer

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"

	"github.com/FrenchBen/oracle-sdk-go/bmc"

	"github.com/Sirupsen/logrus"
)

// LoadBalancer represents the listener's configuration: https://docs.us-phoenix-1.oraclecloud.com/api/#/en/loadbalancer/20170115/LoadBalancer/
type LoadBalancer struct {
	// A mapping of strings to BackendSet objects
	BackendSets map[string]BackendSet `json:"backendSets,omitempty"`
	// A user-friendly name
	DisplayName string `json:"displayName"`
	// A mapping of strings to Certificate objects
	Certificates map[string]Certificate `json:"certificates,omitempty"`
	// The OCID of the compartment containing the load balancer
	CompartmentID string `json:"compartmentId"`
	// The OCID of the load balancer
	ID string `json:"id"`
	// An array of IP addresses
	IPAddresses []IP `json:"ipAddresses"`
	// Whether the load balancer has a VCN-local (private) IP address
	Private bool `json:"isPrivate"`
	// The current state of the instance.
	// CREATING | ACTIVE
	// FAILED | DELETING | DELETED
	LifeCycleState string `json:"lifecycleState"`
	// A mapping of strings to Listener objects
	Listeners map[string]Listener `json:"listeners"`
	// A template that determines the total pre-provisioned bandwidth
	ShapeName string `json:"shapeName"` // HTTP or TCP
	// An array of subnet OCIDs
	SubnetIDs []string `json:"subnetIds"`
	// The date and time the instance was created (RFC3339)
	TimeCreated string `json:"timeCreated"`
}

// IP is a load balancer IP address
type IP struct {
	Address string `json:"ipAddress"`
	Public  bool   `json:"isPublic"`
}

// GetLoadBalancer gets the specified load balancer's configuration information
func (c *Client) GetLoadBalancer(loadBalancerID string) (LoadBalancer, *bmc.Error) {
	loadBalancer := LoadBalancer{}
	loadBalancerID = url.PathEscape(loadBalancerID)
	resp, err := c.Request("GET", fmt.Sprintf("/loadBalancers/%s", loadBalancerID), nil)
	if err != nil {
		logrus.Error(err)
		bmcError := bmc.Error{Code: string(resp.StatusCode), Message: err.Error()}
		return loadBalancer, &bmcError
	}
	logrus.Debug("StatusCode: ", resp.StatusCode)
	if resp.StatusCode != 200 {
		return loadBalancer, bmc.NewError(*resp)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	logrus.Debug("Body: ", string(body))
	if err != nil {
		logrus.Fatalf("Could not read JSON response: %s", err)
	}

	if err = json.Unmarshal(body, &loadBalancer); err != nil {
		logrus.Fatalf("Unmarshal impossible: %s", err)
	}
	return loadBalancer, nil
}

// ListLoadBalancers lists all load balancers in the specified compartment
func (c *Client) ListLoadBalancers() ([]LoadBalancer, *bmc.Error) {
	loadBalancers := []LoadBalancer{}
	resp, err := c.Request("GET", fmt.Sprintf("/loadBalancers"), nil)
	if err != nil {
		logrus.Error(err)
		bmcError := bmc.Error{Code: string(resp.StatusCode), Message: err.Error()}
		return loadBalancers, &bmcError
	}
	logrus.Debug("StatusCode: ", resp.StatusCode)
	if resp.StatusCode != 200 {
		return loadBalancers, bmc.NewError(*resp)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	logrus.Debug("Body: ", string(body))
	if err != nil {
		logrus.Fatalf("Could not read JSON response: %s", err)
	}

	if err = json.Unmarshal(body, &loadBalancers); err != nil {
		logrus.Fatalf("Unmarshal impossible: %s", err)
	}
	return loadBalancers, nil
}
<|endoftext|>


<commit_before>package chart

import (
	"testing"
	"time"

	"github.com/blendlabs/go-assert"
)

func TestRangeTranslate(t *testing.T) {
	assert := assert.New(t)
	values := []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}
	r := NewRange(1000, values...)
	assert.Equal(1.0, r.MinValue)
	assert.Equal(8.0, r.MaxValue)
	assert.Equal(7.0, r.MinMaxDelta)
	assert.Equal(1000, r.Domain)
	assert.Equal(428, r.Translate(5.0))
}

func TestRangeOfTimeTranslate(t *testing.T) {
	assert := assert.New(t)
	values := []time.Time{
		time.Now().AddDate(0, 0, -1),
		time.Now().AddDate(0, 0, -2),
		time.Now().AddDate(0, 0, -3),
		time.Now().AddDate(0, 0, -4),
		time.Now().AddDate(0, 0, -5),
		time.Now().AddDate(0, 0, -6),
		time.Now().AddDate(0, 0, -7),
		time.Now().AddDate(0, 0, -8),
	}
	r := NewRangeOfTime(1000, values...)
	assert.Equal(values[7], r.MinValue)
	assert.Equal(values[0], r.MaxValue)
	assert.Equal(values[0].Unix()-values[7].Unix(), r.MinMaxDelta)
	assert.Equal(1000, r.Domain)
	assert.Equal(571, r.Translate(time.Now().AddDate(0, 0, -5)))
}
<commit_msg>stuff.<commit_after>package chart

import (
	"testing"
	"time"

	"github.com/blendlabs/go-assert"
)

func TestRangeTranslate(t *testing.T) {
	assert := assert.New(t)
	values := []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}
	r := NewRangeOfFloat64(1000, values...)
	assert.Equal(1.0, r.GetMin())
	assert.Equal(8.0, r.GetMax())
	assert.Equal(428, r.Translate(5.0))
}

func TestRangeOfTimeTranslate(t *testing.T) {
	assert := assert.New(t)
	values := []time.Time{
		time.Now().AddDate(0, 0, -1),
		time.Now().AddDate(0, 0, -2),
		time.Now().AddDate(0, 0, -3),
		time.Now().AddDate(0, 0, -4),
		time.Now().AddDate(0, 0, -5),
		time.Now().AddDate(0, 0, -6),
		time.Now().AddDate(0, 0, -7),
		time.Now().AddDate(0, 0, -8),
	}
	r := NewRangeOfTime(1000, values...)
	assert.Equal(values[7], r.GetMin())
	assert.Equal(values[0], r.GetMax())
	assert.Equal(571, r.Translate(time.Now().AddDate(0, 0, -5)))
}
<|endoftext|>


<commit_before>package rbd

/*
#include <errno.h>
*/
import "C"

import (
	"errors"
	"fmt"

	"github.com/ceph/go-ceph/internal/errutil"
)

// revive:disable:exported Temporarily live with stuttering

// RBDError represents an error condition returned from the librbd APIs.
type RBDError int

// revive:enable:exported

func (e RBDError) Error() string {
	errno, s := errutil.FormatErrno(int(e))
	if s == "" {
		return fmt.Sprintf("rbd: ret=%d", errno)
	}
	return fmt.Sprintf("rbd: ret=%d, %s", errno, s)
}

func getError(err C.int) error {
	if err != 0 {
		if err == -C.ENOENT {
			return ErrNotFound
		}
		return RBDError(err)
	}
	return nil
}

// getErrorIfNegative converts a ceph return code to error if negative.
// This is useful for functions that return a usable positive value on
// success but a negative error number on error.
func getErrorIfNegative(ret C.int) error {
	if ret >= 0 {
		return nil
	}
	return getError(ret)
}

// Public go errors:

var (
	// ErrNoIOContext may be returned if an api call requires an IOContext and
	// it is not provided.
	ErrNoIOContext = errors.New("RBD image does not have an IOContext")
	// ErrNoName may be returned if an api call requires a name and it is
	// not provided.
	ErrNoName = errors.New("RBD image does not have a name")
	// ErrSnapshotNoName may be returned if an aip call requires a snapshot
	// name and it is not provided.
	ErrSnapshotNoName = errors.New("RBD snapshot does not have a name")
	// ErrImageNotOpen may be returned if an api call requires an open image handle and one is not provided.
	ErrImageNotOpen = errors.New("RBD image not open")
	// ErrImageIsOpen may be returned if an api call requires a closed image handle and one is not provided.
	ErrImageIsOpen = errors.New("RBD image is open")
	// ErrNotFound may be returned from an api call when the requested item is
	// missing.
	ErrNotFound = errors.New("RBD image not found")
	// ErrNoNamespaceName maye be returned if an api call requires a namespace
	// name and it is not provided.
	ErrNoNamespaceName = errors.New("Namespace value is missing")

	// revive:disable:exported for compatibility with old versions
	RbdErrorImageNotOpen = ErrImageNotOpen
	RbdErrorNotFound     = ErrNotFound
	// revive:enable:exported
)

// Private errors:

const (
	errRange = RBDError(-C.ERANGE)
)
<commit_msg>rbd: minor fixes in error.go<commit_after>package rbd

/*
#include <errno.h>
*/
import "C"

import (
	"errors"
	"fmt"

	"github.com/ceph/go-ceph/internal/errutil"
)

// revive:disable:exported Temporarily live with stuttering

// RBDError represents an error condition returned from the librbd APIs.
type RBDError int

// revive:enable:exported

func (e RBDError) Error() string {
	errno, s := errutil.FormatErrno(int(e))
	if s == "" {
		return fmt.Sprintf("rbd: ret=%d", errno)
	}
	return fmt.Sprintf("rbd: ret=%d, %s", errno, s)
}

func getError(err C.int) error {
	if err != 0 {
		if err == -C.ENOENT {
			return ErrNotFound
		}
		return RBDError(err)
	}
	return nil
}

// getErrorIfNegative converts a ceph return code to error if negative.
// This is useful for functions that return a usable positive value on
// success but a negative error number on error.
func getErrorIfNegative(ret C.int) error {
	if ret >= 0 {
		return nil
	}
	return getError(ret)
}

// Public go errors:

var (
	// ErrNoIOContext may be returned if an api call requires an IOContext and
	// it is not provided.
	ErrNoIOContext = errors.New("IOContext is missing")
	// ErrNoName may be returned if an api call requires a name and it is
	// not provided.
	ErrNoName = errors.New("RBD image does not have a name")
	// ErrSnapshotNoName may be returned if an api call requires a snapshot
	// name and it is not provided.
	ErrSnapshotNoName = errors.New("RBD snapshot does not have a name")
	// ErrImageNotOpen may be returned if an api call requires an open image handle and one is not provided.
	ErrImageNotOpen = errors.New("RBD image not open")
	// ErrImageIsOpen may be returned if an api call requires a closed image handle and one is not provided.
	ErrImageIsOpen = errors.New("RBD image is open")
	// ErrNotFound may be returned from an api call when the requested item is
	// missing.
	ErrNotFound = errors.New("RBD image not found")
	// ErrNoNamespaceName maye be returned if an api call requires a namespace
	// name and it is not provided.
	ErrNoNamespaceName = errors.New("Namespace value is missing")

	// revive:disable:exported for compatibility with old versions
	RbdErrorImageNotOpen = ErrImageNotOpen
	RbdErrorNotFound     = ErrNotFound
	// revive:enable:exported
)

// Private errors:

const (
	errRange = RBDError(-C.ERANGE)
)
<|endoftext|>