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

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"v.io/jiri/jiri"
	"v.io/x/lib/gosh"
)

type upgradeTestCase struct {
	Args        []string
	Exist       bool
	Local, Want string
	Stderr      string
}

func TestUpgrade(t *testing.T) {
	tests := []upgradeTestCase{
		{
			Stderr: `must specify upgrade kind`,
		},
		{
			Args:   []string{"foo"},
			Stderr: `unknown upgrade kind "foo"`,
		},
		// Test v23 upgrades.
		{
			Args:   []string{"v23"},
			Exist:  true,
			Stderr: `.jiri_manifest already exists`,
		},
		{
			Args: []string{"v23"},
			Want: `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
    <import name="infrastructure"/>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="infrastructure" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
    <import name="infrastructure"/>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="infrastructure" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="private" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		// Test fuchsia upgrades.
		{
			Args:   []string{"fuchsia"},
			Exist:  true,
			Stderr: `.jiri_manifest already exists`,
		},
		{
			Args: []string{"fuchsia"},
			Want: `<manifest>
  <imports>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
    <import name="infrastructure"/>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
    <import manifest="infrastructure" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
    <import name="infrastructure"/>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
    <import manifest="infrastructure" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
    <import manifest="private" name="fnl-start" remote="https://github.com/effenel/fnl-start.git"/>
  </imports>
</manifest>
`,
		},
	}
	opts := gosh.Opts{Fatalf: t.Fatalf, Logf: t.Logf}
	sh := gosh.NewShell(opts)
	defer sh.Cleanup()
	jiriTool := sh.BuildGoPkg("v.io/jiri")
	for _, test := range tests {
		if err := testUpgrade(opts, jiriTool, test); err != nil {
			t.Errorf("%v: %v", test.Args, err)
		}
	}
}

func testUpgrade(opts gosh.Opts, jiriTool string, test upgradeTestCase) error {
	opts.PropagateChildOutput = true
	sh := gosh.NewShell(opts)
	defer sh.Cleanup()
	jiriRoot := sh.MakeTempDir()
	sh.Pushd(jiriRoot)
	// Set up an existing file or local_manifest, if they were specified
	if test.Exist {
		if err := ioutil.WriteFile(".jiri_manifest", []byte("<manifest/>"), 0644); err != nil {
			return err
		}
	}
	if test.Local != "" {
		if err := ioutil.WriteFile(".local_manifest", []byte(test.Local), 0644); err != nil {
			return err
		}
	}
	// Run upgrade and check the error.
	sh.Vars[jiri.RootEnv] = jiriRoot
	cmd := sh.Cmd(jiriTool, append([]string{"upgrade"}, test.Args...)...)
	if test.Stderr != "" {
		cmd.ExitErrorIsOk = true
	}
	_, stderr := cmd.StdoutStderr()
	if got, want := stderr, test.Stderr; !strings.Contains(got, want) || (got != "" && want == "") {
		return fmt.Errorf("stderr got %q, want substr %q", got, want)
	}
	// Make sure the right file is generated.
	if test.Want != "" {
		data, err := ioutil.ReadFile(".jiri_manifest")
		if err != nil {
			return err
		}
		if got, want := string(data), test.Want; got != want {
			return fmt.Errorf("GOT\n%s\nWANT\n%s", got, want)
		}
	}
	// Make sure the .local_manifest file is backed up.
	if test.Local != "" && test.Stderr == "" {
		data, err := ioutil.ReadFile(".local_manifest.BACKUP")
		if err != nil {
			return fmt.Errorf("local manifest backup got error: %v", err)
		}
		if got, want := string(data), test.Local; got != want {
			return fmt.Errorf("local manifest backup GOT\n%s\nWANT\n%s", got, want)
		}
	}
	return nil
}

func TestUpgradeRevert(t *testing.T) {
	sh := gosh.NewShell(gosh.Opts{Fatalf: t.Fatalf, Logf: t.Logf})
	defer sh.Cleanup()
	jiriRoot := sh.MakeTempDir()
	sh.Pushd(jiriRoot)
	jiriTool := sh.BuildGoPkg("v.io/jiri")
	localData := `<manifest/>`
	jiriData := `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`
	// Set up an existing local_manifest.
	if err := ioutil.WriteFile(".local_manifest", []byte(localData), 0644); err != nil {
		t.Errorf("couldn't write local manifest: %v", err)
	}
	// Run a regular upgrade first, and make sure files are as expected.
	sh.Vars[jiri.RootEnv] = jiriRoot
	sh.Cmd(jiriTool, "upgrade", "v23").Run()
	gotJiri, err := ioutil.ReadFile(".jiri_manifest")
	if err != nil {
		t.Errorf("couldn't read jiri manifest: %v", err)
	}
	if got, want := string(gotJiri), jiriData; got != want {
		t.Errorf("jiri manifest GOT\n%s\nWANT\n%s", got, want)
	}
	gotBackup, err := ioutil.ReadFile(".local_manifest.BACKUP")
	if err != nil {
		t.Errorf("couldn't read local manifest backup: %v", err)
	}
	if got, want := string(gotBackup), localData; got != want {
		t.Errorf("local manifest backup GOT\n%s\nWANT\n%s", got, want)
	}
	// Now run a revert, and make sure files are as expected.
	sh.Cmd(jiriTool, "upgrade", "-revert").Run()
	if _, err := os.Stat(".jiri_manifest"); !os.IsNotExist(err) {
		t.Errorf(".jiri_manifest still exists after revert: %v", err)
	}
	if _, err := os.Stat(".local_manifest.BACKUP"); !os.IsNotExist(err) {
		t.Errorf(".local_manifest.BACKUP still exists after revert: %v", err)
	}
	gotLocal, err := ioutil.ReadFile(".local_manifest")
	if err != nil {
		t.Errorf("couldn't read local manifest: %v", err)
	}
	if got, want := string(gotLocal), localData; got != want {
		t.Errorf("local manifest GOT\n%s\nWANT\n%s", got, want)
	}
}
<commit_msg>jiri: Fix failing TestUpgrade test.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"v.io/jiri/jiri"
	"v.io/x/lib/gosh"
)

type upgradeTestCase struct {
	Args        []string
	Exist       bool
	Local, Want string
	Stderr      string
}

func TestUpgrade(t *testing.T) {
	tests := []upgradeTestCase{
		{
			Stderr: `must specify upgrade kind`,
		},
		{
			Args:   []string{"foo"},
			Stderr: `unknown upgrade kind "foo"`,
		},
		// Test v23 upgrades.
		{
			Args:   []string{"v23"},
			Exist:  true,
			Stderr: `.jiri_manifest already exists`,
		},
		{
			Args: []string{"v23"},
			Want: `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
    <import name="infrastructure"/>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="infrastructure" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"v23"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
    <import name="infrastructure"/>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="infrastructure" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
    <import manifest="private" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`,
		},
		// Test fuchsia upgrades.
		{
			Args:   []string{"fuchsia"},
			Exist:  true,
			Stderr: `.jiri_manifest already exists`,
		},
		{
			Args: []string{"fuchsia"},
			Want: `<manifest>
  <imports>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="private"/>
    <import name="infrastructure"/>
    <import name="default"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="private" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
    <import manifest="infrastructure" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
  </imports>
</manifest>
`,
		},
		{
			Args: []string{"fuchsia"},
			Local: `<manifest>
  <imports>
    <import name="default"/>
    <import name="infrastructure"/>
    <import name="private"/>
  </imports>
</manifest>
`,
			Want: `<manifest>
  <imports>
    <import manifest="manifest/fuchsia" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
    <import manifest="infrastructure" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
    <import manifest="private" name="fnl-start" remote="https://fuchsia.googlesource.com/fnl-start"/>
  </imports>
</manifest>
`,
		},
	}
	opts := gosh.Opts{Fatalf: t.Fatalf, Logf: t.Logf}
	sh := gosh.NewShell(opts)
	defer sh.Cleanup()
	jiriTool := sh.BuildGoPkg("v.io/jiri")
	for _, test := range tests {
		if err := testUpgrade(opts, jiriTool, test); err != nil {
			t.Errorf("%v: %v", test.Args, err)
		}
	}
}

func testUpgrade(opts gosh.Opts, jiriTool string, test upgradeTestCase) error {
	opts.PropagateChildOutput = true
	sh := gosh.NewShell(opts)
	defer sh.Cleanup()
	jiriRoot := sh.MakeTempDir()
	sh.Pushd(jiriRoot)
	// Set up an existing file or local_manifest, if they were specified
	if test.Exist {
		if err := ioutil.WriteFile(".jiri_manifest", []byte("<manifest/>"), 0644); err != nil {
			return err
		}
	}
	if test.Local != "" {
		if err := ioutil.WriteFile(".local_manifest", []byte(test.Local), 0644); err != nil {
			return err
		}
	}
	// Run upgrade and check the error.
	sh.Vars[jiri.RootEnv] = jiriRoot
	cmd := sh.Cmd(jiriTool, append([]string{"upgrade"}, test.Args...)...)
	if test.Stderr != "" {
		cmd.ExitErrorIsOk = true
	}
	_, stderr := cmd.StdoutStderr()
	if got, want := stderr, test.Stderr; !strings.Contains(got, want) || (got != "" && want == "") {
		return fmt.Errorf("stderr got %q, want substr %q", got, want)
	}
	// Make sure the right file is generated.
	if test.Want != "" {
		data, err := ioutil.ReadFile(".jiri_manifest")
		if err != nil {
			return err
		}
		if got, want := string(data), test.Want; got != want {
			return fmt.Errorf("GOT\n%s\nWANT\n%s", got, want)
		}
	}
	// Make sure the .local_manifest file is backed up.
	if test.Local != "" && test.Stderr == "" {
		data, err := ioutil.ReadFile(".local_manifest.BACKUP")
		if err != nil {
			return fmt.Errorf("local manifest backup got error: %v", err)
		}
		if got, want := string(data), test.Local; got != want {
			return fmt.Errorf("local manifest backup GOT\n%s\nWANT\n%s", got, want)
		}
	}
	return nil
}

func TestUpgradeRevert(t *testing.T) {
	sh := gosh.NewShell(gosh.Opts{Fatalf: t.Fatalf, Logf: t.Logf})
	defer sh.Cleanup()
	jiriRoot := sh.MakeTempDir()
	sh.Pushd(jiriRoot)
	jiriTool := sh.BuildGoPkg("v.io/jiri")
	localData := `<manifest/>`
	jiriData := `<manifest>
  <imports>
    <import manifest="public" name="manifest" remote="https://vanadium.googlesource.com/manifest"/>
  </imports>
</manifest>
`
	// Set up an existing local_manifest.
	if err := ioutil.WriteFile(".local_manifest", []byte(localData), 0644); err != nil {
		t.Errorf("couldn't write local manifest: %v", err)
	}
	// Run a regular upgrade first, and make sure files are as expected.
	sh.Vars[jiri.RootEnv] = jiriRoot
	sh.Cmd(jiriTool, "upgrade", "v23").Run()
	gotJiri, err := ioutil.ReadFile(".jiri_manifest")
	if err != nil {
		t.Errorf("couldn't read jiri manifest: %v", err)
	}
	if got, want := string(gotJiri), jiriData; got != want {
		t.Errorf("jiri manifest GOT\n%s\nWANT\n%s", got, want)
	}
	gotBackup, err := ioutil.ReadFile(".local_manifest.BACKUP")
	if err != nil {
		t.Errorf("couldn't read local manifest backup: %v", err)
	}
	if got, want := string(gotBackup), localData; got != want {
		t.Errorf("local manifest backup GOT\n%s\nWANT\n%s", got, want)
	}
	// Now run a revert, and make sure files are as expected.
	sh.Cmd(jiriTool, "upgrade", "-revert").Run()
	if _, err := os.Stat(".jiri_manifest"); !os.IsNotExist(err) {
		t.Errorf(".jiri_manifest still exists after revert: %v", err)
	}
	if _, err := os.Stat(".local_manifest.BACKUP"); !os.IsNotExist(err) {
		t.Errorf(".local_manifest.BACKUP still exists after revert: %v", err)
	}
	gotLocal, err := ioutil.ReadFile(".local_manifest")
	if err != nil {
		t.Errorf("couldn't read local manifest: %v", err)
	}
	if got, want := string(gotLocal), localData; got != want {
		t.Errorf("local manifest GOT\n%s\nWANT\n%s", got, want)
	}
}
<|endoftext|>


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

// +build windows

// Package terminal provides support functions for dealing with terminals, as
// commonly found on UNIX systems.
//
// Putting a terminal into raw mode is the most common requirement:
//
// 	oldState, err := terminal.MakeRaw(0)
// 	if err != nil {
// 	        panic(err)
// 	}
// 	defer terminal.Restore(0, oldState)
package terminal

import (
	"os"

	"golang.org/x/sys/windows"
)

type State struct {
	mode uint32
}

// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
	var st uint32
	err := windows.GetConsoleMode(windows.Handle(fd), &st)
	return err == nil
}

// MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd int) (*State, error) {
	var st uint32
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
		return nil, err
	}
	raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
	if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
		return nil, err
	}
	return &State{st}, nil
}

// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
	var st uint32
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
		return nil, err
	}
	return &State{st}, nil
}

// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, state *State) error {
	return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}

// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
	var info windows.ConsoleScreenBufferInfo
	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
		return 0, 0, err
	}
	return int(info.Size.X), int(info.Size.Y), nil
}

// ReadPassword reads a line of input from a terminal without local echo.  This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
	var st uint32
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
		return nil, err
	}
	old := st

	st &^= (windows.ENABLE_ECHO_INPUT)
	st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
	if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
		return nil, err
	}

	defer func() {
		windows.SetConsoleMode(windows.Handle(fd), old)
	}()

	return readPasswordLine(os.NewFile(uintptr(fd), "stdin"))
}
<commit_msg>ssh/terminal: use duplicate handle in ReadPassword<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

// Package terminal provides support functions for dealing with terminals, as
// commonly found on UNIX systems.
//
// Putting a terminal into raw mode is the most common requirement:
//
// 	oldState, err := terminal.MakeRaw(0)
// 	if err != nil {
// 	        panic(err)
// 	}
// 	defer terminal.Restore(0, oldState)
package terminal

import (
	"os"

	"golang.org/x/sys/windows"
)

type State struct {
	mode uint32
}

// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
	var st uint32
	err := windows.GetConsoleMode(windows.Handle(fd), &st)
	return err == nil
}

// MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd int) (*State, error) {
	var st uint32
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
		return nil, err
	}
	raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
	if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
		return nil, err
	}
	return &State{st}, nil
}

// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
	var st uint32
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
		return nil, err
	}
	return &State{st}, nil
}

// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, state *State) error {
	return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}

// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
	var info windows.ConsoleScreenBufferInfo
	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
		return 0, 0, err
	}
	return int(info.Size.X), int(info.Size.Y), nil
}

// ReadPassword reads a line of input from a terminal without local echo.  This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
	var st uint32
	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
		return nil, err
	}
	old := st

	st &^= (windows.ENABLE_ECHO_INPUT)
	st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
	if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
		return nil, err
	}

	defer func() {
		windows.SetConsoleMode(windows.Handle(fd), old)
	}()

	var h windows.Handle
	p, _ := windows.GetCurrentProcess()
	if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
		return nil, err
	}

	f := os.NewFile(uintptr(h), "stdin")
	defer f.Close()
	return readPasswordLine(f)
}
<|endoftext|>


<commit_before>package utils

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/1l0/identicon"

	"github.com/eirka/eirka-libs/amazon"
)

// save an avatar
func (i *ImageType) SaveAvatar() (err error) {

	// for special handling
	i.avatar = true

	// check given file ext
	err = i.checkReqExt()
	if err != nil {
		return
	}

	// get file md5
	err = i.getMD5()
	if err != nil {
		return
	}

	// check file magic sig
	err = i.checkMagic()
	if err != nil {
		return
	}

	// videos cant be avatars
	if i.video {
		return errors.New("Format not supported")
	}

	// check image stats
	err = i.getStats()
	if err != nil {
		return
	}

	// save the file to disk
	err = i.saveFile()
	if err != nil {
		return
	}

	// create a thumbnail
	err = i.createThumbnail(200, 200)
	if err != nil {
		return
	}

	// copy the file to s3
	err = i.avatarToS3()
	if err != nil {
		return
	}

	return

}

// this will create a random avatar
func GenerateAvatar(uid uint) (err error) {

	img := ImageType{
		avatar:     true,
		OrigWidth:  420,
		OrigHeight: 420,
		Ext:        ".png",
		image:      new(bytes.Buffer),
		Ib:         uid,
		MD5:        "fake",
		mime:       "image/png",
	}

	id := identicon.New()

	// generate a random avatar
	err = id.GeneratePNG(img.image)
	if err != nil {
		return
	}

	// save the file to disk
	err = img.saveFile()
	if err != nil {
		return
	}

	// create a thumbnail
	err = img.createThumbnail(200, 200)
	if err != nil {
		return
	}

	// copy the file to s3
	err = img.avatarToS3()
	if err != nil {
		return
	}

	return
}

// uploads to the avatar folder
func (i *ImageType) avatarToS3() (err error) {

	s3 := amazon.New()

	err = s3.Save(i.Thumbpath, fmt.Sprintf("avatars/%s", i.Thumbnail), i.mime, true)
	if err != nil {
		return
	}

	return
}
<commit_msg>add random avatar when registering<commit_after>package utils

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/1l0/identicon"

	"github.com/eirka/eirka-libs/amazon"
)

// save an avatar
func (i *ImageType) SaveAvatar() (err error) {

	// for special handling
	i.avatar = true

	// check given file ext
	err = i.checkReqExt()
	if err != nil {
		return
	}

	// get file md5
	err = i.getMD5()
	if err != nil {
		return
	}

	// check file magic sig
	err = i.checkMagic()
	if err != nil {
		return
	}

	// videos cant be avatars
	if i.video {
		return errors.New("Format not supported")
	}

	// check image stats
	err = i.getStats()
	if err != nil {
		return
	}

	// save the file to disk
	err = i.saveFile()
	if err != nil {
		return
	}

	// create a thumbnail
	err = i.createThumbnail(200, 200)
	if err != nil {
		return
	}

	// copy the file to s3
	err = i.avatarToS3()
	if err != nil {
		return
	}

	return

}

// this will create a random avatar
func GenerateAvatar(uid uint) (err error) {

	img := ImageType{
		avatar:     true,
		OrigWidth:  420,
		OrigHeight: 420,
		Ext:        ".png",
		image:      new(bytes.Buffer),
		Ib:         uid,
		MD5:        "fake",
		mime:       "image/png",
	}

	// generates a random avatar
	id := identicon.New()
	// a colorful theme
	id.Theme = identicon.Free
	// put the output into our image buffer
	err = id.GeneratePNG(img.image)
	if err != nil {
		return
	}

	// save the file to disk
	err = img.saveFile()
	if err != nil {
		return
	}

	// create a thumbnail
	err = img.createThumbnail(200, 200)
	if err != nil {
		return
	}

	// copy the file to s3
	err = img.avatarToS3()
	if err != nil {
		return
	}

	return
}

// uploads to the avatar folder
func (i *ImageType) avatarToS3() (err error) {

	s3 := amazon.New()

	err = s3.Save(i.Thumbpath, fmt.Sprintf("avatars/%s", i.Thumbnail), i.mime, true)
	if err != nil {
		return
	}

	return
}
<|endoftext|>


<commit_before>package bitfinex

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"log"
	"net/http"
	"reflect"

	"github.com/bitfinexcom/bitfinex-api-go/utils"

	"github.com/gorilla/websocket"
)

// Pairs available
const (
	// Pairs
	BTCUSD = "BTCUSD"
	LTCUSD = "LTCUSD"
	LTCBTC = "LTCBTC"
	ETHUSD = "ETHUSD"
	ETHBTC = "ETHBTC"
	ETCUSD = "ETCUSD"
	ETCBTC = "ETCBTC"
	BFXUSD = "BFXUSD"
	BFXBTC = "BFXBTC"
	ZECUSD = "ZECUSD"
	ZECBTC = "ZECBTC"
	XMRUSD = "XMRUSD"
	XMRBTC = "XMRBTC"
	RRTUSD = "RRTUSD"
	RRTBTC = "RRTBTC"
	XRPUSD = "XRPUSD"
	XRPBTC = "XRPBTC"

	// Channels
	ChanBook   = "book"
	ChanTrade  = "trades"
	ChanTicker = "ticker"
)

// WebSocketService allow to connect and receive stream data
// from bitfinex.com ws service.
type WebSocketService struct {
	// http client
	client *Client
	// websocket client
	ws *websocket.Conn
	// special web socket for private messages
	privateWs *websocket.Conn
	// map internal channels to websocket's
	chanMap    map[float64]chan []float64
	subscribes []subscribeToChannel
}

type subscribeMsg struct {
	Event   string  `json:"event"`
	Channel string  `json:"channel"`
	Pair    string  `json:"pair"`
	ChanID  float64 `json:"chanId,omitempty"`
}

type subscribeToChannel struct {
	Channel string
	Pair    string
	Chan    chan []float64
}

// NewWebSocketService returns a WebSocketService using the given client.
func NewWebSocketService(c *Client) *WebSocketService {
	return &WebSocketService{
		client:     c,
		chanMap:    make(map[float64]chan []float64),
		subscribes: make([]subscribeToChannel, 0),
	}
}

// Connect create new bitfinex websocket connection
func (w *WebSocketService) Connect() error {
	var d = websocket.Dialer{
		Subprotocols:    []string{"p1", "p2"},
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		Proxy:           http.ProxyFromEnvironment,
	}

	if w.client.WebSocketTLSSkipVerify {
		d.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}

	ws, _, err := d.Dial(w.client.WebSocketURL, nil)
	if err != nil {
		return err
	}
	w.ws = ws
	return nil
}

// Close web socket connection
func (w *WebSocketService) Close() {
	w.ws.Close()
}

func (w *WebSocketService) AddSubscribe(channel string, pair string, c chan []float64) {
	s := subscribeToChannel{
		Channel: channel,
		Pair:    pair,
		Chan:    c,
	}
	w.subscribes = append(w.subscribes, s)
}

func (w *WebSocketService) ClearSubscriptions() {
	w.subscribes = make([]subscribeToChannel, 0)
}

func (w *WebSocketService) sendSubscribeMessages() error {
	for _, s := range w.subscribes {
		msg, _ := json.Marshal(subscribeMsg{
			Event:   "subscribe",
			Channel: s.Channel,
			Pair:    s.Pair,
		})

		err := w.ws.WriteMessage(websocket.TextMessage, msg)
		if err != nil {
			return err
		}
	}
	return nil
}

// Subscribe allows to subsribe to channels and watch for new updates.
// This method supports next channels: book, trade, ticker.
func (w *WebSocketService) Subscribe() error {
	// Subscribe to each channel
	if err := w.sendSubscribeMessages(); err != nil {
		return err
	}

	for {
		_, p, err := w.ws.ReadMessage()
		if err != nil {
			return err
		}

		if bytes.Contains(p, []byte("event")) {
			w.handleEventMessage(p)
		} else {
			w.handleDataMessage(p)
		}
	}

	return nil
}

func (w *WebSocketService) handleEventMessage(msg []byte) {
	// Check for first message(event:subscribed)
	event := &subscribeMsg{}
	err := json.Unmarshal(msg, event)

	// Received "subscribed" resposne. Link channels.
	if err == nil {
		for _, k := range w.subscribes {
			if event.Event == "subscribed" && event.Pair == k.Pair && event.Channel == k.Channel {
				w.chanMap[event.ChanID] = k.Chan
			}
		}
	}
}

func (w *WebSocketService) handleDataMessage(msg []byte) {
	// Received payload or data update
	var dataUpdate []float64
	err := json.Unmarshal(msg, &dataUpdate)
	if err == nil {
		chanID := dataUpdate[0]
		// Remove chanID from data update
		// and send message to internal chan
		w.chanMap[chanID] <- dataUpdate[1:]
	}

	// Payload received
	var fullPayload []interface{}
	err = json.Unmarshal(msg, &fullPayload)

	if err != nil {
		log.Println("Error decoding fullPayload", err)
	} else {
		if len(fullPayload) > 3 {
			itemsSlice := fullPayload[3:]
			i, _ := json.Marshal(itemsSlice)
			var item []float64
			err = json.Unmarshal(i, &item)
			if err == nil {
				chanID := fullPayload[0].(float64)
				w.chanMap[chanID] <- item
			}
		} else {
			itemsSlice := fullPayload[1]
			i, _ := json.Marshal(itemsSlice)
			var items [][]float64
			err = json.Unmarshal(i, &items)
			if err == nil {
				chanID := fullPayload[0].(float64)
				for _, v := range items {
					w.chanMap[chanID] <- v
				}
			}
		}
	}
}

/////////////////////////////
// Private websocket messages
/////////////////////////////

type privateConnect struct {
	Event       string `json:"event"`
	APIKey      string `json:"apiKey"`
	AuthSig     string `json:"authSig"`
	AuthPayload string `json:"authPayload"`
}

// Private channel auth response
type privateResponse struct {
	Event  string  `json:"event"`
	Status string  `json:"status"`
	ChanID float64 `json:"chanId,omitempty"`
	UserID float64 `json:"userId"`
}

type TermData struct {
	// Data term. E.g: ps, ws, ou, etc... See official documentation for more details.
	Term string
	// Data will contain different number of elements for each term.
	// Examples:
	// Term: ws, Data: ["exchange","BTC",0.01410829,0]
	// Term: oc, Data: [0,"BTCUSD",0,-0.01,"","CANCELED",270,0,"2015-10-15T11:26:13Z",0]
	Data  []interface{}
	Error string
}

func (c *TermData) HasError() bool {
	return len(c.Error) > 0
}

func (w *WebSocketService) ConnectPrivate(ch chan TermData) {

	var d = websocket.Dialer{
		Subprotocols:    []string{"p1", "p2"},
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		Proxy:           http.ProxyFromEnvironment,
	}

	if w.client.WebSocketTLSSkipVerify {
		d.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}

	ws, _, err := d.Dial(w.client.WebSocketURL, nil)
	if err != nil {
		ch <- TermData{
			Error: err.Error(),
		}
		return
	}

	nonce := utils.GetNonce()
	payload := "AUTH" + nonce
	connectMsg, _ := json.Marshal(&privateConnect{
		Event:       "auth",
		APIKey:      w.client.APIKey,
		AuthSig:     w.client.signPayload(payload),
		AuthPayload: payload,
	})

	// Send auth message
	err = ws.WriteMessage(websocket.TextMessage, connectMsg)
	if err != nil {
		ch <- TermData{
			Error: err.Error(),
		}
		ws.Close()
		return
	}

	for {
		_, p, err := ws.ReadMessage()
		if err != nil {
			ch <- TermData{
				Error: err.Error(),
			}
			ws.Close()
			return
		}

		event := &privateResponse{}
		err = json.Unmarshal(p, &event)
		if err != nil {
			// received data update
			var data []interface{}
			err = json.Unmarshal(p, &data)
			if err == nil {
				if len(data) == 2 { // Heartbeat
					// XXX: Consider adding a switch to enable/disable passing these along.
					ch <- TermData{Term: data[1].(string)}
					return
				}

				dataTerm := data[1].(string)
				dataList := data[2].([]interface{})

				// check for empty data
				if len(dataList) > 0 {
					if reflect.TypeOf(dataList[0]) == reflect.TypeOf([]interface{}{}) {
						// received list of lists
						for _, v := range dataList {
							ch <- TermData{
								Term: dataTerm,
								Data: v.([]interface{}),
							}
						}
					} else {
						// received flat list
						ch <- TermData{
							Term: dataTerm,
							Data: dataList,
						}
					}
				}
			}
		} else {
			// received auth response
			if event.Event == "auth" && event.Status != "OK" {
				ch <- TermData{
					Error: "Error connecting to private web socket channel.",
				}
				ws.Close()
			}
		}
	}
}
<commit_msg>added EOS, IOT, and BCC pairs<commit_after>package bitfinex

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"log"
	"net/http"
	"reflect"

	"github.com/bitfinexcom/bitfinex-api-go/utils"

	"github.com/gorilla/websocket"
)

// Pairs available
const (
	// Pairs
	BTCUSD = "BTCUSD"
	LTCUSD = "LTCUSD"
	LTCBTC = "LTCBTC"
	ETHUSD = "ETHUSD"
	ETHBTC = "ETHBTC"
	ETCUSD = "ETCUSD"
	ETCBTC = "ETCBTC"
	BFXUSD = "BFXUSD"
	BFXBTC = "BFXBTC"
	ZECUSD = "ZECUSD"
	ZECBTC = "ZECBTC"
	XMRUSD = "XMRUSD"
	XMRBTC = "XMRBTC"
	RRTUSD = "RRTUSD"
	RRTBTC = "RRTBTC"
	XRPUSD = "XRPUSD"
	XRPBTC = "XRPBTC"
	EOSETH = "EOSETH"
	EOSUSD = "EOSUSD"
	EOSBTC = "EOSBTC"
	IOTUSD = "IOTUSD"
	IOTBTC = "IOTBTC"
	IOTETH = "IOTETH"
	BCCBTC = "BCCBTC"
	BCUBTC = "BCUBTC"
	BCCUSD = "BCCUSD"
	BCUUSD = "BCUUSD"

	// Channels
	ChanBook   = "book"
	ChanTrade  = "trades"
	ChanTicker = "ticker"
)

// WebSocketService allow to connect and receive stream data
// from bitfinex.com ws service.
type WebSocketService struct {
	// http client
	client *Client
	// websocket client
	ws *websocket.Conn
	// special web socket for private messages
	privateWs *websocket.Conn
	// map internal channels to websocket's
	chanMap    map[float64]chan []float64
	subscribes []subscribeToChannel
}

type subscribeMsg struct {
	Event   string  `json:"event"`
	Channel string  `json:"channel"`
	Pair    string  `json:"pair"`
	ChanID  float64 `json:"chanId,omitempty"`
}

type subscribeToChannel struct {
	Channel string
	Pair    string
	Chan    chan []float64
}

// NewWebSocketService returns a WebSocketService using the given client.
func NewWebSocketService(c *Client) *WebSocketService {
	return &WebSocketService{
		client:     c,
		chanMap:    make(map[float64]chan []float64),
		subscribes: make([]subscribeToChannel, 0),
	}
}

// Connect create new bitfinex websocket connection
func (w *WebSocketService) Connect() error {
	var d = websocket.Dialer{
		Subprotocols:    []string{"p1", "p2"},
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		Proxy:           http.ProxyFromEnvironment,
	}

	if w.client.WebSocketTLSSkipVerify {
		d.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}

	ws, _, err := d.Dial(w.client.WebSocketURL, nil)
	if err != nil {
		return err
	}
	w.ws = ws
	return nil
}

// Close web socket connection
func (w *WebSocketService) Close() {
	w.ws.Close()
}

func (w *WebSocketService) AddSubscribe(channel string, pair string, c chan []float64) {
	s := subscribeToChannel{
		Channel: channel,
		Pair:    pair,
		Chan:    c,
	}
	w.subscribes = append(w.subscribes, s)
}

func (w *WebSocketService) ClearSubscriptions() {
	w.subscribes = make([]subscribeToChannel, 0)
}

func (w *WebSocketService) sendSubscribeMessages() error {
	for _, s := range w.subscribes {
		msg, _ := json.Marshal(subscribeMsg{
			Event:   "subscribe",
			Channel: s.Channel,
			Pair:    s.Pair,
		})

		err := w.ws.WriteMessage(websocket.TextMessage, msg)
		if err != nil {
			return err
		}
	}
	return nil
}

// Subscribe allows to subsribe to channels and watch for new updates.
// This method supports next channels: book, trade, ticker.
func (w *WebSocketService) Subscribe() error {
	// Subscribe to each channel
	if err := w.sendSubscribeMessages(); err != nil {
		return err
	}

	for {
		_, p, err := w.ws.ReadMessage()
		if err != nil {
			return err
		}

		if bytes.Contains(p, []byte("event")) {
			w.handleEventMessage(p)
		} else {
			w.handleDataMessage(p)
		}
	}

	return nil
}

func (w *WebSocketService) handleEventMessage(msg []byte) {
	// Check for first message(event:subscribed)
	event := &subscribeMsg{}
	err := json.Unmarshal(msg, event)

	// Received "subscribed" resposne. Link channels.
	if err == nil {
		for _, k := range w.subscribes {
			if event.Event == "subscribed" && event.Pair == k.Pair && event.Channel == k.Channel {
				w.chanMap[event.ChanID] = k.Chan
			}
		}
	}
}

func (w *WebSocketService) handleDataMessage(msg []byte) {
	// Received payload or data update
	var dataUpdate []float64
	err := json.Unmarshal(msg, &dataUpdate)
	if err == nil {
		chanID := dataUpdate[0]
		// Remove chanID from data update
		// and send message to internal chan
		w.chanMap[chanID] <- dataUpdate[1:]
	}

	// Payload received
	var fullPayload []interface{}
	err = json.Unmarshal(msg, &fullPayload)

	if err != nil {
		log.Println("Error decoding fullPayload", err)
	} else {
		if len(fullPayload) > 3 {
			itemsSlice := fullPayload[3:]
			i, _ := json.Marshal(itemsSlice)
			var item []float64
			err = json.Unmarshal(i, &item)
			if err == nil {
				chanID := fullPayload[0].(float64)
				w.chanMap[chanID] <- item
			}
		} else {
			itemsSlice := fullPayload[1]
			i, _ := json.Marshal(itemsSlice)
			var items [][]float64
			err = json.Unmarshal(i, &items)
			if err == nil {
				chanID := fullPayload[0].(float64)
				for _, v := range items {
					w.chanMap[chanID] <- v
				}
			}
		}
	}
}

/////////////////////////////
// Private websocket messages
/////////////////////////////

type privateConnect struct {
	Event       string `json:"event"`
	APIKey      string `json:"apiKey"`
	AuthSig     string `json:"authSig"`
	AuthPayload string `json:"authPayload"`
}

// Private channel auth response
type privateResponse struct {
	Event  string  `json:"event"`
	Status string  `json:"status"`
	ChanID float64 `json:"chanId,omitempty"`
	UserID float64 `json:"userId"`
}

type TermData struct {
	// Data term. E.g: ps, ws, ou, etc... See official documentation for more details.
	Term string
	// Data will contain different number of elements for each term.
	// Examples:
	// Term: ws, Data: ["exchange","BTC",0.01410829,0]
	// Term: oc, Data: [0,"BTCUSD",0,-0.01,"","CANCELED",270,0,"2015-10-15T11:26:13Z",0]
	Data  []interface{}
	Error string
}

func (c *TermData) HasError() bool {
	return len(c.Error) > 0
}

func (w *WebSocketService) ConnectPrivate(ch chan TermData) {

	var d = websocket.Dialer{
		Subprotocols:    []string{"p1", "p2"},
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		Proxy:           http.ProxyFromEnvironment,
	}

	if w.client.WebSocketTLSSkipVerify {
		d.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}

	ws, _, err := d.Dial(w.client.WebSocketURL, nil)
	if err != nil {
		ch <- TermData{
			Error: err.Error(),
		}
		return
	}

	nonce := utils.GetNonce()
	payload := "AUTH" + nonce
	connectMsg, _ := json.Marshal(&privateConnect{
		Event:       "auth",
		APIKey:      w.client.APIKey,
		AuthSig:     w.client.signPayload(payload),
		AuthPayload: payload,
	})

	// Send auth message
	err = ws.WriteMessage(websocket.TextMessage, connectMsg)
	if err != nil {
		ch <- TermData{
			Error: err.Error(),
		}
		ws.Close()
		return
	}

	for {
		_, p, err := ws.ReadMessage()
		if err != nil {
			ch <- TermData{
				Error: err.Error(),
			}
			ws.Close()
			return
		}

		event := &privateResponse{}
		err = json.Unmarshal(p, &event)
		if err != nil {
			// received data update
			var data []interface{}
			err = json.Unmarshal(p, &data)
			if err == nil {
				if len(data) == 2 { // Heartbeat
					// XXX: Consider adding a switch to enable/disable passing these along.
					ch <- TermData{Term: data[1].(string)}
					return
				}

				dataTerm := data[1].(string)
				dataList := data[2].([]interface{})

				// check for empty data
				if len(dataList) > 0 {
					if reflect.TypeOf(dataList[0]) == reflect.TypeOf([]interface{}{}) {
						// received list of lists
						for _, v := range dataList {
							ch <- TermData{
								Term: dataTerm,
								Data: v.([]interface{}),
							}
						}
					} else {
						// received flat list
						ch <- TermData{
							Term: dataTerm,
							Data: dataList,
						}
					}
				}
			}
		} else {
			// received auth response
			if event.Event == "auth" && event.Status != "OK" {
				ch <- TermData{
					Error: "Error connecting to private web socket channel.",
				}
				ws.Close()
			}
		}
	}
}
<|endoftext|>


<commit_before>// ************
// Inspired by : https://semaphoreci.com/community/tutorials/building-and-testing-a-rest-api-in-go-with-gorilla-mux-and-postgresql
// ************

package main_test

import (
	"."
	"bytes"
	"encoding/json"
	"github.com/spf13/viper"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"strings"
	"testing"
)

var a main.App

const tableCreationQuery = `CREATE TABLE IF NOT EXISTS orders
(
id SERIAL,
NAME TEXT NOT NULL,
price NUMERIC (10, 2) NOT NULL DEFAULT 0.00,
CONSTRAINT orders_pkey PRIMARY KEY (id)
)`

func TestMain(m *testing.M) {

	viper.SetConfigName("config")
	viper.AddConfigPath(".")
	viper.ReadInConfig()

	a = main.App{}
	a.Initialize(
		viper.GetString("testing.dbUser"),
		viper.GetString("testing.dbPass"),
		viper.GetString("testing.db"))

	ensureTableExists()
	code := m.Run()
	// clearTable()

	os.Exit(code)
}

func ensureTableExists() {
	if _, err := a.DB.Exec(tableCreationQuery); err != nil {
		log.Fatal(err)
	}
}

func clearTable() {
	a.DB.Exec("DELETE FROM orders")
	a.DB.Exec("ALTER SEQUENCE orders_id_seq RESTART WITH 1")
}

func executeRequest(req *http.Request) *httptest.ResponseRecorder {
	rr := httptest.NewRecorder()
	a.Router.ServeHTTP(rr, req)

	return rr
}

func checkResponseCode(t *testing.T, expected, actual int) {
	if expected != actual {
		t.Errorf("Expected response code %d. Got %d\n", expected, actual)
	}
}

// Model: TODOs
func TestGetTodos(t *testing.T) {
	req, _ := http.NewRequest("GET", "/todos", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

// Model: Order
func TestEmptyTable(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)

	if body := response.Body.String(); strings.TrimSpace(body) != "[]" {
		t.Errorf("Expected an empty array. Got %s", body)
	}
}

func TestGetNonExistentProduct(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/order/999", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusNotFound, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["text"] != "order not found" {
		t.Errorf("Expected the 'text' key of the response to be set to 'order not found'. Got '%s'", m["text"])
	}
}

func TestGetOrders(t *testing.T) {
	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func TestGetOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func addProducts(count int) {
	if count < 1 {
		count = 1
	}

	for i := 0; i < count; i++ {
		a.DB.Exec("INSERT INTO orders(name, price) VALUES($1, $2)", "Order "+strconv.Itoa(i), (i+1.0)*10)
	}
}

func TestCreateorder(t *testing.T) {
	clearTable()
	payload := []byte(`{"name": "test order", "price": 11.22 }`)

	req, _ := http.NewRequest("POST", "/order", bytes.NewBuffer(payload))
	response := executeRequest(req)
	checkResponseCode(t, http.StatusCreated, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["name"] != "test order" {
		t.Errorf("expected name to be 'test order'. Got %v", m["name"])
	}

	if m["price"] != 11.22 {
		t.Errorf("expected price to be '11.22'. Got %v", m["price"])
	}

	// m[string]interface{} converts int to float
	if m["id"] != 1.0 {
		t.Errorf("expected id to be '1.0'. Got %v", m["id"])
	}

}

func TestUpdateOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var originalOrder map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &originalOrder)

	payload := []byte(`{"name": "updated order", "price": 11.22 }`)

	req, _ = http.NewRequest("PUT", "/order/1", bytes.NewBuffer(payload))
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["id"] != originalOrder["id"] {
		t.Errorf("Expected the id to remain the same (%v). Got %v", originalOrder["id"], m["id"])
	}

	if m["name"] == originalOrder["name"] {
		t.Errorf("Expected the name to change from '%v' to '%v'. Got '%v'", originalOrder["name"], m["name"], m["name"])
	}

	if m["price"] == originalOrder["price"] {
		t.Errorf("Expected the price to change from '%v' to '%v'. Got '%v'", originalOrder["price"], m["price"], m["price"])
	}
}

func TestDeleteOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("DELETE", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("GET", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusNotFound, response.Code)

}
<commit_msg>v2: More test cases<commit_after>// ************
// Inspired by : https://semaphoreci.com/community/tutorials/building-and-testing-a-rest-api-in-go-with-gorilla-mux-and-postgresql
// ************

package main_test

import (
	"."
	"bytes"
	"encoding/json"
	"github.com/spf13/viper"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"strings"
	"testing"
)

var app main.App

const tableCreationQuery = `CREATE TABLE IF NOT EXISTS orders
(
id SERIAL,
NAME TEXT NOT NULL,
price NUMERIC (10, 2) NOT NULL DEFAULT 0.00,
CONSTRAINT orders_pkey PRIMARY KEY (id)
)`

func TestMain(m *testing.M) {

	viper.SetConfigName("config")
	viper.AddConfigPath(".")
	viper.ReadInConfig()

	app = main.App{}
	app.Initialize(
		viper.GetString("testing.dbUser"),
		viper.GetString("testing.dbPass"),
		viper.GetString("testing.db"))

	ensureTableExists()
	code := m.Run()
	// clearTable()

	os.Exit(code)
}

func ensureTableExists() {
	if _, err := app.DB.Exec(tableCreationQuery); err != nil {
		log.Fatal(err)
	}
}

func clearTable() {
	app.DB.Exec("DELETE FROM orders")
	app.DB.Exec("ALTER SEQUENCE orders_id_seq RESTART WITH 1")
}

func executeRequest(req *http.Request) *httptest.ResponseRecorder {
	rr := httptest.NewRecorder()
	app.Router.ServeHTTP(rr, req)

	return rr
}

func checkResponseCode(t *testing.T, expected, actual int) {
	if expected != actual {
		t.Errorf("Expected response code %d. Got %d\n", expected, actual)
	}
}

// Model: TODOs
func TestGetTodos(t *testing.T) {
	req, _ := http.NewRequest("GET", "/todos", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

// Model: Order
func TestEmptyTable(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)

	if body := response.Body.String(); strings.TrimSpace(body) != "[]" {
		t.Errorf("Expected an empty array. Got %s", body)
	}
}

func TestGetNonExistentProduct(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/order/999", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusNotFound, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["text"] != "order not found" {
		t.Errorf("Expected the 'text' key of the response to be set to 'order not found'. Got '%s'", m["text"])
	}
}

func TestGetOrders(t *testing.T) {
	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func TestGetOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func addProducts(count int) {
	if count < 1 {
		count = 1
	}

	for i := 0; i < count; i++ {
		app.DB.Exec("INSERT INTO orders(name, price) VALUES($1, $2)", "Order "+strconv.Itoa(i), (i+1.0)*10)
	}
}

func TestCreateorder(t *testing.T) {
	clearTable()
	payload := []byte(`{"name": "test order", "price": 11.22 }`)

	req, _ := http.NewRequest("POST", "/order", bytes.NewBuffer(payload))
	response := executeRequest(req)
	checkResponseCode(t, http.StatusCreated, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["name"] != "test order" {
		t.Errorf("expected name to be 'test order'. Got %v", m["name"])
	}

	if m["price"] != 11.22 {
		t.Errorf("expected price to be '11.22'. Got %v", m["price"])
	}

	// m[string]interface{} converts int to float
	if m["id"] != 1.0 {
		t.Errorf("expected id to be '1.0'. Got %v", m["id"])
	}

}

func TestUpdateOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var originalOrder map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &originalOrder)

	payload := []byte(`{"name": "updated order", "price": 11.22 }`)

	req, _ = http.NewRequest("PUT", "/order/1", bytes.NewBuffer(payload))
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["id"] != originalOrder["id"] {
		t.Errorf("Expected the id to remain the same (%v). Got %v", originalOrder["id"], m["id"])
	}

	if m["name"] == originalOrder["name"] {
		t.Errorf("Expected the name to change from '%v' to '%v'. Got '%v'", originalOrder["name"], m["name"], m["name"])
	}

	if m["price"] == originalOrder["price"] {
		t.Errorf("Expected the price to change from '%v' to '%v'. Got '%v'", originalOrder["price"], m["price"], m["price"])
	}
}

func TestDeleteOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("DELETE", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("GET", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusNotFound, response.Code)

}
<|endoftext|>


<commit_before>package vagrantutil

import (
	"fmt"
	"log"
	"os"
	"testing"

	"github.com/hashicorp/go-version"
)

const testVagrantFile = `# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.hostname = "vagrant"

  config.vm.provider "virtualbox" do |vb|
    # Use VBoxManage to customize the VM. For example to change memory:
    vb.customize ["modifyvm", :id, "--memory", "2048", "--cpus", "2"]
  end
end
`

var (
	vg          *Vagrant
	vagrantName = "vagrantTest"
)

func TestMain(m *testing.M) {
	var err error
	vg, err = NewVagrant(vagrantName)
	if err != nil {
		log.Fatalln(err)
	}

	os.Exit(m.Run())
}

func TestVersion(t *testing.T) {
	out, err := vg.Version()
	if err != nil {
		t.Fatal(err)
	}

	// check if the output is correct
	_, err = version.NewVersion(out)
	if err != nil {
		t.Error(err)
	}
}

func TestCreate(t *testing.T) {
	err := vg.Create(testVagrantFile)
	if err != nil {
		t.Fatal(err)
	}

	if err := vg.vagrantfileExists(); err != nil {
		t.Error(err)
	}
}

func TestProvider(t *testing.T) {
	provider, err := vg.Provider()
	if err != nil {
		t.Fatal(err)
	}

	if provider != "virtualbox" {
		t.Errorf("Vagrant provider should be 'virtualbox'. Got: %s", provider)
	}
}

func TestUp(t *testing.T) {
	out, err := vg.Up()
	if err != nil {
		t.Fatal(err)
	}

	log.Printf("Starting to read the stream output of 'vagrant up':\n\n")
	for res := range out {
		if res.Error != nil {
			t.Error(err)
		}
		log.Println(res.Line)
	}

	log.Printf("\n\nStreaming is finished for 'vagrant up' command")

	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if status != Running {
		t.Errorf("Vagrant status should be: %s. Got: %s", Running, status)
	}
}

func TestHalt(t *testing.T) {
	out, err := vg.Halt()
	if err != nil {
		t.Fatal(err)
	}

	log.Printf("Starting to read the stream output of 'vagrant halt':\n\n")
	for res := range out {
		if res.Error != nil {
			t.Error(err)
		}
		log.Println(res.Line)
	}

	log.Printf("\n\nStreaming is finished for 'vagrant halt' command")

	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if status != PowerOff {
		t.Errorf("Vagrant status should be: %s. Got: %s", PowerOff, status)
	}
}

func TestList(t *testing.T) {
	list, err := vg.List()
	if err != nil {
		t.Fatal(err)
	}

	for i, l := range list {
		status, err := l.Status()
		if err != nil {
			if l.State != Unknown.String() {
				t.Errorf("failed state should be: Unknown, got: %s", l.State)
			}

			log.Println("continue because: ", err)
			continue
		}

		if l.State != status.String() {
			t.Errorf("internal state should be: %s, got: %s", status, l.State)
		}

		if l.VagrantfilePath == "" {
			t.Error("path should be not empty for list command")
		}

		fmt.Printf("[%d] status = %s path = %s\n", i, status, l.VagrantfilePath)
	}
}

func TestDestroy(t *testing.T) {
	out, err := vg.Destroy()
	if err != nil {
		t.Fatal(err)
	}

	log.Printf("Starting to read the stream output of 'vagrant destroy':\n\n")
	for res := range out {
		if res.Error != nil {
			t.Error(err)
		}
		log.Println(res.Line)
	}
	log.Printf("\n\nStreaming is finished for 'vagrant destroy' command")

	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if status != NotCreated {
		t.Errorf("Vagrant status should be: %s. Got: %s", NotCreated, status)
	}

}

func TestStatus(t *testing.T) {
	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if vg.State != status.String() {
		t.Errorf("Internal state should be: %s, got: %s", status, vg.State)
	}
}
<commit_msg>vagrant: clean after test<commit_after>package vagrantutil

import (
	"fmt"
	"log"
	"os"
	"testing"

	"github.com/hashicorp/go-version"
)

const testVagrantFile = `# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.hostname = "vagrant"

  config.vm.provider "virtualbox" do |vb|
    # Use VBoxManage to customize the VM. For example to change memory:
    vb.customize ["modifyvm", :id, "--memory", "2048", "--cpus", "2"]
  end
end
`

var (
	vg          *Vagrant
	vagrantName = "vagrantTest"
)

func TestMain(m *testing.M) {
	var err error
	vg, err = NewVagrant(vagrantName)
	if err != nil {
		log.Fatalln(err)
	}

	ret := m.Run()
	os.RemoveAll(vagrantName)
	os.Exit(ret)
}

func TestVersion(t *testing.T) {
	out, err := vg.Version()
	if err != nil {
		t.Fatal(err)
	}

	// check if the output is correct
	_, err = version.NewVersion(out)
	if err != nil {
		t.Error(err)
	}
}

func TestCreate(t *testing.T) {
	err := vg.Create(testVagrantFile)
	if err != nil {
		t.Fatal(err)
	}

	if err := vg.vagrantfileExists(); err != nil {
		t.Error(err)
	}
}

func TestProvider(t *testing.T) {
	provider, err := vg.Provider()
	if err != nil {
		t.Fatal(err)
	}

	if provider != "virtualbox" {
		t.Errorf("Vagrant provider should be 'virtualbox'. Got: %s", provider)
	}
}

func TestUp(t *testing.T) {
	out, err := vg.Up()
	if err != nil {
		t.Fatal(err)
	}

	log.Printf("Starting to read the stream output of 'vagrant up':\n\n")
	for res := range out {
		if res.Error != nil {
			t.Error(err)
		}
		log.Println(res.Line)
	}

	log.Printf("\n\nStreaming is finished for 'vagrant up' command")

	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if status != Running {
		t.Errorf("Vagrant status should be: %s. Got: %s", Running, status)
	}
}

func TestHalt(t *testing.T) {
	out, err := vg.Halt()
	if err != nil {
		t.Fatal(err)
	}

	log.Printf("Starting to read the stream output of 'vagrant halt':\n\n")
	for res := range out {
		if res.Error != nil {
			t.Error(err)
		}
		log.Println(res.Line)
	}

	log.Printf("\n\nStreaming is finished for 'vagrant halt' command")

	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if status != PowerOff {
		t.Errorf("Vagrant status should be: %s. Got: %s", PowerOff, status)
	}
}

func TestList(t *testing.T) {
	list, err := vg.List()
	if err != nil {
		t.Fatal(err)
	}

	for i, l := range list {
		status, err := l.Status()
		if err != nil {
			if l.State != Unknown.String() {
				t.Errorf("failed state should be: Unknown, got: %s", l.State)
			}

			log.Println("continue because: ", err)
			continue
		}

		if l.State != status.String() {
			t.Errorf("internal state should be: %s, got: %s", status, l.State)
		}

		if l.VagrantfilePath == "" {
			t.Error("path should be not empty for list command")
		}

		fmt.Printf("[%d] status = %s path = %s\n", i, status, l.VagrantfilePath)
	}
}

func TestDestroy(t *testing.T) {
	out, err := vg.Destroy()
	if err != nil {
		t.Fatal(err)
	}

	log.Printf("Starting to read the stream output of 'vagrant destroy':\n\n")
	for res := range out {
		if res.Error != nil {
			t.Error(err)
		}
		log.Println(res.Line)
	}
	log.Printf("\n\nStreaming is finished for 'vagrant destroy' command")

	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if status != NotCreated {
		t.Errorf("Vagrant status should be: %s. Got: %s", NotCreated, status)
	}

}

func TestStatus(t *testing.T) {
	status, err := vg.Status()
	if err != nil {
		t.Fatal(err)
	}

	if vg.State != status.String() {
		t.Errorf("Internal state should be: %s, got: %s", status, vg.State)
	}
}
<|endoftext|>


<commit_before>package tail

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"testing"
	"time"
)

const (
	RotateMarker   = "__ROTATE__\n"
	TruncateMarker = "__TRUNCATE__\n"
	EOFMarker      = "__EOF__\n"
)

var Logs = []string{
	"single line\n",
	"multi line 1\nmulti line 2\nmulti line 3\n",
	"continuous line 1", "continuous line 2", "continuous line 3\n",
	RotateMarker,
	"foo\n",
	"bar\n",
	"baz\n",
	TruncateMarker,
	"FOOOO\n",
	"BAAAR\n",
	"BAZZZZZZZ\n",
	EOFMarker,
}

func TestTailFile(t *testing.T) {
	tmpdir, err := ioutil.TempDir("", "go-tail.")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	defer os.RemoveAll(tmpdir)

	go writeFile(t, tmpdir)
	tail, err := NewTailFile(filepath.Join(tmpdir, "test.log"))
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	defer tail.Close()

	expected := strings.Join(Logs, "")
	actual, err := receive(t, tail)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if actual != expected {
		t.Errorf("got %s\nwant %s", actual, expected)
	}
}

func TestTailReader(t *testing.T) {
	reader, writer := io.Pipe()

	go writeWriter(t, writer)
	tail, err := NewTailReader(reader)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	expected := strings.Join(Logs, "")
	actual, err := receive(t, tail)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if actual != expected {
		t.Errorf("got %s\nwant %s", actual, expected)
	}

	reader.Close()
	writer.Close()
	select {
	case _, ok := <-tail.Lines:
		if ok {
			t.Error("want closed, but not")
		}
	case <-time.After(time.Second):
		t.Error("want closed, but not")
	}
	select {
	case _, ok := <-tail.Errors:
		if ok {
			t.Error("want closed, but not")
		}
	case <-time.After(time.Second):
		t.Error("want closed, but not")
	}
	tail.Close()
}

func writeFile(t *testing.T, tmpdir string) error {
	filename := filepath.Join(tmpdir, "test.log")
	file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}

	// wait for starting to tail...
	time.Sleep(2 * time.Second)

	for _, line := range Logs {
		_, err := file.WriteString(line)
		if err != nil {
			return err
		}
		t.Logf("write: %s", line)
		switch line {
		case RotateMarker:
			if err := file.Close(); err != nil {
				return err
			}
			if err := os.Rename(filename, filename+".old"); err != nil {
				return err
			}
			file, err = os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				return err
			}
		case TruncateMarker:
			time.Sleep(1 * time.Second)
			if _, err := file.Seek(0, os.SEEK_SET); err != nil {
				return err
			}
			if err := os.Truncate(filename, 0); err != nil {
				return err
			}
		}
		time.Sleep(90 * time.Millisecond)
	}

	if err := file.Close(); err != nil {
		return err
	}
	return nil
}

func writeWriter(t *testing.T, writer io.Writer) error {
	w := bufio.NewWriter(writer)
	for _, line := range Logs {
		_, err := w.WriteString(line)
		if err != nil {
			return err
		}
		if err := w.Flush(); err != nil {
			return err
		}
		t.Logf("write: %s", line)
		time.Sleep(90 * time.Millisecond)
	}
	return nil
}

func receive(t *testing.T, tail *Tail) (string, error) {
	actual := ""
	for {
		select {
		case line := <-tail.Lines:
			t.Logf("received: %s", line.Text)
			actual += line.Text
			if line.Text == EOFMarker {
				return actual, nil
			}
		case err := <-tail.Errors:
			return "", err
		case <-time.After(5 * time.Second):
			return "", errors.New("timeout")
		}
	}
}

func TestTailFile_Rotate(t *testing.T) {
	tmpdir, err := ioutil.TempDir("", "go-tail.")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	defer os.RemoveAll(tmpdir)

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		filename := filepath.Join(tmpdir, "test.log")
		for i := 0; i < 10; i++ {
			i := i
			file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				t.Error(err)
				return
			}
			if i == 0 {
				// wait for starting to tail...
				time.Sleep(2 * time.Second)
			}

			// start to write logs
			wg.Add(1)
			go func() {
				defer wg.Done()
				writeFileAndClose(t, file, fmt.Sprintf("file: %d\n", i))
			}()
			time.Sleep(time.Second)

			// Rotate log file, and start writing logs into a new file.
			// While, some logs are still written into the old file.
			if err := os.Rename(filename, fmt.Sprintf("%s.%d", filename, i)); err != nil {
				t.Error("failed to rename", err)
			}
		}
	}()

	tail, err := NewTailFile(filepath.Join(tmpdir, "test.log"))
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	go func() {
		wg.Wait()
		tail.Close()
	}()
	go func() {
		for err := range tail.Errors {
			t.Log("error: ", err)
		}
	}()

	var cnt int
	for range tail.Lines {
		cnt++
	}
	if cnt != 1000 {
		t.Errorf("want 1000, got %d", cnt)
	}
}

func writeFileAndClose(t *testing.T, file *os.File, line string) {
	for i := 0; i < 100; i++ {
		_, err := file.WriteString(line)
		if err != nil {
			_ = file.Close()
			t.Error(err)
			return
		}
		time.Sleep(90 * time.Millisecond)
	}

	if err := file.Close(); err != nil {
		t.Error(err)
	}
}
<commit_msg>add a test case for very very long lines<commit_after>package tail

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"testing"
	"time"
)

const (
	RotateMarker   = "__ROTATE__\n"
	TruncateMarker = "__TRUNCATE__\n"
	EOFMarker      = "__EOF__\n"
)

var Logs = []string{
	"single line\n",
	strings.Repeat("very very very long line. ", 4096) + "\n",
	"multi line 1\nmulti line 2\nmulti line 3\n",
	"continuous line 1", "continuous line 2", "continuous line 3\n",
	RotateMarker,
	"foo\n",
	"bar\n",
	"baz\n",
	TruncateMarker,
	"FOOOO\n",
	"BAAAR\n",
	"BAZZZZZZZ\n",
	EOFMarker,
}

func TestTailFile(t *testing.T) {
	tmpdir, err := ioutil.TempDir("", "go-tail.")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	defer os.RemoveAll(tmpdir)

	go writeFile(t, tmpdir)
	tail, err := NewTailFile(filepath.Join(tmpdir, "test.log"))
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	defer tail.Close()

	expected := strings.Join(Logs, "")
	actual, err := receive(t, tail)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if actual != expected {
		t.Errorf("got %s\nwant %s", actual, expected)
	}
}

func TestTailReader(t *testing.T) {
	reader, writer := io.Pipe()

	go writeWriter(t, writer)
	tail, err := NewTailReader(reader)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	expected := strings.Join(Logs, "")
	actual, err := receive(t, tail)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if actual != expected {
		t.Errorf("got %s\nwant %s", actual, expected)
	}

	reader.Close()
	writer.Close()
	select {
	case _, ok := <-tail.Lines:
		if ok {
			t.Error("want closed, but not")
		}
	case <-time.After(time.Second):
		t.Error("want closed, but not")
	}
	select {
	case _, ok := <-tail.Errors:
		if ok {
			t.Error("want closed, but not")
		}
	case <-time.After(time.Second):
		t.Error("want closed, but not")
	}
	tail.Close()
}

func writeFile(t *testing.T, tmpdir string) error {
	filename := filepath.Join(tmpdir, "test.log")
	file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}

	// wait for starting to tail...
	time.Sleep(2 * time.Second)

	for _, line := range Logs {
		_, err := file.WriteString(line)
		if err != nil {
			return err
		}
		if len(line) < 100 {
			t.Logf("write: %s", line)
		} else {
			t.Logf("write: %s...(snip)", line[:100])
		}
		switch line {
		case RotateMarker:
			if err := file.Close(); err != nil {
				return err
			}
			if err := os.Rename(filename, filename+".old"); err != nil {
				return err
			}
			file, err = os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				return err
			}
		case TruncateMarker:
			time.Sleep(1 * time.Second)
			if _, err := file.Seek(0, os.SEEK_SET); err != nil {
				return err
			}
			if err := os.Truncate(filename, 0); err != nil {
				return err
			}
		}
		time.Sleep(90 * time.Millisecond)
	}

	if err := file.Close(); err != nil {
		return err
	}
	return nil
}

func writeWriter(t *testing.T, writer io.Writer) error {
	w := bufio.NewWriter(writer)
	for _, line := range Logs {
		_, err := w.WriteString(line)
		if err != nil {
			return err
		}
		if err := w.Flush(); err != nil {
			return err
		}
		if len(line) < 100 {
			t.Logf("write: %s", line)
		} else {
			t.Logf("write: %s...(snip)", line[:100])
		}
		time.Sleep(90 * time.Millisecond)
	}
	return nil
}

func receive(t *testing.T, tail *Tail) (string, error) {
	actual := ""
	for {
		select {
		case line := <-tail.Lines:
			if len(line.Text) < 100 {
				t.Logf("received: %s", line.Text)
			} else {
				t.Logf("received: %s...(snip)", line.Text[:100])
			}
			actual += line.Text
			if line.Text == EOFMarker {
				return actual, nil
			}
		case err := <-tail.Errors:
			return "", err
		case <-time.After(5 * time.Second):
			return "", errors.New("timeout")
		}
	}
}

func TestTailFile_Rotate(t *testing.T) {
	tmpdir, err := ioutil.TempDir("", "go-tail.")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	defer os.RemoveAll(tmpdir)

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		filename := filepath.Join(tmpdir, "test.log")
		for i := 0; i < 10; i++ {
			i := i
			file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				t.Error(err)
				return
			}
			if i == 0 {
				// wait for starting to tail...
				time.Sleep(2 * time.Second)
			}

			// start to write logs
			wg.Add(1)
			go func() {
				defer wg.Done()
				writeFileAndClose(t, file, fmt.Sprintf("file: %d\n", i))
			}()
			time.Sleep(time.Second)

			// Rotate log file, and start writing logs into a new file.
			// While, some logs are still written into the old file.
			if err := os.Rename(filename, fmt.Sprintf("%s.%d", filename, i)); err != nil {
				t.Error("failed to rename", err)
			}
		}
	}()

	tail, err := NewTailFile(filepath.Join(tmpdir, "test.log"))
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	go func() {
		wg.Wait()
		tail.Close()
	}()
	go func() {
		for err := range tail.Errors {
			t.Log("error: ", err)
		}
	}()

	var cnt int
	for range tail.Lines {
		cnt++
	}
	if cnt != 1000 {
		t.Errorf("want 1000, got %d", cnt)
	}
}

func writeFileAndClose(t *testing.T, file *os.File, line string) {
	for i := 0; i < 100; i++ {
		_, err := file.WriteString(line)
		if err != nil {
			_ = file.Close()
			t.Error(err)
			return
		}
		time.Sleep(90 * time.Millisecond)
	}

	if err := file.Close(); err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package redkeep_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"text/template"

	. "github.com/manyminds/redkeep"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var testConfigurationTemplate = `{
  "mongo": {
    "connectionURI": "localhost:30000,localhost:30001,localhost:30002"
  },
  "watches": [
    {
      "trackCollection": "{{.Database}}.user",
      "trackFields": ["username", "gender"],
      "targetCollection": "{{.Database}}.comment",
      "targetNormalizedField": "meta",
      "triggerReference": "user",
      "behaviourSettings": {
        "cascadeDelete": false
      }
    },
    {
      "trackCollection": "{{.Database}}.user",
      "trackFields": ["name", "username"],
      "targetCollection": "{{.Database}}.answer",
      "targetNormalizedField": "meta",
      "triggerReference": "user",
      "behaviourSettings": {
        "cascadeDelete": false
      }
    }
  ]
}`

var _ = Describe("Tail", func() {
	var (
		running  chan bool
		database string
	)

	BeforeSuite(func() {
		randomDB := func() string {
			return fmt.Sprintf("redkeep_tests_%d", time.Now().UnixNano())
		}()
		tmp, err := template.New("config").Parse(testConfigurationTemplate)
		Expect(err).ToNot(HaveOccurred())
		var data []byte
		buffer := bytes.NewBuffer(data)
		err = tmp.Execute(buffer, struct{ Database string }{Database: randomDB})
		Expect(err).ToNot(HaveOccurred())
		data, err = ioutil.ReadAll(buffer)
		Expect(err).ToNot(HaveOccurred())
		config, err := NewConfiguration(data)
		Expect(err).ToNot(HaveOccurred())
		database = randomDB
		agent, err := NewTailAgent(*config)
		if err != nil {
			log.Fatal(err)
		}
		running = make(chan bool)
		go agent.Tail(running, false)
	})

	AfterSuite(func() {
		running <- false
	})

	Context("Database testcases", func() {
		type comment struct {
			Text string
			User mgo.DBRef
			Meta map[string]interface{}
		}

		type answer struct {
			AnswerText string `bson:"answerText"`
			User       mgo.DBRef
			Meta       map[string]interface{}
		}

		var (
			db         *mgo.Session
			userOneRef mgo.DBRef
		)

		BeforeEach(func() {
			var err error
			db, err = mgo.Dial("localhost:30000,localhost:30001,localhost:30002")
			Expect(err).ToNot(HaveOccurred())
			userID := bson.ObjectIdHex("56a65494b204ccd1edc0b055")
			userOneRef = mgo.DBRef{
				Database:   database,
				Id:         userID,
				Collection: "user",
			}
		})

		It("Should update infos on insert correctly", func() {
			db.DB(database).C("user").Insert(
				bson.M{
					"_id":      userOneRef.Id,
					"username": "naan",
					"gender":   "male",
					"name": bson.M{
						"firstName": "Naan",
						"lastName":  "Waana",
					},
				},
			)

			db.DB(database).C("comment").Insert(
				bson.M{
					"text": "this is my first comment",
					"user": userOneRef,
				},
			)

			actual := comment{}
			time.Sleep(10 * time.Millisecond)
			db.Copy().DB(database).C("comment").Find(bson.M{}).One(&actual)

			Expect(actual.Meta["username"]).To(Equal("naan"))
			Expect(actual.Meta["gender"]).To(Equal("male"))
		})

		It("will also work with answers and different mapping", func() {
			db.DB(database).C("answer").Insert(&answer{AnswerText: "this is my answer", User: userOneRef})

			actual := answer{}
			time.Sleep(10 * time.Millisecond)
			db.Copy().DB(database).C("answer").Find(bson.M{"answerText": "this is my answer"}).One(&actual)

			Expect(actual.Meta["username"]).To(Equal("naan"))
			Expect(actual.Meta["name"]).To(Equal(map[string]interface{}{
				"firstName": "Naan",
				"lastName":  "Waana",
			}))
		})

		It("will then update usernames everywhere", func() {
			_, err := db.DB(database).C("user").UpdateAll(
				bson.M{"username": "naan"},
				bson.M{
					"$set": bson.M{
						"username": "anonym",
						"name": bson.M{
							"firstName": "Not",
							"lastName":  "Known",
						},
					},
				},
			)

			Expect(err).ToNot(HaveOccurred())
			time.Sleep(10 * time.Millisecond)
			actual := answer{}
			db.Copy().DB(database).C("answer").Find(bson.M{"answerText": "this is my answer"}).One(&actual)

			Expect(actual.Meta["username"]).To(Equal("anonym"))
			Expect(actual.Meta["name"]).To(HaveKey("firstName"))
			Expect(actual.Meta["name"]).To(HaveKey("lastName"))
		})
	})

	Context("test GetValue", func() {
		It("will find the first value", func() {
			testReference := mgo.DBRef{
				Collection: "diff",
				Database:   "this",
				Id:         bson.ObjectIdHex("569e787d14b9802c9628b300"),
			}
			toTest := map[string]interface{}{
				"fish": map[string]interface{}{
					"dog": "cat",
				},
				"author": testReference,
				"tree":   nil,
			}

			actual := GetValue("fish.dog", toTest)
			Expect(actual).To(Equal("cat"))

			actual = GetValue("invalid", toTest)
			Expect(actual).To(BeNil())

			actual = GetValue("tree", toTest)
			Expect(actual).To(BeNil())

			actual = GetValue("author", toTest)
			Expect(actual).To(Equal(testReference))

			actual = GetValue("author.fisch.baum", toTest)
			Expect(actual).To(BeNil())

			actual = GetValue("fish", toTest)
			Expect(actual).To(Equal(map[string]interface{}{"dog": "cat"}))
		})
	})
})
<commit_msg>Add actual assertions to the test<commit_after>package redkeep_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"text/template"

	. "github.com/manyminds/redkeep"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var testConfigurationTemplate = `{
  "mongo": {
    "connectionURI": "localhost:30000,localhost:30001,localhost:30002"
  },
  "watches": [
    {
      "trackCollection": "{{.Database}}.user",
      "trackFields": ["username", "gender"],
      "targetCollection": "{{.Database}}.comment",
      "targetNormalizedField": "meta",
      "triggerReference": "user",
      "behaviourSettings": {
        "cascadeDelete": false
      }
    },
    {
      "trackCollection": "{{.Database}}.user",
      "trackFields": ["name", "username"],
      "targetCollection": "{{.Database}}.answer",
      "targetNormalizedField": "meta",
      "triggerReference": "user",
      "behaviourSettings": {
        "cascadeDelete": false
      }
    }
  ]
}`

var _ = Describe("Tail", func() {
	var (
		running  chan bool
		database string
	)

	BeforeSuite(func() {
		randomDB := func() string {
			return fmt.Sprintf("redkeep_tests_%d", time.Now().UnixNano())
		}()
		tmp, err := template.New("config").Parse(testConfigurationTemplate)
		Expect(err).ToNot(HaveOccurred())
		var data []byte
		buffer := bytes.NewBuffer(data)
		err = tmp.Execute(buffer, struct{ Database string }{Database: randomDB})
		Expect(err).ToNot(HaveOccurred())
		data, err = ioutil.ReadAll(buffer)
		Expect(err).ToNot(HaveOccurred())
		config, err := NewConfiguration(data)
		Expect(err).ToNot(HaveOccurred())
		database = randomDB
		agent, err := NewTailAgent(*config)
		if err != nil {
			log.Fatal(err)
		}
		running = make(chan bool)
		go agent.Tail(running, false)
	})

	AfterSuite(func() {
		running <- false
	})

	Context("Database testcases", func() {
		type comment struct {
			Text string
			User mgo.DBRef
			Meta map[string]interface{}
		}

		type answer struct {
			AnswerText string `bson:"answerText"`
			User       mgo.DBRef
			Meta       map[string]interface{}
		}

		var (
			db         *mgo.Session
			userOneRef mgo.DBRef
		)

		BeforeEach(func() {
			var err error
			db, err = mgo.Dial("localhost:30000,localhost:30001,localhost:30002")
			Expect(err).ToNot(HaveOccurred())
			userID := bson.ObjectIdHex("56a65494b204ccd1edc0b055")
			userOneRef = mgo.DBRef{
				Database:   database,
				Id:         userID,
				Collection: "user",
			}
		})

		It("Should update infos on insert correctly", func() {
			db.DB(database).C("user").Insert(
				bson.M{
					"_id":      userOneRef.Id,
					"username": "naan",
					"gender":   "male",
					"name": bson.M{
						"firstName": "Naan",
						"lastName":  "Waana",
					},
				},
			)

			db.DB(database).C("comment").Insert(
				bson.M{
					"text": "this is my first comment",
					"user": userOneRef,
				},
			)

			actual := comment{}
			time.Sleep(10 * time.Millisecond)
			db.Copy().DB(database).C("comment").Find(bson.M{}).One(&actual)

			Expect(actual.Meta["username"]).To(Equal("naan"))
			Expect(actual.Meta["gender"]).To(Equal("male"))
		})

		It("will also work with answers and different mapping", func() {
			db.DB(database).C("answer").Insert(&answer{AnswerText: "this is my answer", User: userOneRef})

			actual := answer{}
			time.Sleep(10 * time.Millisecond)
			db.Copy().DB(database).C("answer").Find(bson.M{"answerText": "this is my answer"}).One(&actual)

			Expect(actual.Meta["username"]).To(Equal("naan"))
			Expect(actual.Meta["name"]).To(Equal(map[string]interface{}{
				"firstName": "Naan",
				"lastName":  "Waana",
			}))
		})

		It("will then update usernames everywhere", func() {
			_, err := db.DB(database).C("user").UpdateAll(
				bson.M{"username": "naan"},
				bson.M{
					"$set": bson.M{
						"username": "anonym",
						"name": bson.M{
							"firstName": "Not",
							"lastName":  "Known",
						},
					},
				},
			)

			Expect(err).ToNot(HaveOccurred())
			time.Sleep(10 * time.Millisecond)
			actual := answer{}
			db.Copy().DB(database).C("answer").Find(bson.M{"answerText": "this is my answer"}).One(&actual)

			Expect(actual.Meta["username"]).To(Equal("anonym"))
			Expect(actual.Meta["name"]).To(HaveKey("firstName"))
			Expect(actual.Meta["name"]).To(HaveKey("lastName"))
			Expect(actual.Meta["name"].(map[string]interface{})["firstName"]).To(Equal("Not"))
			Expect(actual.Meta["name"].(map[string]interface{})["lastName"]).To(Equal("Known"))
		})
	})

	Context("test GetValue", func() {
		It("will find the first value", func() {
			testReference := mgo.DBRef{
				Collection: "diff",
				Database:   "this",
				Id:         bson.ObjectIdHex("569e787d14b9802c9628b300"),
			}
			toTest := map[string]interface{}{
				"fish": map[string]interface{}{
					"dog": "cat",
				},
				"author": testReference,
				"tree":   nil,
			}

			actual := GetValue("fish.dog", toTest)
			Expect(actual).To(Equal("cat"))

			actual = GetValue("invalid", toTest)
			Expect(actual).To(BeNil())

			actual = GetValue("tree", toTest)
			Expect(actual).To(BeNil())

			actual = GetValue("author", toTest)
			Expect(actual).To(Equal(testReference))

			actual = GetValue("author.fisch.baum", toTest)
			Expect(actual).To(BeNil())

			actual = GetValue("fish", toTest)
			Expect(actual).To(Equal(map[string]interface{}{"dog": "cat"}))
		})
	})
})
<|endoftext|>


<commit_before>package task

import (
	"log"

	"github.com/nzai/stockrecorder/analyse"
	"github.com/nzai/stockrecorder/crawl"
)

//	启动任务
func StartTasks() error {
	log.Print("启动任务")

	//	启动抓取任务
	go crawl.StartJobs()

	//	启动分析任务
	go analyse.StartJobs()

	return nil
}
<commit_msg>修改了数据抓取任务的调用方法名称<commit_after>package task

import (
	"log"

	"github.com/nzai/stockrecorder/analyse"
	"github.com/nzai/stockrecorder/crawl"
)

//	启动任务
func StartTasks() error {
	log.Print("启动任务")

	//	启动抓取任务
	go crawl.Start()

	//	启动分析任务
	go analyse.StartJobs()

	return nil
}
<|endoftext|>


<commit_before>package k8s

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/servicebroker/servicebroker/k8s/service_controller/server"
	model "github.com/servicebroker/servicebroker/model/service_controller"
)

type K8sServiceStorage struct {
	// Host is the location where we'll talk to k8s
	host            string
	defaultResource string
}

const serviceDomain string = "cncf.org"
const apiVersion string = "v1alpha1"
const brokerResource string = "servicebrokers"
const defaultUri string = "http://%v/apis/" + serviceDomain + "/" + apiVersion + "/namespaces/default/" + brokerResource

// The k8s implementation should leverage Third Party Resources
// https://github.com/kubernetes/kubernetes/blob/master/docs/design/extending-api.md

var _ server.ServiceStorage = (*K8sServiceStorage)(nil)

type Meta struct {
	Name string `json:"name"`
}

type k8sServiceBroker struct {
	*model.ServiceBroker
	ApiVersion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Metadata   Meta   `json:"metadata"`
}

type VName struct {
	Name string `json:"name"`
}

type TPR struct {
	Meta       `json:"metadata"`
	ApiVersion string  `json:"apiVersion"`
	kind       string  `json:"kind"`
	Versions   []VName `json:"versions"`
}

const TPRapiVersion string = "extensions/v1beta1"
const thirdPartyResourceString string = "ThirdPartyResource"

var versionMap []VName = []VName{{"v1alpha1"}}
var serviceBrokerMeta Meta = Meta{"service-broker.cncf.org"}
var serviceMeta Meta = Meta{"sbservice.cncf.org"} // sbservice so it does not conflict with the built in Service
var serviceBindingMeta Meta = Meta{"service-binding.cncf.org"}
var serviceInstanceMeta Meta = Meta{"service-instance.cncf.org"}
var serviceBrokerDefinition TPR = TPR{serviceBrokerMeta, TPRapiVersion, thirdPartyResourceString, versionMap}
var serviceDefinition TPR = TPR{serviceMeta, TPRapiVersion, thirdPartyResourceString, versionMap}
var serviceBindingDefinition TPR = TPR{serviceBindingMeta, TPRapiVersion, thirdPartyResourceString, versionMap}
var serviceInstanceDefinition TPR = TPR{serviceInstanceMeta, TPRapiVersion, thirdPartyResourceString, versionMap}

func CreateServiceStorage(host string) server.ServiceStorage {
	k := &K8sServiceStorage{host: host,
		defaultResource: fmt.Sprintf(defaultUri, host)}
	fmt.Println(" root host is:", k.defaultUri())
	// define the resources once at startup
	// results in ServiceBrokers

	k.createTPR(serviceBrokerDefinition)
	k.createTPR(serviceDefinition)
	k.createTPR(serviceBindingDefinition)
	k.createTPR(serviceInstanceDefinition)
	// cleanup afterwards by `kubectl delete thirdpartyresource service-broker.cncf.org`

	return k
}

// listSB is only used for unmarshalling the list of service brokers
// for returning to the client
type listSB struct {
	Items []*k8sServiceBroker `json:"items"`
}

func (kss *K8sServiceStorage) defaultUri() string {
	return kss.defaultResource
}

func (kss *K8sServiceStorage) createTPR(tpr TPR) {
	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(&tpr)
	fmt.Printf("encoded bytes: %v\n", b.String())
	r, e := http.Post("http://"+kss.host+"/apis/extensions/v1beta1/thirdpartyresources", "application/json", b)
	fmt.Printf("result: %v\n", r)
	if nil != e || 201 != r.StatusCode {
		fmt.Printf("Error creating k8s TPR [%s]...\n%v\n", e, r)
	}
}

func (kss *K8sServiceStorage) ListBrokers() ([]*model.ServiceBroker, error) {
	fmt.Println("listing all brokers")
	// get the ServiceBroker

	r, e := http.Get(kss.defaultUri())
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service brokers. %v, [%v]", e, r)
	}

	var lsb listSB
	e = json.NewDecoder(r.Body).Decode(&lsb)
	if nil != e { // wrong json format error
		fmt.Println("json not unmarshalled:", e, r)
		return nil, e
	}
	fmt.Println("Got", len(lsb.Items), "brokers.")
	ret := make([]*model.ServiceBroker, 0, len(lsb.Items))
	for _, v := range lsb.Items {
		ret = append(ret, v.ServiceBroker)
	}
	return ret, nil
}

func (kss *K8sServiceStorage) GetBroker(name string) (*model.ServiceBroker, error) {
	uri := kss.defaultUri() + "/" + name
	fmt.Println("uri is:", uri)
	r, e := http.Get(uri)
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service broker. %v, [%v]", e, r)
	}
	defer r.Body.Close()
	var sb k8sServiceBroker
	e = json.NewDecoder(r.Body).Decode(&sb)
	if nil != e { // wrong json format error
		return nil, e
	}
	fmt.Printf("returned json: %+v\n", sb)
	return sb.ServiceBroker, nil
}

func (kss *K8sServiceStorage) GetBrokerByService(id string) (*model.ServiceBroker, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetInventory() (*model.Catalog, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func NewK8sSB() *k8sServiceBroker {
	return &k8sServiceBroker{ApiVersion: serviceDomain + "/" + apiVersion,
		Kind: "ServiceBroker"}
}

func (kss *K8sServiceStorage) AddBroker(broker *model.ServiceBroker, catalog *model.Catalog) error {
	fmt.Println("adding broker to k8s", broker)
	// create TPR
	// tpr is
	//    kind.fqdn
	// or
	//    kind.domain.tld
	//
	// use service-broker.cncf.org
	// end up with k8s resource of ServiceBroker
	// version v1alpha1 for now
	//
	// store name/host/port/user/pass as metadata
	//
	// example yaml
	// metadata:
	//   name: service-broker.cncf.org
	//   (service)name/host/port/user/pass
	// apiVersion: extensions/v1beta1
	// kind: ThirdPartyResource
	// versions:
	// - name: v1alpha1
	ksb := NewK8sSB()
	ksb.Metadata = Meta{Name: broker.GUID}
	ksb.ServiceBroker = broker

	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(&ksb)
	fmt.Printf("sending: %v", b)
	r, e := http.Post(kss.defaultUri(), "application/json", b)
	fmt.Sprintf("result: %v", r)
	if nil != e || 201 != r.StatusCode {
		fmt.Printf("Error creating k8s TPR [%s]...\n%v\n", e, r)
		return e
	}

	fmt.Println("installing the", len(catalog.Services), "services for this broker")
	for i, service := range catalog.Services {
		fmt.Println(i, service)
	}

	return nil
}

func (kss *K8sServiceStorage) DeleteBroker(name string) error {
	uri := kss.defaultUri() + "/" + name
	fmt.Println("uri is:", uri)

	// utter failure of an http API
	req, _ := http.NewRequest("DELETE", uri, nil)
	_, e := http.DefaultClient.Do(req)
	if nil != e {
		return fmt.Errorf("couldn't nuke %v, [%v]", name, e)
	}
	return nil
}

func (kss *K8sServiceStorage) ServiceExists(id string) bool {
	return false
}

func (kss *K8sServiceStorage) ListServices() ([]*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetService(id string) (*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) SetService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteService(id string) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) ListServiceBindings() ([]*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetServiceBinding(id string) (*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddServiceBinding(binding *model.ServiceBinding, cred *model.Credential) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteServiceBinding(id string) error {
	return fmt.Errorf("Not implemented yet")
}
<commit_msg>add the logic to post services<commit_after>package k8s

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/servicebroker/servicebroker/k8s/service_controller/server"
	model "github.com/servicebroker/servicebroker/model/service_controller"
)

type K8sServiceStorage struct {
	// Host is the location where we'll talk to k8s
	host            string
	defaultResource string
}

const serviceDomain string = "cncf.org"
const apiVersion string = "v1alpha1"
const brokerResource string = "servicebrokers"
const defaultUri string = "http://%v/apis/" + serviceDomain + "/" + apiVersion + "/namespaces/default/" + brokerResource

// The k8s implementation should leverage Third Party Resources
// https://github.com/kubernetes/kubernetes/blob/master/docs/design/extending-api.md

var _ server.ServiceStorage = (*K8sServiceStorage)(nil)

type Meta struct {
	Name string `json:"name"`
}

type KubeData struct {
	ApiVersion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Metadata   Meta   `json:"metadata"`
}

type k8sServiceBroker struct {
	*model.ServiceBroker
	ApiVersion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Metadata   Meta   `json:"metadata"`
}

type k8sService struct {
	*model.Service
	ApiVersion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Metadata   Meta   `json:"metadata"`
}

type VName struct {
	Name string `json:"name"`
}

type TPR struct {
	Meta       `json:"metadata"`
	ApiVersion string  `json:"apiVersion"`
	kind       string  `json:"kind"`
	Versions   []VName `json:"versions"`
}

const TPRapiVersion string = "extensions/v1beta1"
const thirdPartyResourceString string = "ThirdPartyResource"

var versionMap []VName = []VName{{"v1alpha1"}}
var serviceBrokerMeta Meta = Meta{"service-broker.cncf.org"}
var serviceMeta Meta = Meta{"sbservice.cncf.org"} // sbservice so it does not conflict with the built in Service
var serviceBindingMeta Meta = Meta{"service-binding.cncf.org"}
var serviceInstanceMeta Meta = Meta{"service-instance.cncf.org"}
var serviceBrokerDefinition TPR = TPR{serviceBrokerMeta, TPRapiVersion, thirdPartyResourceString, versionMap}
var serviceDefinition TPR = TPR{serviceMeta, TPRapiVersion, thirdPartyResourceString, versionMap}
var serviceBindingDefinition TPR = TPR{serviceBindingMeta, TPRapiVersion, thirdPartyResourceString, versionMap}
var serviceInstanceDefinition TPR = TPR{serviceInstanceMeta, TPRapiVersion, thirdPartyResourceString, versionMap}

func CreateServiceStorage(host string) server.ServiceStorage {
	k := &K8sServiceStorage{host: host,
		defaultResource: fmt.Sprintf(defaultUri, host)}
	fmt.Println(" root host is:", k.defaultUri())
	// define the resources once at startup
	// results in ServiceBrokers

	k.createTPR(serviceBrokerDefinition)
	k.createTPR(serviceDefinition)
	k.createTPR(serviceBindingDefinition)
	k.createTPR(serviceInstanceDefinition)
	// cleanup afterwards by `kubectl delete thirdpartyresource service-broker.cncf.org`

	return k
}

// listSB is only used for unmarshalling the list of service brokers
// for returning to the client
type listSB struct {
	Items []*k8sServiceBroker `json:"items"`
}

func (kss *K8sServiceStorage) defaultUri() string {
	return kss.defaultResource
}

func (kss *K8sServiceStorage) createTPR(tpr TPR) {
	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(&tpr)
	fmt.Printf("encoded bytes: %v\n", b.String())
	r, e := http.Post("http://"+kss.host+"/apis/extensions/v1beta1/thirdpartyresources", "application/json", b)
	fmt.Printf("result: %v\n", r)
	if nil != e || 201 != r.StatusCode {
		fmt.Printf("Error creating k8s TPR [%s]...\n%v\n", e, r)
	}
}

func (kss *K8sServiceStorage) ListBrokers() ([]*model.ServiceBroker, error) {
	fmt.Println("listing all brokers")
	// get the ServiceBroker

	r, e := http.Get(kss.defaultUri())
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service brokers. %v, [%v]", e, r)
	}

	var lsb listSB
	e = json.NewDecoder(r.Body).Decode(&lsb)
	if nil != e { // wrong json format error
		fmt.Println("json not unmarshalled:", e, r)
		return nil, e
	}
	fmt.Println("Got", len(lsb.Items), "brokers.")
	ret := make([]*model.ServiceBroker, 0, len(lsb.Items))
	for _, v := range lsb.Items {
		ret = append(ret, v.ServiceBroker)
	}
	return ret, nil
}

func (kss *K8sServiceStorage) GetBroker(name string) (*model.ServiceBroker, error) {
	uri := kss.defaultUri() + "/" + name
	fmt.Println("uri is:", uri)
	r, e := http.Get(uri)
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service broker. %v, [%v]", e, r)
	}
	defer r.Body.Close()
	var sb k8sServiceBroker
	e = json.NewDecoder(r.Body).Decode(&sb)
	if nil != e { // wrong json format error
		return nil, e
	}
	fmt.Printf("returned json: %+v\n", sb)
	return sb.ServiceBroker, nil
}

func (kss *K8sServiceStorage) GetBrokerByService(id string) (*model.ServiceBroker, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetInventory() (*model.Catalog, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func NewK8sSB() *k8sServiceBroker {
	return &k8sServiceBroker{ApiVersion: serviceDomain + "/" + apiVersion,
		Kind: "ServiceBroker"}
}

func NewK8sService() *k8sService {
	return &k8sService{ApiVersion: serviceDomain + "/" + apiVersion,
		Kind: "Sbservice"}
}

func (kss *K8sServiceStorage) AddBroker(broker *model.ServiceBroker, catalog *model.Catalog) error {
	fmt.Println("adding broker to k8s", broker)
	// create TPR
	// tpr is
	//    kind.fqdn
	// or
	//    kind.domain.tld
	//
	// use service-broker.cncf.org
	// end up with k8s resource of ServiceBroker
	// version v1alpha1 for now
	//
	// store name/host/port/user/pass as metadata
	//
	// example yaml
	// metadata:
	//   name: service-broker.cncf.org
	//   (service)name/host/port/user/pass
	// apiVersion: extensions/v1beta1
	// kind: ThirdPartyResource
	// versions:
	// - name: v1alpha1
	ksb := NewK8sSB()
	ksb.Metadata = Meta{Name: broker.GUID}
	ksb.ServiceBroker = broker

	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(&ksb)
	fmt.Printf("sending: %v", b)
	r, e := http.Post(kss.defaultUri(), "application/json", b)
	fmt.Sprintf("result: %v", r)
	if nil != e || 201 != r.StatusCode {
		fmt.Printf("Error creating k8s service broker TPR [%s]...\n%v\n", e, r)
		return e
	}

	fmt.Println("installing the", len(catalog.Services), "services for this broker")
	for i, service := range catalog.Services {
		fmt.Println(i, service)

		ks := NewK8sService()
		ks.Metadata = Meta{Name: service.ID}
		ks.Service = service

		b := new(bytes.Buffer)
		if err := json.NewEncoder(b).Encode(&ks); nil != err {
			fmt.Println("failed to encode")
			return err
		}
		defaultUri := "http://%v/apis/" + serviceDomain + "/" + apiVersion + "/namespaces/default/" + "sbservices"
		fmt.Printf("sending: %v\n to %v", b, defaultUri)
		r, e := http.Post(fmt.Sprintf(defaultUri, kss.host), "application/json", b)
		fmt.Sprintf("result: %v", r)
		if nil != e || 201 != r.StatusCode {
			fmt.Printf("Error creating k8s service TPR [%s]...\n%v\n", e, r)
			return e
		}
	}

	return nil
}

func (kss *K8sServiceStorage) DeleteBroker(name string) error {
	uri := kss.defaultUri() + "/" + name
	fmt.Println("uri is:", uri)

	// utter failure of an http API
	req, _ := http.NewRequest("DELETE", uri, nil)
	_, e := http.DefaultClient.Do(req)
	if nil != e {
		return fmt.Errorf("couldn't nuke %v, [%v]", name, e)
	}
	return nil
}

func (kss *K8sServiceStorage) ServiceExists(id string) bool {
	return false
}

func (kss *K8sServiceStorage) ListServices() ([]*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetService(id string) (*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) SetService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteService(id string) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) ListServiceBindings() ([]*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetServiceBinding(id string) (*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddServiceBinding(binding *model.ServiceBinding, cred *model.Credential) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteServiceBinding(id string) error {
	return fmt.Errorf("Not implemented yet")
}
<|endoftext|>


<commit_before>package quorum

import (
	"common"
)

func RandomPlacement(toPlace int, SEED string) []int {
	ascii := []byte(SEED)
	intAscii := make([]int, len(ascii))
	buckets := make([]int, common.QUORUMSIZE)
	tmp := toPlace
	index := 0
	ascInd := 0
	//splits toPlace into the buckets according to given SEED
	for tmp != 0 {
		index += intAscii[ascInd]
		if index >= common.QUORUMSIZE {
			index = index - common.QUORUMSIZE
		}
		buckets[index] += 1
		tmp--
		ascInd++
		if ascInd == len(intAscii) {
			ascInd = 0
		}
	}
	return buckets
}
<commit_msg>Fixed randomplacement<commit_after>package quorum

import (
	"common"
)

func RandomPlacement(toPlace int, SEED string) []int {
	ascii := []byte(SEED)
	intAscii := make([]int, len(ascii))
	buckets := make([]int, common.QuorumSize)
	tmp := toPlace
	index := 0
	ascInd := 0
	//splits toPlace into the buckets according to given SEED
	for tmp != 0 {
		index += intAscii[ascInd]
		if index >= common.QuorumSize {
			index = index - common.QuorumSize
		}
		buckets[index] += 1
		tmp--
		ascInd++
		if ascInd == len(intAscii) {
			ascInd = 0
		}
	}
	return buckets
}
<|endoftext|>