<commit_before>package edy

import (
	"../felica"
	"fmt"
	"strings"
	"time"
	"unsafe"
)

/*
 #include "edy_get.h"
*/
import "C"

type felica_module string

var Module felica_module = "Edy"

// Edy
type Edy struct {
	Info EdyInfo     // Edyカード情報
	Last EdyLast     // Edy残額情報
	Hist []*EdyValue // 利用履歴

	cardinfo felica.CardInfo // カード情報（生データ）
}

// Edyカード情報
type EdyInfo struct {
	EdyNo []byte // Edy番号

	Raw [][]byte // Rawデータ
}

// Edy残額情報（最終利用状況）
type EdyLast struct {
	Rest int // 残額
	Use  int // 直近使用金額（チャージのときは更新されない場合がある）
	No   int // 取引通番

	Raw [][]byte // Rawデータ
}

// Edy利用履歴データ
type EdyValue struct {
	DateTime time.Time // 処理日時
	Type     int       // 端末種
	No       int       // 連番
	Use      int       // 入金／出金
	Rest     int       // 残額金

	Charge  int // チャージ
	Payment int // 支払い

	Raw []byte // Rawデータ
}

const (
	FELICA_POLLING_EDY  = uint16(C.FELICA_POLLING_EDY)  // Edyシステムコード
	FELICA_SC_EDY_INFO  = uint16(C.FELICA_SC_EDY_INFO)  // Edyカード情報・サービスコード
	FELICA_SC_EDY_LAST  = uint16(C.FELICA_SC_EDY_LAST)  // Edy残額情報・サービスコード
	FELICA_SC_EDY_VALUE = uint16(C.FELICA_SC_EDY_VALUE) // Edy利用履歴データ・サービスコード
)

// *** felica_module メソッド
// 対応カードか？
func (module *felica_module) IsCard(cardinfo felica.CardInfo) bool {
	for syscode, _ := range cardinfo {
		if syscode == FELICA_POLLING_EDY {
			return true
		}
	}

	return false
}

// CardInfo を束縛した Engine を作成する
func (module *felica_module) Bind(cardinfo felica.CardInfo) felica.Engine {
	return &Edy{cardinfo: cardinfo}
}

// *** Edy メソッド
// カード名
func (edy *Edy) Name() string {
	return string(Module)
}

// カード情報を読込む
func (edy *Edy) Read() {
	if 0 < len(edy.Hist) {
		// 読込済みなら何もしない
		return
	}

	cardinfo := edy.cardinfo

	// システムデータの取得
	currsys := cardinfo[FELICA_POLLING_EDY]

	// Edyカード情報
	raw_info := currsys.Services[FELICA_SC_EDY_INFO]
	edy.Info.Raw = raw_info

	info := (*C.edy_info0_t)(felica.DataPtr(&raw_info[0]))

	edyno := unsafe.Pointer(&info.edyno[0])
	edy.Info.EdyNo = C.GoBytes(edyno, C.int(unsafe.Sizeof(edyno)))

	// Edy残額情報（最終利用状況）
	raw_last := currsys.Services[FELICA_SC_EDY_LAST]
	edy.Last.Raw = raw_last

	last := (*C.edy_last_t)(felica.DataPtr(&raw_last[0]))
	edy.Last.Rest = int(C.edy_last_rest(last))
	edy.Last.Use = int(C.edy_last_use(last))
	edy.Last.No = int(C.edy_last_no(last))

	// Edy利用履歴
	for _, raw := range currsys.Services[FELICA_SC_EDY_VALUE] {
		history := (*C.edy_value_t)(felica.DataPtr(&raw))
		h_time := C.edy_value_datetime(history)
		if h_time == 0 {
			continue
		}

		value := EdyValue{}
		value.DateTime = time.Unix(int64(h_time), 0)
		value.Type = int(C.edy_value_type(history))
		value.No = int(C.edy_value_no(history))
		value.Use = int(C.edy_value_use(history))
		value.Rest = int(C.edy_value_rest(history))
		value.Raw = raw

		edy.Hist = append(edy.Hist, &value)
	}

	for _, value := range edy.Hist {
		switch value.Type {
		case 0x02, 0x04: // 入金（チャージ）, 入金（Edyギフト）
			value.Charge = value.Use
		case 0x20: // 出金
			value.Payment = value.Use
		}
	}
}

// カード情報を表示する
func (edy *Edy) ShowInfo(options *felica.Options) {
	// テーブルデータの読込み
	if edy_tables == nil {
		edy_tables, _ = felica.LoadYAML("edy.yml")
	}

	// データの読込み
	edy.Read()

	// インデント
	indent := 0
	indent_space := ""

	if options.Hex {
		indent = 38
		indent_space = strings.Repeat(" ", indent)
	}

	// 表示
	fmt.Println("\n[Edyカード情報]")
	if options.Hex {
		fmt.Println()
		for _, v := range edy.Info.Raw {
			fmt.Printf("   %16X\n", v)
		}
	}
	fmt.Printf("\n  Edy番号: %v\n", edy.Info.EdyNoDisp())

	fmt.Println("\n[Edy残額情報]")
	if options.Hex {
		fmt.Println()
		for _, v := range edy.Last.Raw {
			fmt.Printf("   %16X\n", v)
		}
	}
	fmt.Printf(`
  残額: %14d円
  直近使用金額: %6d円
  取引通番: %10d
`, edy.Last.Rest, edy.Last.Use, edy.Last.No)

	if options.Extend || options.Hex {
		fmt.Println("\n[利用履歴（元データ）]\n")
		fmt.Printf("%s      利用年月日         支払い        残額  (連番)  タイプ\n", indent_space)
		fmt.Printf("  %s\n", strings.Repeat("-", indent+85))
		for _, value := range edy.Hist {
			if options.Hex {
				fmt.Printf("   %16X   ", value.Raw)
			}
			fmt.Printf("   %s  %8d円  %8d円  (%4d)  %v\n",
				value.DateTime.Format("2006-01-02 15:04"),
				value.Use,
				value.Rest,
				value.No,
				value.TypeName())
		}
	}

	fmt.Println("\n[利用履歴]\n")
	fmt.Printf("%s      利用年月日        チャージ      支払い        残額  (連番)  タイプ\n", indent_space)
	fmt.Printf("  %s\n", strings.Repeat("-", indent+98))
	for _, value := range edy.Hist {
		if options.Hex {
			fmt.Printf("   %16X   ", value.Raw)
		}
		fmt.Printf("   %s  %10v  %10v  %8d円  (%4d)  %v\n",
			value.DateTime.Format("2006-01-02 15:04"),
			disp_money(value.Charge),
			disp_money(value.Payment),
			value.Rest,
			value.No,
			value.TypeName())
	}
}

// *** EdyInfo メソッド
// Edy番号
func (info *EdyInfo) EdyNoDisp() string {
	edyno := info.EdyNo
	return fmt.Sprintf("%0X-%0X-%0X-%X", edyno[:2], edyno[2:4], edyno[4:6], edyno[6:])
}

// タイプ
func (value *EdyValue) TypeName() interface{} {
	return edy_disp_name("TYPE", value.Type, 2)
}

// *** 表示用関数
// 金額（0円なら空文字列）
func disp_money(money int) string {
	if money == 0 {
		return ""
	}

	return fmt.Sprintf("%d円", money)
}

// ***
// Edyテーブル
var edy_tables map[interface{}]interface{}

// Edyテーブルを検索して表示用の文字列を返す
func edy_disp_name(name string, value int, base int, opt_values ...int) interface{} {
	return felica.DispName(edy_tables, name, value, base, opt_values...)
}
<commit_msg>nanaco/waonカードを間違って Edy と認識してしまいエラーになってしまう問題を修正<commit_after>package edy

import (
	"../felica"
	"fmt"
	"strings"
	"time"
	"unsafe"
)

/*
 #include "edy_get.h"
*/
import "C"

type felica_module string

var Module felica_module = "Edy"

// Edy
type Edy struct {
	Info EdyInfo     // Edyカード情報
	Last EdyLast     // Edy残額情報
	Hist []*EdyValue // 利用履歴

	cardinfo felica.CardInfo // カード情報（生データ）
}

// Edyカード情報
type EdyInfo struct {
	EdyNo []byte // Edy番号

	Raw [][]byte // Rawデータ
}

// Edy残額情報（最終利用状況）
type EdyLast struct {
	Rest int // 残額
	Use  int // 直近使用金額（チャージのときは更新されない場合がある）
	No   int // 取引通番

	Raw [][]byte // Rawデータ
}

// Edy利用履歴データ
type EdyValue struct {
	DateTime time.Time // 処理日時
	Type     int       // 端末種
	No       int       // 連番
	Use      int       // 入金／出金
	Rest     int       // 残額金

	Charge  int // チャージ
	Payment int // 支払い

	Raw []byte // Rawデータ
}

const (
	FELICA_POLLING_EDY  = uint16(C.FELICA_POLLING_EDY)  // Edyシステムコード
	FELICA_SC_EDY_INFO  = uint16(C.FELICA_SC_EDY_INFO)  // Edyカード情報・サービスコード
	FELICA_SC_EDY_LAST  = uint16(C.FELICA_SC_EDY_LAST)  // Edy残額情報・サービスコード
	FELICA_SC_EDY_VALUE = uint16(C.FELICA_SC_EDY_VALUE) // Edy利用履歴データ・サービスコード
)

// *** felica_module メソッド
// 対応カードか？
func (module *felica_module) IsCard(cardinfo felica.CardInfo) bool {
	for syscode, currsys := range cardinfo {
		if syscode == FELICA_POLLING_EDY {
			if currsys.Services[FELICA_SC_EDY_INFO] != nil {
				return true
			}
			break
		}
	}

	return false
}

// CardInfo を束縛した Engine を作成する
func (module *felica_module) Bind(cardinfo felica.CardInfo) felica.Engine {
	return &Edy{cardinfo: cardinfo}
}

// *** Edy メソッド
// カード名
func (edy *Edy) Name() string {
	return string(Module)
}

// カード情報を読込む
func (edy *Edy) Read() {
	if 0 < len(edy.Hist) {
		// 読込済みなら何もしない
		return
	}

	cardinfo := edy.cardinfo

	// システムデータの取得
	currsys := cardinfo[FELICA_POLLING_EDY]

	// Edyカード情報
	raw_info := currsys.Services[FELICA_SC_EDY_INFO]
	edy.Info.Raw = raw_info

	info := (*C.edy_info0_t)(felica.DataPtr(&raw_info[0]))

	edyno := unsafe.Pointer(&info.edyno[0])
	edy.Info.EdyNo = C.GoBytes(edyno, C.int(unsafe.Sizeof(edyno)))

	// Edy残額情報（最終利用状況）
	raw_last := currsys.Services[FELICA_SC_EDY_LAST]
	edy.Last.Raw = raw_last

	last := (*C.edy_last_t)(felica.DataPtr(&raw_last[0]))
	edy.Last.Rest = int(C.edy_last_rest(last))
	edy.Last.Use = int(C.edy_last_use(last))
	edy.Last.No = int(C.edy_last_no(last))

	// Edy利用履歴
	for _, raw := range currsys.Services[FELICA_SC_EDY_VALUE] {
		history := (*C.edy_value_t)(felica.DataPtr(&raw))
		h_time := C.edy_value_datetime(history)
		if h_time == 0 {
			continue
		}

		value := EdyValue{}
		value.DateTime = time.Unix(int64(h_time), 0)
		value.Type = int(C.edy_value_type(history))
		value.No = int(C.edy_value_no(history))
		value.Use = int(C.edy_value_use(history))
		value.Rest = int(C.edy_value_rest(history))
		value.Raw = raw

		edy.Hist = append(edy.Hist, &value)
	}

	for _, value := range edy.Hist {
		switch value.Type {
		case 0x02, 0x04: // 入金（チャージ）, 入金（Edyギフト）
			value.Charge = value.Use
		case 0x20: // 出金
			value.Payment = value.Use
		}
	}
}

// カード情報を表示する
func (edy *Edy) ShowInfo(options *felica.Options) {
	// テーブルデータの読込み
	if edy_tables == nil {
		edy_tables, _ = felica.LoadYAML("edy.yml")
	}

	// データの読込み
	edy.Read()

	// インデント
	indent := 0
	indent_space := ""

	if options.Hex {
		indent = 38
		indent_space = strings.Repeat(" ", indent)
	}

	// 表示
	fmt.Println("\n[Edyカード情報]")
	if options.Hex {
		fmt.Println()
		for _, v := range edy.Info.Raw {
			fmt.Printf("   %16X\n", v)
		}
	}
	fmt.Printf("\n  Edy番号: %v\n", edy.Info.EdyNoDisp())

	fmt.Println("\n[Edy残額情報]")
	if options.Hex {
		fmt.Println()
		for _, v := range edy.Last.Raw {
			fmt.Printf("   %16X\n", v)
		}
	}
	fmt.Printf(`
  残額: %14d円
  直近使用金額: %6d円
  取引通番: %10d
`, edy.Last.Rest, edy.Last.Use, edy.Last.No)

	if options.Extend || options.Hex {
		fmt.Println("\n[利用履歴（元データ）]\n")
		fmt.Printf("%s      利用年月日         支払い        残額  (連番)  タイプ\n", indent_space)
		fmt.Printf("  %s\n", strings.Repeat("-", indent+85))
		for _, value := range edy.Hist {
			if options.Hex {
				fmt.Printf("   %16X   ", value.Raw)
			}
			fmt.Printf("   %s  %8d円  %8d円  (%4d)  %v\n",
				value.DateTime.Format("2006-01-02 15:04"),
				value.Use,
				value.Rest,
				value.No,
				value.TypeName())
		}
	}

	fmt.Println("\n[利用履歴]\n")
	fmt.Printf("%s      利用年月日        チャージ      支払い        残額  (連番)  タイプ\n", indent_space)
	fmt.Printf("  %s\n", strings.Repeat("-", indent+98))
	for _, value := range edy.Hist {
		if options.Hex {
			fmt.Printf("   %16X   ", value.Raw)
		}
		fmt.Printf("   %s  %10v  %10v  %8d円  (%4d)  %v\n",
			value.DateTime.Format("2006-01-02 15:04"),
			disp_money(value.Charge),
			disp_money(value.Payment),
			value.Rest,
			value.No,
			value.TypeName())
	}
}

// *** EdyInfo メソッド
// Edy番号
func (info *EdyInfo) EdyNoDisp() string {
	edyno := info.EdyNo
	return fmt.Sprintf("%0X-%0X-%0X-%X", edyno[:2], edyno[2:4], edyno[4:6], edyno[6:])
}

// タイプ
func (value *EdyValue) TypeName() interface{} {
	return edy_disp_name("TYPE", value.Type, 2)
}

// *** 表示用関数
// 金額（0円なら空文字列）
func disp_money(money int) string {
	if money == 0 {
		return ""
	}

	return fmt.Sprintf("%d円", money)
}

// ***
// Edyテーブル
var edy_tables map[interface{}]interface{}

// Edyテーブルを検索して表示用の文字列を返す
func edy_disp_name(name string, value int, base int, opt_values ...int) interface{} {
	return felica.DispName(edy_tables, name, value, base, opt_values...)
}
<|endoftext|>


<commit_before>package main

type element struct {
	Name  string
	Links []*element
}

var (
	_ element
	air, earth, fire, ice
	dust, lava, water, steam, mist, smoke, mud
	time, gravity, electric, light, dark
	void, spiritual, chaotic, illusion
)

type Element uint8

const (
	Air Element = iota
	Earth
	Fire
	Ice
	Dust
	Lava
	Water
	Steam
	Mist
	Smoke
	Mud
	Time
	Gravity
	Electric
	Light
	Dark
	Void
	Spiritual
	Chaotic
	Illusion

	elementCount
)

var elements [elementCount]*Element

func init() {
	air = element{
		Name:  "Air",
		Links: []*element{&smoke, &dust, &mist},
	}
	earth = element{
		Name:  "Earth",
		Links: []*element{&dust, &mud, &lava},
	}
	fire = element{
		Name:  "Fire",
		Links: []*element{&smoke, &lava, &steam},
	}
	ice = element{
		Name:  "Ice",
		Links: []*element{&water, &mist},
	}
	dust = element{
		Name:  "Dust",
		Links: []*element{&earth, &air},
	}
	lava = element{
		Name:  "Lava",
		Links: []*element{&earth, &fire},
	}
	water = element{
		Name:  "Water",
		Links: []*element{&mist, &steam, &mud, &ice},
	}
	steam = element{
		Name:  "Steam",
		Links: []*element{&water, &fire},
	}
	mist = element{
		Name:  "Mist",
		Links: []*element{&air, &water},
	}
	smoke = element{
		Name:  "Smoke",
		Links: []*element{&air, &fire},
	}
	mud = element{
		Name:  "Mud",
		Links: []*element{&water, &earth},
	}
	time = element{
		Name:  "Time",
		Links: []*element{&earth, &gravity, &void},
	}
	gravity = element{
		Name:  "Gravity",
		Links: []*element{&earth, &water, &time},
	}
	electric = element{
		Name:  "Electric",
		Links: []*element{&air, &light, &void},
	}
	light = element{
		Name:  "Light",
		Links: []*element{&air, &water, &electric},
	}
	dark = element{
		Name:  "Dark",
		Links: []*element{&fire, &smoke, &void},
	}
	void = element{
		Name:  "Void",
		Links: []*element{&dark, &time, &illusion},
	}
	spiritual = element{
		Name:  "Spiritual",
		Links: []*element{&air, &mist, &time},
	}
	chaotic = element{
		Name:  "Chaotic",
		Links: []*element{&light, &dark, &void},
	}
	illusion = element{
		Name:  "Illusion",
		Links: []*element{&void, &time, &gravity},
	}
	elements[Air] = &air
	// TODO: other elements
}
<commit_msg>fix build<commit_after>package main

type element struct {
	Name  string
	Links []*element
}

var (
	air, earth, fire, ice                      element
	dust, lava, water, steam, mist, smoke, mud element
	time, gravity, electric, light, dark       element
	void, spiritual, chaotic, illusion         element
)

type Element uint8

const (
	Air Element = iota
	Earth
	Fire
	Ice
	Dust
	Lava
	Water
	Steam
	Mist
	Smoke
	Mud
	Time
	Gravity
	Electric
	Light
	Dark
	Void
	Spiritual
	Chaotic
	Illusion

	elementCount
)

var elements [elementCount]*element

func init() {
	air = element{
		Name:  "Air",
		Links: []*element{&smoke, &dust, &mist},
	}
	earth = element{
		Name:  "Earth",
		Links: []*element{&dust, &mud, &lava},
	}
	fire = element{
		Name:  "Fire",
		Links: []*element{&smoke, &lava, &steam},
	}
	ice = element{
		Name:  "Ice",
		Links: []*element{&water, &mist},
	}
	dust = element{
		Name:  "Dust",
		Links: []*element{&earth, &air},
	}
	lava = element{
		Name:  "Lava",
		Links: []*element{&earth, &fire},
	}
	water = element{
		Name:  "Water",
		Links: []*element{&mist, &steam, &mud, &ice},
	}
	steam = element{
		Name:  "Steam",
		Links: []*element{&water, &fire},
	}
	mist = element{
		Name:  "Mist",
		Links: []*element{&air, &water},
	}
	smoke = element{
		Name:  "Smoke",
		Links: []*element{&air, &fire},
	}
	mud = element{
		Name:  "Mud",
		Links: []*element{&water, &earth},
	}
	time = element{
		Name:  "Time",
		Links: []*element{&earth, &gravity, &void},
	}
	gravity = element{
		Name:  "Gravity",
		Links: []*element{&earth, &water, &time},
	}
	electric = element{
		Name:  "Electric",
		Links: []*element{&air, &light, &void},
	}
	light = element{
		Name:  "Light",
		Links: []*element{&air, &water, &electric},
	}
	dark = element{
		Name:  "Dark",
		Links: []*element{&fire, &smoke, &void},
	}
	void = element{
		Name:  "Void",
		Links: []*element{&dark, &time, &illusion},
	}
	spiritual = element{
		Name:  "Spiritual",
		Links: []*element{&air, &mist, &time},
	}
	chaotic = element{
		Name:  "Chaotic",
		Links: []*element{&light, &dark, &void},
	}
	illusion = element{
		Name:  "Illusion",
		Links: []*element{&void, &time, &gravity},
	}
	elements[Air] = &air
	// TODO: other elements
}
<|endoftext|>


<commit_before>package main

type element struct {
	Name  string
	Links []*element
}

var (
	air, earth, fire, ice, nature              element
	dust, lava, water, steam, mist, smoke, mud element
	time_, gravity, electric, light, dark      element
	void, spiritual, chaotic, illusion         element
)

type Element uint8

const (
	Air Element = iota
	Earth
	Fire
	Ice
	Nature
	Dust
	Lava
	Water
	Steam
	Mist
	Smoke
	Mud
	Time
	Gravity
	Electric
	Light
	Dark
	Void
	Spiritual
	Chaotic
	Illusion

	elementCount
)

var elements [elementCount]*element

func init() {
	air = element{
		Name:  "Air",
		Links: []*element{&smoke, &dust, &mist, &nature},
	}
	elements[Air] = &air
	earth = element{
		Name:  "Earth",
		Links: []*element{&dust, &mud, &lava, &nature},
	}
	elements[Earth] = &earth
	fire = element{
		Name:  "Fire",
		Links: []*element{&smoke, &lava, &steam, &nature},
	}
	elements[Fire] = &fire
	ice = element{
		Name:  "Ice",
		Links: []*element{&water, &mist, &nature},
	}
	elements[Ice] = &ice
	nature = element{
		Name:  "Nature",
		Links: []*element{}, //special: all elements contain nature
	}
	elements[Nature] = &nature
	dust = element{
		Name:  "Dust",
		Links: []*element{&earth, &air, &nature},
	}
	elements[Dust] = &dust
	lava = element{
		Name:  "Lava",
		Links: []*element{&earth, &fire, &nature},
	}
	elements[Lava] = &lava
	water = element{
		Name:  "Water",
		Links: []*element{&mist, &steam, &mud, &ice, &nature},
	}
	elements[Water] = &water
	steam = element{
		Name:  "Steam",
		Links: []*element{&water, &fire, &nature},
	}
	elements[Steam] = &steam
	mist = element{
		Name:  "Mist",
		Links: []*element{&air, &water, &nature},
	}
	elements[Mist] = &mist
	smoke = element{
		Name:  "Smoke",
		Links: []*element{&air, &fire, &nature},
	}
	elements[Smoke] = &smoke
	mud = element{
		Name:  "Mud",
		Links: []*element{&water, &earth, &nature},
	}
	elements[Mud] = &mud
	time_ = element{
		Name:  "Time",
		Links: []*element{&earth, &gravity, &void, &nature},
	}
	elements[Time] = &time_
	gravity = element{
		Name:  "Gravity",
		Links: []*element{&earth, &water, &time_, &nature},
	}
	elements[Gravity] = &gravity
	electric = element{
		Name:  "Electric",
		Links: []*element{&air, &light, &void, &nature},
	}
	elements[Electric] = &electric
	light = element{
		Name:  "Light",
		Links: []*element{&air, &water, &electric, &spiritual, &nature},
	}
	elements[Light] = &light
	dark = element{
		Name:  "Dark",
		Links: []*element{&fire, &smoke, &void, &spiritual, &nature},
	}
	elements[Dark] = &dark
	void = element{
		Name:  "Void",
		Links: []*element{&dark, &time_, &illusion, &nature},
	}
	elements[Void] = &void
	spiritual = element{
		Name:  "Spiritual",
		Links: []*element{&air, &mist, &time_, &nature},
	}
	elements[Spiritual] = &spiritual
	chaotic = element{
		Name:  "Chaotic",
		// Special: Chaotic zones contain all element types.
	}
	elements[Chaotic] = &chaotic
	illusion = element{
		Name:  "Illusion",
		Links: []*element{&void, &time_, &gravity, &nature},
	}
	elements[Illusion] = &illusion
}
<commit_msg>fix build<commit_after>package main

type element struct {
	Name  string
	Links []*element
}

var (
	air, earth, fire, ice, nature              element
	dust, lava, water, steam, mist, smoke, mud element
	time_, gravity, electric, light, dark      element
	void, spiritual, chaotic, illusion         element
)

type Element uint8

const (
	Air Element = iota
	Earth
	Fire
	Ice
	Nature
	Dust
	Lava
	Water
	Steam
	Mist
	Smoke
	Mud
	Time
	Gravity
	Electric
	Light
	Dark
	Void
	Spiritual
	Chaotic
	Illusion

	elementCount
)

var elements [elementCount]*element

func init() {
	air = element{
		Name:  "Air",
		Links: []*element{&smoke, &dust, &mist, &nature},
	}
	elements[Air] = &air
	earth = element{
		Name:  "Earth",
		Links: []*element{&dust, &mud, &lava, &nature},
	}
	elements[Earth] = &earth
	fire = element{
		Name:  "Fire",
		Links: []*element{&smoke, &lava, &steam, &nature},
	}
	elements[Fire] = &fire
	ice = element{
		Name:  "Ice",
		Links: []*element{&water, &mist, &nature},
	}
	elements[Ice] = &ice
	nature = element{
		Name:  "Nature",
		Links: []*element{&air, &water, &earth},
	}
	elements[Nature] = &nature
	dust = element{
		Name:  "Dust",
		Links: []*element{&earth, &air},
	}
	elements[Dust] = &dust
	lava = element{
		Name:  "Lava",
		Links: []*element{&earth, &fire},
	}
	elements[Lava] = &lava
	water = element{
		Name:  "Water",
		Links: []*element{&mist, &steam, &mud, &ice},
	}
	elements[Water] = &water
	steam = element{
		Name:  "Steam",
		Links: []*element{&water, &fire},
	}
	elements[Steam] = &steam
	mist = element{
		Name:  "Mist",
		Links: []*element{&air, &water},
	}
	elements[Mist] = &mist
	smoke = element{
		Name:  "Smoke",
		Links: []*element{&air, &fire},
	}
	elements[Smoke] = &smoke
	mud = element{
		Name:  "Mud",
		Links: []*element{&water, &earth},
	}
	elements[Mud] = &mud
	time_ = element{
		Name:  "Time",
		Links: []*element{&earth, &gravity, &void},
	}
	elements[Time] = &time_
	gravity = element{
		Name:  "Gravity",
		Links: []*element{&earth, &water, &time_},
	}
	elements[Gravity] = &gravity
	electric = element{
		Name:  "Electric",
		Links: []*element{&air, &light, &void},
	}
	elements[Electric] = &electric
	light = element{
		Name:  "Light",
		Links: []*element{&air, &water, &electric, &spiritual},
	}
	elements[Light] = &light
	dark = element{
		Name:  "Dark",
		Links: []*element{&fire, &smoke, &void, &spiritual},
	}
	elements[Dark] = &dark
	void = element{
		Name:  "Void",
		Links: []*element{&dark, &time_, &illusion},
	}
	elements[Void] = &void
	spiritual = element{
		Name:  "Spiritual",
		Links: []*element{&air, &mist, &time_},
	}
	elements[Spiritual] = &spiritual
	chaotic = element{
		Name:  "Chaotic",
		// Special: Chaotic zones contain all element types.
	}
	elements[Chaotic] = &chaotic
	illusion = element{
		Name:  "Illusion",
		Links: []*element{&void, &time_, &gravity},
	}
	elements[Illusion] = &illusion
}
<|endoftext|>


<commit_before>package deb

import (
	"path"
	"testing"
)

func TestDefaultPackageSpec(t *testing.T) {
	p := DefaultPackageSpec()
	expected := "deb-pkg"
	if p.AutoPath != expected {
		t.Fatalf("Expected AutoPath to be %q, got %q", expected, p.AutoPath)
	}
}

func TestFilename(t *testing.T) {
	p := &PackageSpec{
		Package:      "mkdeb",
		Version:      "0.1.0",
		Architecture: "amd64",
	}
	expected := "mkdeb-0.1.0-amd64.deb"
	if p.Filename() != expected {
		t.Fatalf("Expected filename to be %q, got %q", expected, p.Filename())
	}
}

func TestValidate(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	if err := p.Validate(); err != nil {
		t.Fatal(err)
	}

	p2 := &PackageSpec{}
	err = p2.Validate()
	expected := "These required fields are missing: package, version, architecture, maintainer, description"
	if err.Error() != expected {
		t.Fatalf("-- Expected --\n%s\n-- Found --\n%s\n", expected, err.Error())
	}
}

func TestListControlFiles(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	files, err := p.ListControlFiles()
	if err != nil {
		t.Fatalf("Failed to list control files: %s", err)
	}

	search := "test-fixtures/package1/preinst"
	if !hasString(files, search) {
		t.Errorf("Unable to find %q in %+v", search, files)
	}
}

func TestListFiles(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	files, err := p.ListFiles()
	if err != nil {
		t.Fatal(err)
	}

	configPath := path.Join("test-fixtures", "package1", "etc", "package1", "config")
	if !hasString(files, configPath) {
		t.Errorf("%q is missing: %+v", configPath, files)
	}

	binaryPath := path.Join("test-fixtures", "package1", "usr", "local", "bin", "package1")
	if !hasString(files, binaryPath) {
		t.Errorf("%q is missing: %+v", binaryPath, files)
	}
}

func TestCalculateSize(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	// find deb/test-fixtures/package1/ | xargs cat 2>/dev/null | wc -c
	// divide by 1024 and round up remainder to go from bytes => kilobytes
	expected := int64(1)

	size, err := p.CalculateSize()
	if err != nil {
		t.Fatal(err)
	}
	if size != expected {
		t.Errorf("Expected %d got %d", expected, size)
	}
}

func TestNormalizeFilename(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	configPath := path.Join("test-fixtures", "package1", "etc", "package1", "config")
	configExpected := "etc/package1/config"
	if filename, err := p.NormalizeFilename(configPath); err != nil {
		t.Fatal()
	} else if filename != configExpected {
		t.Errorf("Expected %q got %q", configExpected, filename)
	}

	hardcodedPath := "package1/binary"
	hardcodedExpected := "usr/local/bin/package1"
	if filename, err := p.NormalizeFilename(hardcodedPath); err != nil {
		t.Fatal()
	} else if filename != hardcodedExpected {
		t.Errorf("Expected %q got %q", hardcodedExpected, filename)
	}
}

func TestListEtcFiles(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	files, err := p.ListEtcFiles()
	if err != nil {
		t.Fatal(err)
	}

	if len(files) == 0 {
		t.Fatalf("No config files found")
	}

	expected := "/etc/package1/config"
	if files[0] != expected {
		t.Errorf("Expected %q got %q", expected, files[0])
	}
}

func TestUpgradeConfig(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}
	p.UpgradeConfigs = true

	data, err := p.ListEtcFiles()
	if err != nil {
		t.Fatal(err)
	}

	if len(data) != 0 {
		t.Errorf("Found unexpected config files in conffiles list: %+v", data)
	}
}

func TestMD5SumFile(t *testing.T) {
	sum, err := md5SumFile(path.Join("test-fixtures", "example-depends.json"))
	if err != nil {
		t.Fatal(err)
	}

	expected := "e8f79d2b1995292911388a9d13a9528d"
	if sum != expected {
		t.Errorf("Expected %q got %q", expected, sum)
	}
}

func TestCalculateChecksums(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	expected := `adcc07f30ee844b18eab61f69f8c32c4  etc/package1/config
0940b4d946e3e2b8bbfdf5cfcf722518  usr/local/bin/package1
`

	data, err := p.CalculateChecksums()
	if err != nil {
		t.Fatal(err)
	}

	found := string(data)
	if found != expected {
		t.Errorf("--Expected--\n%s\n--Found--\n%s\n", expected, found)
	}
}

func TestBuild(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	err = p.Build("output")
}
<commit_msg>Updated build test to error on failure<commit_after>package deb

import (
	"os"
	"path"
	"testing"
)

func TestDefaultPackageSpec(t *testing.T) {
	p := DefaultPackageSpec()
	expected := "deb-pkg"
	if p.AutoPath != expected {
		t.Fatalf("Expected AutoPath to be %q, got %q", expected, p.AutoPath)
	}
}

func TestFilename(t *testing.T) {
	p := &PackageSpec{
		Package:      "mkdeb",
		Version:      "0.1.0",
		Architecture: "amd64",
	}
	expected := "mkdeb-0.1.0-amd64.deb"
	if p.Filename() != expected {
		t.Fatalf("Expected filename to be %q, got %q", expected, p.Filename())
	}
}

func TestValidate(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	if err := p.Validate(); err != nil {
		t.Fatal(err)
	}

	p2 := &PackageSpec{}
	err = p2.Validate()
	expected := "These required fields are missing: package, version, architecture, maintainer, description"
	if err.Error() != expected {
		t.Fatalf("-- Expected --\n%s\n-- Found --\n%s\n", expected, err.Error())
	}
}

func TestListControlFiles(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	files, err := p.ListControlFiles()
	if err != nil {
		t.Fatalf("Failed to list control files: %s", err)
	}

	search := "test-fixtures/package1/preinst"
	if !hasString(files, search) {
		t.Errorf("Unable to find %q in %+v", search, files)
	}
}

func TestListFiles(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	files, err := p.ListFiles()
	if err != nil {
		t.Fatal(err)
	}

	configPath := path.Join("test-fixtures", "package1", "etc", "package1", "config")
	if !hasString(files, configPath) {
		t.Errorf("%q is missing: %+v", configPath, files)
	}

	binaryPath := path.Join("test-fixtures", "package1", "usr", "local", "bin", "package1")
	if !hasString(files, binaryPath) {
		t.Errorf("%q is missing: %+v", binaryPath, files)
	}
}

func TestCalculateSize(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	// find deb/test-fixtures/package1/ | xargs cat 2>/dev/null | wc -c
	// divide by 1024 and round up remainder to go from bytes => kilobytes
	expected := int64(1)

	size, err := p.CalculateSize()
	if err != nil {
		t.Fatal(err)
	}
	if size != expected {
		t.Errorf("Expected %d got %d", expected, size)
	}
}

func TestNormalizeFilename(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	configPath := path.Join("test-fixtures", "package1", "etc", "package1", "config")
	configExpected := "etc/package1/config"
	if filename, err := p.NormalizeFilename(configPath); err != nil {
		t.Fatal()
	} else if filename != configExpected {
		t.Errorf("Expected %q got %q", configExpected, filename)
	}

	hardcodedPath := "package1/binary"
	hardcodedExpected := "usr/local/bin/package1"
	if filename, err := p.NormalizeFilename(hardcodedPath); err != nil {
		t.Fatal()
	} else if filename != hardcodedExpected {
		t.Errorf("Expected %q got %q", hardcodedExpected, filename)
	}
}

func TestListEtcFiles(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	files, err := p.ListEtcFiles()
	if err != nil {
		t.Fatal(err)
	}

	if len(files) == 0 {
		t.Fatalf("No config files found")
	}

	expected := "/etc/package1/config"
	if files[0] != expected {
		t.Errorf("Expected %q got %q", expected, files[0])
	}
}

func TestUpgradeConfig(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}
	p.UpgradeConfigs = true

	data, err := p.ListEtcFiles()
	if err != nil {
		t.Fatal(err)
	}

	if len(data) != 0 {
		t.Errorf("Found unexpected config files in conffiles list: %+v", data)
	}
}

func TestMD5SumFile(t *testing.T) {
	sum, err := md5SumFile(path.Join("test-fixtures", "example-depends.json"))
	if err != nil {
		t.Fatal(err)
	}

	expected := "e8f79d2b1995292911388a9d13a9528d"
	if sum != expected {
		t.Errorf("Expected %q got %q", expected, sum)
	}
}

func TestCalculateChecksums(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	expected := `adcc07f30ee844b18eab61f69f8c32c4  etc/package1/config
0940b4d946e3e2b8bbfdf5cfcf722518  usr/local/bin/package1
`

	data, err := p.CalculateChecksums()
	if err != nil {
		t.Fatal(err)
	}

	found := string(data)
	if found != expected {
		t.Errorf("--Expected--\n%s\n--Found--\n%s\n", expected, found)
	}
}

func TestBuild(t *testing.T) {
	p, err := NewPackageSpecFromFile(path.Join("test-fixtures", "example-basic.json"))
	p.AutoPath = path.Join("test-fixtures", "package1")
	if err != nil {
		t.Fatalf("Failed to load fixture: %s", err)
	}

	err = p.Build("output")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(path.Join("output", p.Filename()))
}
<|endoftext|>


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

package oglematchers_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"bytes"
	"testing"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DeepEqualsTest struct {}
func init() { RegisterTestSuite(&DeepEqualsTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *DeepEqualsTest) WrongTypeCandidateWithScalarValue() {
	var x int = 17
	m := DeepEquals(x)

	var err error

	// Nil candidate.
	err = m.Matches(nil)
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("<nil>")))

	// Int alias candidate.
	type intAlias int
	err = m.Matches(intAlias(x))
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("intAlias")))

	// String candidate.
	err = m.Matches("taco")
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("string")))

	// Slice candidate.
	err = m.Matches([]uint8{})
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint8")))

	// Unsigned int candidate.
	err = m.Matches(uint(17))
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("uint")))
}

func (t *DeepEqualsTest) WrongTypeCandidateWithSliceValue() {
	x := []uint8{}
	m := DeepEquals(x)

	var err error

	// Nil candidate.
	err = m.Matches(nil)
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("<nil>")))

	// String candidate.
	err = m.Matches("taco")
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("string")))

	// Slice candidate with wrong value type.
	err = m.Matches([]uint16{})
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint16")))
}

func (t *DeepEqualsTest) WrongTypeCandidateWithNilLiteralValue() {
	m := DeepEquals(nil)

	var err error

	// String candidate.
	err = m.Matches("taco")
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("string")))

	// Nil slice candidate.
	err = m.Matches([]uint8(nil))
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint8")))
}

func (t *DeepEqualsTest) NilLiteralValue() {
	m := DeepEquals(nil)
	ExpectEq("deep equals: <nil>", m.Description())

	var c interface{}
	var err error

	// Nil literal candidate.
	c = nil
	err = m.Matches(c)
	ExpectEq(nil, err)
}

func (t *DeepEqualsTest) IntValue() {
	m := DeepEquals(int(17))
	ExpectEq("deep equals: 17", m.Description())

	var c interface{}
	var err error

	// Matching int.
	c = int(17)
	err = m.Matches(c)
	ExpectEq(nil, err)

	// Non-matching int.
	c = int(18)
	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

func (t *DeepEqualsTest) SliceValue() {
	x := []uint8{17, 19}
	m := DeepEquals(x)
	ExpectEq("deep equals: [17 19]", m.Description())

	var c []uint8
	var err error

	// Matching.
	c = make([]uint8, len(x))
	AssertEq(len(x), copy(c, x))

	err = m.Matches(c)
	ExpectEq(nil, err)

	// Prefix.
	AssertGt(len(x), 1)
	c = make([]uint8, len(x)-1)
	AssertEq(len(x)-1, copy(c, x))

	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))

	// Suffix.
	c = make([]uint8, len(x)+1)
	AssertEq(len(x), copy(c, x))

	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

func (t *DeepEqualsTest) NilSliceValue() {
	x := []uint8(nil)
	m := DeepEquals(x)
	ExpectEq("deep equals: []", m.Description())

	var c []uint8
	var err error

	// Nil slice.
	c = []uint8(nil)
	err = m.Matches(c)
	ExpectEq(nil, err)

	// Non-nil slice.
	c = []uint8{}
	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

////////////////////////////////////////////////////////////////////////
// Benchmarks
////////////////////////////////////////////////////////////////////////

func benchmarkWithSize(b *testing.B, size int) {
	b.StopTimer()
	buf := bytes.Repeat([]byte{0x01}, size)
	bufCopy := make([]byte, size)
	copy(bufCopy, buf)

	matcher := DeepEquals(buf)
	b.StartTimer()

	for i := 0; i < b.N; i++ {
		matcher.Matches(bufCopy)
	}

	b.SetBytes(int64(size))
}

func BenchmarkShortByteSlice(b *testing.B) {
	benchmarkWithSize(b, 256)
}

func BenchmarkLongByteSlice(b *testing.B) {
	benchmarkWithSize(b, 1<<24)
}
<commit_msg>Expanded tests for byte slices.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package oglematchers_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"bytes"
	"testing"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DeepEqualsTest struct {}
func init() { RegisterTestSuite(&DeepEqualsTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *DeepEqualsTest) WrongTypeCandidateWithScalarValue() {
	var x int = 17
	m := DeepEquals(x)

	var err error

	// Nil candidate.
	err = m.Matches(nil)
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("<nil>")))

	// Int alias candidate.
	type intAlias int
	err = m.Matches(intAlias(x))
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("intAlias")))

	// String candidate.
	err = m.Matches("taco")
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("string")))

	// Byte slice candidate.
	err = m.Matches([]byte{})
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint8")))

	// Other slice candidate.
	err = m.Matches([]uint16{})
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint16")))

	// Unsigned int candidate.
	err = m.Matches(uint(17))
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("uint")))
}

func (t *DeepEqualsTest) WrongTypeCandidateWithByteSliceValue() {
	x := []byte{}
	m := DeepEquals(x)

	var err error

	// Nil candidate.
	err = m.Matches(nil)
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("<nil>")))

	// String candidate.
	err = m.Matches("taco")
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("string")))

	// Slice candidate with wrong value type.
	err = m.Matches([]uint16{})
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint16")))
}

func (t *DeepEqualsTest) WrongTypeCandidateWithOtherSliceValue() {
	x := []uint16{}
	m := DeepEquals(x)

	var err error

	// Nil candidate.
	err = m.Matches(nil)
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("<nil>")))

	// String candidate.
	err = m.Matches("taco")
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("string")))

	// Byte slice candidate with wrong value type.
	err = m.Matches([]byte{})
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint8")))

	// Other slice candidate with wrong value type.
	err = m.Matches([]uint32{})
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint32")))
}

func (t *DeepEqualsTest) WrongTypeCandidateWithNilLiteralValue() {
	m := DeepEquals(nil)

	var err error

	// String candidate.
	err = m.Matches("taco")
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("string")))

	// Nil byte slice candidate.
	err = m.Matches([]byte(nil))
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint8")))

	// Nil other slice candidate.
	err = m.Matches([]uint16(nil))
	AssertNe(nil, err)
	ExpectTrue(isFatal(err))
	ExpectThat(err, Error(HasSubstr("type")))
	ExpectThat(err, Error(HasSubstr("[]uint16")))
}

func (t *DeepEqualsTest) NilLiteralValue() {
	m := DeepEquals(nil)
	ExpectEq("deep equals: <nil>", m.Description())

	var c interface{}
	var err error

	// Nil literal candidate.
	c = nil
	err = m.Matches(c)
	ExpectEq(nil, err)
}

func (t *DeepEqualsTest) IntValue() {
	m := DeepEquals(int(17))
	ExpectEq("deep equals: 17", m.Description())

	var c interface{}
	var err error

	// Matching int.
	c = int(17)
	err = m.Matches(c)
	ExpectEq(nil, err)

	// Non-matching int.
	c = int(18)
	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

func (t *DeepEqualsTest) ByteSliceValue() {
	x := []byte{17, 19}
	m := DeepEquals(x)
	ExpectEq("deep equals: [17 19]", m.Description())

	var c []byte
	var err error

	// Matching.
	c = make([]byte, len(x))
	AssertEq(len(x), copy(c, x))

	err = m.Matches(c)
	ExpectEq(nil, err)

	// Prefix.
	AssertGt(len(x), 1)
	c = make([]byte, len(x)-1)
	AssertEq(len(x)-1, copy(c, x))

	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))

	// Suffix.
	c = make([]byte, len(x)+1)
	AssertEq(len(x), copy(c, x))

	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

func (t *DeepEqualsTest) OtherSliceValue() {
	x := []uint16{17, 19}
	m := DeepEquals(x)
	ExpectEq("deep equals: [17 19]", m.Description())

	var c []uint16
	var err error

	// Matching.
	c = make([]uint16, len(x))
	AssertEq(len(x), copy(c, x))

	err = m.Matches(c)
	ExpectEq(nil, err)

	// Prefix.
	AssertGt(len(x), 1)
	c = make([]uint16, len(x)-1)
	AssertEq(len(x)-1, copy(c, x))

	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))

	// Suffix.
	c = make([]uint16, len(x)+1)
	AssertEq(len(x), copy(c, x))

	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

func (t *DeepEqualsTest) NilByteSliceValue() {
	x := []byte(nil)
	m := DeepEquals(x)
	ExpectEq("deep equals: []", m.Description())

	var c []byte
	var err error

	// Nil slice.
	c = []byte(nil)
	err = m.Matches(c)
	ExpectEq(nil, err)

	// Non-nil slice.
	c = []byte{}
	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

func (t *DeepEqualsTest) NilOtherSliceValue() {
	x := []uint16(nil)
	m := DeepEquals(x)
	ExpectEq("deep equals: []", m.Description())

	var c []uint16
	var err error

	// Nil slice.
	c = []uint16(nil)
	err = m.Matches(c)
	ExpectEq(nil, err)

	// Non-nil slice.
	c = []uint16{}
	err = m.Matches(c)
	ExpectThat(err, Error(Equals("")))
}

////////////////////////////////////////////////////////////////////////
// Benchmarks
////////////////////////////////////////////////////////////////////////

func benchmarkWithSize(b *testing.B, size int) {
	b.StopTimer()
	buf := bytes.Repeat([]byte{0x01}, size)
	bufCopy := make([]byte, size)
	copy(bufCopy, buf)

	matcher := DeepEquals(buf)
	b.StartTimer()

	for i := 0; i < b.N; i++ {
		matcher.Matches(bufCopy)
	}

	b.SetBytes(int64(size))
}

func BenchmarkShortByteSlice(b *testing.B) {
	benchmarkWithSize(b, 256)
}

func BenchmarkLongByteSlice(b *testing.B) {
	benchmarkWithSize(b, 1<<24)
}
<|endoftext|>


<commit_before>package main

import (
	"io"
)

func Start(stop chan int) {
	for _, in := range Plugins.Inputs {
		go CopyMulty(in, Plugins.Outputs...)
	}

	select {
	case <-stop:
		return
	}
}

// Copy from 1 reader to multiple writers
func CopyMulty(src io.Reader, writers ...io.Writer) (err error) {
	buf := make([]byte, 32*1024)
	wIndex := 0

	for {
		nr, er := src.Read(buf)
		if nr > 0 && len(buf) > nr{
			Debug("Sending", src, ": ", string(buf[0:nr]))

			if Settings.splitOutput {
				// Simple round robin
				writers[wIndex].Write(buf[0:nr])

				wIndex++

				if wIndex >= len(writers) {
					wIndex = 0
				}
			} else {
				for _, dst := range writers {
					dst.Write(buf[0:nr])
				}
			}

		}
		if er == io.EOF {
			break
		}
		if er != nil {
			err = er
			break
		}
	}
	return err
}
<commit_msg>new buffer each loop<commit_after>package main

import (
	"io"
)

func Start(stop chan int) {
	for _, in := range Plugins.Inputs {
		go CopyMulty(in, Plugins.Outputs...)
	}

	select {
	case <-stop:
		return
	}
}

// Copy from 1 reader to multiple writers
func CopyMulty(src io.Reader, writers ...io.Writer) (err error) {
	wIndex := 0

	for {
		buf := make([]byte, 32*1024)
		nr, er := src.Read(buf)
		if nr > 0 && len(buf) > nr{
			Debug("Sending", src, ": ", string(buf[0:nr]))

			if Settings.splitOutput {
				// Simple round robin
				writers[wIndex].Write(buf[0:nr])

				wIndex++

				if wIndex >= len(writers) {
					wIndex = 0
				}
			} else {
				for _, dst := range writers {
					dst.Write(buf[0:nr])
				}
			}

		}
		if er == io.EOF {
			break
		}
		if er != nil {
			err = er
			break
		}
	}
	return err
}
<|endoftext|>


<commit_before>package rest

import (
	"encoding/json"
	"mime"
	"net/http"
	"strconv"
	"strings"
)

// JSON является вспомогательным типом для быстрого создания JSON-структур.
type JSON map[string]interface{}

// Coder описывает интерфейс кодировщика форматов для разбора и отдачи ответов.
// По умолчанию используется кодировщик в формате JSON с ограничением на размер
// запроса в 16 мегабайт. Вы можете задать свой кодировщик при инициализации
// ServeMux.
type Coder interface {
	Decode(c *Context, data interface{}) error
	Encode(c *Context, data interface{}) error
}

// defaultCoder содержит Coder по умолчанию: JSON с максимальным размером данных
// в запросе — 16 мегабайт.
var defaultCoder Coder = JSONCoder{MaxBodyBytes: 1 << 24}

// JSONCoder описывает Coder, поддерживающий кодирование и декодирование данных
// запроса в формат JSON.
//
// MaxBodyBytes ограничивает размер данных, принимаемых в запросе. Если данных
// будет больше указанного размера, то они просто обрежутся. Это позволяет
// защитить сервер от слишком больших запросов.
// По умолчанию ограничение установлено в 32 мегабайта.
// Если не хотите использовать ограничений, то установить данное значение в 0.
type JSONCoder struct {
	MaxBodyBytes int64 // максимально допустимый размер данных в запросе
}

// Encode отдает data в формате JSON.Если `Content-Type` не установлен, то
// устанавливает его как `application/json; charset=utf-8`. Так же устанавливает
// размер данных.
func (JSONCoder) Encode(c *Context, data interface{}) error {
	jdata, err := json.MarshalIndent(data, "", "\t")
	if err != nil {
		return err
	}
	if c.Header().Get("ContentType") == "" {
		c.HeaderSet("Content-Type", "application/json; charset=utf-8")
	}
	c.HeaderSet("Content-Length", strconv.Itoa(len(jdata)))
	_, err = c.Write(jdata)
	return err

	// buf := buffers.Get().(*bytes.Buffer) // получаем буфер из пула
	// defer buffers.Put(buf)               // возвращаем в пул по окончании
	// buf.Reset()                          // сбрасываем предыдущие состояния
	// // декодируем объект в формат JSON используя буфер
	// if err := json.NewEncoder(buf).Encode(data); err != nil {
	// 	return err
	// }
	// if c.Header().Get("ContentType") == "" {
	// 	c.HeaderSet("Content-Type", "application/json; charset=utf-8")
	// }
	// c.HeaderSet("Content-Length", strconv.Itoa(buf.Len()))
	// if _, err := buf.WriteTo(c); err != nil { // отдаем сформированный ответ
	// 	return err
	// }
	// return nil
}

// Decoder декодирует содержимое запроса в формате JSON в объект. Перед
// декодированием проверяется, что данные представлены в формате JSON и не
// превышают максимально допустимый размер, задаваемый в MaxBodyBytes.
func (j JSONCoder) Decode(c *Context, data interface{}) error {
	// разбираем заголовок с типом информации в запросе
	mediatype, params, _ := mime.ParseMediaType(
		c.Request.Header.Get("Content-Type"))
	charset, ok := params["charset"]
	if !ok {
		charset = "UTF-8"
	}
	// если запрос не является JSON, то возвращаем ошибку
	if mediatype != "application/json" || strings.ToUpper(charset) != "UTF-8" {
		return NewError(http.StatusUnsupportedMediaType, "")
	}
	// если запрос превышает допустимый объем, то возвращаем ошибку
	if j.MaxBodyBytes > 0 {
		if c.Request.ContentLength == 0 {
			return NewError(http.StatusLengthRequired, "")
		} else if c.Request.ContentLength > j.MaxBodyBytes {
			return NewError(http.StatusRequestEntityTooLarge, "")
		}
	}
	// разбираем содержимое запроса
	if err := json.NewDecoder(c.Request.Body).Decode(data); err != nil {
		return NewError(http.StatusBadRequest, err.Error())
	}
	return nil
}

// var buffers = sync.Pool{New: func() interface{} { return new(bytes.Buffer) }}
<commit_msg>форматирование JSON<commit_after>package rest

import (
	"encoding/json"
	"mime"
	"net/http"
	"strconv"
	"strings"
)

// JSON является вспомогательным типом для быстрого создания JSON-структур.
type JSON map[string]interface{}

func (j JSON) MarshalJSON() ([]byte, error) {
	return json.MarshalIndent((map[string]interface{})(j), "", "\t")
}

// Coder описывает интерфейс кодировщика форматов для разбора и отдачи ответов.
// По умолчанию используется кодировщик в формате JSON с ограничением на размер
// запроса в 16 мегабайт. Вы можете задать свой кодировщик при инициализации
// ServeMux.
type Coder interface {
	Decode(c *Context, data interface{}) error
	Encode(c *Context, data interface{}) error
}

// defaultCoder содержит Coder по умолчанию: JSON с максимальным размером данных
// в запросе — 16 мегабайт.
var defaultCoder Coder = JSONCoder{MaxBodyBytes: 1 << 24}

// JSONCoder описывает Coder, поддерживающий кодирование и декодирование данных
// запроса в формат JSON.
//
// MaxBodyBytes ограничивает размер данных, принимаемых в запросе. Если данных
// будет больше указанного размера, то они просто обрежутся. Это позволяет
// защитить сервер от слишком больших запросов.
// По умолчанию ограничение установлено в 32 мегабайта.
// Если не хотите использовать ограничений, то установить данное значение в 0.
type JSONCoder struct {
	MaxBodyBytes int64 // максимально допустимый размер данных в запросе
}

// Encode отдает data в формате JSON.Если `Content-Type` не установлен, то
// устанавливает его как `application/json; charset=utf-8`. Так же устанавливает
// размер данных.
func (JSONCoder) Encode(c *Context, data interface{}) error {
	jdata, err := json.MarshalIndent(data, "", "\t")
	if err != nil {
		return err
	}
	if c.Header().Get("ContentType") == "" {
		c.HeaderSet("Content-Type", "application/json; charset=utf-8")
	}
	c.HeaderSet("Content-Length", strconv.Itoa(len(jdata)))
	_, err = c.Write(jdata)
	return err

	// buf := buffers.Get().(*bytes.Buffer) // получаем буфер из пула
	// defer buffers.Put(buf)               // возвращаем в пул по окончании
	// buf.Reset()                          // сбрасываем предыдущие состояния
	// // декодируем объект в формат JSON используя буфер
	// if err := json.NewEncoder(buf).Encode(data); err != nil {
	// 	return err
	// }
	// if c.Header().Get("ContentType") == "" {
	// 	c.HeaderSet("Content-Type", "application/json; charset=utf-8")
	// }
	// c.HeaderSet("Content-Length", strconv.Itoa(buf.Len()))
	// if _, err := buf.WriteTo(c); err != nil { // отдаем сформированный ответ
	// 	return err
	// }
	// return nil
}

// Decoder декодирует содержимое запроса в формате JSON в объект. Перед
// декодированием проверяется, что данные представлены в формате JSON и не
// превышают максимально допустимый размер, задаваемый в MaxBodyBytes.
func (j JSONCoder) Decode(c *Context, data interface{}) error {
	// разбираем заголовок с типом информации в запросе
	mediatype, params, _ := mime.ParseMediaType(
		c.Request.Header.Get("Content-Type"))
	charset, ok := params["charset"]
	if !ok {
		charset = "UTF-8"
	}
	// если запрос не является JSON, то возвращаем ошибку
	if mediatype != "application/json" || strings.ToUpper(charset) != "UTF-8" {
		return NewError(http.StatusUnsupportedMediaType, "")
	}
	// если запрос превышает допустимый объем, то возвращаем ошибку
	if j.MaxBodyBytes > 0 {
		if c.Request.ContentLength == 0 {
			return NewError(http.StatusLengthRequired, "")
		} else if c.Request.ContentLength > j.MaxBodyBytes {
			return NewError(http.StatusRequestEntityTooLarge, "")
		}
	}
	// разбираем содержимое запроса
	if err := json.NewDecoder(c.Request.Body).Decode(data); err != nil {
		return NewError(http.StatusBadRequest, err.Error())
	}
	return nil
}

// var buffers = sync.Pool{New: func() interface{} { return new(bytes.Buffer) }}
<|endoftext|>


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

/*
Package pubsub provides an easy way to publish and receive Google Cloud Pub/Sub
messages, hiding the the details of the underlying server RPCs.  Google Cloud
Pub/Sub is a many-to-many, asynchronous messaging system that decouples senders
and receivers.

Note: This package is experimental and may make backwards-incompatible changes.

More information about Google Cloud Pub/Sub is available at
https://cloud.google.com/pubsub/docs

Publishing

Google Cloud Pub/Sub messages are published to topics. Topics may be created
using the pubsub package like so:

 topic, err := pubsubClient.CreateTopic(context.Background(), "topic-name")

Messages may then be published to a topic:

 msgIDs, err := topic.Publish(ctx, &pubsub.Message{
	Data: []byte("payload"),
 })

Receiving

To receive messages published to a topic, clients create subscriptions
to the topic. There may be more than one subscription per topic; each message
that is published to the topic will be delivered to all of its subscriptions.

Subsciptions may be created like so:

 sub, err := pubsubClient.NewSubscription(context.Background(), "sub-name", topic, 0, nil)

Messages are then consumed from a subscription via an iterator:

 // Construct the iterator
 it, err := sub.Pull(context.Background())
 if err != nil {
	// handle err ...
 }
 defer it.Stop()

 // Consume N messages
 for i := 0; i < N; i++ {
 	msg, err := it.Next()
 	if err == iterator.Done {
 		break
 	}
 	if err != nil {
 		// handle err ...
 		break
 	}

 	log.Print("got message: ", string(msg.Data))
 	msg.Done(true)
 }

The message iterator returns messages one at a time, fetching batches of
messages behind the scenes as needed. Once client code has processed the
message, it must call Message.Done, otherwise the message will eventually be
redelivered. For more information and configuration options, see "Deadlines"
below.

Note: It is possible for Messages to be redelivered, even if Message.Done has
been called. Client code must be robust to multiple deliveries of messages.

Deadlines

The default pubsub deadlines are suitable for most use cases, but may be
overridden.  This section describes the tradeoffs that should be considered
when overriding the defaults.

Behind the scenes, each message returned by the Pub/Sub server has an
associated lease, known as an "ACK deadline".
Unless a message is acknowledged within the ACK deadline, or the client requests that
the ACK deadline be extended, the message will become elegible for redelivery.
As a convenience, the pubsub package will automatically extend deadlines until
either:
 * Message.Done is called, or
 * the "MaxExtension" period elapses from the time the message is fetched from the server.

The initial ACK deadline given to each messages defaults to 10 seconds, but may
be overridden during subscription creation.  Selecting an ACK deadline is a
tradeoff between message redelivery latency and RPC volume. If the pubsub
package fails to acknowledge or extend a message (e.g. due to unexpected
termination of the process), a shorter ACK deadline will generally result in
faster message redelivery by the Pub/Sub system. However, a short ACK deadline
may also increase the number of deadline extension RPCs that the pubsub package
sends to the server.

The default max extension period is DefaultMaxExtension, and can be overridden
by passing a MaxExtension option to Subscription.Pull. Selecting a max
extension period is a tradeoff between the speed at which client code must
process messages, and the redelivery delay if messages fail to be acknowledged
(e.g. because client code neglects to do so).  Using a large MaxExtension
increases the available time for client code to process messages.  However, if
the client code neglects to call Message.Done, a large MaxExtension will
increase the delay before the message is redelivered.
*/
package pubsub // import "cloud.google.com/go/pubsub"
<commit_msg>pubsub: fix package doc<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package pubsub provides an easy way to publish and receive Google Cloud Pub/Sub
messages, hiding the the details of the underlying server RPCs.  Google Cloud
Pub/Sub is a many-to-many, asynchronous messaging system that decouples senders
and receivers.

Note: This package is experimental and may make backwards-incompatible changes.

More information about Google Cloud Pub/Sub is available at
https://cloud.google.com/pubsub/docs

Publishing

Google Cloud Pub/Sub messages are published to topics. Topics may be created
using the pubsub package like so:

 topic, err := pubsubClient.CreateTopic(context.Background(), "topic-name")

Messages may then be published to a topic:

 msgIDs, err := topic.Publish(ctx, &pubsub.Message{
	Data: []byte("payload"),
 })

Receiving

To receive messages published to a topic, clients create subscriptions
to the topic. There may be more than one subscription per topic; each message
that is published to the topic will be delivered to all of its subscriptions.

Subsciptions may be created like so:

 sub, err := pubsubClient.CreateSubscription(context.Background(), "sub-name", topic, 0, nil)

Messages are then consumed from a subscription via an iterator:

 // Construct the iterator
 it, err := sub.Pull(context.Background())
 if err != nil {
	// handle err ...
 }
 defer it.Stop()

 // Consume N messages
 for i := 0; i < N; i++ {
 	msg, err := it.Next()
 	if err == iterator.Done {
 		break
 	}
 	if err != nil {
 		// handle err ...
 		break
 	}

 	log.Print("got message: ", string(msg.Data))
 	msg.Done(true)
 }

The message iterator returns messages one at a time, fetching batches of
messages behind the scenes as needed. Once client code has processed the
message, it must call Message.Done, otherwise the message will eventually be
redelivered. For more information and configuration options, see "Deadlines"
below.

Note: It is possible for Messages to be redelivered, even if Message.Done has
been called. Client code must be robust to multiple deliveries of messages.

Deadlines

The default pubsub deadlines are suitable for most use cases, but may be
overridden.  This section describes the tradeoffs that should be considered
when overriding the defaults.

Behind the scenes, each message returned by the Pub/Sub server has an
associated lease, known as an "ACK deadline".
Unless a message is acknowledged within the ACK deadline, or the client requests that
the ACK deadline be extended, the message will become elegible for redelivery.
As a convenience, the pubsub package will automatically extend deadlines until
either:
 * Message.Done is called, or
 * the "MaxExtension" period elapses from the time the message is fetched from the server.

The initial ACK deadline given to each messages defaults to 10 seconds, but may
be overridden during subscription creation.  Selecting an ACK deadline is a
tradeoff between message redelivery latency and RPC volume. If the pubsub
package fails to acknowledge or extend a message (e.g. due to unexpected
termination of the process), a shorter ACK deadline will generally result in
faster message redelivery by the Pub/Sub system. However, a short ACK deadline
may also increase the number of deadline extension RPCs that the pubsub package
sends to the server.

The default max extension period is DefaultMaxExtension, and can be overridden
by passing a MaxExtension option to Subscription.Pull. Selecting a max
extension period is a tradeoff between the speed at which client code must
process messages, and the redelivery delay if messages fail to be acknowledged
(e.g. because client code neglects to do so).  Using a large MaxExtension
increases the available time for client code to process messages.  However, if
the client code neglects to call Message.Done, a large MaxExtension will
increase the delay before the message is redelivered.
*/
package pubsub // import "cloud.google.com/go/pubsub"
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package agent

import (
	"fmt"

	"launchpad.net/juju-core/constraints"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/names"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/state/api/params"
	"launchpad.net/juju-core/utils"
	"launchpad.net/juju-core/version"
)

// InitializeState should be called on the bootstrap machine's agent
// configuration. It uses that information to dial the state server and
// initialize it. It also generates a new password for the bootstrap
// machine and calls Write to save the the configuration.
//
// The envCfg values will be stored in the state's EnvironConfig; the
// machineCfg values will be used to configure the bootstrap Machine,
// and its constraints will be also be used for the environment-level
// constraints. The connection to the state server will respect the
// given timeout parameter.
//
// InitializeState returns the newly initialized state and bootstrap
// machine. If it fails, the state may well be irredeemably compromised.
type StateInitializer interface {
	InitializeState(envCfg *config.Config, machineCfg BootstrapMachineConfig, timeout state.DialOpts, policy state.Policy) (*state.State, *state.Machine, error)
}

// BootstrapMachineConfig holds configuration information
// to attach to the bootstrap machine.
type BootstrapMachineConfig struct {
	// Constraints holds the bootstrap machine's constraints.
	// This value is also used for the environment-level constraints.
	Constraints constraints.Value

	// Jobs holds the jobs that the machine agent will run.
	Jobs []params.MachineJob

	// InstanceId holds the instance id of the bootstrap machine.
	InstanceId instance.Id

	// Characteristics holds hardware information on the
	// bootstrap machine.
	Characteristics instance.HardwareCharacteristics
}

const bootstrapMachineId = "0"

func InitializeState(c ConfigSetter, envCfg *config.Config, machineCfg BootstrapMachineConfig, timeout state.DialOpts, policy state.Policy) (*state.State, *state.Machine, error) {
	if c.Tag() != names.MachineTag(bootstrapMachineId) {
		return nil, nil, fmt.Errorf("InitializeState not called with bootstrap machine's configuration")
	}
	info := c.StateInfo()
	info.Tag = ""
	info.Password = ""
	logger.Debugf("initializing address %v", info.Addrs)
	st, err := state.Initialize(info, envCfg, timeout, policy)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to initialize state: %v", err)
	}
	logger.Debugf("connected to initial state")
	m, err := initUsersAndBootstrapMachine(c, st, machineCfg)
	if err != nil {
		st.Close()
		return nil, nil, err
	}
	st.SetStateServingInfo(params.StateServingInfo{
		APIPort:    c.apiPort,
		StatePort:  c.statePort,
		Cert:       string(c.stateServerCert),
		PrivateKey: string(c.stateServerKey),
	})
	return st, m, nil
}

func initUsersAndBootstrapMachine(c ConfigSetter, st *state.State, cfg BootstrapMachineConfig) (*state.Machine, error) {
	if err := initBootstrapUser(st, c.OldPassword()); err != nil {
		return nil, fmt.Errorf("cannot initialize bootstrap user: %v", err)
	}
	if err := st.SetEnvironConstraints(cfg.Constraints); err != nil {
		return nil, fmt.Errorf("cannot set initial environ constraints: %v", err)
	}
	m, err := initBootstrapMachine(c, st, cfg)
	if err != nil {
		return nil, fmt.Errorf("cannot initialize bootstrap machine: %v", err)
	}
	return m, nil
}

// initBootstrapUser creates the initial admin user for the database, and sets
// the initial password.
func initBootstrapUser(st *state.State, passwordHash string) error {
	logger.Debugf("adding admin user")
	// Set up initial authentication.
	u, err := st.AddUser("admin", "")
	if err != nil {
		return err
	}

	// Note that at bootstrap time, the password is set to
	// the hash of its actual value. The first time a client
	// connects to mongo, it changes the mongo password
	// to the original password.
	logger.Debugf("setting password hash for admin user")
	// TODO(jam): http://pad.lv/1248839
	// We could teach bootstrap how to generate a custom salt and apply
	// that to the hash that was generated. At which point we'd need to set
	// it here. For now, we pass "" so that on first login we will create a
	// new salt, but the fixed-salt password is still available from
	// cloud-init.
	if err := u.SetPasswordHash(passwordHash, ""); err != nil {
		return err
	}
	if err := st.SetAdminMongoPassword(passwordHash); err != nil {
		return err
	}
	return nil
}

// initBootstrapMachine initializes the initial bootstrap machine in state.
func initBootstrapMachine(c ConfigSetter, st *state.State, cfg BootstrapMachineConfig) (*state.Machine, error) {

	logger.Infof("initialising bootstrap machine with config: %+v", cfg)

	jobs := make([]state.MachineJob, len(cfg.Jobs))
	for i, job := range cfg.Jobs {
		machineJob, err := state.MachineJobFromParams(job)
		if err != nil {
			return nil, fmt.Errorf("invalid bootstrap machine job %q: %v", job, err)
		}
		jobs[i] = machineJob
	}
	m, err := st.AddOneMachine(state.MachineTemplate{
		Series:                  version.Current.Series,
		Nonce:                   state.BootstrapNonce,
		Constraints:             cfg.Constraints,
		InstanceId:              cfg.InstanceId,
		HardwareCharacteristics: cfg.Characteristics,
		Jobs: jobs,
	})
	if err != nil {
		return nil, fmt.Errorf("cannot create bootstrap machine in state: %v", err)
	}
	if m.Id() != bootstrapMachineId {
		return nil, fmt.Errorf("bootstrap machine expected id 0, got %q", m.Id())
	}
	// Read the machine agent's password and change it to
	// a new password (other agents will change their password
	// via the API connection).
	logger.Debugf("create new random password for machine %v", m.Id())

	newPassword, err := utils.RandomPassword()
	if err != nil {
		return nil, err
	}
	if err := m.SetPassword(newPassword); err != nil {
		return nil, err
	}
	if err := m.SetMongoPassword(newPassword); err != nil {
		return nil, err
	}
	c.SetPassword(newPassword)
	return m, nil
}
<commit_msg>Switch to using interface rather than fields<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package agent

import (
	"fmt"

	"launchpad.net/juju-core/constraints"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/names"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/state/api/params"
	"launchpad.net/juju-core/utils"
	"launchpad.net/juju-core/version"
)

// InitializeState should be called on the bootstrap machine's agent
// configuration. It uses that information to dial the state server and
// initialize it. It also generates a new password for the bootstrap
// machine and calls Write to save the the configuration.
//
// The envCfg values will be stored in the state's EnvironConfig; the
// machineCfg values will be used to configure the bootstrap Machine,
// and its constraints will be also be used for the environment-level
// constraints. The connection to the state server will respect the
// given timeout parameter.
//
// InitializeState returns the newly initialized state and bootstrap
// machine. If it fails, the state may well be irredeemably compromised.
type StateInitializer interface {
	InitializeState(envCfg *config.Config, machineCfg BootstrapMachineConfig, timeout state.DialOpts, policy state.Policy) (*state.State, *state.Machine, error)
}

// BootstrapMachineConfig holds configuration information
// to attach to the bootstrap machine.
type BootstrapMachineConfig struct {
	// Constraints holds the bootstrap machine's constraints.
	// This value is also used for the environment-level constraints.
	Constraints constraints.Value

	// Jobs holds the jobs that the machine agent will run.
	Jobs []params.MachineJob

	// InstanceId holds the instance id of the bootstrap machine.
	InstanceId instance.Id

	// Characteristics holds hardware information on the
	// bootstrap machine.
	Characteristics instance.HardwareCharacteristics
}

const bootstrapMachineId = "0"

func InitializeState(c ConfigSetter, envCfg *config.Config, machineCfg BootstrapMachineConfig, timeout state.DialOpts, policy state.Policy) (*state.State, *state.Machine, error) {
	if c.Tag() != names.MachineTag(bootstrapMachineId) {
		return nil, nil, fmt.Errorf("InitializeState not called with bootstrap machine's configuration")
	}
	info := c.StateInfo()
	info.Tag = ""
	info.Password = ""
	logger.Debugf("initializing address %v", info.Addrs)
	st, err := state.Initialize(info, envCfg, timeout, policy)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to initialize state: %v", err)
	}
	logger.Debugf("connected to initial state")
	m, err := initUsersAndBootstrapMachine(c, st, machineCfg)
	if err != nil {
		st.Close()
		return nil, nil, err
	}
	stateServingInfo, _ := c.StateServingInfo()
	st.SetStateServingInfo(stateServingInfo)
	return st, m, nil
}

func initUsersAndBootstrapMachine(c ConfigSetter, st *state.State, cfg BootstrapMachineConfig) (*state.Machine, error) {
	if err := initBootstrapUser(st, c.OldPassword()); err != nil {
		return nil, fmt.Errorf("cannot initialize bootstrap user: %v", err)
	}
	if err := st.SetEnvironConstraints(cfg.Constraints); err != nil {
		return nil, fmt.Errorf("cannot set initial environ constraints: %v", err)
	}
	m, err := initBootstrapMachine(c, st, cfg)
	if err != nil {
		return nil, fmt.Errorf("cannot initialize bootstrap machine: %v", err)
	}
	return m, nil
}

// initBootstrapUser creates the initial admin user for the database, and sets
// the initial password.
func initBootstrapUser(st *state.State, passwordHash string) error {
	logger.Debugf("adding admin user")
	// Set up initial authentication.
	u, err := st.AddUser("admin", "")
	if err != nil {
		return err
	}

	// Note that at bootstrap time, the password is set to
	// the hash of its actual value. The first time a client
	// connects to mongo, it changes the mongo password
	// to the original password.
	logger.Debugf("setting password hash for admin user")
	// TODO(jam): http://pad.lv/1248839
	// We could teach bootstrap how to generate a custom salt and apply
	// that to the hash that was generated. At which point we'd need to set
	// it here. For now, we pass "" so that on first login we will create a
	// new salt, but the fixed-salt password is still available from
	// cloud-init.
	if err := u.SetPasswordHash(passwordHash, ""); err != nil {
		return err
	}
	if err := st.SetAdminMongoPassword(passwordHash); err != nil {
		return err
	}
	return nil
}

// initBootstrapMachine initializes the initial bootstrap machine in state.
func initBootstrapMachine(c ConfigSetter, st *state.State, cfg BootstrapMachineConfig) (*state.Machine, error) {

	logger.Infof("initialising bootstrap machine with config: %+v", cfg)

	jobs := make([]state.MachineJob, len(cfg.Jobs))
	for i, job := range cfg.Jobs {
		machineJob, err := state.MachineJobFromParams(job)
		if err != nil {
			return nil, fmt.Errorf("invalid bootstrap machine job %q: %v", job, err)
		}
		jobs[i] = machineJob
	}
	m, err := st.AddOneMachine(state.MachineTemplate{
		Series:                  version.Current.Series,
		Nonce:                   state.BootstrapNonce,
		Constraints:             cfg.Constraints,
		InstanceId:              cfg.InstanceId,
		HardwareCharacteristics: cfg.Characteristics,
		Jobs: jobs,
	})
	if err != nil {
		return nil, fmt.Errorf("cannot create bootstrap machine in state: %v", err)
	}
	if m.Id() != bootstrapMachineId {
		return nil, fmt.Errorf("bootstrap machine expected id 0, got %q", m.Id())
	}
	// Read the machine agent's password and change it to
	// a new password (other agents will change their password
	// via the API connection).
	logger.Debugf("create new random password for machine %v", m.Id())

	newPassword, err := utils.RandomPassword()
	if err != nil {
		return nil, err
	}
	if err := m.SetPassword(newPassword); err != nil {
		return nil, err
	}
	if err := m.SetMongoPassword(newPassword); err != nil {
		return nil, err
	}
	c.SetPassword(newPassword)
	return m, nil
}
<|endoftext|>


<commit_before>package httpd

import (
	"bufio"
	"fmt"
	"github.com/Symantec/Dominator/lib/format"
	"github.com/Symantec/Dominator/lib/html"
	"io"
	"net/http"
	"sort"
)

func (s state) statusHandler(w http.ResponseWriter, req *http.Request) {
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	fmt.Fprintln(writer, "<title>image-unpacker status page</title>")
	fmt.Fprintln(writer, ``)
	fmt.Fprintln(writer, "")
	fmt.Fprintln(writer, "")
	fmt.Fprintln(writer, "
image-unpacker status page
")
	fmt.Fprintln(writer, "")
	html.WriteHeaderWithRequest(writer, req)
	fmt.Fprintln(writer, "
")
	s.writeDashboard(writer)
	for _, htmlWriter := range htmlWriters {
		htmlWriter.WriteHtml(writer)
	}
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "
")
	html.WriteFooter(writer)
	fmt.Fprintln(writer, "")
}

func (s state) writeDashboard(writer io.Writer) {
	status := s.unpacker.GetStatus()
	fmt.Fprintln(writer, "Image streams:
")
	fmt.Fprintln(writer, `<table border="1">`)
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "    Image Stream	")
	fmt.Fprintln(writer, "    Device Id	")
	fmt.Fprintln(writer, "    Device Name	")
	fmt.Fprintln(writer, "    Status	")
	fmt.Fprintln(writer, "
")
	streamNames := make([]string, 0, len(status.ImageStreams))
	for streamName := range status.ImageStreams {
		streamNames = append(streamNames, streamName)
	}
	sort.Strings(streamNames)
	for _, streamName := range streamNames {
		stream := status.ImageStreams[streamName]
		fmt.Fprintf(writer, "
\n")
		fmt.Fprintf(writer,
			"    %s	\n",
			streamName, streamName)
		fmt.Fprintf(writer, "    %s	\n", stream.DeviceId)
		fmt.Fprintf(writer, "    %s	\n",
			status.Devices[stream.DeviceId].DeviceName)
		fmt.Fprintf(writer, "    %s	\n", stream.Status)
		fmt.Fprintf(writer, "
\n")
	}
	fmt.Fprintln(writer, "

")
	fmt.Fprintln(writer, "Devices:
")
	fmt.Fprintln(writer, `<table border="1">`)
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "    Device Id	")
	fmt.Fprintln(writer, "    Device Name	")
	fmt.Fprintln(writer, "    Size	")
	fmt.Fprintln(writer, "
")
	deviceIds := make([]string, 0, len(status.Devices))
	for deviceId := range status.Devices {
		deviceIds = append(deviceIds, deviceId)
	}
	sort.Strings(deviceIds)
	for _, deviceId := range deviceIds {
		fmt.Fprintf(writer, "
\n")
		fmt.Fprintf(writer, "    %s	\n", deviceId)
		fmt.Fprintf(writer, "    %s	\n",
			status.Devices[deviceId].DeviceName)
		fmt.Fprintf(writer, "    %s	\n",
			format.FormatBytes(status.Devices[deviceId].Size))
		fmt.Fprintf(writer, "
\n")
	}
	fmt.Fprintln(writer, "

")
}
<commit_msg>Improve image-unpacker dashboard.<commit_after>package httpd

import (
	"bufio"
	"fmt"
	"github.com/Symantec/Dominator/lib/format"
	"github.com/Symantec/Dominator/lib/html"
	"io"
	"net/http"
	"sort"
)

func (s state) statusHandler(w http.ResponseWriter, req *http.Request) {
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	fmt.Fprintln(writer, "<title>image-unpacker status page</title>")
	fmt.Fprintln(writer, ``)
	fmt.Fprintln(writer, "")
	fmt.Fprintln(writer, "")
	fmt.Fprintln(writer, "
image-unpacker status page
")
	fmt.Fprintln(writer, "")
	html.WriteHeaderWithRequest(writer, req)
	fmt.Fprintln(writer, "
")
	s.writeDashboard(writer)
	for _, htmlWriter := range htmlWriters {
		htmlWriter.WriteHtml(writer)
	}
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "
")
	html.WriteFooter(writer)
	fmt.Fprintln(writer, "")
}

func (s state) writeDashboard(writer io.Writer) {
	status := s.unpacker.GetStatus()
	fmt.Fprintln(writer, "Image streams:
")
	fmt.Fprintln(writer, `<table border="1">`)
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "    Image Stream	")
	fmt.Fprintln(writer, "    Device Id	")
	fmt.Fprintln(writer, "    Device Name	")
	fmt.Fprintln(writer, "    Size	")
	fmt.Fprintln(writer, "    Status	")
	fmt.Fprintln(writer, "
")
	streamNames := make([]string, 0, len(status.ImageStreams))
	for streamName := range status.ImageStreams {
		streamNames = append(streamNames, streamName)
	}
	sort.Strings(streamNames)
	for _, streamName := range streamNames {
		stream := status.ImageStreams[streamName]
		fmt.Fprintf(writer, "
\n")
		fmt.Fprintf(writer,
			"    %s	\n",
			streamName, streamName)
		fmt.Fprintf(writer, "    %s	\n", stream.DeviceId)
		fmt.Fprintf(writer, "    %s	\n",
			status.Devices[stream.DeviceId].DeviceName)
		size := status.Devices[stream.DeviceId].Size
		sizeString := format.FormatBytes(size)
		if size < 1 {
			sizeString = ""
		}
		fmt.Fprintf(writer, "    %s	\n", sizeString)
		fmt.Fprintf(writer, "    %s	\n", stream.Status)
		fmt.Fprintf(writer, "
\n")
	}
	fmt.Fprintln(writer, "

")
	fmt.Fprintln(writer, "Devices:
")
	fmt.Fprintln(writer, `<table border="1">`)
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "    Device Id	")
	fmt.Fprintln(writer, "    Device Name	")
	fmt.Fprintln(writer, "    Size	")
	fmt.Fprintln(writer, "    Image Stream	")
	fmt.Fprintln(writer, "    Status	")
	fmt.Fprintln(writer, "
")
	deviceIds := make([]string, 0, len(status.Devices))
	for deviceId := range status.Devices {
		deviceIds = append(deviceIds, deviceId)
	}
	sort.Strings(deviceIds)
	for _, deviceId := range deviceIds {
		deviceInfo := status.Devices[deviceId]
		fmt.Fprintf(writer, "
\n")
		fmt.Fprintf(writer, "    %s	\n", deviceId)
		fmt.Fprintf(writer, "    %s	\n", deviceInfo.DeviceName)
		fmt.Fprintf(writer, "    %s	\n",
			format.FormatBytes(deviceInfo.Size))
		streamName := deviceInfo.StreamName
		if stream, ok := status.ImageStreams[streamName]; ok {
			fmt.Fprintf(writer,
				"    %s	\n",
				streamName, streamName)
			fmt.Fprintf(writer, "    %s	\n", stream.Status)
		} else {
			fmt.Fprintln(writer, "    	")
			fmt.Fprintln(writer, "    	")
		}
		fmt.Fprintf(writer, "
\n")
	}
	fmt.Fprintln(writer, "

")
}
<|endoftext|>


<commit_before>package main

// @author Robin Verlangen
// Tool for logging data to CloudPelican directly from Go

// Imports
import (
    "cloudpelican"
    "log"
    "strconv"
)

// Example
func main() {
    // Token
    cloudpelican.SetToken("123456")

    // Basic message
    var msg string = "This is a log message"

    // Write message and validate
    for i := 0; i < 10; i++ {
        // Basic message with a sequence number for esting purposes
        res := cloudpelican.LogMessage(msg + " " + strconv.Itoa(i))

        // Validate the writing
        if !res {
            log.Println("Something went wrong")
        } else {
            log.Printf("Written %d bytes of data '%s' to backend.\n", len(msg), msg)
        }
    }

    // Make sure any pending messages are written to the backend
    cloudpelican.Drain()
}<commit_msg>Change repo name<commit_after>package main

// @author Robin Verlangen
// Tool for logging data to CloudPelican directly from Go

// Imports
import (
    "github.com/RobinUS2/cloudpelican-golang/cloudpelican"
    "log"
    "strconv"
)

// Example
func main() {
    // Token
    cloudpelican.SetToken("123456")

    // Basic message
    var msg string = "This is a log message"

    // Write message and validate
    for i := 0; i < 10; i++ {
        // Basic message with a sequence number for esting purposes
        res := cloudpelican.LogMessage(msg + " " + strconv.Itoa(i))

        // Validate the writing
        if !res {
            log.Println("Something went wrong")
        } else {
            log.Printf("Written %d bytes of data '%s' to backend.\n", len(msg), msg)
        }
    }

    // Make sure any pending messages are written to the backend
    cloudpelican.Drain()
}<|endoftext|>