<commit_before>package slot

import (
    "testing"

    .   "chunkymonkey/types"
)

func slotEq(s1, s2 *Slot) bool {
    return (s1.ItemTypeId == s2.ItemTypeId &&
        s1.Count == s2.Count &&
        s1.Data == s2.Data)
}

type slotTest struct {
    desc                 string
    initialA, initialB   Slot
    expectedA, expectedB Slot
    expectedChange       bool
}

func (test *slotTest) run(t *testing.T, op func(a, b *Slot) bool) {
    t.Logf("Test %s:", test.desc)
    t.Logf("    initial   a=%+v, b=%+v", test.initialA, test.initialB)
    t.Logf("    expecting a=%+v, b=%+v, changed=%t",
        test.expectedA, test.expectedB,
        test.expectedChange)

    // Sanity check the test itself. Sum of inputs must equal sum of
    // outputs.
    sumInput := test.initialA.Count + test.initialB.Count
    sumExpectedOutput := test.expectedA.Count + test.expectedB.Count
    if sumInput != sumExpectedOutput {
        t.Errorf(
            "    Test incorrect: sum of inputs %d != sum of expected outputs %d",
            sumInput, sumExpectedOutput,
        )
        return
    }

    a := test.initialA
    b := test.initialB
    changed := op(&a, &b)
    if !slotEq(&test.expectedA, &a) || !slotEq(&test.expectedB, &b) {
        t.Errorf("    Fail: got a=%+v, b=%+v", a, b)
    }
    if test.expectedChange != changed {
        t.Errorf("    Fail: got changed=%t", changed)
    }
}

func runTests(t *testing.T, tests []slotTest, op func(a, b *Slot) bool) {
    for i := range tests {
        tests[i].run(t, op)
    }
}

func TestSlot_Add(t *testing.T) {

    tests := []slotTest{
        {
            "one empty slot added to another",
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        // Tests involving the same item types: (or empty plus an item)
        {
            "1 + 0 => 1 + 0",
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "1 + 1 => 2 + 0",
            Slot{1, 1, 0}, Slot{1, 1, 0},
            Slot{1, 2, 0}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "0 + 20 => 20 + 0",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 20, 0},
            Slot{1, 20, 0}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "0 + 64 => 64 + 0",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 64, 0},
            Slot{1, 64, 0}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "32 + 33 => 64 + 1 (hitting max count)",
            Slot{1, 32, 0}, Slot{1, 33, 0},
            Slot{1, 64, 0}, Slot{1, 1, 0},
            true,
        },
        {
            "65 + 1 => 65 + 1 (already above max count)",
            Slot{1, 65, 0}, Slot{1, 1, 0},
            Slot{1, 65, 0}, Slot{1, 1, 0},
            false,
        },
        {
            "64 + 64 => 64 + 64",
            Slot{1, 64, 0}, Slot{1, 64, 0},
            Slot{1, 64, 0}, Slot{1, 64, 0},
            false,
        },
        {
            "1 + 1 => 1 + 1 where items' \"Data\" value differs",
            Slot{1, 1, 5}, Slot{1, 1, 6},
            Slot{1, 1, 5}, Slot{1, 1, 6},
            false,
        },
        {
            "1 + 1 => 2 + 0 where items' \"Data\" value is the same",
            Slot{1, 1, 5}, Slot{1, 1, 5},
            Slot{1, 2, 5}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "0 + 1 => 1 + 0 - carrying the \"Data\" value",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 1, 5},
            Slot{1, 1, 5}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        // Tests involving different item types:
        {
            "different item types don't mingle",
            Slot{1, 5, 0}, Slot{2, 5, 0},
            Slot{1, 5, 0}, Slot{2, 5, 0},
            false,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.Add(b)
        },
    )
}

func TestSlot_Swap(t *testing.T) {
    tests := []slotTest{
        {
            "swapping unequal slots",
            Slot{1, 2, 3}, Slot{4, 5, 6},
            Slot{4, 5, 6}, Slot{1, 2, 3},
            true,
        },
        {
            "swapping equal slots",
            Slot{1, 2, 3}, Slot{1, 2, 3},
            Slot{1, 2, 3}, Slot{1, 2, 3},
            false,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.Swap(b)
        },
    )
}

func TestSlot_Split(t *testing.T) {
    tests := []slotTest{
        // No-op tests.
        {
            "splitting an empty slot",
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "splitting from a non-empty slot to another non-empty",
            Slot{1, 2, 0}, Slot{1, 3, 0},
            Slot{1, 2, 0}, Slot{1, 3, 0},
            false,
        },
        {
            "splitting from an empty slot to a non-empty",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 3, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 3, 0},
            false,
        },
        {
            "splitting from a non-empty slot to another non-empty with" +
            " incompatible types",
            Slot{1, 2, 0}, Slot{2, 3, 0},
            Slot{1, 2, 0}, Slot{2, 3, 0},
            false,
        },
        // Remaining tests should all result in changes. They all take from a
        // non-empty subject slot and into the src empty slot.
        {
            "splitting even-numbered stack",
            Slot{1, 64, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 32, 0}, Slot{1, 32, 0},
            true,
        },
        {
            "splitting odd-numbered stack",
            Slot{1, 5, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 2, 0}, Slot{1, 3, 0},
            true,
        },
        {
            "splitting single-item stack",
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 1, 0},
            true,
        },
        {
            "item type and data copy",
            Slot{1, 64, 5}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 32, 5}, Slot{1, 32, 5},
            true,
        },
        {
            "item type and data move",
            Slot{1, 1, 5}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 1, 5},
            true,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.Split(b)
        },
    )
}

func TestSlot_AddOne(t *testing.T) {
    tests := []slotTest{
        // No-op tests.
        {
            "adding from empty to empty",
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "adding from empty to non-empty",
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "adding incompatible types",
            Slot{1, 1, 0}, Slot{2, 4, 0},
            Slot{1, 1, 0}, Slot{2, 4, 0},
            false,
        },
        {
            "adding incompatible data values",
            Slot{1, 1, 0}, Slot{1, 1, 2},
            Slot{1, 1, 0}, Slot{1, 1, 2},
            false,
        },
        {
            "adding to an already full stack",
            Slot{1, SlotCountMax, 0}, Slot{1, 10, 0},
            Slot{1, SlotCountMax, 0}, Slot{1, 10, 0},
            false,
        },
        // Remaining tests should all result in changes. They all take from a
        // non-empty src slot into a compatible subject slot.
        {
            "adding item to empty, copies type and data",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 3, 0},
            Slot{1, 1, 0}, Slot{1, 2, 0},
            true,
        },
        {
            "adding item to non-empty",
            Slot{1, 5, 0}, Slot{1, 3, 0},
            Slot{1, 6, 0}, Slot{1, 2, 0},
            true,
        },
        {
            "adding item to non-empty, empties src",
            Slot{1, 5, 2}, Slot{1, 1, 2},
            Slot{1, 6, 2}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.AddOne(b)
        },
    )
}
<commit_msg>gofmt run.<commit_after>package slot

import (
    "testing"

    .   "chunkymonkey/types"
)

func slotEq(s1, s2 *Slot) bool {
    return (s1.ItemTypeId == s2.ItemTypeId &&
        s1.Count == s2.Count &&
        s1.Data == s2.Data)
}

type slotTest struct {
    desc                 string
    initialA, initialB   Slot
    expectedA, expectedB Slot
    expectedChange       bool
}

func (test *slotTest) run(t *testing.T, op func(a, b *Slot) bool) {
    t.Logf("Test %s:", test.desc)
    t.Logf("    initial   a=%+v, b=%+v", test.initialA, test.initialB)
    t.Logf("    expecting a=%+v, b=%+v, changed=%t",
        test.expectedA, test.expectedB,
        test.expectedChange)

    // Sanity check the test itself. Sum of inputs must equal sum of
    // outputs.
    sumInput := test.initialA.Count + test.initialB.Count
    sumExpectedOutput := test.expectedA.Count + test.expectedB.Count
    if sumInput != sumExpectedOutput {
        t.Errorf(
            "    Test incorrect: sum of inputs %d != sum of expected outputs %d",
            sumInput, sumExpectedOutput,
        )
        return
    }

    a := test.initialA
    b := test.initialB
    changed := op(&a, &b)
    if !slotEq(&test.expectedA, &a) || !slotEq(&test.expectedB, &b) {
        t.Errorf("    Fail: got a=%+v, b=%+v", a, b)
    }
    if test.expectedChange != changed {
        t.Errorf("    Fail: got changed=%t", changed)
    }
}

func runTests(t *testing.T, tests []slotTest, op func(a, b *Slot) bool) {
    for i := range tests {
        tests[i].run(t, op)
    }
}

func TestSlot_Add(t *testing.T) {

    tests := []slotTest{
        {
            "one empty slot added to another",
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        // Tests involving the same item types: (or empty plus an item)
        {
            "1 + 0 => 1 + 0",
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "1 + 1 => 2 + 0",
            Slot{1, 1, 0}, Slot{1, 1, 0},
            Slot{1, 2, 0}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "0 + 20 => 20 + 0",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 20, 0},
            Slot{1, 20, 0}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "0 + 64 => 64 + 0",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 64, 0},
            Slot{1, 64, 0}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "32 + 33 => 64 + 1 (hitting max count)",
            Slot{1, 32, 0}, Slot{1, 33, 0},
            Slot{1, 64, 0}, Slot{1, 1, 0},
            true,
        },
        {
            "65 + 1 => 65 + 1 (already above max count)",
            Slot{1, 65, 0}, Slot{1, 1, 0},
            Slot{1, 65, 0}, Slot{1, 1, 0},
            false,
        },
        {
            "64 + 64 => 64 + 64",
            Slot{1, 64, 0}, Slot{1, 64, 0},
            Slot{1, 64, 0}, Slot{1, 64, 0},
            false,
        },
        {
            "1 + 1 => 1 + 1 where items' \"Data\" value differs",
            Slot{1, 1, 5}, Slot{1, 1, 6},
            Slot{1, 1, 5}, Slot{1, 1, 6},
            false,
        },
        {
            "1 + 1 => 2 + 0 where items' \"Data\" value is the same",
            Slot{1, 1, 5}, Slot{1, 1, 5},
            Slot{1, 2, 5}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        {
            "0 + 1 => 1 + 0 - carrying the \"Data\" value",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 1, 5},
            Slot{1, 1, 5}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
        // Tests involving different item types:
        {
            "different item types don't mingle",
            Slot{1, 5, 0}, Slot{2, 5, 0},
            Slot{1, 5, 0}, Slot{2, 5, 0},
            false,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.Add(b)
        },
    )
}

func TestSlot_Swap(t *testing.T) {
    tests := []slotTest{
        {
            "swapping unequal slots",
            Slot{1, 2, 3}, Slot{4, 5, 6},
            Slot{4, 5, 6}, Slot{1, 2, 3},
            true,
        },
        {
            "swapping equal slots",
            Slot{1, 2, 3}, Slot{1, 2, 3},
            Slot{1, 2, 3}, Slot{1, 2, 3},
            false,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.Swap(b)
        },
    )
}

func TestSlot_Split(t *testing.T) {
    tests := []slotTest{
        // No-op tests.
        {
            "splitting an empty slot",
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "splitting from a non-empty slot to another non-empty",
            Slot{1, 2, 0}, Slot{1, 3, 0},
            Slot{1, 2, 0}, Slot{1, 3, 0},
            false,
        },
        {
            "splitting from an empty slot to a non-empty",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 3, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 3, 0},
            false,
        },
        {
            "splitting from a non-empty slot to another non-empty with" +
                " incompatible types",
            Slot{1, 2, 0}, Slot{2, 3, 0},
            Slot{1, 2, 0}, Slot{2, 3, 0},
            false,
        },
        // Remaining tests should all result in changes. They all take from a
        // non-empty subject slot and into the src empty slot.
        {
            "splitting even-numbered stack",
            Slot{1, 64, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 32, 0}, Slot{1, 32, 0},
            true,
        },
        {
            "splitting odd-numbered stack",
            Slot{1, 5, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 2, 0}, Slot{1, 3, 0},
            true,
        },
        {
            "splitting single-item stack",
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 1, 0},
            true,
        },
        {
            "item type and data copy",
            Slot{1, 64, 5}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 32, 5}, Slot{1, 32, 5},
            true,
        },
        {
            "item type and data move",
            Slot{1, 1, 5}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 1, 5},
            true,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.Split(b)
        },
    )
}

func TestSlot_AddOne(t *testing.T) {
    tests := []slotTest{
        // No-op tests.
        {
            "adding from empty to empty",
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{ItemTypeIdNull, 0, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "adding from empty to non-empty",
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            Slot{1, 1, 0}, Slot{ItemTypeIdNull, 0, 0},
            false,
        },
        {
            "adding incompatible types",
            Slot{1, 1, 0}, Slot{2, 4, 0},
            Slot{1, 1, 0}, Slot{2, 4, 0},
            false,
        },
        {
            "adding incompatible data values",
            Slot{1, 1, 0}, Slot{1, 1, 2},
            Slot{1, 1, 0}, Slot{1, 1, 2},
            false,
        },
        {
            "adding to an already full stack",
            Slot{1, SlotCountMax, 0}, Slot{1, 10, 0},
            Slot{1, SlotCountMax, 0}, Slot{1, 10, 0},
            false,
        },
        // Remaining tests should all result in changes. They all take from a
        // non-empty src slot into a compatible subject slot.
        {
            "adding item to empty, copies type and data",
            Slot{ItemTypeIdNull, 0, 0}, Slot{1, 3, 0},
            Slot{1, 1, 0}, Slot{1, 2, 0},
            true,
        },
        {
            "adding item to non-empty",
            Slot{1, 5, 0}, Slot{1, 3, 0},
            Slot{1, 6, 0}, Slot{1, 2, 0},
            true,
        },
        {
            "adding item to non-empty, empties src",
            Slot{1, 5, 2}, Slot{1, 1, 2},
            Slot{1, 6, 2}, Slot{ItemTypeIdNull, 0, 0},
            true,
        },
    }

    runTests(
        t, tests,
        func(a, b *Slot) bool {
            return a.AddOne(b)
        },
    )
}
<|endoftext|>


<commit_before>package integration

import (
	"fmt"
	"runtime"
	"testing"

	"github.com/bitrise-io/go-utils/command"
	"github.com/stretchr/testify/require"
)

func Test_VersionOutput(t *testing.T) {
	t.Log("Version")
	{
		out, err := command.RunCommandAndReturnCombinedStdoutAndStderr(binPath(), "version")
		require.NoError(t, err, out)
		require.Equal(t, "0.9.27", out)
	}

	t.Log("Version --full")
	{
		out, err := command.RunCommandAndReturnCombinedStdoutAndStderr(binPath(), "version", "--full")
		require.NoError(t, err, out)

		expectedOSVersion := fmt.Sprintf("%s (%s)", runtime.GOOS, runtime.GOARCH)
		expectedVersionOut := fmt.Sprintf(`version: 0.9.27
os: %s
go: %s
build_number:
commit:`, expectedOSVersion, runtime.Version())

		require.Equal(t, expectedVersionOut, out)
	}
}
<commit_msg>version test update<commit_after>package integration

import (
	"fmt"
	"runtime"
	"testing"

	"github.com/bitrise-io/go-utils/command"
	"github.com/stretchr/testify/require"
)

func Test_VersionOutput(t *testing.T) {
	t.Log("Version")
	{
		out, err := command.RunCommandAndReturnCombinedStdoutAndStderr(binPath(), "version")
		require.NoError(t, err, out)
		require.Equal(t, "0.9.28", out)
	}

	t.Log("Version --full")
	{
		out, err := command.RunCommandAndReturnCombinedStdoutAndStderr(binPath(), "version", "--full")
		require.NoError(t, err, out)

		expectedOSVersion := fmt.Sprintf("%s (%s)", runtime.GOOS, runtime.GOARCH)
		expectedVersionOut := fmt.Sprintf(`version: 0.9.28
os: %s
go: %s
build_number:
commit:`, expectedOSVersion, runtime.Version())

		require.Equal(t, expectedVersionOut, out)
	}
}
<|endoftext|>


<commit_before>package action

import (
	bosherr "github.com/cloudfoundry/bosh-utils/errors"

	bslcvm "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/vm"
)

type ConcreteFactoryOptions struct {
	Softlayer SoftLayerConfig `json:"softlayer"`

	Baremetal BaremetalConfig `json:"baremetal,omitempty"`

	Pool  PoolConfig `json:"pool,omitempty"`

	StemcellsDir string `json:"stemcelldir,omitempty"`

	Agent bslcvm.AgentOptions `json:"agent"`

	AgentEnvService string `json:"agentenvservice,omitempty"`

	Registry bslcvm.RegistryOptions `json:"registry,omitempty"`
}

func (o ConcreteFactoryOptions) Validate() error {
	err := o.Agent.Validate()
	if err != nil {
		return bosherr.WrapError(err, "Validating Agent configuration")
	}

	err = o.Softlayer.Validate()
	if err != nil {
		return bosherr.WrapError(err, "Validating SoftLayer configuration")
	}

	return nil
}

type SoftLayerConfig struct {
	Username       string                `json:"username"`
	ApiKey         string                `json:"apiKey"`
	FeatureOptions bslcvm.FeatureOptions `json:"featureOptions"`
}

type BaremetalConfig struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	EndPoint string `json:"endpoint,omitempty"`
}

type PoolConfig struct {
	Host string `json:"host,omitempty"`
	Port int `json:"port,omitempty"`
}

func (c SoftLayerConfig) Validate() error {
	if c.Username == "" {
		return bosherr.Error("Must provide non-empty Username")
	}

	if c.ApiKey == "" {
		return bosherr.Error("Must provide non-empty ApiKey")
	}

	return nil
}
<commit_msg>FeatureOptions should be omitempty<commit_after>package action

import (
	bosherr "github.com/cloudfoundry/bosh-utils/errors"

	bslcvm "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/vm"
)

type ConcreteFactoryOptions struct {
	Softlayer SoftLayerConfig `json:"softlayer"`

	Baremetal BaremetalConfig `json:"baremetal,omitempty"`

	Pool  PoolConfig `json:"pool,omitempty"`

	StemcellsDir string `json:"stemcelldir,omitempty"`

	Agent bslcvm.AgentOptions `json:"agent"`

	AgentEnvService string `json:"agentenvservice,omitempty"`

	Registry bslcvm.RegistryOptions `json:"registry,omitempty"`
}

func (o ConcreteFactoryOptions) Validate() error {
	err := o.Agent.Validate()
	if err != nil {
		return bosherr.WrapError(err, "Validating Agent configuration")
	}

	err = o.Softlayer.Validate()
	if err != nil {
		return bosherr.WrapError(err, "Validating SoftLayer configuration")
	}

	return nil
}

type SoftLayerConfig struct {
	Username       string                `json:"username"`
	ApiKey         string                `json:"apiKey"`
	FeatureOptions bslcvm.FeatureOptions `json:"featureOptions,omitempty"`
}

type BaremetalConfig struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	EndPoint string `json:"endpoint,omitempty"`
}

type PoolConfig struct {
	Host string `json:"host,omitempty"`
	Port int `json:"port,omitempty"`
}

func (c SoftLayerConfig) Validate() error {
	if c.Username == "" {
		return bosherr.Error("Must provide non-empty Username")
	}

	if c.ApiKey == "" {
		return bosherr.Error("Must provide non-empty ApiKey")
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 handlers

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strconv"
	"testing"

	"github.com/aws/amazon-ecs-agent/agent/api"
	"github.com/aws/amazon-ecs-agent/agent/config"
	"github.com/aws/amazon-ecs-agent/agent/engine"
	"github.com/aws/amazon-ecs-agent/agent/utils"
)

const TestContainerInstanceArn = "test_container_instance_arn"
const TestClusterArn = "test_cluster_arn"

func TestMetadataHandler(t *testing.T) {
	metadataHandler := MetadataV1RequestHandlerMaker(utils.Strptr(TestContainerInstanceArn), &config.Config{Cluster: TestClusterArn})

	w := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "http://localhost:"+strconv.Itoa(config.AGENT_INTROSPECTION_PORT), nil)
	metadataHandler(w, req)

	var resp MetadataResponse
	json.Unmarshal(w.Body.Bytes(), &resp)

	if resp.Cluster != TestClusterArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
	if *resp.ContainerInstanceArn != TestContainerInstanceArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
}

func getResponseBodyFromLocalHost(url string, t *testing.T) []byte {
	resp, err := http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + url)
	if err != nil {
		t.Fatal(err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	return body
}

func TestServeHttp(t *testing.T) {
	taskEngine := engine.NewTaskEngine(&config.Config{})
	taskEngine.MustInit()
	containers := []*api.Container{
		&api.Container{
			Name: "c1",
		},
	}
	testTask := api.Task{
		Arn:           "task1",
		DesiredStatus: api.TaskRunning,
		KnownStatus:   api.TaskRunning,
		Family:        "test",
		Version:       "1",
		Containers:    containers,
	}
	// Populate Tasks and Container map in the engine.
	taskEngine.AddTask(&testTask)
	dockerTaskEngine, _ := taskEngine.(*engine.DockerTaskEngine)
	dockerTaskEngine.State().AddContainer(&api.DockerContainer{DockerId: "docker1", DockerName: "someName", Container: containers[0]}, &testTask)
	go ServeHttp(utils.Strptr(TestContainerInstanceArn), taskEngine, &config.Config{Cluster: TestClusterArn})

	body := getResponseBodyFromLocalHost("/v1/metadata", t)
	var metadata MetadataResponse
	json.Unmarshal(body, &metadata)

	if metadata.Cluster != TestClusterArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
	if *metadata.ContainerInstanceArn != TestContainerInstanceArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
	var tasksResponse TasksResponse
	body = getResponseBodyFromLocalHost("/v1/tasks", t)
	json.Unmarshal(body, &tasksResponse)
	tasks := tasksResponse.Tasks

	if len(tasks) != 1 {
		t.Error("Incorrect number of tasks in response: ", len(tasks))
	}
	if tasks[0].Arn != "task1" {
		t.Error("Incorrect task arn in response: ", tasks[0].Arn)
	}
	containersResponse := tasks[0].Containers
	if len(containersResponse) != 1 {
		t.Error("Incorrect number of containers in response: ", len(containersResponse))
	}
	if containersResponse[0].Name != "c1" {
		t.Error("Incorrect container name in response: ", containersResponse[0].Name)
	}
	var taskResponse TaskResponse
	body = getResponseBodyFromLocalHost("/v1/tasks?dockerid=docker1", t)
	json.Unmarshal(body, &taskResponse)
	if taskResponse.Arn != "task1" {
		t.Error("Incorrect task arn in response")
	}
	if taskResponse.Containers[0].Name != "c1" {
		t.Error("Incorrect task arn in response")
	}

	resp, err := http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?dockerid=docker2")
	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status for invalid docker id")
	}

	body = getResponseBodyFromLocalHost("/v1/tasks?taskarn=task1", t)
	json.Unmarshal(body, &taskResponse)
	if taskResponse.Arn != "task1" {
		t.Error("Incorrect task arn in response")
	}

	resp, err = http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?taskarn=task2")
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status for invalid task id")
	}

	resp, err = http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?taskarn=")
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status for invalid task id")
	}

	resp, err = http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?taskarn=task1&dockerid=docker1")
	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status when both dockerid and taskarn are specified.")
	}
}
<commit_msg>Make handler-test avoid trying to talk to Docker<commit_after>// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 handlers

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strconv"
	"testing"

	"github.com/aws/amazon-ecs-agent/agent/api"
	"github.com/aws/amazon-ecs-agent/agent/config"
	"github.com/aws/amazon-ecs-agent/agent/engine"
	"github.com/aws/amazon-ecs-agent/agent/utils"
)

const TestContainerInstanceArn = "test_container_instance_arn"
const TestClusterArn = "test_cluster_arn"

func TestMetadataHandler(t *testing.T) {
	metadataHandler := MetadataV1RequestHandlerMaker(utils.Strptr(TestContainerInstanceArn), &config.Config{Cluster: TestClusterArn})

	w := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "http://localhost:"+strconv.Itoa(config.AGENT_INTROSPECTION_PORT), nil)
	metadataHandler(w, req)

	var resp MetadataResponse
	json.Unmarshal(w.Body.Bytes(), &resp)

	if resp.Cluster != TestClusterArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
	if *resp.ContainerInstanceArn != TestContainerInstanceArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
}

func getResponseBodyFromLocalHost(url string, t *testing.T) []byte {
	resp, err := http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + url)
	if err != nil {
		t.Fatal(err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	return body
}

func TestServeHttp(t *testing.T) {
	taskEngine := engine.NewTaskEngine(&config.Config{})
	containers := []*api.Container{
		&api.Container{
			Name: "c1",
		},
	}
	testTask := api.Task{
		Arn:           "task1",
		DesiredStatus: api.TaskRunning,
		KnownStatus:   api.TaskRunning,
		Family:        "test",
		Version:       "1",
		Containers:    containers,
	}
	// Populate Tasks and Container map in the engine.
	dockerTaskEngine, _ := taskEngine.(*engine.DockerTaskEngine)
	dockerTaskEngine.State().AddOrUpdateTask(&testTask)
	dockerTaskEngine.State().AddContainer(&api.DockerContainer{DockerId: "docker1", DockerName: "someName", Container: containers[0]}, &testTask)
	go ServeHttp(utils.Strptr(TestContainerInstanceArn), taskEngine, &config.Config{Cluster: TestClusterArn})

	body := getResponseBodyFromLocalHost("/v1/metadata", t)
	var metadata MetadataResponse
	json.Unmarshal(body, &metadata)

	if metadata.Cluster != TestClusterArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
	if *metadata.ContainerInstanceArn != TestContainerInstanceArn {
		t.Error("Metadata returned the wrong cluster arn")
	}
	var tasksResponse TasksResponse
	body = getResponseBodyFromLocalHost("/v1/tasks", t)
	json.Unmarshal(body, &tasksResponse)
	tasks := tasksResponse.Tasks

	if len(tasks) != 1 {
		t.Error("Incorrect number of tasks in response: ", len(tasks))
	}
	if tasks[0].Arn != "task1" {
		t.Error("Incorrect task arn in response: ", tasks[0].Arn)
	}
	containersResponse := tasks[0].Containers
	if len(containersResponse) != 1 {
		t.Error("Incorrect number of containers in response: ", len(containersResponse))
	}
	if containersResponse[0].Name != "c1" {
		t.Error("Incorrect container name in response: ", containersResponse[0].Name)
	}
	var taskResponse TaskResponse
	body = getResponseBodyFromLocalHost("/v1/tasks?dockerid=docker1", t)
	json.Unmarshal(body, &taskResponse)
	if taskResponse.Arn != "task1" {
		t.Error("Incorrect task arn in response")
	}
	if taskResponse.Containers[0].Name != "c1" {
		t.Error("Incorrect task arn in response")
	}

	resp, err := http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?dockerid=docker2")
	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status for invalid docker id")
	}

	body = getResponseBodyFromLocalHost("/v1/tasks?taskarn=task1", t)
	json.Unmarshal(body, &taskResponse)
	if taskResponse.Arn != "task1" {
		t.Error("Incorrect task arn in response")
	}

	resp, err = http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?taskarn=task2")
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status for invalid task id")
	}

	resp, err = http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?taskarn=")
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status for invalid task id")
	}

	resp, err = http.Get("http://localhost:" + strconv.Itoa(config.AGENT_INTROSPECTION_PORT) + "/v1/tasks?taskarn=task1&dockerid=docker1")
	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 400 {
		t.Error("API did not return bad request status when both dockerid and taskarn are specified.")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"time"

	"text/template"

	"github.com/dustin/go-nmea"
)

const kmlHeader = `<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2"
          xmlns:gx="http://www.google.com/kml/ext/2.2">

<Folder>
<gx:Tour><name>%s</name><gx:Playlist>
`

const kmlPoint = `<!-- {{ .D }} -->
<gx:FlyTo>
       <gx:duration>{{.FlyDur}}</gx:duration>
       <gx:flyToMode>smooth</gx:flyToMode>
       <TimeStamp>{{.TS}}</TimeStamp>
	<LookAt>
		<longitude>{{.Lon}}</longitude>
		<latitude>{{.Lat}}</latitude>
		<altitude>{{.Altitude}}</altitude>
		<heading>{{.H}}</heading>
		<tilt>{{.Tilt}}</tilt>
		<range>{{.Range}}</range>
		<altitudeMode>relativeToGround</altitudeMode>
	</LookAt>
</gx:FlyTo>
<gx:Wait><gx:duration>{{.WaitDur}}</gx:duration></gx:Wait>
`
const kmlFooter = `</gx:Playlist></gx:Tour></Folder></kml>`

const tsFormat = "2006-01-02T15:04:05Z"

var (
	minDist = flag.Int("minDist", 1000, "minimum distance (meters) between points")
	minTime = flag.Duration("minTime", 1*time.Minute, "minimum time between points")
	tilt    = flag.Float64("tilt", 85, "viewing angle")
	rng     = flag.Float64("range", 800, "viewing range")
	alt     = flag.Float64("alt", 20, "altitude")
	flyDur  = flag.Duration("flyDur", time.Second, "fly-to duration")
	waitDur = flag.Duration("waitDur", 0, "wait duration")
	title   = flag.String("title", "Road Trip", "KML title")

	tmpl = template.Must(template.New("").Parse(kmlPoint))
)

type errRememberer struct {
	w   io.WriteCloser
	err error
}

func (e errRememberer) Write(b []byte) (int, error) {
	if e.err != nil {
		return 0, e.err
	}

	var n int
	n, e.err = e.w.Write(b)

	return n, e.err
}

func (e errRememberer) Close() error {
	if e.err != nil {
		e.w.Close()
		return e.err
	}
	return e.w.Close()
}

type kmlWriter struct {
	w          errRememberer
	plat, plon float64
	pts        time.Time
}

func (k *kmlWriter) HandleRMC(m nmea.RMC) {
	Δλ := distance(m.Longitude, m.Latitude, k.plon, k.plat)
	Δt := m.Timestamp.Sub(k.pts)
	if Δλ > float64(*minDist) || Δt > *minTime {
		tmpl.Execute(k.w, struct {
			Lon, Lat float64
			TS       string
			D        float64
			H        float64
			Tilt     float64
			Range    float64
			Altitude float64
			FlyDur   float64
			WaitDur  float64
		}{m.Longitude, m.Latitude, m.Timestamp.Format(tsFormat), Δλ, m.Angle,
			*tilt, *rng, *alt,
			flyDur.Seconds(), waitDur.Seconds()})
		k.plat = m.Latitude
		k.plon = m.Longitude
		k.pts = m.Timestamp
	}
}

func (k kmlWriter) Init() error {
	fmt.Fprintf(k.w, kmlHeader, *title)
	return k.w.err
}

func (k kmlWriter) Close() error {
	k.w.Write([]byte(kmlFooter))
	return k.w.Close()
}

func d2r(d float64) float64 {
	return d * math.Pi / 180.0
}

func distance(lon1, lat1, lon2, lat2 float64) float64 {
	φ1 := d2r(lat1)
	φ2 := d2r(lat2)
	Δφ := d2r(lat2 - lat1)
	Δλ := d2r(lon2 - lon1)

	a := math.Sin(Δφ/2)*math.Sin(Δφ/2) +
		math.Cos(φ1)*math.Cos(φ2)*
			math.Sin(Δλ/2)*math.Sin(Δλ/2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	return 6371000 * c
}

func main() {
	flag.Parse()
	h := &kmlWriter{w: errRememberer{w: os.Stdout}}
	h.Init()
	err := nmea.Process(os.Stdin, h, func(s string, err error) error {
		if err != nil {
			log.Printf("On %q: %v", s, err)
		}
		return nil
	})

	if err != nil {
		log.Fatalf("Error processing stuff: %v", err)
	}
	if err := h.Close(); err != nil {
		log.Fatalf("Error finishing up KML output: %v", err)
	}
}
<commit_msg>Instead of making trails, just detect stops<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"time"

	"text/template"

	"github.com/dustin/go-nmea"
)

const kmlHeader = `<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2"
          xmlns:gx="http://www.google.com/kml/ext/2.2">

<Document>
<name>%s</name>
`

const kmlPoint = `<Placemark>
    <Point><coordinates>{{.Lon}},{{.Lat}},0.0</coordinates></Point>
</Placemark>
`

const kmlFooter = `</Document></kml>`

const tsFormat = "2006-01-02T15:04:05Z"

var (
	minDist = flag.Int("minDist", 1000, "minimum distance (meters) between points")
	minTime = flag.Duration("minTime", 1*time.Minute, "minimum time between points")
	tilt    = flag.Float64("tilt", 85, "viewing angle")
	rng     = flag.Float64("range", 800, "viewing range")
	alt     = flag.Float64("alt", 20, "altitude")
	flyDur  = flag.Duration("flyDur", time.Second, "fly-to duration")
	waitDur = flag.Duration("waitDur", 0, "wait duration")
	title   = flag.String("title", "Road Trip", "KML title")

	tmpl = template.Must(template.New("").Parse(kmlPoint))
)

type errRememberer struct {
	w   io.WriteCloser
	err error
}

func (e errRememberer) Write(b []byte) (int, error) {
	if e.err != nil {
		return 0, e.err
	}

	var n int
	n, e.err = e.w.Write(b)

	return n, e.err
}

func (e errRememberer) Close() error {
	if e.err != nil {
		e.w.Close()
		return e.err
	}
	return e.w.Close()
}

type kmlWriter struct {
	w          errRememberer
	plat, plon float64
	pts        time.Time
}

func (k *kmlWriter) render(m nmea.RMC, Δλ float64) {
	tmpl.Execute(k.w, struct {
		Lon, Lat float64
		TS       string
		D        float64
		H        float64
		Tilt     float64
		Range    float64
		Altitude float64
		FlyDur   float64
		WaitDur  float64
	}{m.Longitude, m.Latitude, m.Timestamp.Format(tsFormat), Δλ, m.Angle,
		*tilt, *rng, *alt,
		flyDur.Seconds(), waitDur.Seconds()})
}

func (k *kmlWriter) HandleRMC(m nmea.RMC) {
	if k.plat == 0 {
		k.render(m, 0)
		k.plat = m.Latitude
		k.plon = m.Longitude
		k.pts = m.Timestamp
		return
	}
	Δλ := distance(m.Longitude, m.Latitude, k.plon, k.plat)
	Δt := m.Timestamp.Sub(k.pts)
	if Δλ < float64(*minDist) && Δt > *minTime {
		log.Printf("Δλ = %v, Δt = %v", Δλ, Δt)
		k.render(m, Δλ)
	} else {
		k.plat = m.Latitude
		k.plon = m.Longitude
	}
	k.pts = m.Timestamp
}

func (k kmlWriter) Init() error {
	fmt.Fprintf(k.w, kmlHeader, *title)
	return k.w.err
}

func (k kmlWriter) Close() error {
	k.w.Write([]byte(kmlFooter))
	return k.w.Close()
}

func d2r(d float64) float64 {
	return d * math.Pi / 180.0
}

func distance(lon1, lat1, lon2, lat2 float64) float64 {
	φ1 := d2r(lat1)
	φ2 := d2r(lat2)
	Δφ := d2r(lat2 - lat1)
	Δλ := d2r(lon2 - lon1)

	a := math.Sin(Δφ/2)*math.Sin(Δφ/2) +
		math.Cos(φ1)*math.Cos(φ2)*
			math.Sin(Δλ/2)*math.Sin(Δλ/2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	return 6371000 * c
}

func main() {
	flag.Parse()
	h := &kmlWriter{w: errRememberer{w: os.Stdout}}
	h.Init()
	err := nmea.Process(os.Stdin, h, func(s string, err error) error {
		if err != nil {
			log.Printf("On %q: %v", s, err)
		}
		return nil
	})

	if err != nil {
		log.Fatalf("Error processing stuff: %v", err)
	}
	if err := h.Close(); err != nil {
		log.Fatalf("Error finishing up KML output: %v", err)
	}
}
<|endoftext|>


<commit_before>package notifier

import (
	"log"

	"github.com/turnkey-commerce/go-ping-sites/database"
)

// Notifier sends the notifications to the recipients on a status change.
type Notifier struct {
	Site    database.Site
	Message string
	Subject string
}

// NewNotifier returns a new Notifier object to perform notifications about status change
func NewNotifier(site database.Site, message string, subject string) *Notifier {
	n := Notifier{Site: site, Message: message, Subject: subject}
	return &n
}

// Notify starts the notification for each contact for the site.
func (n *Notifier) Notify() {
	log.Println("Sending Notification of Site Contacts about", n.Subject+"...")
	for _, c := range n.Site.Contacts {
		if c.SmsActive || c.EmailActive {
			// Notify contacts
			log.Println("Sending notifications for", c.Name)
		} else {
			log.Println("No active contact methods for", c.Name)
		}
	}
}
<commit_msg>Add function to call in go routine for notifications.<commit_after>package notifier

import (
	"log"
	"sync"

	"github.com/turnkey-commerce/go-ping-sites/database"
)

// Notifier sends the notifications to the recipients on a status change.
type Notifier struct {
	Site    database.Site
	Message string
	Subject string
}

// NewNotifier returns a new Notifier object to perform notifications about status change
func NewNotifier(site database.Site, message string, subject string) *Notifier {
	n := Notifier{Site: site, Message: message, Subject: subject}
	return &n
}

// Notify starts the notification for each contact for the site.
func (n *Notifier) Notify() {
	var wg sync.WaitGroup
	log.Println("Sending Notification of Site Contacts about", n.Subject+"...")
	for _, c := range n.Site.Contacts {
		if c.SmsActive || c.EmailActive {
			// Notify contact
			wg.Add(1)
			go send(c, n.Message, n.Subject, &wg)
		} else {
			log.Println("No active contact methods for", c.Name)
		}
	}
	wg.Wait()
}

func send(c database.Contact, message string, subject string, wg *sync.WaitGroup) {
	log.Println("Sending notifications for", c.Name, subject, message)
	wg.Done()
}
<|endoftext|>


<commit_before>package daemon

import (
	log "github.com/Sirupsen/logrus"
	"github.com/docker/go-plugins-helpers/volume"
	"path/filepath"
)

const socketAddress = "/run/docker/plugins/nvd.sock"

var (
	defaultDir = filepath.Join(volume.DefaultDockerRootDirectory, "nvd")
)

func Start(cfgFile string, debug bool) {
	if debug {
		log.SetLevel(log.DebugLevel)
	} else {
		log.SetLevel(log.InfoLevel)
	}
	log.Info("Default docker root nvd: ", defaultDir)
	d := DriverAlloc(cfgFile)
	h := volume.NewHandler(d)
	log.Info("Driver Created, Handler Initialized")
	log.Info(h.ServeUnix("root", socketAddress))
}
<commit_msg>h.ServeUnix params update<commit_after>package daemon

import (
	log "github.com/Sirupsen/logrus"
	"github.com/docker/go-plugins-helpers/volume"
	"path/filepath"
)

const socketAddress = "/run/docker/plugins/nvd.sock"

var (
	defaultDir = filepath.Join(volume.DefaultDockerRootDirectory, "nvd")
)

func Start(cfgFile string, debug bool) {
	if debug {
		log.SetLevel(log.DebugLevel)
	} else {
		log.SetLevel(log.InfoLevel)
	}
	log.Info("Default docker root nvd: ", defaultDir)
	d := DriverAlloc(cfgFile)
	h := volume.NewHandler(d)
	log.Info("Driver Created, Handler Initialized")
	log.Info(h.ServeUnix(socketAddress, 0))
}
<|endoftext|>


<commit_before>// +build windows

package win_perf_counters

import (
	"errors"
	"fmt"
	"strings"
	"unsafe"

	"github.com/influxdata/telegraf"
	"github.com/influxdata/telegraf/plugins/inputs"
)

var sampleConfig = `
  ## By default this plugin returns basic CPU and Disk statistics.
  ## See the README file for more examples.
  ## Uncomment examples below or write your own as you see fit. If the system
  ## being polled for data does not have the Object at startup of the Telegraf
  ## agent, it will not be gathered.
  ## Settings:
  # PrintValid = false # Print All matching performance counters

  [[inputs.win_perf_counters.object]]
    # Processor usage, alternative to native, reports on a per core.
    ObjectName = "Processor"
    Instances = ["*"]
    Counters = [
      "%% Idle Time", "%% Interrupt Time",
      "%% Privileged Time", "%% User Time",
      "%% Processor Time"
    ]
    Measurement = "win_cpu"
    # Set to true to include _Total instance when querying for all (*).
    # IncludeTotal=false
    # Print out when the performance counter is missing from object, counter or instance.
    # WarnOnMissing = false

  [[inputs.win_perf_counters.object]]
    # Disk times and queues
    ObjectName = "LogicalDisk"
    Instances = ["*"]
    Counters = [
      "%% Idle Time", "%% Disk Time","%% Disk Read Time",
      "%% Disk Write Time", "%% User Time", "Current Disk Queue Length"
    ]
    Measurement = "win_disk"

  [[inputs.win_perf_counters.object]]
    ObjectName = "System"
    Counters = ["Context Switches/sec","System Calls/sec"]
    Instances = ["------"]
    Measurement = "win_system"

  [[inputs.win_perf_counters.object]]
    # Example query where the Instance portion must be removed to get data back,
    # such as from the Memory object.
    ObjectName = "Memory"
    Counters = [
      "Available Bytes", "Cache Faults/sec", "Demand Zero Faults/sec",
      "Page Faults/sec", "Pages/sec", "Transition Faults/sec",
      "Pool Nonpaged Bytes", "Pool Paged Bytes"
    ]
    Instances = ["------"] # Use 6 x - to remove the Instance bit from the query.
    Measurement = "win_mem"
`

type Win_PerfCounters struct {
	PrintValid      bool
	PreVistaSupport bool
	Object          []perfobject

	configParsed bool
	itemCache    []*item
}

type perfobject struct {
	ObjectName    string
	Counters      []string
	Instances     []string
	Measurement   string
	WarnOnMissing bool
	FailOnMissing bool
	IncludeTotal  bool
}

type item struct {
	query         string
	objectName    string
	counter       string
	instance      string
	measurement   string
	include_total bool
	handle        PDH_HQUERY
	counterHandle PDH_HCOUNTER
}

var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
	" ", "_", "%", "Percent", `\`, "")

func (m *Win_PerfCounters) AddItem(query string, objectName string, counter string, instance string,
	measurement string, include_total bool) error {

	var handle PDH_HQUERY
	var counterHandle PDH_HCOUNTER
	ret := PdhOpenQuery(0, 0, &handle)
	if m.PreVistaSupport {
		ret = PdhAddCounter(handle, query, 0, &counterHandle)
	} else {
		ret = PdhAddEnglishCounter(handle, query, 0, &counterHandle)
	}

	// Call PdhCollectQueryData one time to check existence of the counter
	ret = PdhCollectQueryData(handle)
	if ret != ERROR_SUCCESS {
		PdhCloseQuery(handle)
		return errors.New(PdhFormatError(ret))
	}

	newItem := &item{query, objectName, counter, instance, measurement,
		include_total, handle, counterHandle}
	m.itemCache = append(m.itemCache, newItem)

	return nil
}

func (m *Win_PerfCounters) Description() string {
	return "Input plugin to query Performance Counters on Windows operating systems"
}

func (m *Win_PerfCounters) SampleConfig() string {
	return sampleConfig
}

func (m *Win_PerfCounters) ParseConfig() error {
	var query string

	if len(m.Object) > 0 {
		for _, PerfObject := range m.Object {
			for _, counter := range PerfObject.Counters {
				for _, instance := range PerfObject.Instances {
					objectname := PerfObject.ObjectName

					if instance == "------" {
						query = "\\" + objectname + "\\" + counter
					} else {
						query = "\\" + objectname + "(" + instance + ")\\" + counter
					}

					err := m.AddItem(query, objectname, counter, instance,
						PerfObject.Measurement, PerfObject.IncludeTotal)

					if err == nil {
						if m.PrintValid {
							fmt.Printf("Valid: %s\n", query)
						}
					} else {
						if PerfObject.FailOnMissing || PerfObject.WarnOnMissing {
							fmt.Printf("Invalid query: '%s'. Error: %s", query, err.Error())
						}
						if PerfObject.FailOnMissing {
							return err
						}
					}
				}
			}
		}

		return nil
	} else {
		err := errors.New("No performance objects configured!")
		return err
	}
}

func (m *Win_PerfCounters) GetParsedItemsForTesting() []*item {
	return m.itemCache
}

func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
	// Parse the config once
	if !m.configParsed {
		err := m.ParseConfig()
		m.configParsed = true
		if err != nil {
			return err
		}
	}

	var bufSize uint32
	var bufCount uint32
	var size uint32 = uint32(unsafe.Sizeof(PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
	var emptyBuf [1]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.

	// For iterate over the known metrics and get the samples.
	for _, metric := range m.itemCache {
		// collect
		ret := PdhCollectQueryData(metric.handle)
		if ret == ERROR_SUCCESS {
			ret = PdhGetFormattedCounterArrayDouble(metric.counterHandle, &bufSize,
				&bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN.
			if ret == PDH_MORE_DATA {
				filledBuf := make([]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
				if len(filledBuf) == 0 {
					continue
				}
				ret = PdhGetFormattedCounterArrayDouble(metric.counterHandle,
					&bufSize, &bufCount, &filledBuf[0])
				for i := 0; i < int(bufCount); i++ {
					c := filledBuf[i]
					var s string = UTF16PtrToString(c.SzName)

					var add bool

					if metric.include_total {
						// If IncludeTotal is set, include all.
						add = true
					} else if metric.instance == "*" && !strings.Contains(s, "_Total") {
						// Catch if set to * and that it is not a '*_Total*' instance.
						add = true
					} else if metric.instance == s {
						// Catch if we set it to total or some form of it
						add = true
					} else if strings.Contains(metric.instance, "#") && strings.HasPrefix(metric.instance, s) {
						// If you are using a multiple instance identifier such as "w3wp#1"
						// phd.dll returns only the first 2 characters of the identifier.
						add = true
						s = metric.instance
					} else if metric.instance == "------" {
						add = true
					}

					if add {
						fields := make(map[string]interface{})
						tags := make(map[string]string)
						if s != "" {
							tags["instance"] = s
						}
						tags["objectname"] = metric.objectName
						fields[sanitizedChars.Replace(metric.counter)] =
							float32(c.FmtValue.DoubleValue)

						measurement := sanitizedChars.Replace(metric.measurement)
						if measurement == "" {
							measurement = "win_perf_counters"
						}
						acc.AddFields(measurement, fields, tags)
					}
				}

				filledBuf = nil
				// Need to at least set bufSize to zero, because if not, the function will not
				// return PDH_MORE_DATA and will not set the bufSize.
				bufCount = 0
				bufSize = 0
			}
		}
	}

	return nil
}

func init() {
	inputs.Add("win_perf_counters", func() telegraf.Input { return &Win_PerfCounters{} })
}
<commit_msg>Fix win_perf_counters to collect counters per instance (#4036)<commit_after>// +build windows

package win_perf_counters

import (
	"errors"
	"fmt"
	"strings"
	"unsafe"

	"github.com/influxdata/telegraf"
	"github.com/influxdata/telegraf/plugins/inputs"
)

var sampleConfig = `
  ## By default this plugin returns basic CPU and Disk statistics.
  ## See the README file for more examples.
  ## Uncomment examples below or write your own as you see fit. If the system
  ## being polled for data does not have the Object at startup of the Telegraf
  ## agent, it will not be gathered.
  ## Settings:
  # PrintValid = false # Print All matching performance counters

  [[inputs.win_perf_counters.object]]
    # Processor usage, alternative to native, reports on a per core.
    ObjectName = "Processor"
    Instances = ["*"]
    Counters = [
      "%% Idle Time", "%% Interrupt Time",
      "%% Privileged Time", "%% User Time",
      "%% Processor Time"
    ]
    Measurement = "win_cpu"
    # Set to true to include _Total instance when querying for all (*).
    # IncludeTotal=false
    # Print out when the performance counter is missing from object, counter or instance.
    # WarnOnMissing = false

  [[inputs.win_perf_counters.object]]
    # Disk times and queues
    ObjectName = "LogicalDisk"
    Instances = ["*"]
    Counters = [
      "%% Idle Time", "%% Disk Time","%% Disk Read Time",
      "%% Disk Write Time", "%% User Time", "Current Disk Queue Length"
    ]
    Measurement = "win_disk"

  [[inputs.win_perf_counters.object]]
    ObjectName = "System"
    Counters = ["Context Switches/sec","System Calls/sec"]
    Instances = ["------"]
    Measurement = "win_system"

  [[inputs.win_perf_counters.object]]
    # Example query where the Instance portion must be removed to get data back,
    # such as from the Memory object.
    ObjectName = "Memory"
    Counters = [
      "Available Bytes", "Cache Faults/sec", "Demand Zero Faults/sec",
      "Page Faults/sec", "Pages/sec", "Transition Faults/sec",
      "Pool Nonpaged Bytes", "Pool Paged Bytes"
    ]
    Instances = ["------"] # Use 6 x - to remove the Instance bit from the query.
    Measurement = "win_mem"
`

type Win_PerfCounters struct {
	PrintValid      bool
	PreVistaSupport bool
	Object          []perfobject

	configParsed bool
	itemCache    []*item
}

type perfobject struct {
	ObjectName    string
	Counters      []string
	Instances     []string
	Measurement   string
	WarnOnMissing bool
	FailOnMissing bool
	IncludeTotal  bool
}

type item struct {
	query         string
	objectName    string
	counter       string
	instance      string
	measurement   string
	include_total bool
	handle        PDH_HQUERY
	counterHandle PDH_HCOUNTER
}

var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
	" ", "_", "%", "Percent", `\`, "")

func (m *Win_PerfCounters) AddItem(query string, objectName string, counter string, instance string,
	measurement string, include_total bool) error {

	var handle PDH_HQUERY
	var counterHandle PDH_HCOUNTER
	ret := PdhOpenQuery(0, 0, &handle)
	if m.PreVistaSupport {
		ret = PdhAddCounter(handle, query, 0, &counterHandle)
	} else {
		ret = PdhAddEnglishCounter(handle, query, 0, &counterHandle)
	}

	// Call PdhCollectQueryData one time to check existence of the counter
	ret = PdhCollectQueryData(handle)
	if ret != ERROR_SUCCESS {
		PdhCloseQuery(handle)
		return errors.New(PdhFormatError(ret))
	}

	newItem := &item{query, objectName, counter, instance, measurement,
		include_total, handle, counterHandle}
	m.itemCache = append(m.itemCache, newItem)

	return nil
}

func (m *Win_PerfCounters) Description() string {
	return "Input plugin to query Performance Counters on Windows operating systems"
}

func (m *Win_PerfCounters) SampleConfig() string {
	return sampleConfig
}

func (m *Win_PerfCounters) ParseConfig() error {
	var query string

	if len(m.Object) > 0 {
		for _, PerfObject := range m.Object {
			for _, counter := range PerfObject.Counters {
				for _, instance := range PerfObject.Instances {
					objectname := PerfObject.ObjectName

					if instance == "------" {
						query = "\\" + objectname + "\\" + counter
					} else {
						query = "\\" + objectname + "(" + instance + ")\\" + counter
					}

					err := m.AddItem(query, objectname, counter, instance,
						PerfObject.Measurement, PerfObject.IncludeTotal)

					if err == nil {
						if m.PrintValid {
							fmt.Printf("Valid: %s\n", query)
						}
					} else {
						if PerfObject.FailOnMissing || PerfObject.WarnOnMissing {
							fmt.Printf("Invalid query: '%s'. Error: %s", query, err.Error())
						}
						if PerfObject.FailOnMissing {
							return err
						}
					}
				}
			}
		}

		return nil
	} else {
		err := errors.New("No performance objects configured!")
		return err
	}
}

func (m *Win_PerfCounters) GetParsedItemsForTesting() []*item {
	return m.itemCache
}

func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
	// Parse the config once
	if !m.configParsed {
		err := m.ParseConfig()
		m.configParsed = true
		if err != nil {
			return err
		}
	}

	var bufSize uint32
	var bufCount uint32
	var size uint32 = uint32(unsafe.Sizeof(PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
	var emptyBuf [1]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.

	type InstanceGrouping struct {
		name       string
		instance   string
		objectname string
	}

	var collectFields = make(map[InstanceGrouping]map[string]interface{})

	// For iterate over the known metrics and get the samples.
	for _, metric := range m.itemCache {
		// collect
		ret := PdhCollectQueryData(metric.handle)
		if ret == ERROR_SUCCESS {
			ret = PdhGetFormattedCounterArrayDouble(metric.counterHandle, &bufSize,
				&bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN.
			if ret == PDH_MORE_DATA {
				filledBuf := make([]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
				if len(filledBuf) == 0 {
					continue
				}
				ret = PdhGetFormattedCounterArrayDouble(metric.counterHandle,
					&bufSize, &bufCount, &filledBuf[0])
				for i := 0; i < int(bufCount); i++ {
					c := filledBuf[i]
					var s string = UTF16PtrToString(c.SzName)

					var add bool

					if metric.include_total {
						// If IncludeTotal is set, include all.
						add = true
					} else if metric.instance == "*" && !strings.Contains(s, "_Total") {
						// Catch if set to * and that it is not a '*_Total*' instance.
						add = true
					} else if metric.instance == s {
						// Catch if we set it to total or some form of it
						add = true
					} else if strings.Contains(metric.instance, "#") && strings.HasPrefix(metric.instance, s) {
						// If you are using a multiple instance identifier such as "w3wp#1"
						// phd.dll returns only the first 2 characters of the identifier.
						add = true
						s = metric.instance
					} else if metric.instance == "------" {
						add = true
					}

					if add {
						tags := make(map[string]string)
						if s != "" {
							tags["instance"] = s
						}
						tags["objectname"] = metric.objectName

						measurement := sanitizedChars.Replace(metric.measurement)
						if measurement == "" {
							measurement = "win_perf_counters"
						}
						var instance = InstanceGrouping{measurement, s, metric.objectName}

						if collectFields[instance] == nil {
							collectFields[instance] = make(map[string]interface{})
						}
						collectFields[instance][sanitizedChars.Replace(metric.counter)] = float32(c.FmtValue.DoubleValue)
					}
				}

				filledBuf = nil
				// Need to at least set bufSize to zero, because if not, the function will not
				// return PDH_MORE_DATA and will not set the bufSize.
				bufCount = 0
				bufSize = 0
			}
		}
	}

	for instance, fields := range collectFields {
		var tags = map[string]string{
			"instance":   instance.instance,
			"objectname": instance.objectname,
		}
		acc.AddFields(instance.name, fields, tags)
	}

	return nil
}

func init() {
	inputs.Add("win_perf_counters", func() telegraf.Input { return &Win_PerfCounters{} })
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
)

//checks if I have the blob, it returns yes or no
func blobAvailable(hash HCID) bool {
	localfileserviceInstance.GetBlob(hash)
	return false
}

////checks if I have the key, it returns yes or no
func keyAvailable(hash HKID) bool {
	return false
}

//checks if I have the tag, it returns yes or no and the latest version
func tagAvailable(hash HKID, name string) (bool, int64) {
	return false, 0
}

//checks if I have the commit, it returns yes or no and the latest version
func commitAvailable(hash HKID) (bool, int64) {
	return false, 0
}
func parseMessage(message string) (HKID, HCID, string, string) {
	var Message map[string]interface{}

	err := json.Unmarshal([]byte(message), &Message)
	if err != nil {
		log.Printf("Error %s\n", err)
	}

	hcid := HCID{}
	if Message["hcid"] != nil {
		hcid, err = HcidFromHex(Message["hcid"].(string))
	}
	if err != nil {
		log.Printf("Error with hex to string %s", err)
	}

	hkid := HKID{}
	if Message["hkid"] != nil {
		hkid, err = HkidFromHex(Message["hkid"].(string))
	}
	if err != nil {
		log.Printf("Error with hex to string %s", err)
	}
	typeString := ""
	if Message["type"] != nil {
		typeString = Message["type"].(string)
	}
	nameSegment := ""
	if Message["nameSegment"] != nil {
		nameSegment = Message["nameSegment"].(string)
	}
	return hkid, hcid, typeString, nameSegment
}

func responseAvaiable(hkid HKID, hcid HCID, typeString string, nameSegment string) (available bool, version int64) {

	if typeString == "blob" {
		if hcid == nil {
			log.Printf("Malformed json")
			return
		}
		available = blobAvailable(hcid)
		version = 0
		return

		//Might wanna validate laterrrr
	} else if typeString == "commit" {
		if hkid == nil {
			log.Printf("Malformed json")
			return
		}
		available, version = commitAvailable(hkid)
		return
		//localfileserviceInstance.getCommit(h)
	} else if typeString == "tag" {
		if hkid == nil || nameSegment == "" {
			log.Printf("Malformed json")
			return
		}
		available, version = tagAvailable(hkid, nameSegment)
		return
		//localfileserviceInstance.getTag(h, nameSegment.(string))
	} else if typeString == "key" {
		if hkid == nil {
			log.Printf("Malformed json")
			return
		}
		available = keyAvailable(hkid)
		version = 0
		return
		//localfileserviceInstance.getKey(h)
	} else {
		log.Printf("Malformed json")
		return
	}
}
func buildResponse(hkid HKID, hcid HCID, typeString string, nameSegment string, version int64) (response string) {
	if typeString == "blob" {
		response = fmt.Sprintf("{\"type\": \"blob\", \"HCID\": \"%s\", \"URL\": \"%s\"}", hcid.Hex(),
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else if typeString == "commit" {
		response = fmt.Sprintf("{\"type\": \"commit\",\"HKID\": \"%s\", \"URL\": \"%s\"}", hkid.Hex(),
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else if typeString == "tag" {
		response = fmt.Sprintf("{\"type\": \"tag\", \"HKID\": \"%s\", \"namesegment\": \"%s\", \"URL\": \"%s\"}", hkid.Hex(), nameSegment,
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else if typeString == "key" {
		response = fmt.Sprintf("{\"type\": \"key\",\"HKID\": \"%s\", \"URL\": \"%s\"}", hkid.Hex(),
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else {
		return ""
	}
	return response

}
func getHostName() string {
	//ToDo
	return "localhost:8080"
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		log.Printf("Something meaningful... %s\n", err)
		return "localhost:8080"
	}
	for _, addr := range addrs {
		log.Printf("Network:%s  \nString:%s\n", addr.Network(), addr.String())
	}
	return "LAME"

}
func makeURL(hkid HKID, hcid HCID, typeString string, nameSegment string, version int64) (response string) {
	//Host Name
	host := getHostName()
	//Path
	if typeString == "blob" {
		response = fmt.Sprintf("%s/b/%s", host, hcid.Hex())
	} else if typeString == "commit" {
		response = fmt.Sprintf("%s/c/%s/%d", host, hkid.Hex(), version)
	} else if typeString == "tag" {
		response = fmt.Sprintf("%s/t/%s/%s/%d", host, hkid.Hex(), nameSegment, version)
	} else if typeString == "key" {
		response = fmt.Sprintf("%s/k/%s", host, hkid.Hex())
	} else {
		response = ""
	}
	return response
}
<commit_msg>Added variable names for parsemessage function<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	//"net"
)

//checks if I have the blob, it returns yes or no
func blobAvailable(hash HCID) bool {
	localfileserviceInstance.GetBlob(hash)
	return false
}

////checks if I have the key, it returns yes or no
func keyAvailable(hash HKID) bool {
	return false
}

//checks if I have the tag, it returns yes or no and the latest version
func tagAvailable(hash HKID, name string) (bool, int64) {
	return false, 0
}

//checks if I have the commit, it returns yes or no and the latest version
func commitAvailable(hash HKID) (bool, int64) {
	return false, 0
}
func parseMessage(message string) (hkid HKID, hcid HCID, typestring string, namesegment string) {
	var Message map[string]interface{}

	err := json.Unmarshal([]byte(message), &Message)
	if err != nil {
		log.Printf("Error %s\n", err)
	}

	if Message["hcid"] != nil {
		hcid, err = HcidFromHex(Message["hcid"].(string))
	}
	if err != nil {
		log.Printf("Error with hex to string %s", err)
	}

	if Message["hkid"] != nil {
		hkid, err = HkidFromHex(Message["hkid"].(string))
	}
	if err != nil {
		log.Printf("Error with hex to string %s", err)
	}
	typeString := ""
	if Message["type"] != nil {
		typeString = Message["type"].(string)
	}
	nameSegment := ""
	if Message["nameSegment"] != nil {
		nameSegment = Message["nameSegment"].(string)
	}
	return hkid, hcid, typeString, nameSegment
}

func responseAvaiable(hkid HKID, hcid HCID, typeString string, nameSegment string) (available bool, version int64) {

	if typeString == "blob" {
		if hcid == nil {
			log.Printf("Malformed json")
			return
		}
		available = blobAvailable(hcid)
		version = 0
		return

		//Might wanna validate laterrrr
	} else if typeString == "commit" {
		if hkid == nil {
			log.Printf("Malformed json")
			return
		}
		available, version = commitAvailable(hkid)
		return
		//localfileserviceInstance.getCommit(h)
	} else if typeString == "tag" {
		if hkid == nil || nameSegment == "" {
			log.Printf("Malformed json")
			return
		}
		available, version = tagAvailable(hkid, nameSegment)
		return
		//localfileserviceInstance.getTag(h, nameSegment.(string))
	} else if typeString == "key" {
		if hkid == nil {
			log.Printf("Malformed json")
			return
		}
		available = keyAvailable(hkid)
		version = 0
		return
		//localfileserviceInstance.getKey(h)
	} else {
		log.Printf("Malformed json")
		return
	}
}
func buildResponse(hkid HKID, hcid HCID, typeString string, nameSegment string, version int64) (response string) {
	if typeString == "blob" {
		response = fmt.Sprintf("{\"type\": \"blob\", \"HCID\": \"%s\", \"URL\": \"%s\"}", hcid.Hex(),
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else if typeString == "commit" {
		response = fmt.Sprintf("{\"type\": \"commit\",\"HKID\": \"%s\", \"URL\": \"%s\"}", hkid.Hex(),
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else if typeString == "tag" {
		response = fmt.Sprintf("{\"type\": \"tag\", \"HKID\": \"%s\", \"namesegment\": \"%s\", \"URL\": \"%s\"}", hkid.Hex(), nameSegment,
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else if typeString == "key" {
		response = fmt.Sprintf("{\"type\": \"key\",\"HKID\": \"%s\", \"URL\": \"%s\"}", hkid.Hex(),
			makeURL(hkid, hcid, typeString, nameSegment, version))
	} else {
		return ""
	}
	return response

}
func getHostName() string {
	//ToDo
	//return "224.0.1.20:5354"
	return "localhost:8080"
	//addrs, err := net.InterfaceAddrs()
	//if err != nil {
	//	log.Printf("Something meaningful... %s\n", err)
	//	return "localhost:8080"
	//}
	//for _, addr := range addrs {
	//	log.Printf("Network:%s  \nString:%s\n", addr.Network(), addr.String())
	//}
	//return "LAME"

}
func makeURL(hkid HKID, hcid HCID, typeString string, nameSegment string, version int64) (response string) {
	//Host Name
	host := getHostName()
	//Path
	if typeString == "blob" {
		response = fmt.Sprintf("%s/b/%s", host, hcid.Hex())
	} else if typeString == "commit" {
		response = fmt.Sprintf("%s/c/%s/%d", host, hkid.Hex(), version)
	} else if typeString == "tag" {
		response = fmt.Sprintf("%s/t/%s/%s/%d", host, hkid.Hex(), nameSegment, version)
	} else if typeString == "key" {
		response = fmt.Sprintf("%s/k/%s", host, hkid.Hex())
	} else {
		response = ""
	}
	return response
}
<|endoftext|>


<commit_before>package tcp

import (
	"encoding/binary"
	"io"
	"net"
	"runtime"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/eliothedeman/bangarang/event"
	"github.com/eliothedeman/bangarang/provider"
)

const START_HANDSHAKE = "BANGARANG: TCP_PROVIDER"

func init() {
	provider.LoadEventProviderFactory("tcp", NewTCPProvider)
}

// provides events from tcp connections
type TCPProvider struct {
	encoding string
	pool     *event.EncodingPool
	laddr    *net.TCPAddr
	listener *net.TCPListener
}

func NewTCPProvider() provider.EventProvider {
	return &TCPProvider{}
}

// the config struct for the tcp provider
type TCPConfig struct {
	Encoding    string `json:"encoding"`
	Listen      string `json:"listen"`
	MaxDecoders int    `json:"max_decoders"`
}

func (t *TCPProvider) Init(i interface{}) error {
	c := i.(*TCPConfig)

	// make sure we have a valid address
	addr, err := net.ResolveTCPAddr("tcp4", c.Listen)
	if err != nil {
		return err
	}

	t.laddr = addr

	// build an encoding pool
	t.pool = event.NewEncodingPool(event.EncoderFactories[c.Encoding], event.DecoderFactories[c.Encoding], c.MaxDecoders)
	return nil
}

func (t *TCPProvider) ConfigStruct() interface{} {
	return &TCPConfig{
		Encoding:    event.ENCODING_TYPE_JSON,
		MaxDecoders: runtime.NumCPU(),
	}
}

// start accepting connections and consume each of them as they come in
func (t *TCPProvider) Start(p event.Passer) {

	logrus.Infof("TCP Provider listening on %s", t.laddr.String())
	// start listening on that addr
	err := t.listen()
	if err != nil {
		logrus.Error(err)
		return
	}

	go func() {
		// listen for ever
		for {
			c, err := t.listener.AcceptTCP()
			if err != nil {
				logrus.Errorf("Cannot accept new tcp connection %s", err.Error())
			} else {
				// consume the connection
				logrus.Infof("Accpeted new tcp connection from %s", c.RemoteAddr().String())
				go t.consume(c, p)
			}
		}
	}()
}

func readFull(conn *net.TCPConn, buff []byte) error {
	off := 0
	slp := time.Millisecond
	for off < len(buff) {
		n, err := conn.Read(buff[off:])
		if err != nil {
			return err
		}

		// exponentially back off if we don't have anything
		if n == 0 {
			slp = slp * 2
			time.Sleep(slp)
		}
		off += n
	}
	return nil
}

func (t *TCPProvider) consume(conn *net.TCPConn, p event.Passer) {
	buff := make([]byte, 1024*200)
	var size_buff = make([]byte, 8)
	var nextEventSize uint64
	var err error

	// write the start of the handshake so the client can verify this is a bangarang client
	conn.Write([]byte(START_HANDSHAKE))
	for {

		// read the size of the next event
		err = readFull(conn, size_buff)
		if err != nil {

			if err == io.EOF {
				time.Sleep(50 * time.Millisecond)
			} else {
				logrus.Error(err)
				return
			}
		} else {

			nextEventSize = binary.LittleEndian.Uint64(size_buff)

			// read the next event
			err = readFull(conn, buff[:nextEventSize])
			if err != nil {
				logrus.Error(err)
				conn.Close()
				return
			}
			e := &event.Event{}

			err = t.pool.Decode(buff[:nextEventSize], e)

			if err != nil {
				logrus.Error(err, string(buff[:nextEventSize]))
			} else {
				p.Pass(e)
			}
		}
	}
}

func (t *TCPProvider) listen() error {
	l, err := net.ListenTCP("tcp", t.laddr)
	if err != nil {
		logrus.Error(err)
		return err
	}

	t.listener = l
	return nil
}
<commit_msg>fixed tcp waiting functionality<commit_after>package tcp

import (
	"encoding/binary"
	"io"
	"net"
	"runtime"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/eliothedeman/bangarang/event"
	"github.com/eliothedeman/bangarang/provider"
)

const START_HANDSHAKE = "BANGARANG: TCP_PROVIDER"

func init() {
	provider.LoadEventProviderFactory("tcp", NewTCPProvider)
}

// provides events from tcp connections
type TCPProvider struct {
	encoding string
	pool     *event.EncodingPool
	laddr    *net.TCPAddr
	listener *net.TCPListener
}

func NewTCPProvider() provider.EventProvider {
	return &TCPProvider{}
}

// the config struct for the tcp provider
type TCPConfig struct {
	Encoding    string `json:"encoding"`
	Listen      string `json:"listen"`
	MaxDecoders int    `json:"max_decoders"`
}

func (t *TCPProvider) Init(i interface{}) error {
	c := i.(*TCPConfig)

	// make sure we have a valid address
	addr, err := net.ResolveTCPAddr("tcp4", c.Listen)
	if err != nil {
		return err
	}

	t.laddr = addr

	// build an encoding pool
	t.pool = event.NewEncodingPool(event.EncoderFactories[c.Encoding], event.DecoderFactories[c.Encoding], c.MaxDecoders)
	return nil
}

func (t *TCPProvider) ConfigStruct() interface{} {
	return &TCPConfig{
		Encoding:    event.ENCODING_TYPE_JSON,
		MaxDecoders: runtime.NumCPU(),
	}
}

// start accepting connections and consume each of them as they come in
func (t *TCPProvider) Start(p event.Passer) {

	logrus.Infof("TCP Provider listening on %s", t.laddr.String())
	// start listening on that addr
	err := t.listen()
	if err != nil {
		logrus.Error(err)
		return
	}

	go func() {
		// listen for ever
		for {
			c, err := t.listener.AcceptTCP()
			if err != nil {
				logrus.Errorf("Cannot accept new tcp connection %s", err.Error())
			} else {
				// consume the connection
				logrus.Infof("Accpeted new tcp connection from %s", c.RemoteAddr().String())
				go t.consume(c, p)
			}
		}
	}()
}

func readFull(conn *net.TCPConn, buff []byte) error {
	off := 0
	slp := time.Millisecond
	for off < len(buff) {
		n, err := conn.Read(buff[off:])
		if err != nil {
			return err
		}

		// exponentially back off if we don't have anything
		if n == 0 {
			slp = slp * 2
			time.Sleep(slp)
		} else {

			// reset the sleep timer
			slp = time.Millisecond
		}
		off += n
	}
	return nil
}

func (t *TCPProvider) consume(conn *net.TCPConn, p event.Passer) {
	buff := make([]byte, 1024*200)
	var size_buff = make([]byte, 8)
	var nextEventSize uint64
	var err error

	// write the start of the handshake so the client can verify this is a bangarang client
	conn.Write([]byte(START_HANDSHAKE))
	for {

		// read the size of the next event
		err = readFull(conn, size_buff)
		if err != nil {

			if err == io.EOF {
				time.Sleep(50 * time.Millisecond)
			} else {
				logrus.Error(err)
				return
			}
		} else {

			nextEventSize = binary.LittleEndian.Uint64(size_buff)

			// read the next event
			err = readFull(conn, buff[:nextEventSize])
			if err != nil {
				logrus.Error(err)
				conn.Close()
				return
			}
			e := &event.Event{}

			err = t.pool.Decode(buff[:nextEventSize], e)

			if err != nil {
				logrus.Error(err, string(buff[:nextEventSize]))
			} else {
				p.Pass(e)
			}
		}
	}
}

func (t *TCPProvider) listen() error {
	l, err := net.ListenTCP("tcp", t.laddr)
	if err != nil {
		logrus.Error(err)
		return err
	}

	t.listener = l
	return nil
}
<|endoftext|>


<commit_before>package core

import (
	"errors"
	"testing"

	"github.com/elves/elvish/edit/ui"
	"github.com/elves/elvish/styled"
	"github.com/elves/elvish/tt"
)

var Args = tt.Args

func TestRenderers(t *testing.T) {
	tt.Test(t, tt.Fn("ui.Render", ui.Render), tt.Table{
		// mainRenderer: No modeline, no listing, enough height - result is the
		// same as bufCode
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeMode{},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer()),

		// mainRenderer: No modeline, no listing, not enough height - show
		// lines close to where the dot is on
		Args(&mainRenderer{
			maxHeight: 2,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").Newline().
				WriteUnstyled("line 3").SetDotToCursor().Buffer(),
			mode: &fakeMode{},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").Newline().
				WriteUnstyled("line 3").SetDotToCursor().Buffer()),

		// mainRenderer: No modeline, no listing, height = 1: show current line
		// of code area
		Args(&mainRenderer{
			maxHeight: 1,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Newline().
				WriteUnstyled("line 3").Buffer(),
			mode: &fakeMode{},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Buffer()),

		// mainRenderer: Modeline, no listing, enough height - result is the
		// bufCode + bufMode
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Buffer()),

		// mainRenderer: Modeline, no listing, modeline fits, but not enough
		// height to show all of code area: trim code area
		Args(&mainRenderer{
			maxHeight: 2,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Buffer()),

		// mainRenderer: Modeline, no listing, cannot fit all of modeline
		// without hiding code area: trim both modeline and code area
		Args(&mainRenderer{
			maxHeight: 2,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE", "MODE 2"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Buffer()),

		// mainRenderer: Modeline, no listing, height = 1. Show current line in
		// code area.
		Args(&mainRenderer{
			maxHeight: 1,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE", "MODE 2"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Buffer()),

		// mainRenderer: Listing when there is enough height. Use the remaining
		// height after showing modeline and code area for listing.
		Args(&mainRenderer{
			maxHeight: 4,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Buffer(),
			mode: &fakeListingMode{
				fakeMode{
					modeLine: &linesRenderer{[]string{"MODE"}},
				},
				[]string{"list 1", "list 2", "list 3", "list 4"},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Newline().
				WriteUnstyled("list 1").Newline().
				WriteUnstyled("list 2").Buffer()),

		// mainRenderer: Listing when code area + modeline already takes up all
		// height. No listing is shown.
		Args(&mainRenderer{
			maxHeight: 4,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Newline().
				WriteUnstyled("code 2").Buffer(),
			mode: &fakeListingMode{
				fakeMode{
					modeLine: &linesRenderer{[]string{"MODE 1", "MODE 2"}},
				},
				[]string{"list 1", "list 2", "list 3", "list 4"},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Newline().
				WriteUnstyled("code 2").Newline().
				WriteUnstyled("MODE 1").Newline().
				WriteUnstyled("MODE 2").Buffer()),

		// mainRenderer: CursorOnModeLine
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine:       &linesRenderer{[]string{"MODE"}},
				modeRenderFlag: CursorOnModeLine,
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").Newline().
				SetDotToCursor().WriteUnstyled("MODE").Buffer()),

		// mainRenderer: No RedrawModeLineAfterList
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeListingModeWithModeline{},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Newline().
				WriteUnstyled("#1").Buffer()),

		// mainRenderer: RedrawModeLineAfterList
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeListingModeWithModeline{
				fakeMode: fakeMode{modeRenderFlag: RedrawModeLineAfterList},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Newline().
				WriteUnstyled("#2").Buffer()),

		// codeContentRenderer: Prompt and code, with indentation
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdefg"}}, dot: 7,
			prompt: styled.Text{styled.Segment{Text: "> "}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				SetIndent(2).
				SetEagerWrap(true).
				WriteUnstyled("> abcdefg").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Multi-line prompt and code, without indentation
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdefg"}}, dot: 7,
			prompt: styled.Text{styled.Segment{Text: ">\n"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				// No indent as the prompt is multi-line
				SetEagerWrap(true).
				WriteUnstyled(">\n").
				WriteUnstyled("abcdefg").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Long prompt and code, without indentation
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdefg"}}, dot: 7,
			prompt: styled.Text{styled.Segment{Text: ">>> "}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				// No indent as the prompt is too long
				SetEagerWrap(true).
				WriteUnstyled(">>> abcdefg").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Visible rprompt
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abc"}}, dot: 3,
			rprompt: styled.Text{styled.Segment{Text: "RP"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("abc").
				SetDotToCursor().
				WriteUnstyled("  RP").
				Buffer()),

		// codeContentRenderer: Rprompt hidden as no padding available (negative
		// padding)
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdef"}}, dot: 6,
			rprompt: styled.Text{styled.Segment{Text: "RP"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("abcdef").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Rprompt hidden as no padding available (zero
		// padding)
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcde"}}, dot: 5,
			rprompt: styled.Text{styled.Segment{Text: "RP"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("abcde").
				SetDotToCursor().
				Buffer()),

		Args(&linesRenderer{[]string{
			"note 1", "long note 2",
		}}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("note 1\n").
				WriteUnstyled("long note 2").
				Buffer()),

		Args(&codeErrorsRenderer{[]error{
			errors.New("error 1"),
			errors.New("long error 2"),
		}}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("error 1\n").
				WriteUnstyled("long error 2").
				Buffer()),
	})
}

func TestFindWindow(t *testing.T) {
	tt.Test(t, tt.Fn("findWindow", findWindow), tt.Table{
		Args(0, 10, 3).Rets(0, 3),
		Args(1, 10, 3).Rets(0, 3),
		Args(5, 10, 3).Rets(4, 7),
		Args(9, 10, 3).Rets(7, 10),
		Args(10, 10, 3).Rets(7, 10),
	})
}
<commit_msg>newedit/core: Slightly simplify some test cases.<commit_after>package core

import (
	"errors"
	"testing"

	"github.com/elves/elvish/edit/ui"
	"github.com/elves/elvish/styled"
	"github.com/elves/elvish/tt"
)

var Args = tt.Args

func TestRenderers(t *testing.T) {
	tt.Test(t, tt.Fn("ui.Render", ui.Render), tt.Table{
		// mainRenderer: No modeline, no listing, enough height - result is the
		// same as bufCode
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer()),

		// mainRenderer: No modeline, no listing, not enough height - show
		// lines close to where the dot is on
		Args(&mainRenderer{
			maxHeight: 2,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").Newline().
				WriteUnstyled("line 3").SetDotToCursor().Buffer(),
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").Newline().
				WriteUnstyled("line 3").SetDotToCursor().Buffer()),

		// mainRenderer: No modeline, no listing, height = 1: show current line
		// of code area
		Args(&mainRenderer{
			maxHeight: 1,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Newline().
				WriteUnstyled("line 3").Buffer(),
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Buffer()),

		// mainRenderer: Modeline, no listing, enough height - result is the
		// bufCode + bufMode
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Buffer()),

		// mainRenderer: Modeline, no listing, modeline fits, but not enough
		// height to show all of code area: trim code area
		Args(&mainRenderer{
			maxHeight: 2,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Buffer()),

		// mainRenderer: Modeline, no listing, cannot fit all of modeline
		// without hiding code area: trim both modeline and code area
		Args(&mainRenderer{
			maxHeight: 2,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE", "MODE 2"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Buffer()),

		// mainRenderer: Modeline, no listing, height = 1. Show current line in
		// code area.
		Args(&mainRenderer{
			maxHeight: 1,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("line 1").Newline().
				WriteUnstyled("line 2").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine: &linesRenderer{[]string{"MODE", "MODE 2"}},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("line 2").SetDotToCursor().Buffer()),

		// mainRenderer: Listing when there is enough height. Use the remaining
		// height after showing modeline and code area for listing.
		Args(&mainRenderer{
			maxHeight: 4,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Buffer(),
			mode: &fakeListingMode{
				fakeMode{
					modeLine: &linesRenderer{[]string{"MODE"}},
				},
				[]string{"list 1", "list 2", "list 3", "list 4"},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Newline().
				WriteUnstyled("MODE").Newline().
				WriteUnstyled("list 1").Newline().
				WriteUnstyled("list 2").Buffer()),

		// mainRenderer: Listing when code area + modeline already takes up all
		// height. No listing is shown.
		Args(&mainRenderer{
			maxHeight: 4,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Newline().
				WriteUnstyled("code 2").Buffer(),
			mode: &fakeListingMode{
				fakeMode{
					modeLine: &linesRenderer{[]string{"MODE 1", "MODE 2"}},
				},
				[]string{"list 1", "list 2", "list 3", "list 4"},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("code 1").SetDotToCursor().Newline().
				WriteUnstyled("code 2").Newline().
				WriteUnstyled("MODE 1").Newline().
				WriteUnstyled("MODE 2").Buffer()),

		// mainRenderer: CursorOnModeLine
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeMode{
				modeLine:       &linesRenderer{[]string{"MODE"}},
				modeRenderFlag: CursorOnModeLine,
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").Newline().
				SetDotToCursor().WriteUnstyled("MODE").Buffer()),

		// mainRenderer: No RedrawModeLineAfterList
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeListingModeWithModeline{},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Newline().
				WriteUnstyled("#1").Buffer()),

		// mainRenderer: RedrawModeLineAfterList
		Args(&mainRenderer{
			maxHeight: 10,
			bufCode: ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Buffer(),
			mode: &fakeListingModeWithModeline{
				fakeMode: fakeMode{modeRenderFlag: RedrawModeLineAfterList},
			},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("some code").SetDotToCursor().Newline().
				WriteUnstyled("#2").Buffer()),

		// codeContentRenderer: Prompt and code, with indentation
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdefg"}}, dot: 7,
			prompt: styled.Text{styled.Segment{Text: "> "}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				SetIndent(2).
				SetEagerWrap(true).
				WriteUnstyled("> abcdefg").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Multi-line prompt and code, without indentation
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdefg"}}, dot: 7,
			prompt: styled.Text{styled.Segment{Text: ">\n"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				// No indent as the prompt is multi-line
				SetEagerWrap(true).
				WriteUnstyled(">\n").
				WriteUnstyled("abcdefg").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Long prompt and code, without indentation
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdefg"}}, dot: 7,
			prompt: styled.Text{styled.Segment{Text: ">>> "}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				// No indent as the prompt is too long
				SetEagerWrap(true).
				WriteUnstyled(">>> abcdefg").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Visible rprompt
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abc"}}, dot: 3,
			rprompt: styled.Text{styled.Segment{Text: "RP"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("abc").
				SetDotToCursor().
				WriteUnstyled("  RP").
				Buffer()),

		// codeContentRenderer: Rprompt hidden as no padding available (negative
		// padding)
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcdef"}}, dot: 6,
			rprompt: styled.Text{styled.Segment{Text: "RP"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("abcdef").
				SetDotToCursor().
				Buffer()),

		// codeContentRenderer: Rprompt hidden as no padding available (zero
		// padding)
		Args(&codeContentRenderer{
			code: styled.Text{styled.Segment{Text: "abcde"}}, dot: 5,
			rprompt: styled.Text{styled.Segment{Text: "RP"}},
		}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("abcde").
				SetDotToCursor().
				Buffer()),

		Args(&linesRenderer{[]string{
			"note 1", "long note 2",
		}}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("note 1\n").
				WriteUnstyled("long note 2").
				Buffer()),

		Args(&codeErrorsRenderer{[]error{
			errors.New("error 1"),
			errors.New("long error 2"),
		}}, 7).
			Rets(ui.NewBufferBuilder(7).
				WriteUnstyled("error 1\n").
				WriteUnstyled("long error 2").
				Buffer()),
	})
}

func TestFindWindow(t *testing.T) {
	tt.Test(t, tt.Fn("findWindow", findWindow), tt.Table{
		Args(0, 10, 3).Rets(0, 3),
		Args(1, 10, 3).Rets(0, 3),
		Args(5, 10, 3).Rets(4, 7),
		Args(9, 10, 3).Rets(7, 10),
		Args(10, 10, 3).Rets(7, 10),
	})
}
<|endoftext|>


<commit_before>package service

import (
	"context"
	"crypto/sha1"
	"fmt"
	"io"
	"time"

	"github.com/builderscon/octav/octav/cache"
	"github.com/builderscon/octav/octav/db"
	"github.com/builderscon/octav/octav/model"
	"github.com/builderscon/octav/octav/tools"
	pdebug "github.com/lestrrat/go-pdebug"
	urlenc "github.com/lestrrat/go-urlenc"
	"github.com/pkg/errors"
)

func (v *BlogEntrySvc) Init() {}

func (v *BlogEntrySvc) populateRowForCreate(vdb *db.BlogEntry, payload *model.CreateBlogEntryRequest) error {
	vdb.EID = tools.UUID()
	vdb.ConferenceID = payload.ConferenceID
	vdb.Title = payload.Title
	vdb.URL = payload.URL

	h := sha1.New()
	io.WriteString(h, payload.URL)
	vdb.URLHash = fmt.Sprintf("%x", (h.Sum(nil)))
	return nil
}

func (v *BlogEntrySvc) populateRowForUpdate(vdb *db.BlogEntry, payload *model.UpdateBlogEntryRequest) error {
	if payload.Title.Valid() {
		vdb.Title = payload.Title.String
	}
	if payload.URL.Valid() {
		vdb.URL = payload.URL.String
	}
	return nil
}

func (v *BlogEntrySvc) CreateFromPayload(ctx context.Context, tx *db.Tx, result *model.BlogEntry, payload *model.CreateBlogEntryRequest) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("BlogEntrySvc.CreateFromPayload").BindError(&err)
		defer g.End()
	}

	su := User()
	if err := su.IsConferenceAdministrator(tx, payload.ConferenceID, payload.UserID); err != nil {
		return errors.Wrap(err, "creating blog entries require conference administrator privileges")
	}

	var vdb db.BlogEntry
	if err := v.Create(tx, &vdb, payload); err != nil {
		return errors.Wrap(err, "failed to insert into database")
	}

	if result != nil {
		var m model.BlogEntry
		if err := m.FromRow(&vdb); err != nil {
			return errors.Wrap(err, "failed to populate model from database")
		}

		*result = m
	}
	return nil
}

func (v *BlogEntrySvc) DeleteFromPayload(ctx context.Context, tx *db.Tx, payload *model.DeleteBlogEntryRequest) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("BlogEntrySvc.DeleteFromPayload").BindError(&err)
		defer g.End()
	}

	var m model.BlogEntry
	if err := v.Lookup(tx, &m, payload.ID); err != nil {
		return errors.Wrap(err, "failed to look up blog entry")
	}

	su := User()
	if err := su.IsConferenceAdministrator(tx, m.ConferenceID, payload.UserID); err != nil {
		return errors.Wrap(err, "deleting blog entries requires conference administrator privilege")
	}

	if err := v.Delete(tx, payload.ID); err != nil {
		return errors.Wrap(err, "failed to delete session")
	}
	return nil
}

func (v *BlogEntrySvc) ListFromPayload(tx *db.Tx, result *model.BlogEntryList, payload *model.ListBlogEntriesRequest) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("BlogEntrySvc.ListFromPayload").BindError(&err)
		defer g.End()
	}

	status := payload.Status
	if len(status) == 0 {
		status = append(status, model.StatusPublic)
	}

	keybytes, err := urlenc.Marshal(payload)
	if err != nil {
		return errors.Wrap(err, "failed to marshal payload")
	}
	c := Cache()
	key := c.Key("BlogEntry", "ListFromPayload", string(keybytes))
	x, err := c.GetOrSet(key, result, func() (interface{}, error) {
		if pdebug.Enabled {
			pdebug.Printf("CACHE MISS: Re-generating")
		}

		var vdbl db.BlogEntryList
		if err := vdbl.LoadByConference(tx, payload.ConferenceID, status); err != nil {
			return nil, errors.Wrap(err, "failed to load from database")
		}

		l := make(model.BlogEntryList, len(vdbl))
		for i, vdb := range vdbl {
			if err := l[i].FromRow(&vdb); err != nil {
				return nil, errors.Wrap(err, "failed to populate model from database")
			}

			/*
				if err := v.Decorate(tx, &l[i], payload.TrustedCall, payload.Lang.String); err != nil {
					return nil, errors.Wrap(err, "failed to decorate session with associated data")
				}
			*/
		}

		return &l, nil
	}, cache.WithExpires(10*time.Minute))

	if err != nil {
		return err
	}

	*result = *(x.(*model.BlogEntryList))
	return nil

}
<commit_msg>normalize string<commit_after>package service

import (
	"context"
	"crypto/sha1"
	"fmt"
	"io"
	"net/url"
	"time"

	"github.com/builderscon/octav/octav/cache"
	"github.com/builderscon/octav/octav/db"
	"github.com/builderscon/octav/octav/model"
	"github.com/builderscon/octav/octav/tools"
	pdebug "github.com/lestrrat/go-pdebug"
	urlenc "github.com/lestrrat/go-urlenc"
	"github.com/pkg/errors"
)

func (v *BlogEntrySvc) Init() {}

func (v *BlogEntrySvc) populateRowForCreate(vdb *db.BlogEntry, payload *model.CreateBlogEntryRequest) error {
	vdb.EID = tools.UUID()
	vdb.ConferenceID = payload.ConferenceID
	vdb.Title = payload.Title

	// Parse the URL, and do away with the URL fragment, if any
	u, err := url.Parse(payload.URL)
	if err != nil {
		return errors.Wrap(err, "failed to parse URL")
	}
	u.Fragment = ""
	vdb.URL = u.String()

	h := sha1.New()
	io.WriteString(h, payload.URL)
	vdb.URLHash = fmt.Sprintf("%x", (h.Sum(nil)))
	return nil
}

func (v *BlogEntrySvc) populateRowForUpdate(vdb *db.BlogEntry, payload *model.UpdateBlogEntryRequest) error {
	if payload.Title.Valid() {
		vdb.Title = payload.Title.String
	}
	if payload.URL.Valid() {
		vdb.URL = payload.URL.String
	}
	return nil
}

func (v *BlogEntrySvc) CreateFromPayload(ctx context.Context, tx *db.Tx, result *model.BlogEntry, payload *model.CreateBlogEntryRequest) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("BlogEntrySvc.CreateFromPayload").BindError(&err)
		defer g.End()
	}

	su := User()
	if err := su.IsConferenceAdministrator(tx, payload.ConferenceID, payload.UserID); err != nil {
		return errors.Wrap(err, "creating blog entries require conference administrator privileges")
	}

	var vdb db.BlogEntry
	if err := v.Create(tx, &vdb, payload); err != nil {
		return errors.Wrap(err, "failed to insert into database")
	}

	if result != nil {
		var m model.BlogEntry
		if err := m.FromRow(&vdb); err != nil {
			return errors.Wrap(err, "failed to populate model from database")
		}

		*result = m
	}
	return nil
}

func (v *BlogEntrySvc) DeleteFromPayload(ctx context.Context, tx *db.Tx, payload *model.DeleteBlogEntryRequest) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("BlogEntrySvc.DeleteFromPayload").BindError(&err)
		defer g.End()
	}

	var m model.BlogEntry
	if err := v.Lookup(tx, &m, payload.ID); err != nil {
		return errors.Wrap(err, "failed to look up blog entry")
	}

	su := User()
	if err := su.IsConferenceAdministrator(tx, m.ConferenceID, payload.UserID); err != nil {
		return errors.Wrap(err, "deleting blog entries requires conference administrator privilege")
	}

	if err := v.Delete(tx, payload.ID); err != nil {
		return errors.Wrap(err, "failed to delete session")
	}
	return nil
}

func (v *BlogEntrySvc) ListFromPayload(tx *db.Tx, result *model.BlogEntryList, payload *model.ListBlogEntriesRequest) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("BlogEntrySvc.ListFromPayload").BindError(&err)
		defer g.End()
	}

	status := payload.Status
	if len(status) == 0 {
		status = append(status, model.StatusPublic)
	}

	keybytes, err := urlenc.Marshal(payload)
	if err != nil {
		return errors.Wrap(err, "failed to marshal payload")
	}
	c := Cache()
	key := c.Key("BlogEntry", "ListFromPayload", string(keybytes))
	x, err := c.GetOrSet(key, result, func() (interface{}, error) {
		if pdebug.Enabled {
			pdebug.Printf("CACHE MISS: Re-generating")
		}

		var vdbl db.BlogEntryList
		if err := vdbl.LoadByConference(tx, payload.ConferenceID, status); err != nil {
			return nil, errors.Wrap(err, "failed to load from database")
		}

		l := make(model.BlogEntryList, len(vdbl))
		for i, vdb := range vdbl {
			if err := l[i].FromRow(&vdb); err != nil {
				return nil, errors.Wrap(err, "failed to populate model from database")
			}

			/*
				if err := v.Decorate(tx, &l[i], payload.TrustedCall, payload.Lang.String); err != nil {
					return nil, errors.Wrap(err, "failed to decorate session with associated data")
				}
			*/
		}

		return &l, nil
	}, cache.WithExpires(10*time.Minute))

	if err != nil {
		return err
	}

	*result = *(x.(*model.BlogEntryList))
	return nil

}
<|endoftext|>