<commit_before>// Copyright 2018 The ACH Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

import (
	"testing"
	"strings"
)

func mockAddenda02() *Addenda02 {
	addenda02 := NewAddenda02()
	addenda02.ReferenceInformationOne = "REFONEA"
	addenda02.ReferenceInformationTwo = "REF"
	addenda02.TerminalIdentificationCode = "TERM02"
	addenda02.TransactionSerialNumber = "100049"
	addenda02.TransactionDate = "0612"
	addenda02.AuthorizationCodeOrExpireDate = "123456"
	addenda02.TerminalLocation = "Target Store 0049"
	addenda02.TerminalCity = "PHILADELPHIA"
	addenda02.TerminalState = "PA"
	addenda02.TraceNumber = 91012980000088
	return addenda02
}

func TestMockAddenda02(t *testing.T) {
	addenda02 := mockAddenda02()
	if err := addenda02.Validate(); err != nil {
		t.Error("mockAddenda02 does not validate and will break other tests")
	}
}

func testAddenda02ValidRecordType(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.recordType = "63"
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "recordType" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}
func TestAddenda02ValidRecordType(t *testing.T) {
	testAddenda02ValidRecordType(t)
}

func BenchmarkAddenda02ValidRecordType(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02ValidRecordType(b)
	}
}

func testAddenda02ValidTypeCode(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.typeCode = "65"
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "TypeCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}
func TestAddenda02ValidTypeCode(t *testing.T) {
	testAddenda02ValidTypeCode(t)
}

func BenchmarkAddenda02ValidTypeCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02ValidTypeCode(b)
	}
}

func testAddenda02TypeCode02(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.typeCode = "05"
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "TypeCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}
func TestAddenda02TypeCode02(t *testing.T) {
	testAddenda02TypeCode02(t)
}

func BenchmarkAddenda02TypeCode02(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TypeCode02(b)
	}
}

func testAddenda02RecordType(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.recordType = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02RecordType(t *testing.T) {
	testAddenda02RecordType(t)
}

func BenchmarkAddenda02FieldInclusionRecordType(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02RecordType(b)
	}
}

func testAddenda02TypeCode(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.typeCode = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TypeCode(t *testing.T) {
	testAddenda02TypeCode(t)
}

func BenchmarkAddenda02TypeCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TypeCode(b)
	}
}

func testAddenda02TerminalIdentificationCode(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalIdentificationCode = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalIdentificationCode(t *testing.T) {
	testAddenda02TerminalIdentificationCode(t)
}

func BenchmarkAddenda02TerminalIdentificationCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalIdentificationCode(b)
	}
}

func testAddenda02TransactionSerialNumber(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TransactionSerialNumber = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TransactionSerialNumber(t *testing.T) {
	testAddenda02TransactionSerialNumber(t)
}

func BenchmarkAddenda02TransactionSerialNumber(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TransactionSerialNumber(b)
	}
}

func testAddenda02TransactionDate(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TransactionDate = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TransactionDate(t *testing.T) {
	testAddenda02TransactionDate(t)
}

func BenchmarkAddenda02TransactionDate(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TransactionDate(b)
	}
}

func testAddenda02TerminalLocation(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalLocation = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalLocation(t *testing.T) {
	testAddenda02TerminalLocation(t)
}

func BenchmarkAddenda02TerminalLocation(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalLocation(b)
	}
}

func testAddenda02TerminalCity(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalCity = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalCity(t *testing.T) {
	testAddenda02TerminalCity(t)
}

func BenchmarkAddenda02TerminalCity(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalCity(b)
	}
}

func testAddenda02TerminalState(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalState = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalState(t *testing.T) {
	testAddenda02TerminalState(t)
}

func BenchmarkAddenda02TerminalState(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalState(b)
	}
}

func testParseAddenda02(t testing.TB) {
	addendaPOS := NewAddenda02()
	var line = "702REFONEAREFTERM021000490612123456Target Store 0049          PHILADELPHIA   PA091012980000088"
	addendaPOS.Parse(line)

	r := NewReader(strings.NewReader(line))

	//Add a new BatchPOS
	r.addCurrentBatch(NewBatchPOS(mockBatchPOSHeader()))

	//Add a POS EntryDetail
	entryDetail := mockPOSEntryDetail()

	//Add an addenda to the POS EntryDetail
	entryDetail.AddAddenda(addendaPOS)

	// add the POSentry detail to the batch
	r.currentBatch.AddEntry(entryDetail)

	record := r.currentBatch.GetEntries()[0].Addendum[0].(*Addenda02)

	if record.recordType != "7" {
		t.Errorf("RecordType Expected '7' got: %v", record.recordType)
	}
	if record.TypeCode() != "02" {
		t.Errorf("TypeCode Expected 02 got: %v", record.TypeCode())
	}
	if record.ReferenceInformationOne != "REFONEA" {
		t.Errorf("ReferenceInformationOne Expected 'REFONEA' got: %v", record.ReferenceInformationOneField())
	}
	if record.ReferenceInformationTwo != "REF" {
		t.Errorf("ReferenceInformationTwo Expected 'REF' got: %v", record.ReferenceInformationTwoField())
	}
	if record.TerminalIdentificationCode != "TERM02" {
		t.Errorf("TerminalIdentificationCode Expected 'TERM02' got: %v", record.TerminalIdentificationCodeField())
	}
	if record.TransactionSerialNumber != "100049" {
		t.Errorf("TransactionSerialNumber Expected '100049' got: %v", record.TransactionSerialNumberField())
	}
	if record.TransactionDate != "0612" {
		t.Errorf("TransactionDate Expected '0612' got: %v", record.TransactionDateField())
	}
	if record.AuthorizationCodeOrExpireDate != "123456" {
		t.Errorf("AuthorizationCodeOrExpireDate Expected '123456' got: %v", record.AuthorizationCodeOrExpireDateField())
	}
	if record.TerminalLocation != "Target Store 0049" {
		t.Errorf("TerminalLocation Expected 'Target Store 0049' got: %v", record.TerminalLocationField())
	}
	if record.TerminalCity != "PHILADELPHIA" {
		t.Errorf("TerminalCity Expected '123456' got: %v", record.TerminalCityField())
	}
	if record.TerminalState != "PA" {
		t.Errorf("TerminalState Expected '123456' got: %v", record.TerminalStateField())
	}
	if record.TraceNumber != 91012980000088 {
		t.Errorf("TraceNumber Expected '91012980000088' got: %v", record.TraceNumberField())
	}
}

func TestParseAddenda02(t *testing.T) {
	testParseAddenda02(t)
}

func BenchmarkParseAddenda02(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testParseAddenda02(b)
	}
}<commit_msg>Added addenda02 String test<commit_after>// Copyright 2018 The ACH Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

import (
	"testing"
)

func mockAddenda02() *Addenda02 {
	addenda02 := NewAddenda02()
	addenda02.ReferenceInformationOne = "REFONEA"
	addenda02.ReferenceInformationTwo = "REF"
	addenda02.TerminalIdentificationCode = "TERM02"
	addenda02.TransactionSerialNumber = "100049"
	addenda02.TransactionDate = "0612"
	addenda02.AuthorizationCodeOrExpireDate = "123456"
	addenda02.TerminalLocation = "Target Store 0049"
	addenda02.TerminalCity = "PHILADELPHIA"
	addenda02.TerminalState = "PA"
	addenda02.TraceNumber = 91012980000088
	return addenda02
}

func TestMockAddenda02(t *testing.T) {
	addenda02 := mockAddenda02()
	if err := addenda02.Validate(); err != nil {
		t.Error("mockAddenda02 does not validate and will break other tests")
	}
}

func testAddenda02ValidRecordType(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.recordType = "63"
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "recordType" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}
func TestAddenda02ValidRecordType(t *testing.T) {
	testAddenda02ValidRecordType(t)
}

func BenchmarkAddenda02ValidRecordType(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02ValidRecordType(b)
	}
}

func testAddenda02ValidTypeCode(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.typeCode = "65"
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "TypeCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}
func TestAddenda02ValidTypeCode(t *testing.T) {
	testAddenda02ValidTypeCode(t)
}

func BenchmarkAddenda02ValidTypeCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02ValidTypeCode(b)
	}
}

func testAddenda02TypeCode02(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.typeCode = "05"
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "TypeCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}
func TestAddenda02TypeCode02(t *testing.T) {
	testAddenda02TypeCode02(t)
}

func BenchmarkAddenda02TypeCode02(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TypeCode02(b)
	}
}

func testAddenda02RecordType(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.recordType = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02RecordType(t *testing.T) {
	testAddenda02RecordType(t)
}

func BenchmarkAddenda02FieldInclusionRecordType(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02RecordType(b)
	}
}

func testAddenda02TypeCode(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.typeCode = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TypeCode(t *testing.T) {
	testAddenda02TypeCode(t)
}

func BenchmarkAddenda02TypeCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TypeCode(b)
	}
}

func testAddenda02TerminalIdentificationCode(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalIdentificationCode = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalIdentificationCode(t *testing.T) {
	testAddenda02TerminalIdentificationCode(t)
}

func BenchmarkAddenda02TerminalIdentificationCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalIdentificationCode(b)
	}
}

func testAddenda02TransactionSerialNumber(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TransactionSerialNumber = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TransactionSerialNumber(t *testing.T) {
	testAddenda02TransactionSerialNumber(t)
}

func BenchmarkAddenda02TransactionSerialNumber(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TransactionSerialNumber(b)
	}
}

func testAddenda02TransactionDate(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TransactionDate = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TransactionDate(t *testing.T) {
	testAddenda02TransactionDate(t)
}

func BenchmarkAddenda02TransactionDate(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TransactionDate(b)
	}
}

func testAddenda02TerminalLocation(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalLocation = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalLocation(t *testing.T) {
	testAddenda02TerminalLocation(t)
}

func BenchmarkAddenda02TerminalLocation(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalLocation(b)
	}
}

func testAddenda02TerminalCity(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalCity = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalCity(t *testing.T) {
	testAddenda02TerminalCity(t)
}

func BenchmarkAddenda02TerminalCity(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalCity(b)
	}
}

func testAddenda02TerminalState(t testing.TB) {
	addenda02 := mockAddenda02()
	addenda02.TerminalState = ""
	if err := addenda02.Validate(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.Msg != msgFieldInclusion {
				t.Errorf("%T: %s", err, err)
			}
		}
	}
}

func TestAddenda02TerminalState(t *testing.T) {
	testAddenda02TerminalState(t)
}

func BenchmarkAddenda02TerminalState(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02TerminalState(b)
	}
}

// TestAddenda02 String validates that a known parsed file can be return to a string of the same value
func testAddenda02String(t testing.TB) {
	addenda02 := NewAddenda02()
	var line = "702REFONEAREFTERM021000490612123456Target Store 0049          PHILADELPHIA   PA091012980000088"
	addenda02.Parse(line)
	if addenda02.String() != line {
		t.Errorf("Strings do not match")
	}
}

func TestAddenda02String(t *testing.T) {
	testAddenda02String(t)
}

func BenchmarkAddenda02String(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testAddenda02String(b)
	}
}
<|endoftext|>


<commit_before>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	"code.cloudfoundry.org/cli/integration/helpers/servicebrokerstub"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("update-service-broker command", func() {
	When("logged in", func() {
		var (
			org        string
			cfUsername string
		)

		BeforeEach(func() {
			org = helpers.SetupCFWithGeneratedOrgAndSpaceNames()
			cfUsername, _ = helpers.GetCredentials()
		})

		AfterEach(func() {
			helpers.QuickDeleteOrg(org)
		})

		It("updates the service broker", func() {
			broker1 := servicebrokerstub.Register()
			broker2 := servicebrokerstub.Create()
			defer broker1.Forget()
			defer broker2.Forget()

			session := helpers.CF("update-service-broker", broker1.Name, broker2.Username, broker2.Password, broker2.URL)

			Eventually(session.Wait().Out).Should(SatisfyAll(
				Say("Updating service broker %s as %s...", broker1.Name, cfUsername),
				Say("OK"),
			))
			Eventually(session).Should(Exit(0))
			session = helpers.CF("service-brokers")
			Eventually(session.Out).Should(Say("%s[[:space:]]+%s", broker1.Name, broker2.URL))
		})

		When("the service broker was updated but warnings happened", func() {
			var (
				serviceInstance string
				broker          *servicebrokerstub.ServiceBrokerStub
			)

			BeforeEach(func() {
				broker = servicebrokerstub.EnableServiceAccess()

				serviceInstance = helpers.NewServiceInstanceName()
				session := helpers.CF("create-service", broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstance, "-b", broker.Name)
				Eventually(session).Should(Exit(0))

				broker.Services[0].Plans[0].Name = "different-plan-name"
				broker.Services[0].Plans[0].ID = "different-plan-id"
				broker.Configure()
			})

			AfterEach(func() {
				helpers.CF("delete-service", "-f", serviceInstance)
				broker.Forget()
			})

			It("should yield a warning", func() {
				session := helpers.CF("update-service-broker", broker.Name, broker.Username, broker.Password, broker.URL)

				Eventually(session.Wait().Out).Should(SatisfyAll(
					Say("Updating service broker %s as %s...", broker.Name, cfUsername),
					Say("OK"),
				))
				Eventually(session.Err).Should(Say("Warning: Service plans are missing from the broker's catalog"))
			})
		})

		When("the service broker doesn't exist", func() {
			It("prints an error message", func() {
				session := helpers.CF("update-service-broker", "does-not-exist", "test-user", "test-password", "http://test.com")

				Eventually(session).Should(Say("FAILED"))
				Eventually(session.Err).Should(SatisfyAll(
					Say("Service broker 'does-not-exist' not found"),
				))
				Eventually(session).Should(Exit(1))
			})
		})

		When("the update fails before starting a synchronization job", func() {
			It("prints an error message", func() {
				broker := servicebrokerstub.Register()

				session := helpers.CF("update-service-broker", broker.Name, broker.Username, broker.Password, "not-a-valid-url")

				Eventually(session.Wait().Out).Should(SatisfyAll(
					Say("Updating service broker %s as %s...", broker.Name, cfUsername),
					Say("FAILED"),
				))

				Eventually(session.Err).Should(
					Say("must be a valid url"),
				)

				Eventually(session).Should(Exit(1))
			})
		})

		When("the update fails after starting a synchronization job", func() {
			var broker *servicebrokerstub.ServiceBrokerStub

			BeforeEach(func() {
				broker = servicebrokerstub.Register()
				broker.WithCatalogResponse(500).Configure()
			})

			AfterEach(func() {
				broker.Forget()
			})

			It("prints an error message and the job guid", func() {
				session := helpers.CF("update-service-broker", broker.Name, broker.Username, broker.Password, broker.URL)

				Eventually(session.Wait().Out).Should(SatisfyAll(
					Say("Updating service broker %s as %s...", broker.Name, cfUsername),
					Say("FAILED"),
				))

				Eventually(session.Err).Should(SatisfyAll(
					Say("Job (.*) failed"),
					Say("The service broker returned an invalid response for the request "),
					Say("Status Code: 500 Internal Server Error"),
				))

				Eventually(session).Should(Exit(1))
			})
		})
	})

	When("passing incorrect parameters", func() {
		It("prints an error message", func() {
			session := helpers.CF("update-service-broker", "b1")

			Eventually(session.Err).Should(Say("Incorrect Usage: the required arguments `USERNAME`, `PASSWORD` and `URL` were not provided"))
			eventuallyRendersUpdateServiceBrokerHelp(session)
			Eventually(session).Should(Exit(1))
		})
	})

	When("the environment is not targeted correctly", func() {
		It("fails with the appropriate errors", func() {
			helpers.CheckEnvironmentTargetedCorrectly(false, false, ReadOnlyOrg, "update-service-broker", "broker-name", "username", "password", "https://test.com")
		})
	})

	When("passing --help", func() {
		It("displays command usage to output", func() {
			session := helpers.CF("update-service-broker", "--help")

			eventuallyRendersUpdateServiceBrokerHelp(session)
			Eventually(session).Should(Exit(0))
		})
	})
})

func eventuallyRendersUpdateServiceBrokerHelp(s *Session) {
	Eventually(s).Should(Say("NAME:"))
	Eventually(s).Should(Say("update-service-broker - Update a service broker"))
	Eventually(s).Should(Say("USAGE:"))
	Eventually(s).Should(Say("cf update-service-broker SERVICE_BROKER USERNAME PASSWORD URL"))
	Eventually(s).Should(Say("SEE ALSO:"))
	Eventually(s).Should(Say("rename-service-broker, service-brokers"))
}
<commit_msg>Change expected error message from broker<commit_after>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	"code.cloudfoundry.org/cli/integration/helpers/servicebrokerstub"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("update-service-broker command", func() {
	When("logged in", func() {
		var (
			org        string
			cfUsername string
		)

		BeforeEach(func() {
			org = helpers.SetupCFWithGeneratedOrgAndSpaceNames()
			cfUsername, _ = helpers.GetCredentials()
		})

		AfterEach(func() {
			helpers.QuickDeleteOrg(org)
		})

		It("updates the service broker", func() {
			broker1 := servicebrokerstub.Register()
			broker2 := servicebrokerstub.Create()
			defer broker1.Forget()
			defer broker2.Forget()

			session := helpers.CF("update-service-broker", broker1.Name, broker2.Username, broker2.Password, broker2.URL)

			Eventually(session.Wait().Out).Should(SatisfyAll(
				Say("Updating service broker %s as %s...", broker1.Name, cfUsername),
				Say("OK"),
			))
			Eventually(session).Should(Exit(0))
			session = helpers.CF("service-brokers")
			Eventually(session.Out).Should(Say("%s[[:space:]]+%s", broker1.Name, broker2.URL))
		})

		When("the service broker was updated but warnings happened", func() {
			var (
				serviceInstance string
				broker          *servicebrokerstub.ServiceBrokerStub
			)

			BeforeEach(func() {
				broker = servicebrokerstub.EnableServiceAccess()

				serviceInstance = helpers.NewServiceInstanceName()
				session := helpers.CF("create-service", broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstance, "-b", broker.Name)
				Eventually(session).Should(Exit(0))

				broker.Services[0].Plans[0].Name = "different-plan-name"
				broker.Services[0].Plans[0].ID = "different-plan-id"
				broker.Configure()
			})

			AfterEach(func() {
				helpers.CF("delete-service", "-f", serviceInstance)
				broker.Forget()
			})

			It("should yield a warning", func() {
				session := helpers.CF("update-service-broker", broker.Name, broker.Username, broker.Password, broker.URL)

				Eventually(session.Wait().Out).Should(SatisfyAll(
					Say("Updating service broker %s as %s...", broker.Name, cfUsername),
					Say("OK"),
				))
				Eventually(session.Err).Should(Say("Warning: Service plans are missing from the broker's catalog"))
			})
		})

		When("the service broker doesn't exist", func() {
			It("prints an error message", func() {
				session := helpers.CF("update-service-broker", "does-not-exist", "test-user", "test-password", "http://test.com")

				Eventually(session).Should(Say("FAILED"))
				Eventually(session.Err).Should(SatisfyAll(
					Say("Service broker 'does-not-exist' not found"),
				))
				Eventually(session).Should(Exit(1))
			})
		})

		When("the update fails before starting a synchronization job", func() {
			It("prints an error message", func() {
				broker := servicebrokerstub.Register()

				session := helpers.CF("update-service-broker", broker.Name, broker.Username, broker.Password, "not-a-valid-url")

				Eventually(session.Wait().Out).Should(SatisfyAll(
					Say("Updating service broker %s as %s...", broker.Name, cfUsername),
					Say("FAILED"),
				))

				Eventually(session.Err).Should(
					Say("must be a valid url"),
				)

				Eventually(session).Should(Exit(1))
			})
		})

		When("the update fails after starting a synchronization job", func() {
			var broker *servicebrokerstub.ServiceBrokerStub

			BeforeEach(func() {
				broker = servicebrokerstub.Register()
				broker.WithCatalogResponse(500).Configure()
			})

			AfterEach(func() {
				broker.Forget()
			})

			It("prints an error message and the job guid", func() {
				session := helpers.CF("update-service-broker", broker.Name, broker.Username, broker.Password, broker.URL)

				Eventually(session.Wait().Out).Should(SatisfyAll(
					Say("Updating service broker %s as %s...", broker.Name, cfUsername),
					Say("FAILED"),
				))

				Eventually(session.Err).Should(SatisfyAll(
					Say("Job (.*) failed"),
					Say("The service broker returned an invalid response"),
					Say("Status Code: 500 Internal Server Error"),
				))

				Eventually(session).Should(Exit(1))
			})
		})
	})

	When("passing incorrect parameters", func() {
		It("prints an error message", func() {
			session := helpers.CF("update-service-broker", "b1")

			Eventually(session.Err).Should(Say("Incorrect Usage: the required arguments `USERNAME`, `PASSWORD` and `URL` were not provided"))
			eventuallyRendersUpdateServiceBrokerHelp(session)
			Eventually(session).Should(Exit(1))
		})
	})

	When("the environment is not targeted correctly", func() {
		It("fails with the appropriate errors", func() {
			helpers.CheckEnvironmentTargetedCorrectly(false, false, ReadOnlyOrg, "update-service-broker", "broker-name", "username", "password", "https://test.com")
		})
	})

	When("passing --help", func() {
		It("displays command usage to output", func() {
			session := helpers.CF("update-service-broker", "--help")

			eventuallyRendersUpdateServiceBrokerHelp(session)
			Eventually(session).Should(Exit(0))
		})
	})
})

func eventuallyRendersUpdateServiceBrokerHelp(s *Session) {
	Eventually(s).Should(Say("NAME:"))
	Eventually(s).Should(Say("update-service-broker - Update a service broker"))
	Eventually(s).Should(Say("USAGE:"))
	Eventually(s).Should(Say("cf update-service-broker SERVICE_BROKER USERNAME PASSWORD URL"))
	Eventually(s).Should(Say("SEE ALSO:"))
	Eventually(s).Should(Say("rename-service-broker, service-brokers"))
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package unsharded

import (
	"context"
	"flag"
	"fmt"
	"os"
	"testing"
	"time"

	"vitess.io/vitess/go/vt/vtgate/engine"

	"vitess.io/vitess/go/vt/log"

	"github.com/google/go-cmp/cmp"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/sqltypes"
	"vitess.io/vitess/go/test/endtoend/cluster"
)

var (
	clusterInstance *cluster.LocalProcessCluster
	cell            = "zone1"
	hostname        = "localhost"
	KeyspaceName    = "customer"
	SchemaSQL       = `
CREATE TABLE t1 (
    c1 BIGINT NOT NULL,
    c2 BIGINT NOT NULL,
    c3 BIGINT,
    c4 varchar(100),
    PRIMARY KEY (c1),
    UNIQUE KEY (c2),
    UNIQUE KEY (c3),
    UNIQUE KEY (c4)
) ENGINE=Innodb;

CREATE TABLE allDefaults (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255)
) ENGINE=Innodb;`
	VSchema = `
{
    "sharded": false,
    "tables": {
        "t1": {
            "columns": [
                {
                    "name": "c1",
                    "type": "INT64"
                },
                {
                    "name": "c2",
                    "type": "INT64"
                },
                {
                    "name": "c3",
                    "type": "INT64"
                },
                {
                    "name": "c4",
                    "type": "VARCHAR"
                }
            ]
        },
        "allDefaults": {
            "columns": [
                {
                    "name": "id",
                    "type": "INT64"
                },
                {
                    "name": "name",
                    "type": "VARCHAR"
                }
            ]
        }
    }
}
`

	createProcSQL = `use vt_customer;
CREATE PROCEDURE sp_insert()
BEGIN
	insert into allDefaults () values ();
END;

CREATE PROCEDURE sp_delete()
BEGIN
	delete from allDefaults;
END;

CREATE PROCEDURE sp_multi_dml()
BEGIN
	insert into allDefaults () values ();
	delete from allDefaults;
END;

CREATE PROCEDURE sp_variable()
BEGIN
	insert into allDefaults () values ();
	SELECT min(id) INTO @myvar FROM allDefaults;
	DELETE FROM allDefaults WHERE id = @myvar;
END;

CREATE PROCEDURE sp_select()
BEGIN
	SELECT * FROM allDefaults;
END;

CREATE PROCEDURE sp_all()
BEGIN
	insert into allDefaults () values ();
    select * from allDefaults;
	delete from allDefaults;
    set autocommit = 0;
END;

CREATE PROCEDURE in_parameter(IN val int)
BEGIN
	insert into allDefaults(id) values(val);
END;

CREATE PROCEDURE out_parameter(OUT val int)
BEGIN
	insert into allDefaults(id) values (128);
	select 128 into val from dual;
END;
`
)

type testPlugin struct {
	create, drop func(name string, vcursor engine.VCursor) (*sqltypes.Result, error)
}

func (t *testPlugin) CreateDatabase(name string, vcursor engine.VCursor) (*sqltypes.Result, error) {
	return t.create(name, vcursor)
}

func (t *testPlugin) DropDatabase(name string, vcursor engine.VCursor) (*sqltypes.Result, error) {
	return t.drop(name, vcursor)
}

var _ engine.DBDDLPlugin = (*testPlugin)(nil)

func TestMain(m *testing.M) {
	defer cluster.PanicHandler(nil)
	flag.Parse()

	before := engine.DatabaseCreator
	engine.DatabaseCreator = &testPlugin{
		create: func(name string, vcursor engine.VCursor) (*sqltypes.Result, error) {

		},
		drop: nil,
	}

	exitCode := func() int {
		clusterInstance = cluster.NewCluster(cell, hostname)
		defer clusterInstance.Teardown()

		// Start topo server
		if err := clusterInstance.StartTopo(); err != nil {
			return 1
		}

		// Start keyspace
		Keyspace := &cluster.Keyspace{
			Name:      KeyspaceName,
			SchemaSQL: SchemaSQL,
			VSchema:   VSchema,
		}
		if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil {
			log.Fatal(err.Error())
			return 1
		}

		// Start vtgate
		if err := clusterInstance.StartVtgate(); err != nil {
			log.Fatal(err.Error())
			return 1
		}

		masterProcess := clusterInstance.Keyspaces[0].Shards[0].MasterTablet().VttabletProcess
		if _, err := masterProcess.QueryTablet(createProcSQL, KeyspaceName, false); err != nil {
			log.Fatal(err.Error())
			return 1
		}

		return m.Run()
	}()
	os.Exit(exitCode)
}

func TestSelectIntoAndLoadFrom(t *testing.T) {
	// Test is skipped because it requires secure-file-priv variable to be set to not NULL or empty.
	t.Skip()
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn, err := mysql.Connect(ctx, &vtParams)
	require.Nil(t, err)
	defer conn.Close()

	defer exec(t, conn, `delete from t1`)
	exec(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc')`)
	res := exec(t, conn, `select @@secure_file_priv;`)
	directory := res.Rows[0][0].ToString()
	query := `select * from t1 into outfile '` + directory + `x.txt'`
	exec(t, conn, query)
	defer os.Remove(directory + `x.txt`)
	query = `load data infile '` + directory + `x.txt' into table t1`
	execAssertError(t, conn, query, "Duplicate entry '300' for key 'PRIMARY'")
	exec(t, conn, `delete from t1`)
	exec(t, conn, query)
	assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)]]`)
	query = `select * from t1 into dumpfile '` + directory + `x1.txt'`
	exec(t, conn, query)
	defer os.Remove(directory + `x1.txt`)
	query = `select * from t1 into outfile '` + directory + `x2.txt' Fields terminated by ';' optionally enclosed by '"' escaped by '\t' lines terminated by '\n'`
	exec(t, conn, query)
	defer os.Remove(directory + `x2.txt`)
	query = `load data infile '` + directory + `x2.txt' replace into table t1 Fields terminated by ';' optionally enclosed by '"' escaped by '\t' lines terminated by '\n'`
	exec(t, conn, query)
	assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)]]`)
}

func TestEmptyStatement(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn, err := mysql.Connect(ctx, &vtParams)
	require.Nil(t, err)
	defer conn.Close()
	defer exec(t, conn, `delete from t1`)
	execAssertError(t, conn, " \t;", "Query was empty")
	execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`)
	assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`)
}

func TestTopoDownServingQuery(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn, err := mysql.Connect(ctx, &vtParams)
	require.Nil(t, err)
	defer conn.Close()

	defer exec(t, conn, `delete from t1`)

	execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`)
	assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`)
	clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, *clusterInstance.TopoFlavorString())
	time.Sleep(3 * time.Second)
	assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`)
}

func TestInsertAllDefaults(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	exec(t, conn, `insert into allDefaults () values ()`)
	assertMatches(t, conn, `select * from allDefaults`, "[[INT64(1) NULL]]")
}

func TestDDLUnsharded(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	exec(t, conn, `create table tempt1(c1 BIGINT NOT NULL,c2 BIGINT NOT NULL,c3 BIGINT,c4 varchar(100),PRIMARY KEY (c1), UNIQUE KEY (c2),UNIQUE KEY (c3), UNIQUE KEY (c4))`)
	// Test that create view works and the output is as expected
	exec(t, conn, `create view v1 as select * from tempt1`)
	exec(t, conn, `insert into tempt1(c1, c2, c3, c4) values (300,100,300,'abc'),(30,10,30,'ac'),(3,0,3,'a')`)
	assertMatches(t, conn, "select * from v1", `[[INT64(3) INT64(0) INT64(3) VARCHAR("a")] [INT64(30) INT64(10) INT64(30) VARCHAR("ac")] [INT64(300) INT64(100) INT64(300) VARCHAR("abc")]]`)
	exec(t, conn, `drop view v1`)
	exec(t, conn, `drop table tempt1`)
	assertMatches(t, conn, "show tables", `[[VARCHAR("allDefaults")] [VARCHAR("t1")]]`)
}

func TestCallProcedure(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host:   "localhost",
		Port:   clusterInstance.VtgateMySQLPort,
		Flags:  mysql.CapabilityClientMultiResults,
		DbName: "@master",
	}
	time.Sleep(5 * time.Second)
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()
	qr := exec(t, conn, `CALL sp_insert()`)
	require.EqualValues(t, 1, qr.RowsAffected)

	_, err = conn.ExecuteFetch(`CALL sp_select()`, 1000, true)
	require.Error(t, err)
	require.Contains(t, err.Error(), "Multi-Resultset not supported in stored procedure")

	_, err = conn.ExecuteFetch(`CALL sp_all()`, 1000, true)
	require.Error(t, err)
	require.Contains(t, err.Error(), "Multi-Resultset not supported in stored procedure")

	qr = exec(t, conn, `CALL sp_delete()`)
	require.GreaterOrEqual(t, 1, int(qr.RowsAffected))

	qr = exec(t, conn, `CALL sp_multi_dml()`)
	require.EqualValues(t, 1, qr.RowsAffected)

	qr = exec(t, conn, `CALL sp_variable()`)
	require.EqualValues(t, 1, qr.RowsAffected)

	qr = exec(t, conn, `CALL in_parameter(42)`)
	require.EqualValues(t, 1, qr.RowsAffected)

	_ = exec(t, conn, `SET @foo = 123`)
	qr = exec(t, conn, `CALL in_parameter(@foo)`)
	require.EqualValues(t, 1, qr.RowsAffected)
	qr = exec(t, conn, "select * from allDefaults where id = 123")
	assert.NotEmpty(t, qr.Rows)

	_, err = conn.ExecuteFetch(`CALL out_parameter(@foo)`, 100, true)
	require.Error(t, err)
	require.Contains(t, err.Error(), "OUT and INOUT parameters are not supported")
}

func TestTempTable(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn1, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	_ = exec(t, conn1, `create temporary table temp_t(id bigint primary key)`)
	_ = exec(t, conn1, `insert into temp_t(id) values (1),(2),(3)`)
	assertMatches(t, conn1, `select id from temp_t order by id`, `[[INT64(1)] [INT64(2)] [INT64(3)]]`)
	assertMatches(t, conn1, `select count(table_id) from information_schema.innodb_temp_table_info`, `[[INT64(1)]]`)

	conn2, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn2, `select count(table_id) from information_schema.innodb_temp_table_info`, `[[INT64(1)]]`)
	execAssertError(t, conn2, `show create table temp_t`, `Table 'vt_customer.temp_t' doesn't exist (errno 1146) (sqlstate 42S02)`)
}

func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result {
	t.Helper()
	qr, err := conn.ExecuteFetch(query, 1000, true)
	require.NoError(t, err)
	return qr
}

func execMulti(t *testing.T, conn *mysql.Conn, query string) []*sqltypes.Result {
	t.Helper()
	var res []*sqltypes.Result
	qr, more, err := conn.ExecuteFetchMulti(query, 1000, true)
	res = append(res, qr)
	require.NoError(t, err)
	for more == true {
		qr, more, _, err = conn.ReadQueryResult(1000, true)
		require.NoError(t, err)
		res = append(res, qr)
	}
	return res
}

func execAssertError(t *testing.T, conn *mysql.Conn, query string, errorString string) {
	t.Helper()
	_, err := conn.ExecuteFetch(query, 1000, true)
	require.Error(t, err)
	assert.Contains(t, err.Error(), errorString)
}

func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) {
	t.Helper()
	qr := exec(t, conn, query)
	got := fmt.Sprintf("%v", qr.Rows)
	diff := cmp.Diff(expected, got)
	if diff != "" {
		t.Errorf("Query: %s (-want +got):\n%s", query, diff)
	}
}
<commit_msg>e2e test fir dbddl plugin<commit_after>/*
Copyright 2020 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package unsharded

import (
	"context"
	"flag"
	"fmt"
	"os"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/sqltypes"
	"vitess.io/vitess/go/test/endtoend/cluster"
)

var (
	clusterInstance *cluster.LocalProcessCluster
	vtParams        mysql.ConnParams
	keyspaceName    = "ks"
	cell            = "zone1"
	hostname        = "localhost"
)

func TestMain(m *testing.M) {
	defer cluster.PanicHandler(nil)
	flag.Parse()

	exitCode := func() int {
		clusterInstance = cluster.NewCluster(cell, hostname)
		defer clusterInstance.Teardown()

		// Start topo server
		if err := clusterInstance.StartTopo(); err != nil {
			return 1
		}

		// Start keyspace
		keyspace := &cluster.Keyspace{
			Name: keyspaceName,
		}
		if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 0, false); err != nil {
			return 1
		}

		// Start vtgate
		clusterInstance.VtGateExtraArgs = []string{"-dbddl_plugin", "noop"}
		vtgateProcess := clusterInstance.NewVtgateInstance()
		vtgateProcess.SysVarSetEnabled = true
		if err := vtgateProcess.Setup(); err != nil {
			return 1
		}

		vtParams = mysql.ConnParams{
			Host: clusterInstance.Hostname,
			Port: clusterInstance.VtgateMySQLPort,
		}
		return m.Run()
	}()
	os.Exit(exitCode)
}

func TestDBDDLPluginSync(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	qr := exec(t, conn, `create database aaa`)
	require.EqualValues(t, 1, qr.RowsAffected)

	keyspace := &cluster.Keyspace{
		Name: "aaa",
	}
	require.NoError(t,
		clusterInstance.StartUnshardedKeyspace(*keyspace, 0, false),
		"new database creation failed")

	exec(t, conn, `use aaa`)

	exec(t, conn, `create table t (id bigint primary key)`)
	exec(t, conn, `insert into t(id) values (1),(2),(3),(4),(5)`)
	assertMatches(t, conn, "select count(*) from t", `[[INT64(5)]]`)

	exec(t, conn, `drop database aaa`)

	execAssertError(t, conn, "select count(*) from t", `some error`)
}

func TestDBDDLPluginASync(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	vtParams := mysql.ConnParams{
		Host: "localhost",
		Port: clusterInstance.VtgateMySQLPort,
	}
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	qr := exec(t, conn, `create database aaa`)
	require.EqualValues(t, 1, qr.RowsAffected)

	go func() {
		keyspace := &cluster.Keyspace{
			Name: "aaa",
		}
		require.NoError(t,
			clusterInstance.StartUnshardedKeyspace(*keyspace, 0, false),
			"new database creation failed")
	}()

	exec(t, conn, `use aaa`)

	exec(t, conn, `create table t (id bigint primary key)`)
	exec(t, conn, `insert into t(id) values (1),(2),(3),(4),(5)`)
	assertMatches(t, conn, "select count(*) from t", `[[INT64(5)]]`)

	exec(t, conn, `drop database aaa`)

	execAssertError(t, conn, "select count(*) from t", `some error`)
}

func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result {
	t.Helper()
	qr, err := conn.ExecuteFetch(query, 1000, true)
	require.NoError(t, err)
	return qr
}

func execAssertError(t *testing.T, conn *mysql.Conn, query string, errorString string) {
	t.Helper()
	_, err := conn.ExecuteFetch(query, 1000, true)
	require.Error(t, err)
	assert.Contains(t, err.Error(), errorString)
}

func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) {
	t.Helper()
	qr := exec(t, conn, query)
	got := fmt.Sprintf("%v", qr.Rows)
	diff := cmp.Diff(expected, got)
	if diff != "" {
		t.Errorf("Query: %s (-want +got):\n%s", query, diff)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/decoders"
	"github.com/seadsystem/Backend/DB/landingzone/handlers"
)

func main() {
	// For testing
	log.Println(decoders.DecodeHeader("THS000001t00000001014911X"))

	listener, err := net.Listen("tcp4", constants.HOST+":"+constants.PORT)
	if err != nil {
		log.Println("Failed to open listener on port " + constants.PORT)
		log.Panic("Error was: " + err.Error())
	}
	defer listener.Close()

	log.Println("Listening for connections...")

	// Handle requests in a go routine
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("Failed to accept request: " + err.Error())

		}
		go handlers.HandleRequest(conn)
	}
}
<commit_msg>Fixed compile error<commit_after>package main

import (
	"log"
	"net"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/decoders"
	"github.com/seadsystem/Backend/DB/landingzone/handlers"
)

func main() {
	// For testing
	log.Println(decoders.DecodeHeader([]byte("THS000001t00000001014911X")))

	listener, err := net.Listen("tcp4", constants.HOST+":"+constants.PORT)
	if err != nil {
		log.Println("Failed to open listener on port " + constants.PORT)
		log.Panic("Error was: " + err.Error())
	}
	defer listener.Close()

	log.Println("Listening for connections...")

	// Handle requests in a go routine
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("Failed to accept request: " + err.Error())

		}
		go handlers.HandleRequest(conn)
	}
}
<|endoftext|>


<commit_before>package elk

import (
	"errors"
	// "fmt"
	"io"
	// "log/syslog"
	"net"
	"os"
	// "strings"
	// "time"
	"encoding/json"

	"github.com/delectable/logspout/router"
)

func init() {
	router.AdapterFactories.Register(NewElkAdapter, "elk")
}

// func getopt(name, dfault string) string {
// 	value := os.Getenv(name)
// 	if value == "" {
// 		value = dfault
// 	}
// 	return value
// }

func NewElkAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("udp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}
	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &ElkAdapter{
		route: route,
		conn:  conn,
	}, nil
}

type ElkAdapter struct {
	conn  net.Conn
	route *router.Route
}

func (adapter *ElkAdapter) Stream(logstream chan *router.Message) {
	for message := range logstream {
		elkMessage := NewElkMessage(message)
		io.WriteString(adapter.conn, elkMessage.ToString())
	}
}

type ElkMessage struct {
	routerMessage *router.Message
	Object        struct {
		Time     int64  `json: "time"`
		Message  string `json: "message"`
		Hostname string `json: "hostname"`
	}
}

func NewElkMessage(routerMessage *router.Message) *ElkMessage {
	elkMessage := &ElkMessage{
		routerMessage: routerMessage,
	}

	elkMessage.Object.Time = routerMessage.Time.Unix()
	elkMessage.Object.Message = routerMessage.Data
	elkMessage.Object.Hostname, _ = os.Hostname()

	return elkMessage
}

func (elkMessage *ElkMessage) ToString() string {
	return_string, _ := json.Marshal(elkMessage.Object)
	return string(return_string)
}
<commit_msg>Testing ELK Adapter<commit_after>package elk

import (
	"errors"
	// "fmt"
	"io"
	"io/ioutil"
	// "log/syslog"
	"net"
	// "os"
	// "strings"
	// "time"
	"encoding/json"

	"github.com/delectable/logspout/router"
)

func init() {
	router.AdapterFactories.Register(NewElkAdapter, "elk")
}

// func getopt(name, dfault string) string {
// 	value := os.Getenv(name)
// 	if value == "" {
// 		value = dfault
// 	}
// 	return value
// }

func NewElkAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("udp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}
	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &ElkAdapter{
		route: route,
		conn:  conn,
	}, nil
}

type ElkAdapter struct {
	conn  net.Conn
	route *router.Route
}

func (adapter *ElkAdapter) Stream(logstream chan *router.Message) {
	for message := range logstream {
		elkMessage := NewElkMessage(message)
		io.WriteString(adapter.conn, elkMessage.ToString())
	}
}

type ElkMessage struct {
	routerMessage *router.Message
	Object        struct {
		Time     int64  `json: "time"`
		Message  string `json: "message"`
		Hostname string `json: "hostname"`
	}
}

func NewElkMessage(routerMessage *router.Message) *ElkMessage {
	elkMessage := &ElkMessage{
		routerMessage: routerMessage,
	}

	elkMessage.Object.Time = routerMessage.Time.Unix()
	elkMessage.Object.Message = routerMessage.Data

	hostname_bytestring, _ := ioutil.ReadFile("/etc/hostname")
	elkMessage.Object.Hostname = string(hostname_bytestring)

	return elkMessage
}

func (elkMessage *ElkMessage) ToString() string {
	return_string, _ := json.Marshal(elkMessage.Object)
	return string(return_string)
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package manager

import (
	"errors"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"sort"

	"github.com/prometheus/client_golang/prometheus"

	"github.com/ava-labs/avalanchego/database"
	"github.com/ava-labs/avalanchego/database/leveldb"
	"github.com/ava-labs/avalanchego/database/memdb"
	"github.com/ava-labs/avalanchego/database/meterdb"
	"github.com/ava-labs/avalanchego/database/prefixdb"
	"github.com/ava-labs/avalanchego/utils"
	"github.com/ava-labs/avalanchego/utils/logging"
	"github.com/ava-labs/avalanchego/utils/wrappers"
	"github.com/ava-labs/avalanchego/version"
)

var (
	errNonSortedAndUniqueDBs = errors.New("managed databases were not sorted and unique")
	bootstrappedKey          = []byte{0x00}
	dbPrefix                 = []byte{0x01}

	// First database version where we put [bootstrappedKey] in the top level db
	// to mark that the database has been bootstrapped at least once
	firstVersionWithBootstrappedFlag = version.NewDefaultVersion(1, 1, 0)
)

type Manager interface {
	// Current returns the database with the current database version
	Current() *VersionedDatabase
	// Previous returns the database prior to the current database and true if a previous database exists.
	Previous() (*VersionedDatabase, bool)
	// True if the given database version existed on disk before this run
	PreviouslyUsedDBVersion(v version.Version) bool
	// GetDatabases returns all the managed databases in order from current to the oldest version
	GetDatabases() []*VersionedDatabase
	// Close all of the databases controlled by the manager
	Close() error
	MarkBootstrapped(version.Version) error
	Bootstrapped(version.Version) (bool, error)

	// NewPrefixDBManager returns a new database manager with each of its databases
	// prefixed with [prefix]
	NewPrefixDBManager(prefix []byte) Manager

	// NewMeterDBManager returns a new database manager with each of its databases
	// wrapped with a meterdb instance to support metrics on database performance.
	NewMeterDBManager(namespace string, registerer prometheus.Registerer) (Manager, error)
}

type manager struct {
	// databases with the current version at index 0 and prior versions in
	// descending order
	// invariant: len(databases) > 0
	databases []*VersionedDatabase
}

func (m *manager) Current() *VersionedDatabase { return m.databases[0] }

func (m *manager) Previous() (*VersionedDatabase, bool) {
	if len(m.databases) < 2 {
		return nil, false
	}
	return m.databases[1], true
}

func (m *manager) GetDatabases() []*VersionedDatabase { return m.databases }

func (m *manager) Close() error {
	errs := wrappers.Errs{}
	for _, db := range m.databases {
		errs.Add(db.Close())
	}

	return errs.Err
}

func (m *manager) MarkBootstrapped(v version.Version) error {
	for i := 0; i < len(m.databases); i++ {
		if m.databases[i].Version.Compare(v) == 0 {
			return m.databases[i].MarkBootstrapped()
		}
	}
	return nil
}

func (m *manager) Bootstrapped(v version.Version) (bool, error) {
	for i := 0; i < len(m.databases); i++ {
		if m.databases[i].Version.Compare(v) == 0 {
			return m.databases[i].Bootstrapped()
		}
	}
	return false, nil
}

// wrapManager returns a new database manager with each managed database wrapped by
// the [wrap] function. If an error is returned by wrap, the error is returned
// immediately. If [wrap] never returns an error, then wrapManager is guaranteed to
// never return an error.
// the function wrap must return a database that can be closed without closing the
// underlying database.
func (m *manager) wrapManager(wrap func(db *VersionedDatabase) (*VersionedDatabase, error)) (*manager, error) {
	newManager := &manager{
		databases: make([]*VersionedDatabase, 0, len(m.databases)),
	}

	for _, db := range m.databases {
		wrappedDB, err := wrap(db)
		if err != nil {
			// ignore additional errors in favor of returning the original error
			_ = newManager.Close()
			return nil, err
		}
		newManager.databases = append(newManager.databases, wrappedDB)
	}
	return newManager, nil
}

// NewDefaultMemDBManager returns a database manager with a single memory db instance
// with a default version of v1.0.0
func NewDefaultMemDBManager() Manager {
	return &manager{
		databases: []*VersionedDatabase{
			{
				rawDB:    memdb.New(),
				Database: memdb.New(),
				Version:  version.DefaultVersion1,
			},
		},
	}
}

// New creates a database manager at [filePath] by creating a database instance from each directory
// with a version <= [currentVersion]
func New(
	dbDirPath string,
	log logging.Logger,
	currentVersion version.Version,
	includePreviousVersions bool,
) (Manager, error) {
	parser := version.NewDefaultParser()
	currentDBPath := path.Join(dbDirPath, currentVersion.String())
	rawCurrentDB, err := leveldb.New(currentDBPath, log, 0, 0, 0)
	if err != nil {
		return nil, fmt.Errorf("couldn't create db at %s: %w", currentDBPath, err)
	}
	currentDB := prefixdb.New(dbPrefix, rawCurrentDB)

	manager := &manager{
		databases: []*VersionedDatabase{
			{
				rawDB:    rawCurrentDB,
				Database: currentDB,
				Version:  currentVersion,
			},
		},
	}

	// Conditionally ignore old databases
	if includePreviousVersions {
		err = filepath.Walk(dbDirPath, func(path string, info os.FileInfo, err error) error {
			// the walkFn is called with a non-nil error argument if an os.Lstat
			// or Readdirnames call returns an error. Both cases are considered
			// fatal in the traversal.
			// Reference: https://golang.org/pkg/path/filepath/#WalkFunc
			if err != nil {
				return err
			}
			// Skip the root directory
			if path == dbDirPath {
				return nil
			}

			// The database directory should only contain database directories, no files.
			if !info.IsDir() {
				return fmt.Errorf("unexpectedly found non-directory at %s", path)
			}
			_, dbName := filepath.Split(path)
			version, err := parser.Parse(dbName)
			if err != nil {
				return err
			}

			// If [version] is greater than or equal to the specified version
			// skip over creating the new database to avoid creating the same db
			// twice or creating a database with a version ahead of the desired one.
			if cmp := version.Compare(currentVersion); cmp >= 0 {
				return filepath.SkipDir
			}

			db, err := leveldb.New(path, log, 0, 0, 0)
			if err != nil {
				return fmt.Errorf("couldn't create db at %s: %w", path, err)
			}

			if version.Compare(firstVersionWithBootstrappedFlag) >= 0 {
				manager.databases = append(manager.databases, &VersionedDatabase{
					rawDB:    db,
					Database: prefixdb.New(dbPrefix, db),
					Version:  version,
				})
			} else {
				manager.databases = append(manager.databases, &VersionedDatabase{
					Database: db,
					Version:  version,
				})
			}

			return filepath.SkipDir
		})
	}
	SortDescending(manager.databases)

	// If an error occurred walking [dbDirPath] close the
	// database manager and return the original error here.
	if err != nil {
		_ = manager.Close()
		return nil, err
	}

	return manager, nil
}

// Returns true if database version [v] existed on disk before this run,
// or if [v] is the current database
func (m *manager) PreviouslyUsedDBVersion(v version.Version) bool {
	for i := 0; i < len(m.databases); i++ {
		if m.databases[i].Compare(v) == 0 {
			return true
		}
	}
	return false
}

// NewPrefixDBManager creates a new manager with each database instance prefixed
// by [prefix]
func (m *manager) NewPrefixDBManager(prefix []byte) Manager {
	m, _ = m.wrapManager(func(vdb *VersionedDatabase) (*VersionedDatabase, error) {
		return &VersionedDatabase{
			rawDB:    vdb.rawDB,
			Database: prefixdb.New(prefix, vdb.Database),
			Version:  vdb.Version,
		}, nil
	})
	return m
}

// NewMeterDBManager wraps the current database instance with a meterdb instance.
// Note: calling this more than once with the same [namespace] will cause a conflict error for the [registerer]
func (m *manager) NewMeterDBManager(namespace string, registerer prometheus.Registerer) (Manager, error) {
	currentDB := m.Current()
	currentMeterDB, err := meterdb.New(namespace, registerer, currentDB.Database)
	if err != nil {
		return nil, err
	}
	newManager := &manager{
		databases: make([]*VersionedDatabase, len(m.databases)),
	}
	copy(newManager.databases[1:], m.databases[1:])
	// Overwrite the current database with the meter DB
	newManager.databases[0] = &VersionedDatabase{
		rawDB:    currentDB.rawDB,
		Database: currentMeterDB,
		Version:  currentDB.Version,
	}
	return newManager, nil
}

// NewManagerFromDBs
func NewManagerFromDBs(dbs []*VersionedDatabase) (Manager, error) {
	SortDescending(dbs)
	sortedAndUnique := utils.IsSortedAndUnique(innerSortDescendingVersionedDBs(dbs))
	if !sortedAndUnique {
		return nil, errNonSortedAndUniqueDBs
	}
	return &manager{
		databases: dbs,
	}, nil
}

type VersionedDatabase struct {
	rawDB database.Database
	database.Database
	version.Version
}

func (db *VersionedDatabase) Bootstrapped() (bool, error) {
	if db.rawDB == nil {
		return false, nil
	}
	return db.rawDB.Has(bootstrappedKey)
}

func (db *VersionedDatabase) MarkBootstrapped() error {
	if db.rawDB == nil {
		return nil
	}
	return db.rawDB.Put(bootstrappedKey, nil)
}

type innerSortDescendingVersionedDBs []*VersionedDatabase

// Less returns true if the version at index i is greater than the version at index j
// such that it will sort in descending order (newest version --> oldest version)
func (dbs innerSortDescendingVersionedDBs) Less(i, j int) bool {
	return dbs[i].Version.Compare(dbs[j].Version) > 0
}

func (dbs innerSortDescendingVersionedDBs) Len() int      { return len(dbs) }
func (dbs innerSortDescendingVersionedDBs) Swap(i, j int) { dbs[j], dbs[i] = dbs[i], dbs[j] }

func SortDescending(dbs []*VersionedDatabase) { sort.Sort(innerSortDescendingVersionedDBs(dbs)) }
<commit_msg>remove dead code<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package manager

import (
	"errors"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"sort"

	"github.com/prometheus/client_golang/prometheus"

	"github.com/ava-labs/avalanchego/database"
	"github.com/ava-labs/avalanchego/database/leveldb"
	"github.com/ava-labs/avalanchego/database/memdb"
	"github.com/ava-labs/avalanchego/database/meterdb"
	"github.com/ava-labs/avalanchego/database/prefixdb"
	"github.com/ava-labs/avalanchego/utils"
	"github.com/ava-labs/avalanchego/utils/logging"
	"github.com/ava-labs/avalanchego/utils/wrappers"
	"github.com/ava-labs/avalanchego/version"
)

var (
	errNonSortedAndUniqueDBs = errors.New("managed databases were not sorted and unique")
	bootstrappedKey          = []byte{0x00}
	dbPrefix                 = []byte{0x01}

	// First database version where we put [bootstrappedKey] in the top level db
	// to mark that the database has been bootstrapped at least once
	firstVersionWithBootstrappedFlag = version.NewDefaultVersion(1, 1, 0)
)

type Manager interface {
	// Current returns the database with the current database version
	Current() *VersionedDatabase
	// Previous returns the database prior to the current database and true if a previous database exists.
	Previous() (*VersionedDatabase, bool)
	// GetDatabases returns all the managed databases in order from current to the oldest version
	GetDatabases() []*VersionedDatabase
	// Close all of the databases controlled by the manager
	Close() error
	MarkBootstrapped(version.Version) error
	Bootstrapped(version.Version) (bool, error)

	// NewPrefixDBManager returns a new database manager with each of its databases
	// prefixed with [prefix]
	NewPrefixDBManager(prefix []byte) Manager

	// NewMeterDBManager returns a new database manager with each of its databases
	// wrapped with a meterdb instance to support metrics on database performance.
	NewMeterDBManager(namespace string, registerer prometheus.Registerer) (Manager, error)
}

type manager struct {
	// databases with the current version at index 0 and prior versions in
	// descending order
	// invariant: len(databases) > 0
	databases []*VersionedDatabase
}

func (m *manager) Current() *VersionedDatabase { return m.databases[0] }

func (m *manager) Previous() (*VersionedDatabase, bool) {
	if len(m.databases) < 2 {
		return nil, false
	}
	return m.databases[1], true
}

func (m *manager) GetDatabases() []*VersionedDatabase { return m.databases }

func (m *manager) Close() error {
	errs := wrappers.Errs{}
	for _, db := range m.databases {
		errs.Add(db.Close())
	}

	return errs.Err
}

func (m *manager) MarkBootstrapped(v version.Version) error {
	for i := 0; i < len(m.databases); i++ {
		if m.databases[i].Version.Compare(v) == 0 {
			return m.databases[i].MarkBootstrapped()
		}
	}
	return nil
}

func (m *manager) Bootstrapped(v version.Version) (bool, error) {
	for i := 0; i < len(m.databases); i++ {
		if m.databases[i].Version.Compare(v) == 0 {
			return m.databases[i].Bootstrapped()
		}
	}
	return false, nil
}

// wrapManager returns a new database manager with each managed database wrapped by
// the [wrap] function. If an error is returned by wrap, the error is returned
// immediately. If [wrap] never returns an error, then wrapManager is guaranteed to
// never return an error.
// the function wrap must return a database that can be closed without closing the
// underlying database.
func (m *manager) wrapManager(wrap func(db *VersionedDatabase) (*VersionedDatabase, error)) (*manager, error) {
	newManager := &manager{
		databases: make([]*VersionedDatabase, 0, len(m.databases)),
	}

	for _, db := range m.databases {
		wrappedDB, err := wrap(db)
		if err != nil {
			// ignore additional errors in favor of returning the original error
			_ = newManager.Close()
			return nil, err
		}
		newManager.databases = append(newManager.databases, wrappedDB)
	}
	return newManager, nil
}

// NewDefaultMemDBManager returns a database manager with a single memory db instance
// with a default version of v1.0.0
func NewDefaultMemDBManager() Manager {
	return &manager{
		databases: []*VersionedDatabase{
			{
				rawDB:    memdb.New(),
				Database: memdb.New(),
				Version:  version.DefaultVersion1,
			},
		},
	}
}

// New creates a database manager at [filePath] by creating a database instance from each directory
// with a version <= [currentVersion]
func New(
	dbDirPath string,
	log logging.Logger,
	currentVersion version.Version,
	includePreviousVersions bool,
) (Manager, error) {
	parser := version.NewDefaultParser()
	currentDBPath := path.Join(dbDirPath, currentVersion.String())
	rawCurrentDB, err := leveldb.New(currentDBPath, log, 0, 0, 0)
	if err != nil {
		return nil, fmt.Errorf("couldn't create db at %s: %w", currentDBPath, err)
	}
	currentDB := prefixdb.New(dbPrefix, rawCurrentDB)

	manager := &manager{
		databases: []*VersionedDatabase{
			{
				rawDB:    rawCurrentDB,
				Database: currentDB,
				Version:  currentVersion,
			},
		},
	}

	// Conditionally ignore old databases
	if includePreviousVersions {
		err = filepath.Walk(dbDirPath, func(path string, info os.FileInfo, err error) error {
			// the walkFn is called with a non-nil error argument if an os.Lstat
			// or Readdirnames call returns an error. Both cases are considered
			// fatal in the traversal.
			// Reference: https://golang.org/pkg/path/filepath/#WalkFunc
			if err != nil {
				return err
			}
			// Skip the root directory
			if path == dbDirPath {
				return nil
			}

			// The database directory should only contain database directories, no files.
			if !info.IsDir() {
				return fmt.Errorf("unexpectedly found non-directory at %s", path)
			}
			_, dbName := filepath.Split(path)
			version, err := parser.Parse(dbName)
			if err != nil {
				return err
			}

			// If [version] is greater than or equal to the specified version
			// skip over creating the new database to avoid creating the same db
			// twice or creating a database with a version ahead of the desired one.
			if cmp := version.Compare(currentVersion); cmp >= 0 {
				return filepath.SkipDir
			}

			db, err := leveldb.New(path, log, 0, 0, 0)
			if err != nil {
				return fmt.Errorf("couldn't create db at %s: %w", path, err)
			}

			if version.Compare(firstVersionWithBootstrappedFlag) >= 0 {
				manager.databases = append(manager.databases, &VersionedDatabase{
					rawDB:    db,
					Database: prefixdb.New(dbPrefix, db),
					Version:  version,
				})
			} else {
				manager.databases = append(manager.databases, &VersionedDatabase{
					Database: db,
					Version:  version,
				})
			}

			return filepath.SkipDir
		})
	}
	SortDescending(manager.databases)

	// If an error occurred walking [dbDirPath] close the
	// database manager and return the original error here.
	if err != nil {
		_ = manager.Close()
		return nil, err
	}

	return manager, nil
}

// NewPrefixDBManager creates a new manager with each database instance prefixed
// by [prefix]
func (m *manager) NewPrefixDBManager(prefix []byte) Manager {
	m, _ = m.wrapManager(func(vdb *VersionedDatabase) (*VersionedDatabase, error) {
		return &VersionedDatabase{
			rawDB:    vdb.rawDB,
			Database: prefixdb.New(prefix, vdb.Database),
			Version:  vdb.Version,
		}, nil
	})
	return m
}

// NewMeterDBManager wraps the current database instance with a meterdb instance.
// Note: calling this more than once with the same [namespace] will cause a conflict error for the [registerer]
func (m *manager) NewMeterDBManager(namespace string, registerer prometheus.Registerer) (Manager, error) {
	currentDB := m.Current()
	currentMeterDB, err := meterdb.New(namespace, registerer, currentDB.Database)
	if err != nil {
		return nil, err
	}
	newManager := &manager{
		databases: make([]*VersionedDatabase, len(m.databases)),
	}
	copy(newManager.databases[1:], m.databases[1:])
	// Overwrite the current database with the meter DB
	newManager.databases[0] = &VersionedDatabase{
		rawDB:    currentDB.rawDB,
		Database: currentMeterDB,
		Version:  currentDB.Version,
	}
	return newManager, nil
}

// NewManagerFromDBs
func NewManagerFromDBs(dbs []*VersionedDatabase) (Manager, error) {
	SortDescending(dbs)
	sortedAndUnique := utils.IsSortedAndUnique(innerSortDescendingVersionedDBs(dbs))
	if !sortedAndUnique {
		return nil, errNonSortedAndUniqueDBs
	}
	return &manager{
		databases: dbs,
	}, nil
}

type VersionedDatabase struct {
	rawDB database.Database
	database.Database
	version.Version
}

func (db *VersionedDatabase) Bootstrapped() (bool, error) {
	if db.rawDB == nil {
		return false, nil
	}
	return db.rawDB.Has(bootstrappedKey)
}

func (db *VersionedDatabase) MarkBootstrapped() error {
	if db.rawDB == nil {
		return nil
	}
	return db.rawDB.Put(bootstrappedKey, nil)
}

type innerSortDescendingVersionedDBs []*VersionedDatabase

// Less returns true if the version at index i is greater than the version at index j
// such that it will sort in descending order (newest version --> oldest version)
func (dbs innerSortDescendingVersionedDBs) Less(i, j int) bool {
	return dbs[i].Version.Compare(dbs[j].Version) > 0
}

func (dbs innerSortDescendingVersionedDBs) Len() int      { return len(dbs) }
func (dbs innerSortDescendingVersionedDBs) Swap(i, j int) { dbs[j], dbs[i] = dbs[i], dbs[j] }

func SortDescending(dbs []*VersionedDatabase) { sort.Sort(innerSortDescendingVersionedDBs(dbs)) }
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// A tool to measure the upload throughput of GCS.
package main

import (
	"crypto/rand"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/jacobsa/fuse/fsutil"
	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/oauthutil"
	"golang.org/x/net/context"
)

var fBucket = flag.String("bucket", "", "Name of bucket.")
var fKeyFile = flag.String("key_file", "", "Path to JSON key file.")
var fSize = flag.Int64("size", 1<<26, "Size of content to write.")
var fFile = flag.String("file", "", "If set, use pre-existing contents.")
var fRepeat = flag.Int("repeat", 1, "Repeat the content this many times.")

func createBucket() (bucket gcs.Bucket, err error) {
	// Create an authenticated HTTP client.
	if *fKeyFile == "" {
		err = errors.New("You must set --key_file.")
		return
	}

	httpClient, err := oauthutil.NewJWTHttpClient(
		*fKeyFile,
		[]string{gcs.Scope_FullControl})

	if err != nil {
		err = fmt.Errorf("NewJWTHttpClient: %v", err)
		return
	}

	// Use that to create a connection.
	connCfg := &gcs.ConnConfig{
		HTTPClient: httpClient,
	}

	conn, err := gcs.NewConn(connCfg)
	if err != nil {
		err = fmt.Errorf("NewConn: %v", err)
		return
	}

	// Extract the bucket.
	if *fBucket == "" {
		err = errors.New("You must set --bucket.")
		return
	}

	bucket = conn.GetBucket(*fBucket)

	return
}

func getFile() (f *os.File, err error) {
	// Is there a pre-set file?
	if *fFile != "" {
		f, err = os.OpenFile(*fFile, os.O_RDONLY, 0)
		if err != nil {
			err = fmt.Errorf("OpenFile: %v", err)
			return
		}

		return
	}

	// Create a temporary file to hold random contents.
	f, err = fsutil.AnonymousFile("")
	if err != nil {
		err = fmt.Errorf("AnonymousFile: %v", err)
		return
	}

	// Copy a bunch of random data into the file.
	log.Println("Reading random data.")
	_, err = io.Copy(f, io.LimitReader(rand.Reader, *fSize))
	if err != nil {
		err = fmt.Errorf("Copy: %v", err)
		return
	}

	// Seek back to the start for consumption.
	_, err = f.Seek(0, 0)
	if err != nil {
		err = fmt.Errorf("Seek: %v", err)
		return
	}

	return
}

type repeatReader struct {
	f             *os.File
	N             int
	firstSeekDone bool
}

func (r *repeatReader) Read(p []byte) (n int, err error) {
	// On the very first read, seek the file to the start and cause N to be the
	// number of iterations left..
	if !r.firstSeekDone {
		if _, err = r.f.Seek(0, 0); err != nil {
			err = fmt.Errorf("Seek: %v", err)
			return
		}

		r.firstSeekDone = true

		if r.N <= 0 {
			err = io.EOF
			return
		}

		r.N--
	}

	// Read some content from the file.
	n, err = r.f.Read(p)

	// Ignore EOF if n != 0.
	if n != 0 && err == io.EOF {
		err = nil
	}

	// Otherwise, EOF errors cause a loop, if we're not yet done.
	if err == io.EOF {
		if r.N <= 0 {
			return
		}

		if _, err = r.f.Seek(0, 0); err != nil {
			err = fmt.Errorf("Seek: %v", err)
			return
		}

		r.N--
		return r.Read(p)
	}

	// Propagate other errors.
	if err != nil {
		return
	}

	// All is good.
	return
}

func run() (err error) {
	bucket, err := createBucket()
	if err != nil {
		err = fmt.Errorf("createBucket: %v", err)
		return
	}

	// Get an appropriate file.
	f, err := getFile()
	if err != nil {
		err = fmt.Errorf("getFile: %v", err)
		return
	}

	// Repeat the specified number of times.
	reader := &repeatReader{
		f: f,
		N: *fRepeat,
	}

	// Create an object using the repeated contents.
	log.Println("Creating object.")
	req := &gcs.CreateObjectRequest{
		Name:     "foo",
		Contents: reader,
	}

	before := time.Now()
	_, err = bucket.CreateObject(context.Background(), req)
	if err != nil {
		err = fmt.Errorf("CreateObject: %v", err)
		return
	}

	log.Printf("Wrote object in %v.", time.Since(before))

	return
}

func main() {
	flag.Parse()

	err := run()
	if err != nil {
		log.Fatalln(err)
	}
}
<commit_msg>Fixed gcsthroughput.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// A tool to measure the upload throughput of GCS.
package main

import (
	"crypto/rand"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/jacobsa/fuse/fsutil"
	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

var fBucket = flag.String("bucket", "", "Name of bucket.")
var fSize = flag.Int64("size", 1<<26, "Size of content to write.")
var fFile = flag.String("file", "", "If set, use pre-existing contents.")
var fRepeat = flag.Int("repeat", 1, "Repeat the content this many times.")

func createBucket() (bucket gcs.Bucket, err error) {
	// Create an authenticated HTTP client.
	tokenSrc, err := google.DefaultTokenSource(
		context.Background(),
		gcs.Scope_FullControl)

	if err != nil {
		err = fmt.Errorf("DefaultTokenSource: %v", err)
		return
	}

	httpClient := oauth2.NewClient(
		context.Background(),
		tokenSrc)

	// Use that to create a connection.
	connCfg := &gcs.ConnConfig{
		HTTPClient: httpClient,
	}

	conn, err := gcs.NewConn(connCfg)
	if err != nil {
		err = fmt.Errorf("NewConn: %v", err)
		return
	}

	// Extract the bucket.
	if *fBucket == "" {
		err = errors.New("You must set --bucket.")
		return
	}

	bucket = conn.GetBucket(*fBucket)

	return
}

func getFile() (f *os.File, err error) {
	// Is there a pre-set file?
	if *fFile != "" {
		f, err = os.OpenFile(*fFile, os.O_RDONLY, 0)
		if err != nil {
			err = fmt.Errorf("OpenFile: %v", err)
			return
		}

		return
	}

	// Create a temporary file to hold random contents.
	f, err = fsutil.AnonymousFile("")
	if err != nil {
		err = fmt.Errorf("AnonymousFile: %v", err)
		return
	}

	// Copy a bunch of random data into the file.
	log.Println("Reading random data.")
	_, err = io.Copy(f, io.LimitReader(rand.Reader, *fSize))
	if err != nil {
		err = fmt.Errorf("Copy: %v", err)
		return
	}

	// Seek back to the start for consumption.
	_, err = f.Seek(0, 0)
	if err != nil {
		err = fmt.Errorf("Seek: %v", err)
		return
	}

	return
}

type repeatReader struct {
	f             *os.File
	N             int
	firstSeekDone bool
}

func (r *repeatReader) Read(p []byte) (n int, err error) {
	// On the very first read, seek the file to the start and cause N to be the
	// number of iterations left..
	if !r.firstSeekDone {
		if _, err = r.f.Seek(0, 0); err != nil {
			err = fmt.Errorf("Seek: %v", err)
			return
		}

		r.firstSeekDone = true

		if r.N <= 0 {
			err = io.EOF
			return
		}

		r.N--
	}

	// Read some content from the file.
	n, err = r.f.Read(p)

	// Ignore EOF if n != 0.
	if n != 0 && err == io.EOF {
		err = nil
	}

	// Otherwise, EOF errors cause a loop, if we're not yet done.
	if err == io.EOF {
		if r.N <= 0 {
			return
		}

		if _, err = r.f.Seek(0, 0); err != nil {
			err = fmt.Errorf("Seek: %v", err)
			return
		}

		r.N--
		return r.Read(p)
	}

	// Propagate other errors.
	if err != nil {
		return
	}

	// All is good.
	return
}

func run() (err error) {
	bucket, err := createBucket()
	if err != nil {
		err = fmt.Errorf("createBucket: %v", err)
		return
	}

	// Get an appropriate file.
	f, err := getFile()
	if err != nil {
		err = fmt.Errorf("getFile: %v", err)
		return
	}

	// Repeat the specified number of times.
	reader := &repeatReader{
		f: f,
		N: *fRepeat,
	}

	// Create an object using the repeated contents.
	log.Println("Creating object.")
	req := &gcs.CreateObjectRequest{
		Name:     "foo",
		Contents: reader,
	}

	before := time.Now()
	_, err = bucket.CreateObject(context.Background(), req)
	if err != nil {
		err = fmt.Errorf("CreateObject: %v", err)
		return
	}

	log.Printf("Wrote object in %v.", time.Since(before))

	return
}

func main() {
	flag.Parse()

	err := run()
	if err != nil {
		log.Fatalln(err)
	}
}
<|endoftext|>


<commit_before>// The parallel package provides a way of running functions
// concurrently while limiting the maximum number
// running at once.
package parallel

import (
	"fmt"
	"sync"
)

// Run represents a number of functions running concurrently.
type Run struct {
	n int
	max int
	work chan func() error
	done chan error
	err chan error
	wg sync.WaitGroup
}

// Errors holds any errors encountered during
// the parallel run.
type Errors []error

func (errs Errors) Error() string {
	switch len(errs) {
	case 0:
		return "no error"
	case 1:
		return errs[0].Error()
	}
	return fmt.Sprintf("%s (and %d more)", errs[0].Error(), len(errs) - 1)
}

// NewRun returns a new parallel instance.  It will run up to maxPar
// functions concurrently.
func NewRun(maxPar int) *Run {
	r := &Run{
		max: maxPar,
		work: make(chan func() error),
		done: make(chan error),
		err: make(chan error),
	}
	go func() {
		var errs Errors
		for e := range r.done {
			if e != nil {
				errs = append(errs, e)
			}
		}
		// TODO sort errors by original order of Do request?
		if len(errs) > 0 {
			r.err <- errs
		} else {
			r.err <- nil
		}
	}()
	return r
}

// Do requests that r run f concurrently.  If there are already the maximum
// number of functions running concurrently, it will block until one of
// them has completed.
func (r *Run) Do(f func() error) {
	if r.n < r.max {
		r.wg.Add(1)
		go func(){
			for f := range r.work {
				r.done <- f()
			}
			r.wg.Done()
		}()
	}
	r.work <- f
	r.n++
}

// Wait marks the parallel instance as complete and waits for all the
// functions to complete.  If any errors were encountered, it returns an
// Errors value describing all the errors in arbitrary order.
func (r *Run) Wait() error {
	close(r.work)
	r.wg.Wait()
	close(r.done)
	return <-r.err
}
<commit_msg>parallel: make Do reentrant<commit_after>// The parallel package provides a way of running functions
// concurrently while limiting the maximum number
// running at once.
package parallel

import (
	"fmt"
	"sync"
)

// Run represents a number of functions running concurrently.
type Run struct {
	limiter chan struct{}
	done chan error
	err chan error
	wg sync.WaitGroup
}

// Errors holds any errors encountered during
// the parallel run.
type Errors []error

func (errs Errors) Error() string {
	switch len(errs) {
	case 0:
		return "no error"
	case 1:
		return errs[0].Error()
	}
	return fmt.Sprintf("%s (and %d more)", errs[0].Error(), len(errs) - 1)
}

// NewRun returns a new parallel instance.  It will run up to maxPar
// functions concurrently.
func NewRun(maxPar int) *Run {
	r := &Run{
		limiter: make(chan struct{}, maxPar),
		done: make(chan error),
		err: make(chan error),
	}
	go func() {
		var errs Errors
		for e := range r.done {
			errs = append(errs, e)
		}
		// TODO sort errors by original order of Do request?
		if len(errs) > 0 {
			r.err <- errs
		} else {
			r.err <- nil
		}
	}()
	return r
}

// Do requests that r run f concurrently.  If there are already the maximum
// number of functions running concurrently, it will block until one of
// them has completed. Do may itself be called concurrently.
func (r *Run) Do(f func() error) {
	r.limiter <- struct{}{}
	r.wg.Add(1)
	go func() {
		defer func() {
			r.wg.Done()
			<-r.limiter
		}()
		if err := f(); err != nil {
			r.done <- err
		}
	}()
}

// Wait marks the parallel instance as complete and waits for all the
// functions to complete.  If any errors were encountered, it returns an
// Errors value describing all the errors in arbitrary order.
func (r *Run) Wait() error {
	r.wg.Wait()
	close(r.done)
	return <-r.err
}
<|endoftext|>


<commit_before>package css

import (
	//"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestMedia(t *testing.T) {
	css := Parse(`@media only screen and (max-width: 600px) {
			    table[class="body"] img {
			        width: auto !important;
			        height: auto !important
			        }
			    table[class="body"] center {
			        min-width: 0 !important
			        }
			    table[class="body"] .container {
			        width: 95% !important
			        }
			    table[class="body"] .row {
			        width: 100% !important;
			        display: block !important
			        }
        		}`)

	//fmt.Println(css)
	assert.Equal(t, css.CssRuleList[0].Style.SelectorText, "only screen and (max-width: 600px)")
	assert.Equal(t, css.CssRuleList[0].Type, MEDIA_RULE)
	assert.Equal(t, len(css.CssRuleList[0].Rules), 4)
	assert.Equal(t, css.CssRuleList[0].Rules[0].Style.SelectorText, "table[class=\"body\"] img")
	assert.Equal(t, css.CssRuleList[0].Rules[0].Style.Styles["height"].Value, "auto")
	assert.Equal(t, css.CssRuleList[0].Rules[0].Style.Styles["height"].Important, 1)
	assert.Equal(t, css.CssRuleList[0].Rules[1].Style.SelectorText, "table[class=\"body\"] center")
	assert.Equal(t, css.CssRuleList[0].Rules[2].Style.SelectorText, "table[class=\"body\"] .container")
	assert.Equal(t, css.CssRuleList[0].Rules[3].Style.SelectorText, "table[class=\"body\"] .row")

}

<commit_msg>Adding test for multi sections of media rule<commit_after>package css

import (
	//"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestMedia(t *testing.T) {
	css := Parse(`@media only screen and (max-width: 600px) {
			    table[class="body"] img {
			        width: auto !important;
			        height: auto !important
			        }
			    table[class="body"] center {
			        min-width: 0 !important
			        }
			    table[class="body"] .container {
			        width: 95% !important
			        }
			    table[class="body"] .row {
			        width: 100% !important;
			        display: block !important
			        }
        		}`)

	//fmt.Println(css)
	assert.Equal(t, css.CssRuleList[0].Style.SelectorText, "only screen and (max-width: 600px)")
	assert.Equal(t, css.CssRuleList[0].Type, MEDIA_RULE)
	assert.Equal(t, len(css.CssRuleList[0].Rules), 4)
	assert.Equal(t, css.CssRuleList[0].Rules[0].Style.SelectorText, "table[class=\"body\"] img")
	assert.Equal(t, css.CssRuleList[0].Rules[0].Style.Styles["height"].Value, "auto")
	assert.Equal(t, css.CssRuleList[0].Rules[0].Style.Styles["height"].Important, 1)
	assert.Equal(t, css.CssRuleList[0].Rules[1].Style.SelectorText, "table[class=\"body\"] center")
	assert.Equal(t, css.CssRuleList[0].Rules[2].Style.SelectorText, "table[class=\"body\"] .container")
	assert.Equal(t, css.CssRuleList[0].Rules[3].Style.SelectorText, "table[class=\"body\"] .row")

}

func TestMediaMulti(t *testing.T) {
	css := Parse(`
				table.one {
					width: 30px;
				}
				@media only screen and (max-width: 600px) {
				    table[class="body"] img {
				        width: auto !important;
				        height: auto !important
				    }
				    table[class="body"] center {
				        min-width: 0 !important
				    }
				    table[class="body"] .container {
				        width: 95% !important
				    }
				    table[class="body"] .row {
				        width: 100% !important;
				        display: block !important
				    }
        		}
        		@media all and (min-width: 48em) {
					blockquote {
						font-size: 34px;
						line-height: 40px;
						padding-top: 2px;
						padding-bottom: 3px;
					}
				}
        		table.two {
					width: 80px;
				}`)

	assert.Equal(t, len(css.CssRuleList), 4)

	assert.Equal(t, css.CssRuleList[0].Style.SelectorText, "table.one")
	assert.Equal(t, css.CssRuleList[0].Type, STYLE_RULE)
	assert.Equal(t, css.CssRuleList[0].Style.Styles["width"].Value, "30px")
	assert.Equal(t, len(css.CssRuleList[0].Rules), 0)

	assert.Equal(t, css.CssRuleList[1].Style.SelectorText, "only screen and (max-width: 600px)")
	assert.Equal(t, css.CssRuleList[1].Type, MEDIA_RULE)
	assert.Equal(t, len(css.CssRuleList[1].Rules), 4)
	assert.Equal(t, css.CssRuleList[1].Rules[0].Style.SelectorText, "table[class=\"body\"] img")
	assert.Equal(t, css.CssRuleList[1].Rules[0].Style.Styles["height"].Value, "auto")
	assert.Equal(t, css.CssRuleList[1].Rules[0].Style.Styles["height"].Important, 1)
	assert.Equal(t, css.CssRuleList[1].Rules[1].Style.SelectorText, "table[class=\"body\"] center")
	assert.Equal(t, css.CssRuleList[1].Rules[2].Style.SelectorText, "table[class=\"body\"] .container")
	assert.Equal(t, css.CssRuleList[1].Rules[3].Style.SelectorText, "table[class=\"body\"] .row")

	assert.Equal(t, css.CssRuleList[2].Style.SelectorText, "all and (min-width: 48em)")
	assert.Equal(t, css.CssRuleList[2].Type, MEDIA_RULE)
	assert.Equal(t, css.CssRuleList[2].Rules[0].Style.SelectorText, "blockquote")
	assert.Equal(t, css.CssRuleList[2].Rules[0].Style.Styles["font-size"].Value, "34px")
	assert.Equal(t, css.CssRuleList[2].Rules[0].Style.Styles["line-height"].Value, "40px")
	assert.Equal(t, css.CssRuleList[2].Rules[0].Style.Styles["padding-top"].Value, "2px")
	assert.Equal(t, css.CssRuleList[2].Rules[0].Style.Styles["padding-bottom"].Value, "3px")
	assert.Equal(t, len(css.CssRuleList[2].Rules), 1)

	assert.Equal(t, css.CssRuleList[3].Style.SelectorText, "table.two")
	assert.Equal(t, css.CssRuleList[3].Type, STYLE_RULE)
	assert.Equal(t, css.CssRuleList[3].Style.Styles["width"].Value, "80px")
	assert.Equal(t, len(css.CssRuleList[3].Rules), 0)
}
<|endoftext|>


<commit_before>// Package password provides a library for generating high-entropy random
// password strings via the crypto/rand package.
//
//    res, err := Generate(64, 10, 10, false, false)
//    if err != nil  {
//      log.Fatal(err)
//    }
//    log.Printf(res)
//
// Most functions are safe for concurrent use.
package password

import (
	"crypto/rand"
	"errors"
	"math/big"
	"strings"
)

const (
	// LowerLetters is the list of lowercase letters.
	LowerLetters = "abcdefghijklmnopqrstuvwxyz"

	// UpperLetters is the list of uppercase letters.
	UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// Digits is the list of permitted digits.
	Digits = "0123456789"

	// Symbols is the list of symbols.
	Symbols = "~!@#$%^&*()_+`-={}|[]\\:\"<>?,./"
)

var (
	// ErrExceedsTotalLength is the error returned with the number of digits and
	// symbols is greater than the total length.
	ErrExceedsTotalLength = errors.New("number of digits and symbols must be less than total length")

	// ErrLettersExceedsAvailable is the error returned with the number of letters
	// exceeds the number of available letters and repeats are not allowed.
	ErrLettersExceedsAvailable = errors.New("number of letters exceeds available letters and repeats are not allowed")

	// ErrDigitsExceedsAvailable is the error returned with the number of digits
	// exceeds the number of available digits and repeats are not allowed.
	ErrDigitsExceedsAvailable = errors.New("number of digits exceeds available digits and repeats are not allowed")

	// ErrSymbolsExceedsAvailable is the error returned with the number of symbols
	// exceeds the number of available symbols and repeats are not allowed.
	ErrSymbolsExceedsAvailable = errors.New("number of symbols exceeds available symbols and repeats are not allowed")
)

// Generator is the stateful generator which can be used to customize the list
// of letters, digits, and/or symbols.
type Generator struct {
	lowerLetters string
	upperLetters string
	digits       string
	symbols      string
}

// GeneratorInput is used as input to the NewGenerator function.
type GeneratorInput struct {
	LowerLetters string
	UpperLetters string
	Digits       string
	Symbols      string
}

// NewGenerator creates a new Generator from the specified configuration. If no
// input is given, all the default values are used. This function is safe for
// concurrent use.
func NewGenerator(i *GeneratorInput) (*Generator, error) {
	if i == nil {
		i = new(GeneratorInput)
	}

	g := &Generator{
		lowerLetters: i.LowerLetters,
		upperLetters: i.UpperLetters,
		digits:       i.Digits,
		symbols:      i.Symbols,
	}

	if g.lowerLetters == "" {
		g.lowerLetters = LowerLetters
	}

	if g.upperLetters == "" {
		g.upperLetters = UpperLetters
	}

	if g.digits == "" {
		g.digits = Digits
	}

	if g.symbols == "" {
		g.symbols = Symbols
	}

	return g, nil
}

// Generate generates a password with the given requirements. length is the
// total number of characters in the password. numDigits is the number of digits
// to include in the result. numSymbols is the number of symbols to include in
// the result. noUpper excludes uppercase letters from the results. allowRepeat
// allows characters to repeat.
//
// The algorithm is fast, but it's not designed to be performant; it favors
// entropy over speed. This function is safe for concurrent use.
func (g *Generator) Generate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) (string, error) {
	letters := g.lowerLetters
	if !noUpper {
		letters += g.upperLetters
	}

	chars := length - numDigits - numSymbols
	if chars < 0 {
		return "", ErrExceedsTotalLength
	}

	if !allowRepeat && chars > len(letters) {
		return "", ErrLettersExceedsAvailable
	}

	if !allowRepeat && numDigits > len(g.digits) {
		return "", ErrDigitsExceedsAvailable
	}

	if !allowRepeat && numSymbols > len(g.symbols) {
		return "", ErrSymbolsExceedsAvailable
	}

	var result string

	// Characters
	for i := 0; i < chars; i++ {
		ch, err := randomElement(letters)
		if err != nil {
			return "", err
		}

		if !allowRepeat && strings.Contains(result, ch) {
			i--
			continue
		}

		result, err = randomInsert(result, ch)
		if err != nil {
			return "", err
		}
	}

	// Digits
	for i := 0; i < numDigits; i++ {
		d, err := randomElement(g.digits)
		if err != nil {
			return "", err
		}

		if !allowRepeat && strings.Contains(result, d) {
			i--
			continue
		}

		result, err = randomInsert(result, d)
		if err != nil {
			return "", err
		}
	}

	// Symbols
	for i := 0; i < numSymbols; i++ {
		sym, err := randomElement(g.symbols)
		if err != nil {
			return "", err
		}

		if !allowRepeat && strings.Contains(result, sym) {
			i--
			continue
		}

		result, err = randomInsert(result, sym)
		if err != nil {
			return "", err
		}
	}

	return result, nil
}

// MustGenerate is the same as Generate, but panics on error.
func (g *Generator) MustGenerate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) string {
	res, err := g.Generate(length, numDigits, numSymbols, noUpper, allowRepeat)
	if err != nil {
		panic(err)
	}
	return res
}

// See Generator.Generate for usage.
func Generate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) (string, error) {
	gen, err := NewGenerator(nil)
	if err != nil {
		return "", err
	}

	return gen.Generate(length, numDigits, numSymbols, noUpper, allowRepeat)
}

// See Generator.MustGenerate for usage.
func MustGenerate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) string {
	res, err := Generate(length, numDigits, numSymbols, noUpper, allowRepeat)
	if err != nil {
		panic(err)
	}
	return res
}

// randomInsert randomly inserts the given value into the given string.
func randomInsert(s, val string) (string, error) {
	if s == "" {
		return val, nil
	}

	n, err := rand.Int(rand.Reader, big.NewInt(int64(len(s)+1)))
	if err != nil {
		return "", err
	}
	i := n.Int64()
	return s[0:i] + val + s[i:len(s)], nil
}

// randomElement extracts a random element from the given string.
func randomElement(s string) (string, error) {
	n, err := rand.Int(rand.Reader, big.NewInt(int64(len(s))))
	if err != nil {
		return "", err
	}
	return string(s[n.Int64()]), nil
}
<commit_msg>Fix godoc comments<commit_after>// Package password provides a library for generating high-entropy random
// password strings via the crypto/rand package.
//
//    res, err := Generate(64, 10, 10, false, false)
//    if err != nil  {
//      log.Fatal(err)
//    }
//    log.Printf(res)
//
// Most functions are safe for concurrent use.
package password

import (
	"crypto/rand"
	"errors"
	"math/big"
	"strings"
)

const (
	// LowerLetters is the list of lowercase letters.
	LowerLetters = "abcdefghijklmnopqrstuvwxyz"

	// UpperLetters is the list of uppercase letters.
	UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// Digits is the list of permitted digits.
	Digits = "0123456789"

	// Symbols is the list of symbols.
	Symbols = "~!@#$%^&*()_+`-={}|[]\\:\"<>?,./"
)

var (
	// ErrExceedsTotalLength is the error returned with the number of digits and
	// symbols is greater than the total length.
	ErrExceedsTotalLength = errors.New("number of digits and symbols must be less than total length")

	// ErrLettersExceedsAvailable is the error returned with the number of letters
	// exceeds the number of available letters and repeats are not allowed.
	ErrLettersExceedsAvailable = errors.New("number of letters exceeds available letters and repeats are not allowed")

	// ErrDigitsExceedsAvailable is the error returned with the number of digits
	// exceeds the number of available digits and repeats are not allowed.
	ErrDigitsExceedsAvailable = errors.New("number of digits exceeds available digits and repeats are not allowed")

	// ErrSymbolsExceedsAvailable is the error returned with the number of symbols
	// exceeds the number of available symbols and repeats are not allowed.
	ErrSymbolsExceedsAvailable = errors.New("number of symbols exceeds available symbols and repeats are not allowed")
)

// Generator is the stateful generator which can be used to customize the list
// of letters, digits, and/or symbols.
type Generator struct {
	lowerLetters string
	upperLetters string
	digits       string
	symbols      string
}

// GeneratorInput is used as input to the NewGenerator function.
type GeneratorInput struct {
	LowerLetters string
	UpperLetters string
	Digits       string
	Symbols      string
}

// NewGenerator creates a new Generator from the specified configuration. If no
// input is given, all the default values are used. This function is safe for
// concurrent use.
func NewGenerator(i *GeneratorInput) (*Generator, error) {
	if i == nil {
		i = new(GeneratorInput)
	}

	g := &Generator{
		lowerLetters: i.LowerLetters,
		upperLetters: i.UpperLetters,
		digits:       i.Digits,
		symbols:      i.Symbols,
	}

	if g.lowerLetters == "" {
		g.lowerLetters = LowerLetters
	}

	if g.upperLetters == "" {
		g.upperLetters = UpperLetters
	}

	if g.digits == "" {
		g.digits = Digits
	}

	if g.symbols == "" {
		g.symbols = Symbols
	}

	return g, nil
}

// Generate generates a password with the given requirements. length is the
// total number of characters in the password. numDigits is the number of digits
// to include in the result. numSymbols is the number of symbols to include in
// the result. noUpper excludes uppercase letters from the results. allowRepeat
// allows characters to repeat.
//
// The algorithm is fast, but it's not designed to be performant; it favors
// entropy over speed. This function is safe for concurrent use.
func (g *Generator) Generate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) (string, error) {
	letters := g.lowerLetters
	if !noUpper {
		letters += g.upperLetters
	}

	chars := length - numDigits - numSymbols
	if chars < 0 {
		return "", ErrExceedsTotalLength
	}

	if !allowRepeat && chars > len(letters) {
		return "", ErrLettersExceedsAvailable
	}

	if !allowRepeat && numDigits > len(g.digits) {
		return "", ErrDigitsExceedsAvailable
	}

	if !allowRepeat && numSymbols > len(g.symbols) {
		return "", ErrSymbolsExceedsAvailable
	}

	var result string

	// Characters
	for i := 0; i < chars; i++ {
		ch, err := randomElement(letters)
		if err != nil {
			return "", err
		}

		if !allowRepeat && strings.Contains(result, ch) {
			i--
			continue
		}

		result, err = randomInsert(result, ch)
		if err != nil {
			return "", err
		}
	}

	// Digits
	for i := 0; i < numDigits; i++ {
		d, err := randomElement(g.digits)
		if err != nil {
			return "", err
		}

		if !allowRepeat && strings.Contains(result, d) {
			i--
			continue
		}

		result, err = randomInsert(result, d)
		if err != nil {
			return "", err
		}
	}

	// Symbols
	for i := 0; i < numSymbols; i++ {
		sym, err := randomElement(g.symbols)
		if err != nil {
			return "", err
		}

		if !allowRepeat && strings.Contains(result, sym) {
			i--
			continue
		}

		result, err = randomInsert(result, sym)
		if err != nil {
			return "", err
		}
	}

	return result, nil
}

// MustGenerate is the same as Generate, but panics on error.
func (g *Generator) MustGenerate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) string {
	res, err := g.Generate(length, numDigits, numSymbols, noUpper, allowRepeat)
	if err != nil {
		panic(err)
	}
	return res
}

// Generate is the package shortcut for Generator.Generate.
func Generate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) (string, error) {
	gen, err := NewGenerator(nil)
	if err != nil {
		return "", err
	}

	return gen.Generate(length, numDigits, numSymbols, noUpper, allowRepeat)
}

// MustGenerate is the package shortcut for Generator.MustGenerate.
func MustGenerate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) string {
	res, err := Generate(length, numDigits, numSymbols, noUpper, allowRepeat)
	if err != nil {
		panic(err)
	}
	return res
}

// randomInsert randomly inserts the given value into the given string.
func randomInsert(s, val string) (string, error) {
	if s == "" {
		return val, nil
	}

	n, err := rand.Int(rand.Reader, big.NewInt(int64(len(s)+1)))
	if err != nil {
		return "", err
	}
	i := n.Int64()
	return s[0:i] + val + s[i:len(s)], nil
}

// randomElement extracts a random element from the given string.
func randomElement(s string) (string, error) {
	n, err := rand.Int(rand.Reader, big.NewInt(int64(len(s))))
	if err != nil {
		return "", err
	}
	return string(s[n.Int64()]), nil
}
<|endoftext|>