<commit_before>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package assert

import (
	"errors"
	"testing"
)

func TestGetCallerInfo(t *testing.T) {
	str := getCallerInfo()
	// NOTE:注意这里涉及到调用函数的行号信息
	if str != "TestGetCallerInfo(assert_test.go:13)" {
		t.Errorf("getCallerInfo返回的信息不正确，其返回值为：%v", str)
	}

	// 嵌套调用，第二个参数为当前的行号
	testGetCallerInfo(t, "20")
	testGetCallerInfo(t, "21")

	// 闭合函数，line为调用所在的行号。
	f := func(line string) {
		str := getCallerInfo()
		if str != "TestGetCallerInfo(assert_test.go:"+line+")" ||
			str != "TestGetCallerInfo.fun1(assert_test.go:"+line+")" { // Go1.5之后变这样了
			t.Errorf("getCallerInfo返回的信息不正确，其返回值为：%v", str)
		}
	}
	f("30") // 参数为当前等号
	f("31")
}

// 参数line，为调用此函数所在的行号。
func testGetCallerInfo(t *testing.T, line string) {
	str := getCallerInfo()
	if str != "TestGetCallerInfo(assert_test.go:"+line+")" {
		t.Error("getCallerInfo返回的信息不正确，其返回值为：%v", str)
	}

}

func TestFormatMsg(t *testing.T) {
	msg1 := []interface{}{}
	msg2 := []interface{}{[]rune("msg:%v"), 2}
	msg3 := []interface{}{"msg:%v", 3}
	msg4 := []interface{}{123, 456}

	str := formatMessage(msg1, msg2)
	if str != "msg:2" {
		t.Errorf("formatMessage(msg1,msg2)返回信息错误:[%v]", str)
	}

	str = formatMessage(nil, msg2)
	if str != "msg:2" {
		t.Errorf("formatMessage(msg1,msg2)返回信息错误:[%v]", str)
	}

	str = formatMessage(msg2, msg3)
	if str != "msg:2" {
		t.Errorf("formatMessage(msg2,msg3)返回信息错误:[%v]", str)
	}

	str = formatMessage(nil, nil)
	if str != "<未提供任何错误信息>" {
		t.Errorf("formatMessage(nil,nil)返回信息错误:[%v]", str)
	}

	str = formatMessage(nil, msg4)
	if str != "<无法正确转换错误提示信息>" {
		t.Errorf("formatMessage(nil,nil)返回信息错误:[%v]", str)
	}
}

func TestTrue(t *testing.T) {
	True(t, true)
	True(t, 1 == 1, "True(1==1) falid")
}

func TestFalse(t *testing.T) {
	False(t, false, "False falid")
	False(t, 1 == 2, "False(1==2) falid")
}

func TestNil(t *testing.T) {
	Nil(t, nil, "Nil falid")

	var v interface{}
	Nil(t, v, "Nil(v) falid")
}

func TestNotNil(t *testing.T) {
	NotNil(t, 5, "NotNil falid")

	var v interface{} = 5
	NotNil(t, v, "NotNil falid")
}

func TestEqual(t *testing.T) {
	Equal(t, 5, 5, "Equal(5,5) falid")

	var v1, v2 interface{}
	v1 = 5
	v2 = 5

	Equal(t, 5, v1)
	Equal(t, v1, v2, "Equal(v1,v2) falid")
	Equal(t, int8(126), 126)
	Equal(t, int64(126), int8(126))
	Equal(t, uint(7), int(7))
}

func TestNotEqual(t *testing.T) {
	NotEqual(t, 5, 6, "NotEqual(5,6) falid")

	var v1, v2 interface{} = 5, 6

	NotEqual(t, 5, v2, "NotEqual(5,v2) falid")
	NotEqual(t, v1, v2, "NotEqual(v1,v2) falid")
	NotEqual(t, 128, int8(127))
}

func TestEmpty(t *testing.T) {
	Empty(t, 0, "Empty(0) falid")
	Empty(t, "", "Empty(``) falid")
	Empty(t, false, "Empty(false) falid")
	Empty(t, []string{}, "Empty(slice{}) falid")
	Empty(t, []int{}, "Empty(slice{}) falid")
}

func TestNotEmpty(t *testing.T) {
	NotEmpty(t, 1, "NotEmpty(1) falid")
	NotEmpty(t, true, "NotEmpty(true) falid")
	NotEmpty(t, []string{"ab"}, "NotEmpty(slice(abc)) falid")
}

type ErrorImpl struct {
	msg string
}

func (err *ErrorImpl) Error() string {
	return err.msg
}

func TestError(t *testing.T) {
	err1 := errors.New("test")
	Error(t, err1, "Error(err) falid")

	err2 := &ErrorImpl{msg: "msg"}
	Error(t, err2, "Error(ErrorImpl) falid")
}

func TestNotError(t *testing.T) {
	NotError(t, "123", "NotError(123) falid")

	var err1 error = nil
	NotError(t, err1, "var err1 error falid")

	err2 := &ErrorImpl{msg: "msg"}
	Error(t, err2, "Error(ErrorImpl) falid")
}

func TestFileExists(t *testing.T) {
	FileExists(t, "./assert.go", "FileExists() falid")
	FileExists(t, "./", "FileExists() falid")
}

func TestFileNotExists(t *testing.T) {
	FileNotExists(t, "c:/win", "FileNotExists() falid")
	FileNotExists(t, "./abcefg/", "FileNotExists() falid")
}

func TestPanic(t *testing.T) {
	f1 := func() {
		panic("panic")
	}

	Panic(t, f1)
}

func TestNotPanic(t *testing.T) {
	f1 := func() {
	}

	NotPanic(t, f1)
}

func TestContains(t *testing.T) {
	Contains(t, []int{1, 2, 3}, []int8{1, 2})
}

func TestNotContains(t *testing.T) {
	NotContains(t, []int{1, 2, 3}, []int8{1, 3})
}
<commit_msg>修复测试用例错误<commit_after>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package assert

import (
	"errors"
	"testing"
)

func TestGetCallerInfo(t *testing.T) {
	str := getCallerInfo()
	// NOTE:注意这里涉及到调用函数的行号信息
	if str != "TestGetCallerInfo(assert_test.go:13)" {
		t.Errorf("getCallerInfo返回的信息不正确，其返回值为：%v", str)
	}

	// 嵌套调用，第二个参数为当前的行号
	testGetCallerInfo(t, "20")
	testGetCallerInfo(t, "21")

	// 闭合函数，line为调用所在的行号。
	f := func(line string) {
		str := getCallerInfo()
		if str != "TestGetCallerInfo(assert_test.go:"+line+")" ||
			str != "TestGetCallerInfo.fun1(assert_test.go:"+line+")" { // Go1.5之后变这样了
			t.Errorf("getCallerInfo返回的信息不正确，其返回值为：%v", str)
		}
	}
	f("31") // 参数为当前等号
	f("32")
}

// 参数line，为调用此函数所在的行号。
func testGetCallerInfo(t *testing.T, line string) {
	str := getCallerInfo()
	if str != "TestGetCallerInfo(assert_test.go:"+line+")" {
		t.Error("getCallerInfo返回的信息不正确，其返回值为：%v", str)
	}

}

func TestFormatMsg(t *testing.T) {
	msg1 := []interface{}{}
	msg2 := []interface{}{[]rune("msg:%v"), 2}
	msg3 := []interface{}{"msg:%v", 3}
	msg4 := []interface{}{123, 456}

	str := formatMessage(msg1, msg2)
	if str != "msg:2" {
		t.Errorf("formatMessage(msg1,msg2)返回信息错误:[%v]", str)
	}

	str = formatMessage(nil, msg2)
	if str != "msg:2" {
		t.Errorf("formatMessage(msg1,msg2)返回信息错误:[%v]", str)
	}

	str = formatMessage(msg2, msg3)
	if str != "msg:2" {
		t.Errorf("formatMessage(msg2,msg3)返回信息错误:[%v]", str)
	}

	str = formatMessage(nil, nil)
	if str != "<未提供任何错误信息>" {
		t.Errorf("formatMessage(nil,nil)返回信息错误:[%v]", str)
	}

	str = formatMessage(nil, msg4)
	if str != "<无法正确转换错误提示信息>" {
		t.Errorf("formatMessage(nil,nil)返回信息错误:[%v]", str)
	}
}

func TestTrue(t *testing.T) {
	True(t, true)
	True(t, 1 == 1, "True(1==1) falid")
}

func TestFalse(t *testing.T) {
	False(t, false, "False falid")
	False(t, 1 == 2, "False(1==2) falid")
}

func TestNil(t *testing.T) {
	Nil(t, nil, "Nil falid")

	var v interface{}
	Nil(t, v, "Nil(v) falid")
}

func TestNotNil(t *testing.T) {
	NotNil(t, 5, "NotNil falid")

	var v interface{} = 5
	NotNil(t, v, "NotNil falid")
}

func TestEqual(t *testing.T) {
	Equal(t, 5, 5, "Equal(5,5) falid")

	var v1, v2 interface{}
	v1 = 5
	v2 = 5

	Equal(t, 5, v1)
	Equal(t, v1, v2, "Equal(v1,v2) falid")
	Equal(t, int8(126), 126)
	Equal(t, int64(126), int8(126))
	Equal(t, uint(7), int(7))
}

func TestNotEqual(t *testing.T) {
	NotEqual(t, 5, 6, "NotEqual(5,6) falid")

	var v1, v2 interface{} = 5, 6

	NotEqual(t, 5, v2, "NotEqual(5,v2) falid")
	NotEqual(t, v1, v2, "NotEqual(v1,v2) falid")
	NotEqual(t, 128, int8(127))
}

func TestEmpty(t *testing.T) {
	Empty(t, 0, "Empty(0) falid")
	Empty(t, "", "Empty(``) falid")
	Empty(t, false, "Empty(false) falid")
	Empty(t, []string{}, "Empty(slice{}) falid")
	Empty(t, []int{}, "Empty(slice{}) falid")
}

func TestNotEmpty(t *testing.T) {
	NotEmpty(t, 1, "NotEmpty(1) falid")
	NotEmpty(t, true, "NotEmpty(true) falid")
	NotEmpty(t, []string{"ab"}, "NotEmpty(slice(abc)) falid")
}

type ErrorImpl struct {
	msg string
}

func (err *ErrorImpl) Error() string {
	return err.msg
}

func TestError(t *testing.T) {
	err1 := errors.New("test")
	Error(t, err1, "Error(err) falid")

	err2 := &ErrorImpl{msg: "msg"}
	Error(t, err2, "Error(ErrorImpl) falid")
}

func TestNotError(t *testing.T) {
	NotError(t, "123", "NotError(123) falid")

	var err1 error = nil
	NotError(t, err1, "var err1 error falid")

	err2 := &ErrorImpl{msg: "msg"}
	Error(t, err2, "Error(ErrorImpl) falid")
}

func TestFileExists(t *testing.T) {
	FileExists(t, "./assert.go", "FileExists() falid")
	FileExists(t, "./", "FileExists() falid")
}

func TestFileNotExists(t *testing.T) {
	FileNotExists(t, "c:/win", "FileNotExists() falid")
	FileNotExists(t, "./abcefg/", "FileNotExists() falid")
}

func TestPanic(t *testing.T) {
	f1 := func() {
		panic("panic")
	}

	Panic(t, f1)
}

func TestNotPanic(t *testing.T) {
	f1 := func() {
	}

	NotPanic(t, f1)
}

func TestContains(t *testing.T) {
	Contains(t, []int{1, 2, 3}, []int8{1, 2})
}

func TestNotContains(t *testing.T) {
	NotContains(t, []int{1, 2, 3}, []int8{1, 3})
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net"
	"net/url"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"

	"github.com/asticode/go-astilog"
	"github.com/asticode/go-astitools/flag"
	"github.com/asticode/go-astits"
	"github.com/pkg/errors"
)

// Flags
var (
	ctx, cancel = context.WithCancel(context.Background())
	dataTypes   = astiflag.NewStringsMap()
	format      = flag.String("f", "", "the format")
	inputPath   = flag.String("i", "", "the input path")
)

func main() {
	// Init
	flag.Var(dataTypes, "d", "the datatypes whitelist")
	var s = astiflag.Subcommand()
	flag.Parse()
	astilog.FlagInit()

	// Handle signals
	handleSignals()

	// Build the reader
	var r io.Reader
	var err error
	if r, err = buildReader(); err != nil {
		astilog.Error(errors.Wrap(err, "astits: parsing input failed"))
		return
	}

	// Make sure the reader is closed properly
	if c, ok := r.(io.Closer); ok {
		defer c.Close()
	}

	// Create the demuxer
	var dmx = astits.New(ctx, r)

	// Switch on subcommand
	switch s {
	case "data":
		// Fetch data
		if err = data(dmx); err != nil {
			astilog.Error(errors.Wrap(err, "astits: fetching data failed"))
			return
		}
	default:
		// Fetch the programs
		var pgms []*Program
		if pgms, err = programs(dmx); err != nil {
			astilog.Error(errors.Wrap(err, "astits: fetching programs failed"))
			return
		}

		// Print
		switch *format {
		case "json":
			var e = json.NewEncoder(os.Stdout)
			e.SetIndent("", "  ")
			if err = e.Encode(pgms); err != nil {
				astilog.Error(errors.Wrap(err, "astits: json encoding to stdout failed"))
				return
			}
		default:
			fmt.Println("Programs are:")
			for _, pgm := range pgms {
				fmt.Printf("* %s\n", pgm)
			}
		}
	}
}

func handleSignals() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch)
	go func() {
		for s := range ch {
			astilog.Debugf("Received signal %s", s)
			switch s {
			case syscall.SIGABRT, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM:
				cancel()
			}
			return
		}
	}()
}

func buildReader() (r io.Reader, err error) {
	// Validate input
	if len(*inputPath) <= 0 {
		err = errors.New("Use -i to indicate an input path")
		return
	}

	// Parse input
	var u *url.URL
	if u, err = url.Parse(*inputPath); err != nil {
		err = errors.Wrap(err, "astits: parsing input path failed")
		return
	}

	// Switch on scheme
	switch u.Scheme {
	case "udp":
		// Resolve addr
		var addr *net.UDPAddr
		if addr, err = net.ResolveUDPAddr("udp", u.Host); err != nil {
			err = errors.Wrapf(err, "astits: resolving udp addr %s failed", u.Host)
			return
		}

		// Listen to multicast UDP
		var c *net.UDPConn
		if c, err = net.ListenMulticastUDP("udp", nil, addr); err != nil {
			err = errors.Wrapf(err, "astits: listening on multicast udp addr %s failed", u.Host)
			return
		}
		c.SetReadBuffer(1000)
		r = c
	default:
		// Open file
		var f *os.File
		if f, err = os.Open(*inputPath); err != nil {
			err = errors.Wrapf(err, "astits: opening %s failed", *inputPath)
			return
		}
		r = f
	}
	return
}

func data(dmx *astits.Demuxer) (err error) {
	// Determine which data to log
	var logAll, logEIT, logNIT, logPAT, logPES, logPMT, logSDT, logTOT bool
	if _, ok := dataTypes["all"]; ok {
		logAll = true
	}
	if _, ok := dataTypes["eit"]; ok {
		logEIT = true
	}
	if _, ok := dataTypes["nit"]; ok {
		logNIT = true
	}
	if _, ok := dataTypes["pat"]; ok {
		logPAT = true
	}
	if _, ok := dataTypes["pes"]; ok {
		logPES = true
	}
	if _, ok := dataTypes["pmt"]; ok {
		logPMT = true
	}
	if _, ok := dataTypes["sdt"]; ok {
		logSDT = true
	}
	if _, ok := dataTypes["tot"]; ok {
		logTOT = true
	}

	// Loop through data
	var d *astits.Data
	astilog.Debug("Fetching data...")
	for {
		// Get next data
		if d, err = dmx.NextData(); err != nil {
			if err == astits.ErrNoMorePackets {
				break
			}
			err = errors.Wrap(err, "astits: getting nex data failed")
			return
		}

		// Log data
		if d.EIT != nil && (logAll || logEIT) {
			astilog.Infof("EIT: %d", d.PID)
		} else if d.NIT != nil && (logAll || logNIT) {
			astilog.Infof("NIT: %d", d.PID)
		} else if d.PAT != nil && (logAll || logPAT) {
			astilog.Infof("PAT: %d", d.PID)
		} else if d.PES != nil && (logAll || logPES) {
			astilog.Infof("PES: %d", d.PID)
		} else if d.PMT != nil && (logAll || logPMT) {
			astilog.Infof("PMT: %d", d.PID)
		} else if d.SDT != nil && (logAll || logSDT) {
			astilog.Infof("SDT: %d", d.PID)
		} else if d.TOT != nil && (logAll || logTOT) {
			astilog.Infof("TOT: %d", d.PID)
		}
	}
	return
}

func programs(dmx *astits.Demuxer) (o []*Program, err error) {
	// Loop through data
	var d *astits.Data
	var pgmsToProcess = make(map[uint16]bool)
	var pgms = make(map[uint16]*Program)
	astilog.Debug("Fetching data...")
	for {
		// Get next data
		if d, err = dmx.NextData(); err != nil {
			if err == astits.ErrNoMorePackets {
				var pgmsNotProcessed []string
				for n := range pgms {
					pgmsNotProcessed = append(pgmsNotProcessed, strconv.Itoa(int(n)))
				}
				err = fmt.Errorf("astits: no PMT found for program(s) %s", strings.Join(pgmsNotProcessed, ", "))
			} else {
				err = errors.Wrap(err, "astits: getting next data failed")
			}
			return
		}

		// Check data
		if d.PAT != nil && len(pgms) == 0 {
			// Build programs list
			for _, p := range d.PAT.Programs {
				// Program number 0 is reserved to NIT
				if p.ProgramNumber > 0 {
					pgmsToProcess[p.ProgramNumber] = true
					pgms[p.ProgramNumber] = newProgram(p.ProgramNumber, p.ProgramMapID)
				}
			}
		} else if d.PMT != nil {
			// Program has already been processed
			if _, ok := pgmsToProcess[d.PMT.ProgramNumber]; !ok {
				continue
			}

			// Update program
			for _, dsc := range d.PMT.ProgramDescriptors {
				pgms[d.PMT.ProgramNumber].Descriptors = append(pgms[d.PMT.ProgramNumber].Descriptors, descriptorToString(dsc))
			}

			// Add elementary streams
			for _, es := range d.PMT.ElementaryStreams {
				var s = newStream(es.ElementaryPID, es.StreamType)
				for _, d := range es.ElementaryStreamDescriptors {
					s.Descriptors = append(s.Descriptors, descriptorToString(d))
				}
				pgms[d.PMT.ProgramNumber].Streams = append(pgms[d.PMT.ProgramNumber].Streams, s)
			}

			// Update list of programs to process
			delete(pgmsToProcess, d.PMT.ProgramNumber)

			// All PMTs have been processed
			if len(pgmsToProcess) == 0 {
				break
			}
		}
	}

	// Build final data
	for _, p := range pgms {
		o = append(o, p)
	}
	return
}

// Program represents a program
type Program struct {
	Descriptors []string  `json:"descriptors,omitempty"`
	ID          uint16    `json:"id,omitempty"`
	MapID       uint16    `json:"map_id,omitempty"`
	Streams     []*Stream `json:"streams,omitempty"`
}

// Stream represents a stream
type Stream struct {
	Descriptors []string `json:"descriptors,omitempty"`
	ID          uint16   `json:"id,omitempty"`
	Type        uint8    `json:"type,omitempty"`
}

func newProgram(id, mapID uint16) *Program {
	return &Program{
		ID:    id,
		MapID: mapID,
	}
}

func newStream(id uint16, _type uint8) *Stream {
	return &Stream{
		ID:   id,
		Type: _type,
	}
}

// String implements the Stringer interface
func (p Program) String() (o string) {
	o = fmt.Sprintf("[%d] - Map ID: %d", p.ID, p.MapID)
	for _, d := range p.Descriptors {
		o += fmt.Sprintf(" - %s", d)
	}
	for _, s := range p.Streams {
		o += fmt.Sprintf("\n  * %s", s.String())
	}
	return
}

// String implements the Stringer interface
func (s Stream) String() (o string) {
	// Get type
	var t = fmt.Sprintf("unlisted stream type %d", s.Type)
	switch s.Type {
	case astits.StreamTypeLowerBitrateVideo:
		t = "Lower bitrate video"
	case astits.StreamTypeMPEG1Audio:
		t = "MPEG-1 audio"
	case astits.StreamTypeMPEG2HalvedSampleRateAudio:
		t = "MPEG-2 halved sample rate audio"
	case astits.StreamTypeMPEG2PacketizedData:
		t = "DVB subtitles/VBI or AC-3"
	}

	// Output
	o = fmt.Sprintf("[%d] - Type: %s", s.ID, t)
	for _, d := range s.Descriptors {
		o += fmt.Sprintf(" - %s", d)
	}
	return
}

func descriptorToString(d *astits.Descriptor) string {
	switch d.Tag {
	case astits.DescriptorTagAC3:
		return fmt.Sprintf("AC3 asvc: %d | bsid: %d | component type: %d | mainid: %d | info: %s", d.AC3.ASVC, d.AC3.BSID, d.AC3.ComponentType, d.AC3.MainID, d.AC3.AdditionalInfo)
	case astits.DescriptorTagISO639LanguageAndAudioType:
		return fmt.Sprintf("Language %s and audio type %d", d.ISO639LanguageAndAudioType.Language, d.ISO639LanguageAndAudioType.Type)
	case astits.DescriptorTagMaximumBitrate:
		return fmt.Sprintf("Maximum bitrate: %d", d.MaximumBitrate.Bitrate)
	case astits.DescriptorTagNetworkName:
		return fmt.Sprintf("Network name: %s", d.NetworkName.Name)
	case astits.DescriptorTagService:
		return fmt.Sprintf("Service %s from provider %s", d.Service.Name, d.Service.Provider)
	case astits.DescriptorTagShortEvent:
		return fmt.Sprintf("Short event %s for language %s with text %s", d.ShortEvent.EventName, d.ShortEvent.Language, d.ShortEvent.Text)
	case astits.DescriptorTagStreamIdentifier:
		return fmt.Sprintf("Stream identifier component tag: %d", d.StreamIdentifier.ComponentTag)
	case astits.DescriptorTagSubtitling:
		var os []string
		for _, i := range d.Subtitling.Items {
			os = append(os, fmt.Sprintf("Subtitling composition page %d and ancillary page %d: %s", i.CompositionPageID, i.AncillaryPageID, i.Language))
		}
		return strings.Join(os, " - ")
	case astits.DescriptorTagTeletext:
		var os []string
		for _, t := range d.Teletext.Items {
			os = append(os, fmt.Sprintf("Teletext page %01d%02d: %s", t.Magazine, t.Page, t.Language))
		}
		return strings.Join(os, " - ")
	}
	return fmt.Sprintf("unlisted descriptor tag 0x%x", d.Tag)
}
<commit_msg>Added profiling to CLI<commit_after>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net"
	"net/url"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"

	"github.com/asticode/go-astilog"
	"github.com/asticode/go-astitools/flag"
	"github.com/asticode/go-astits"
	"github.com/pkg/errors"
	"github.com/pkg/profile"
)

// Flags
var (
	ctx, cancel    = context.WithCancel(context.Background())
	dataTypes      = astiflag.NewStringsMap()
	format         = flag.String("f", "", "the format")
	inputPath      = flag.String("i", "", "the input path")
	profileEnabled = flag.Bool("p", false, "if yes, profiling is enabled")
)

func main() {
	// Start profiling
	if *profileEnabled {
		defer profile.Start(profile.MemProfile, profile.CPUProfile, profile.ProfilePath(".")).Stop()
	}

	// Init
	flag.Var(dataTypes, "d", "the datatypes whitelist")
	var s = astiflag.Subcommand()
	flag.Parse()
	astilog.FlagInit()

	// Handle signals
	handleSignals()

	// Build the reader
	var r io.Reader
	var err error
	if r, err = buildReader(); err != nil {
		astilog.Error(errors.Wrap(err, "astits: parsing input failed"))
		return
	}

	// Make sure the reader is closed properly
	if c, ok := r.(io.Closer); ok {
		defer c.Close()
	}

	// Create the demuxer
	var dmx = astits.New(ctx, r)

	// Switch on subcommand
	switch s {
	case "data":
		// Fetch data
		if err = data(dmx); err != nil {
			astilog.Error(errors.Wrap(err, "astits: fetching data failed"))
			return
		}
	default:
		// Fetch the programs
		var pgms []*Program
		if pgms, err = programs(dmx); err != nil {
			astilog.Error(errors.Wrap(err, "astits: fetching programs failed"))
			return
		}

		// Print
		switch *format {
		case "json":
			var e = json.NewEncoder(os.Stdout)
			e.SetIndent("", "  ")
			if err = e.Encode(pgms); err != nil {
				astilog.Error(errors.Wrap(err, "astits: json encoding to stdout failed"))
				return
			}
		default:
			fmt.Println("Programs are:")
			for _, pgm := range pgms {
				fmt.Printf("* %s\n", pgm)
			}
		}
	}
}

func handleSignals() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch)
	go func() {
		for s := range ch {
			astilog.Debugf("Received signal %s", s)
			switch s {
			case syscall.SIGABRT, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM:
				cancel()
			}
			return
		}
	}()
}

func buildReader() (r io.Reader, err error) {
	// Validate input
	if len(*inputPath) <= 0 {
		err = errors.New("Use -i to indicate an input path")
		return
	}

	// Parse input
	var u *url.URL
	if u, err = url.Parse(*inputPath); err != nil {
		err = errors.Wrap(err, "astits: parsing input path failed")
		return
	}

	// Switch on scheme
	switch u.Scheme {
	case "udp":
		// Resolve addr
		var addr *net.UDPAddr
		if addr, err = net.ResolveUDPAddr("udp", u.Host); err != nil {
			err = errors.Wrapf(err, "astits: resolving udp addr %s failed", u.Host)
			return
		}

		// Listen to multicast UDP
		var c *net.UDPConn
		if c, err = net.ListenMulticastUDP("udp", nil, addr); err != nil {
			err = errors.Wrapf(err, "astits: listening on multicast udp addr %s failed", u.Host)
			return
		}
		c.SetReadBuffer(1000)
		r = c
	default:
		// Open file
		var f *os.File
		if f, err = os.Open(*inputPath); err != nil {
			err = errors.Wrapf(err, "astits: opening %s failed", *inputPath)
			return
		}
		r = f
	}
	return
}

func data(dmx *astits.Demuxer) (err error) {
	// Determine which data to log
	var logAll, logEIT, logNIT, logPAT, logPES, logPMT, logSDT, logTOT bool
	if _, ok := dataTypes["all"]; ok {
		logAll = true
	}
	if _, ok := dataTypes["eit"]; ok {
		logEIT = true
	}
	if _, ok := dataTypes["nit"]; ok {
		logNIT = true
	}
	if _, ok := dataTypes["pat"]; ok {
		logPAT = true
	}
	if _, ok := dataTypes["pes"]; ok {
		logPES = true
	}
	if _, ok := dataTypes["pmt"]; ok {
		logPMT = true
	}
	if _, ok := dataTypes["sdt"]; ok {
		logSDT = true
	}
	if _, ok := dataTypes["tot"]; ok {
		logTOT = true
	}

	// Loop through data
	var d *astits.Data
	astilog.Debug("Fetching data...")
	for {
		// Get next data
		if d, err = dmx.NextData(); err != nil {
			if err == astits.ErrNoMorePackets {
				break
			}
			err = errors.Wrap(err, "astits: getting nex data failed")
			return
		}

		// Log data
		if d.EIT != nil && (logAll || logEIT) {
			astilog.Infof("EIT: %d", d.PID)
		} else if d.NIT != nil && (logAll || logNIT) {
			astilog.Infof("NIT: %d", d.PID)
		} else if d.PAT != nil && (logAll || logPAT) {
			astilog.Infof("PAT: %d", d.PID)
		} else if d.PES != nil && (logAll || logPES) {
			astilog.Infof("PES: %d", d.PID)
		} else if d.PMT != nil && (logAll || logPMT) {
			astilog.Infof("PMT: %d", d.PID)
		} else if d.SDT != nil && (logAll || logSDT) {
			astilog.Infof("SDT: %d", d.PID)
		} else if d.TOT != nil && (logAll || logTOT) {
			astilog.Infof("TOT: %d", d.PID)
		}
	}
	return
}

func programs(dmx *astits.Demuxer) (o []*Program, err error) {
	// Loop through data
	var d *astits.Data
	var pgmsToProcess = make(map[uint16]bool)
	var pgms = make(map[uint16]*Program)
	astilog.Debug("Fetching data...")
	for {
		// Get next data
		if d, err = dmx.NextData(); err != nil {
			if err == astits.ErrNoMorePackets {
				var pgmsNotProcessed []string
				for n := range pgms {
					pgmsNotProcessed = append(pgmsNotProcessed, strconv.Itoa(int(n)))
				}
				err = fmt.Errorf("astits: no PMT found for program(s) %s", strings.Join(pgmsNotProcessed, ", "))
			} else {
				err = errors.Wrap(err, "astits: getting next data failed")
			}
			return
		}

		// Check data
		if d.PAT != nil && len(pgms) == 0 {
			// Build programs list
			for _, p := range d.PAT.Programs {
				// Program number 0 is reserved to NIT
				if p.ProgramNumber > 0 {
					pgmsToProcess[p.ProgramNumber] = true
					pgms[p.ProgramNumber] = newProgram(p.ProgramNumber, p.ProgramMapID)
				}
			}
		} else if d.PMT != nil {
			// Program has already been processed
			if _, ok := pgmsToProcess[d.PMT.ProgramNumber]; !ok {
				continue
			}

			// Update program
			for _, dsc := range d.PMT.ProgramDescriptors {
				pgms[d.PMT.ProgramNumber].Descriptors = append(pgms[d.PMT.ProgramNumber].Descriptors, descriptorToString(dsc))
			}

			// Add elementary streams
			for _, es := range d.PMT.ElementaryStreams {
				var s = newStream(es.ElementaryPID, es.StreamType)
				for _, d := range es.ElementaryStreamDescriptors {
					s.Descriptors = append(s.Descriptors, descriptorToString(d))
				}
				pgms[d.PMT.ProgramNumber].Streams = append(pgms[d.PMT.ProgramNumber].Streams, s)
			}

			// Update list of programs to process
			delete(pgmsToProcess, d.PMT.ProgramNumber)

			// All PMTs have been processed
			if len(pgmsToProcess) == 0 {
				break
			}
		}
	}

	// Build final data
	for _, p := range pgms {
		o = append(o, p)
	}
	return
}

// Program represents a program
type Program struct {
	Descriptors []string  `json:"descriptors,omitempty"`
	ID          uint16    `json:"id,omitempty"`
	MapID       uint16    `json:"map_id,omitempty"`
	Streams     []*Stream `json:"streams,omitempty"`
}

// Stream represents a stream
type Stream struct {
	Descriptors []string `json:"descriptors,omitempty"`
	ID          uint16   `json:"id,omitempty"`
	Type        uint8    `json:"type,omitempty"`
}

func newProgram(id, mapID uint16) *Program {
	return &Program{
		ID:    id,
		MapID: mapID,
	}
}

func newStream(id uint16, _type uint8) *Stream {
	return &Stream{
		ID:   id,
		Type: _type,
	}
}

// String implements the Stringer interface
func (p Program) String() (o string) {
	o = fmt.Sprintf("[%d] - Map ID: %d", p.ID, p.MapID)
	for _, d := range p.Descriptors {
		o += fmt.Sprintf(" - %s", d)
	}
	for _, s := range p.Streams {
		o += fmt.Sprintf("\n  * %s", s.String())
	}
	return
}

// String implements the Stringer interface
func (s Stream) String() (o string) {
	// Get type
	var t = fmt.Sprintf("unlisted stream type %d", s.Type)
	switch s.Type {
	case astits.StreamTypeLowerBitrateVideo:
		t = "Lower bitrate video"
	case astits.StreamTypeMPEG1Audio:
		t = "MPEG-1 audio"
	case astits.StreamTypeMPEG2HalvedSampleRateAudio:
		t = "MPEG-2 halved sample rate audio"
	case astits.StreamTypeMPEG2PacketizedData:
		t = "DVB subtitles/VBI or AC-3"
	}

	// Output
	o = fmt.Sprintf("[%d] - Type: %s", s.ID, t)
	for _, d := range s.Descriptors {
		o += fmt.Sprintf(" - %s", d)
	}
	return
}

func descriptorToString(d *astits.Descriptor) string {
	switch d.Tag {
	case astits.DescriptorTagAC3:
		return fmt.Sprintf("AC3 asvc: %d | bsid: %d | component type: %d | mainid: %d | info: %s", d.AC3.ASVC, d.AC3.BSID, d.AC3.ComponentType, d.AC3.MainID, d.AC3.AdditionalInfo)
	case astits.DescriptorTagISO639LanguageAndAudioType:
		return fmt.Sprintf("Language %s and audio type %d", d.ISO639LanguageAndAudioType.Language, d.ISO639LanguageAndAudioType.Type)
	case astits.DescriptorTagMaximumBitrate:
		return fmt.Sprintf("Maximum bitrate: %d", d.MaximumBitrate.Bitrate)
	case astits.DescriptorTagNetworkName:
		return fmt.Sprintf("Network name: %s", d.NetworkName.Name)
	case astits.DescriptorTagService:
		return fmt.Sprintf("Service %s from provider %s", d.Service.Name, d.Service.Provider)
	case astits.DescriptorTagShortEvent:
		return fmt.Sprintf("Short event %s for language %s with text %s", d.ShortEvent.EventName, d.ShortEvent.Language, d.ShortEvent.Text)
	case astits.DescriptorTagStreamIdentifier:
		return fmt.Sprintf("Stream identifier component tag: %d", d.StreamIdentifier.ComponentTag)
	case astits.DescriptorTagSubtitling:
		var os []string
		for _, i := range d.Subtitling.Items {
			os = append(os, fmt.Sprintf("Subtitling composition page %d and ancillary page %d: %s", i.CompositionPageID, i.AncillaryPageID, i.Language))
		}
		return strings.Join(os, " - ")
	case astits.DescriptorTagTeletext:
		var os []string
		for _, t := range d.Teletext.Items {
			os = append(os, fmt.Sprintf("Teletext page %01d%02d: %s", t.Magazine, t.Page, t.Language))
		}
		return strings.Join(os, " - ")
	}
	return fmt.Sprintf("unlisted descriptor tag 0x%x", d.Tag)
}
<|endoftext|>


<commit_before>package vkapi

import "fmt"

type Attachment struct {
	Type      string    `json:"type"`
	AccessKey string    `json:"access_key"`
	Photo     *Photo    `json:"photo"`
	Audio     *Audio    `json:"audio"`
	Video     *Video    `json:"video"`
	Document  *Document `json:"doc"`
}

type Photo struct {
	ID        int64    `json:"id"`
	AlbumID   int64    `json:"album_id"`
	OwnerID   int64    `json:"owner_id"`
	UserID    int64    `json:"user_id"`
	Text      string   `json:"text"`
	Date      int64    `json:"date"`
	Sizes     *[]Sizes `json:"sizes"`
	Photo75   string   `json:"photo_75"`
	Photo130  string   `json:"photo_130"`
	Photo604  string   `json:"photo_604"`
	Photo807  string   `json:"photo_807"`
	Photo1280 string   `json:"photo_1280"`
	Photo2560 string   `json:"photo_2560"`
	Width     int      `json:"width"`
	Height    int      `json:"height"`
}

type Sizes struct {
	Src    string `json:"src"`
	Width  int    `json:"width"`
	Height int    `json:"height"`
	Type   string `json:"type"`
}

func (p *Photo) GetMaxSizePhoto() string {
	if p.Photo2560 != "" {
		return p.Photo2560
	}
	if p.Photo1280 != "" {
		return p.Photo1280
	}
	if p.Photo807 != "" {
		return p.Photo807
	}
	if p.Photo604 != "" {
		return p.Photo604
	}
	if p.Photo130 != "" {
		return p.Photo130
	}
	if p.Photo75 != "" {
		return p.Photo75
	}

	return ""
}

type Audio struct {
	ID       int64  `json:"id"`
	OwnerID  int64  `json:"owner_id"`
	Artist   string `json:"artist"`
	Title    string `json:"title"`
	Duration int64  `json:"duration"`
	Url      string `json:"url"`
	LyricsID int64  `json:"lyrics_id"`
	AlbumID  int64  `json:"album_id"`
	GenreID  int64  `json:"genre_id"`
	Date     int64  `json:"date"`
	NoSearch int    `json:"no_search"`
}

type Document struct {
	ID        int64  `json:"id"`
	OwnerID   int64  `json:"owner_id"`
	Title     string `json:"title"`
	Size      int64  `json:"size"`
	Ext       string `json:"ext"`
	Url       string `json:"url"`
	Date      int64  `json:"date"`
	Type      int    `json:"type"`
	AccessKey string `json:"access_key"`
	Preview   struct {
		Photo *struct {
			Sizes *[]Sizes `json:"sizes"`
		} `json:"photo"`
		Graffiti *Graffiti `json:"graffiti"`
		AudioMsg *AudioMsg `json:"audio_msg"`
	} `json:"preview"`
}

func (doc *Document) IsTxt() bool {
	return doc.Type == 1
}

func (doc *Document) IsArch() bool {
	return doc.Type == 2
}

func (doc *Document) IsGif() bool {
	return doc.Type == 3
}

func (doc *Document) IsImages() bool {
	return doc.Type == 4
}

func (doc *Document) IsAudio() bool {
	return doc.Type == 5
}

func (doc *Document) IsVideo() bool {
	return doc.Type == 6
}

func (doc *Document) IsEBooks() bool {
	return doc.Type == 7
}

func (doc *Document) IsUnknown() bool {
	return doc.Type == 8
}

type Graffiti struct {
	Src    string `json:"src"`
	Width  int64  `json:"width"`
	Height int64  `json:"height"`
}

type AudioMsg struct {
	Duration int64   `json:"duration"`
	Waveform []int64 `json:"waveform"`
	LinkOgg  string  `json:"link_ogg"`
	LinkMp3  string  `json:"link_mp3"`
}

type Video struct {
	ID          int64  `json:"id"`
	OwnerID     int64  `json:"owner_id"`
	Title       string `json:"title"`
	Description string `json:"description"`
	Duration    int64  `json:"duration"`
	Photo130    string `json:"photo_130"`
	Photo320    string `json:"photo_320"`
	Photo640    string `json:"photo_640"`
	Photo800    string `json:"photo_800"`
	Date        int64  `json:"date"`
	AddingDate  int64  `json:"adding_date"`
	Views       int64  `json:"views"`
	Comments    int64  `json:"comments"`
	Player      string `json:"player"`
	AccessKey   string `json:"access_key"`
	Processing  int    `json:"processing"`
	Live        int    `json:"live"`
	Upcoming    int    `json:"upcoming"`
}

func (v *Video) GetMaxPreview() string {
	if v.Photo800 != "" {
		return v.Photo800
	}
	if v.Photo640 != "" {
		return v.Photo640
	}
	if v.Photo320 != "" {
		return v.Photo320
	}
	if v.Photo130 != "" {
		return v.Photo130
	}

	return ""
}

func (client *Client) AddAttachmentPhoto(file interface{}) string {
	server, err := client.GetMessagesUploadServerForPhoto()
	if err != nil {
		return ""
	}

	res, err := client.UploadFile(server.UploadURL, "photo", file)
	if err != nil {
		return ""
	}

	photo, err := client.SaveMessagesPhoto(res)
	if err != nil {
		return ""
	}

	return fmt.Sprintf("photo%d_%d", photo.OwnerID, photo.ID)
}

func (client *Client) AddAttachmentDoc(fieldName string, peerID int64, title string, file interface{}) string {
	server, err := client.GetMessagesUploadServerForDoc(fieldName, peerID)
	if err != nil {
		return ""
	}

	res, err := client.UploadFile(server.UploadURL, "file", file)
	if err != nil {
		return ""
	}

	doc, err := client.SaveMessagesDoc(res.File, title)
	if err != nil {
		return ""
	}

	return fmt.Sprintf("doc%d_%d", doc.OwnerID, doc.ID)
}

func (client *Client) SendPhoto(dst Destination, file interface{}) (int64, *Error) {
	config := MessageConfig{
		Destination: dst,
		Attachment:  client.AddAttachmentPhoto(file),
	}

	return client.SendMessage(config)
}

func (client *Client) SendDoc(dst Destination, title string, file interface{}) (int64, *Error) {
	config := MessageConfig{
		Destination: dst,
		Attachment:  client.AddAttachmentDoc("doc", dst.GetPeerID(), title, file),
	}

	return client.SendMessage(config)
}
<commit_msg>[ ADD ] Add wall<commit_after>package vkapi

import "fmt"

type Attachment struct {
	Type      string    `json:"type"`
	AccessKey string    `json:"access_key"`
	Photo     *Photo    `json:"photo"`
	Audio     *Audio    `json:"audio"`
	Video     *Video    `json:"video"`
	Document  *Document `json:"doc"`
	Wall      *Wall     `json:"wall"`
}

type Photo struct {
	ID        int64    `json:"id"`
	AlbumID   int64    `json:"album_id"`
	OwnerID   int64    `json:"owner_id"`
	UserID    int64    `json:"user_id"`
	Text      string   `json:"text"`
	Date      int64    `json:"date"`
	Sizes     *[]Sizes `json:"sizes"`
	Photo75   string   `json:"photo_75"`
	Photo130  string   `json:"photo_130"`
	Photo604  string   `json:"photo_604"`
	Photo807  string   `json:"photo_807"`
	Photo1280 string   `json:"photo_1280"`
	Photo2560 string   `json:"photo_2560"`
	Width     int      `json:"width"`
	Height    int      `json:"height"`
}

type Sizes struct {
	Src    string `json:"src"`
	Width  int    `json:"width"`
	Height int    `json:"height"`
	Type   string `json:"type"`
}

func (p *Photo) GetMaxSizePhoto() string {
	if p.Photo2560 != "" {
		return p.Photo2560
	}
	if p.Photo1280 != "" {
		return p.Photo1280
	}
	if p.Photo807 != "" {
		return p.Photo807
	}
	if p.Photo604 != "" {
		return p.Photo604
	}
	if p.Photo130 != "" {
		return p.Photo130
	}
	if p.Photo75 != "" {
		return p.Photo75
	}

	return ""
}

type Audio struct {
	ID       int64  `json:"id"`
	OwnerID  int64  `json:"owner_id"`
	Artist   string `json:"artist"`
	Title    string `json:"title"`
	Duration int64  `json:"duration"`
	Url      string `json:"url"`
	LyricsID int64  `json:"lyrics_id"`
	AlbumID  int64  `json:"album_id"`
	GenreID  int64  `json:"genre_id"`
	Date     int64  `json:"date"`
	NoSearch int    `json:"no_search"`
}

type Document struct {
	ID        int64  `json:"id"`
	OwnerID   int64  `json:"owner_id"`
	Title     string `json:"title"`
	Size      int64  `json:"size"`
	Ext       string `json:"ext"`
	Url       string `json:"url"`
	Date      int64  `json:"date"`
	Type      int    `json:"type"`
	AccessKey string `json:"access_key"`
	Preview   struct {
		Photo *struct {
			Sizes *[]Sizes `json:"sizes"`
		} `json:"photo"`
		Graffiti *Graffiti `json:"graffiti"`
		AudioMsg *AudioMsg `json:"audio_msg"`
	} `json:"preview"`
}

func (doc *Document) IsTxt() bool {
	return doc.Type == 1
}

func (doc *Document) IsArch() bool {
	return doc.Type == 2
}

func (doc *Document) IsGif() bool {
	return doc.Type == 3
}

func (doc *Document) IsImages() bool {
	return doc.Type == 4
}

func (doc *Document) IsAudio() bool {
	return doc.Type == 5
}

func (doc *Document) IsVideo() bool {
	return doc.Type == 6
}

func (doc *Document) IsEBooks() bool {
	return doc.Type == 7
}

func (doc *Document) IsUnknown() bool {
	return doc.Type == 8
}

type Graffiti struct {
	Src    string `json:"src"`
	Width  int64  `json:"width"`
	Height int64  `json:"height"`
}

type AudioMsg struct {
	Duration int64   `json:"duration"`
	Waveform []int64 `json:"waveform"`
	LinkOgg  string  `json:"link_ogg"`
	LinkMp3  string  `json:"link_mp3"`
}

type Video struct {
	ID          int64  `json:"id"`
	OwnerID     int64  `json:"owner_id"`
	Title       string `json:"title"`
	Description string `json:"description"`
	Duration    int64  `json:"duration"`
	Photo130    string `json:"photo_130"`
	Photo320    string `json:"photo_320"`
	Photo640    string `json:"photo_640"`
	Photo800    string `json:"photo_800"`
	Date        int64  `json:"date"`
	AddingDate  int64  `json:"adding_date"`
	Views       int64  `json:"views"`
	Comments    int64  `json:"comments"`
	Player      string `json:"player"`
	AccessKey   string `json:"access_key"`
	Processing  int    `json:"processing"`
	Live        int    `json:"live"`
	Upcoming    int    `json:"upcoming"`
}

func (v *Video) GetMaxPreview() string {
	if v.Photo800 != "" {
		return v.Photo800
	}
	if v.Photo640 != "" {
		return v.Photo640
	}
	if v.Photo320 != "" {
		return v.Photo320
	}
	if v.Photo130 != "" {
		return v.Photo130
	}

	return ""
}

func (client *Client) AddAttachmentPhoto(file interface{}) string {
	server, err := client.GetMessagesUploadServerForPhoto()
	if err != nil {
		return ""
	}

	res, err := client.UploadFile(server.UploadURL, "photo", file)
	if err != nil {
		return ""
	}

	photo, err := client.SaveMessagesPhoto(res)
	if err != nil {
		return ""
	}

	return fmt.Sprintf("photo%d_%d", photo.OwnerID, photo.ID)
}

func (client *Client) AddAttachmentDoc(fieldName string, peerID int64, title string, file interface{}) string {
	server, err := client.GetMessagesUploadServerForDoc(fieldName, peerID)
	if err != nil {
		return ""
	}

	res, err := client.UploadFile(server.UploadURL, "file", file)
	if err != nil {
		return ""
	}

	doc, err := client.SaveMessagesDoc(res.File, title)
	if err != nil {
		return ""
	}

	return fmt.Sprintf("doc%d_%d", doc.OwnerID, doc.ID)
}

func (client *Client) SendPhoto(dst Destination, file interface{}) (int64, *Error) {
	config := MessageConfig{
		Destination: dst,
		Attachment:  client.AddAttachmentPhoto(file),
	}

	return client.SendMessage(config)
}

func (client *Client) SendDoc(dst Destination, title string, file interface{}) (int64, *Error) {
	config := MessageConfig{
		Destination: dst,
		Attachment:  client.AddAttachmentDoc("doc", dst.GetPeerID(), title, file),
	}

	return client.SendMessage(config)
}
<|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 backup

import (
	"errors"
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	"path"
)

// An object that knows how to save directories to some underlying storage.
type DirectorySaver interface {
	// Recursively save the contents of the supplied directory to the underlying
	// storage, returning the score of a blob representing the directory's
	// listing in a format that can be recovered with repr.Unmarshal.
	Save(dirpath string) (score blob.Score, err error)
}

// A directory saver that creates a new directory saver for each call to Save.
// This breaks a self-dependency that would be needed to make use of
// NewNonRecursiveDirectorySaver.
type onDemandDirSaver struct {
	createSaver func(wrapped DirectorySaver) DirectorySaver
}

func (s *onDemandDirSaver) Save(dirpath string) (score blob.Score, err error) {
	return s.createSaver(s).Save(dirpath)
}

// Return a directory saver that makes use of the supplied dependencies.
func NewDirectorySaver(
	blobStore blob.Store,
	fileSystem fs.FileSystem,
	fileSaver FileSaver) (DirectorySaver, error) {
	createSaver := func(wrapped DirectorySaver) DirectorySaver {
		saver, err := NewNonRecursiveDirectorySaver(
			blobStore,
			fileSystem,
			fileSaver,
			wrapped)

		if err != nil {
			panic(err)
		}

		return saver
	}

	return &onDemandDirSaver{createSaver}, nil
}

// Equivalent to NewDirectorySaver, but with an injectable wrapped directory
// saver to aid with testability. You should not use this function.
func NewNonRecursiveDirectorySaver(
	store blob.Store,
	fileSystem fs.FileSystem,
	fileSaver FileSaver,
	wrapped DirectorySaver) (DirectorySaver, error) {
	return &dirSaver{
		blobStore:  store,
		fileSystem: fileSystem,
		fileSaver:  fileSaver,
		wrapped:    wrapped,
	}, nil
}

type dirSaver struct {
	blobStore  blob.Store
	fileSystem fs.FileSystem
	fileSaver  FileSaver
	wrapped    DirectorySaver
}

func (s *dirSaver) saveDir(parent string, entry *fs.DirectoryEntry) ([]blob.Score, error) {
	// Recurse.
	score, err := s.wrapped.Save(path.Join(parent, entry.Name))
	if err != nil {
		return nil, err
	}

	return []blob.Score{score}, nil
}

func (s *dirSaver) saveFile(parent string, entry *fs.DirectoryEntry) ([]blob.Score, error) {
	// Open the file.
	f, err := s.fileSystem.OpenForReading(path.Join(parent, entry.Name))
	if err != nil {
		return nil, fmt.Errorf("Opening file: %v", err)
	}
	defer f.Close()

	// Defer to the file saver.
	return s.fileSaver.Save(f)
}

func (s *dirSaver) Save(dirpath string) (score blob.Score, err error) {
	// Grab a listing for the directory.
	entries, err := s.fileSystem.ReadDir(dirpath)
	if err != nil {
		return nil, fmt.Errorf("Listing directory: %v", err)
	}

	// Save the data for each entry.
	for _, entry := range entries {
		// Call the appropriate method based on this entry's type.
		switch entry.Type {
		case fs.TypeFile:
			entry.Scores, err = s.saveFile(dirpath, entry)
		case fs.TypeDirectory:
			entry.Scores, err = s.saveDir(dirpath, entry)
		case fs.TypeSymlink:
		case fs.TypeBlockDevice:
		case fs.TypeCharDevice:
		case fs.TypeNamedPipe:
		default:
			err = fmt.Errorf("Unhandled type: %v", entry.Type)
		}

		if err != nil {
			return nil, err
		}
	}

	// Create a serialized version of this information.
	data, err := repr.Marshal(entries)
	if err != nil {
		return nil, fmt.Errorf("Marshaling: %v", err)
	}

	// Store that serialized version.
	score, err = s.blobStore.Store(data)
	if err != nil {
		err = errors.New("Storing dir blob: " + err.Error())
	}

	return
}
<commit_msg>Required a link resolver.<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 backup

import (
	"errors"
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	"path"
)

// An object that knows how to save directories to some underlying storage.
type DirectorySaver interface {
	// Recursively save the contents of the supplied directory to the underlying
	// storage, returning the score of a blob representing the directory's
	// listing in a format that can be recovered with repr.Unmarshal.
	Save(dirpath string) (score blob.Score, err error)
}

// A directory saver that creates a new directory saver for each call to Save.
// This breaks a self-dependency that would be needed to make use of
// NewNonRecursiveDirectorySaver.
type onDemandDirSaver struct {
	createSaver func(wrapped DirectorySaver) DirectorySaver
}

func (s *onDemandDirSaver) Save(dirpath string) (score blob.Score, err error) {
	return s.createSaver(s).Save(dirpath)
}

// Return a directory saver that makes use of the supplied dependencies.
func NewDirectorySaver(
	blobStore blob.Store,
	fileSystem fs.FileSystem,
	fileSaver FileSaver) (DirectorySaver, error) {
	createSaver := func(wrapped DirectorySaver) DirectorySaver {
		saver, err := NewNonRecursiveDirectorySaver(
			blobStore,
			fileSystem,
			fileSaver,
			wrapped)

		if err != nil {
			panic(err)
		}

		return saver
	}

	return &onDemandDirSaver{createSaver}, nil
}

// Equivalent to NewDirectorySaver, but with an injectable wrapped directory
// saver and link resolver to aid with testability. You should not use this
// function.
func NewNonRecursiveDirectorySaver(
	store blob.Store,
	fileSystem fs.FileSystem,
	fileSaver FileSaver,
	wrapped DirectorySaver,
  linkResolver LinkResolver) (DirectorySaver, error) {
	return &dirSaver{
		blobStore:  store,
		fileSystem: fileSystem,
		fileSaver:  fileSaver,
		wrapped:    wrapped,
	}, nil
}

type dirSaver struct {
	blobStore  blob.Store
	fileSystem fs.FileSystem
	fileSaver  FileSaver
	wrapped    DirectorySaver
}

func (s *dirSaver) saveDir(parent string, entry *fs.DirectoryEntry) ([]blob.Score, error) {
	// Recurse.
	score, err := s.wrapped.Save(path.Join(parent, entry.Name))
	if err != nil {
		return nil, err
	}

	return []blob.Score{score}, nil
}

func (s *dirSaver) saveFile(parent string, entry *fs.DirectoryEntry) ([]blob.Score, error) {
	// Open the file.
	f, err := s.fileSystem.OpenForReading(path.Join(parent, entry.Name))
	if err != nil {
		return nil, fmt.Errorf("Opening file: %v", err)
	}
	defer f.Close()

	// Defer to the file saver.
	return s.fileSaver.Save(f)
}

func (s *dirSaver) Save(dirpath string) (score blob.Score, err error) {
	// Grab a listing for the directory.
	entries, err := s.fileSystem.ReadDir(dirpath)
	if err != nil {
		return nil, fmt.Errorf("Listing directory: %v", err)
	}

	// Save the data for each entry.
	for _, entry := range entries {
		// Call the appropriate method based on this entry's type.
		switch entry.Type {
		case fs.TypeFile:
			entry.Scores, err = s.saveFile(dirpath, entry)
		case fs.TypeDirectory:
			entry.Scores, err = s.saveDir(dirpath, entry)
		case fs.TypeSymlink:
		case fs.TypeBlockDevice:
		case fs.TypeCharDevice:
		case fs.TypeNamedPipe:
		default:
			err = fmt.Errorf("Unhandled type: %v", entry.Type)
		}

		if err != nil {
			return nil, err
		}
	}

	// Create a serialized version of this information.
	data, err := repr.Marshal(entries)
	if err != nil {
		return nil, fmt.Errorf("Marshaling: %v", err)
	}

	// Store that serialized version.
	score, err = s.blobStore.Store(data)
	if err != nil {
		err = errors.New("Storing dir blob: " + err.Error())
	}

	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Ernest Micklei
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package proto

import "strings"

type aligned struct {
	source  string
	left    bool
	padding bool
}

var (
	alignedEquals      = leftAligned(" = ")
	alignedShortEquals = leftAligned("=")
	alignedSpace       = leftAligned(" ")
	alignedComma       = leftAligned(", ")
	alignedEmpty       = leftAligned("")
	alignedSemicolon   = leftAligned(";")
)

func leftAligned(src string) aligned  { return aligned{src, true, true} }
func rightAligned(src string) aligned { return aligned{src, false, true} }
func notAligned(src string) aligned   { return aligned{src, false, false} }

func (a aligned) preferredWidth() int { return len(a.source) }

func (a aligned) formatted(width int) string {
	if len(a.source) > width {
		return a.source[:width]
	}
	if !a.padding {
		return a.source
	}
	if a.left {
		return a.source + strings.Repeat(" ", width-len(a.source))
	}
	return strings.Repeat(" ", width-len(a.source)) + a.source
}
<commit_msg>fix issue #4 , comment affects padding<commit_after>// Copyright (c) 2017 Ernest Micklei
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package proto

import "strings"

type aligned struct {
	source  string
	left    bool
	padding bool
}

var (
	alignedEquals      = leftAligned(" = ")
	alignedShortEquals = leftAligned("=")
	alignedSpace       = leftAligned(" ")
	alignedComma       = leftAligned(", ")
	alignedEmpty       = leftAligned("")
	alignedSemicolon   = leftAligned(";")
)

func leftAligned(src string) aligned  { return aligned{src, true, true} }
func rightAligned(src string) aligned { return aligned{src, false, true} }
func notAligned(src string) aligned   { return aligned{src, false, false} }

func (a aligned) preferredWidth() int {
	if !a.hasAlignment() {
		return 0 // means do not force padding because of this source
	}
	return len(a.source)
}

func (a aligned) formatted(width int) string {
	if !a.padding {
		return a.source
	}
	if a.left {
		return a.source + strings.Repeat(" ", width-len(a.source))
	}
	return strings.Repeat(" ", width-len(a.source)) + a.source
}

func (a aligned) hasAlignment() bool { return a.left || a.padding }
<|endoftext|>


<commit_before>package csvutil

import (
	"encoding/csv"
	"io"
	"math/rand"

	"golang.org/x/text/encoding/japanese"
)

func reader(r io.Reader, enc string) (*csv.Reader, bool) {
	if enc == "sjis" {
		return NewReaderWithEnc(r, japanese.ShiftJIS), false
	} else if enc == "eucjp" {
		return NewReaderWithEnc(r, japanese.EUCJP), false
	}
	return NewReader(r)
}

func writer(w io.Writer, bom bool, enc string) *csv.Writer {
	if enc == "sjis" {
		return NewWriterWithEnc(w, japanese.ShiftJIS)
	} else if enc == "eucjp" {
		return NewWriterWithEnc(w, japanese.EUCJP)
	}
	return NewWriter(w, bom)
}

func isDigit(s string) bool {
	if s == "" {
		return false
	}
	for _, b := range []byte(s) {
		if b < 0x30 || 0x39 < b {
			return false
		}
	}
	return true
}

func isDigitOrEmpty(s string) bool {
	if s == "" {
		return true
	}
	return isDigit(s)
}

func lot(n int) bool {
	if n == 100 {
		return true
	}
	if n == 0 {
		return false
	}
	return rand.Intn(100) < n
}

func sampleString(ss []string) string {
	return ss[rand.Intn(len(ss))]
}

func containsString(ss []string, s string) bool {
	for _, s2 := range ss {
		if s2 == s {
			return true
		}
	}
	return false
}
<commit_msg>使用していない関数を削除<commit_after>package csvutil

import (
	"encoding/csv"
	"io"
	"math/rand"

	"golang.org/x/text/encoding/japanese"
)

func reader(r io.Reader, enc string) (*csv.Reader, bool) {
	if enc == "sjis" {
		return NewReaderWithEnc(r, japanese.ShiftJIS), false
	} else if enc == "eucjp" {
		return NewReaderWithEnc(r, japanese.EUCJP), false
	}
	return NewReader(r)
}

func writer(w io.Writer, bom bool, enc string) *csv.Writer {
	if enc == "sjis" {
		return NewWriterWithEnc(w, japanese.ShiftJIS)
	} else if enc == "eucjp" {
		return NewWriterWithEnc(w, japanese.EUCJP)
	}
	return NewWriter(w, bom)
}

func isDigit(s string) bool {
	if s == "" {
		return false
	}
	for _, b := range []byte(s) {
		if b < 0x30 || 0x39 < b {
			return false
		}
	}
	return true
}

func lot(n int) bool {
	if n == 100 {
		return true
	}
	if n == 0 {
		return false
	}
	return rand.Intn(100) < n
}

func sampleString(ss []string) string {
	return ss[rand.Intn(len(ss))]
}

func containsString(ss []string, s string) bool {
	for _, s2 := range ss {
		if s2 == s {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"fmt"
	"github.com/mathcunha/CloudCapacitor/capacitor"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
)

func restHandlerV1(w http.ResponseWriter, r *http.Request) {
	a_path := strings.Split(r.URL.Path, "/")
	if "POST" != r.Method {
		http.Error(w, "method not allowed, try curl -X POST https://cloudcapacitor.herokuapp.com/api/v1/capacitor", http.StatusMethodNotAllowed)
		return
	}
	if "capacitor" != a_path[3] {
		http.Error(w, "no handler to path "+r.URL.Path, http.StatusNotFound)
		return
	} else {
		callCapacitorResource(w, r)
	}
}

func StartServer() {
	http.HandleFunc("/webui/", staticHandler)
	http.HandleFunc("/api/v1/", restHandlerV1)
	http.ListenAndServe(getPort(), nil)
}

func staticHandler(w http.ResponseWriter, r *http.Request) {
	//log.Printf("INFO: staticHandler:%v", r.URL.Path[1:])
	http.ServeFile(w, r, r.URL.Path[1:])
}

func getPort() string {
	var port = os.Getenv("PORT")
	// Set a default port if there is nothing in the environment
	if port == "" {
		port = "8080"
		log.Println("INFO: No PORT environment variable detected, defaulting to " + port)
	}
	return ":" + port
}

func callCapacitorResource(w http.ResponseWriter, r *http.Request) {
	price := 7.0
	size := 4
	var config struct {
		Slo           int    `json:"slo"`
		Mode          string `json:"mode"`
		Category      bool   `json:"category"`
		Demand        []int  `json:"demand"`
		WKL           string `json:"wkl"`
		Configuration string `json:"configuration"`
	}

	err := json.NewDecoder(r.Body).Decode(&config)
	r.Body.Close()
	if err != nil {
		log.Printf("ERROR: Parsing request body callCapacitorResource:%v", err)
		return
	}

	vms, err := capacitor.LoadTypes("config/dspace.yml")
	if err != nil {
		log.Println("ERROR: callCapacitorResource loanding vm types")
		return
	}
	dspace := capacitor.NewDeploymentSpace(&vms, float32(price), size)
	m := capacitor.MockExecutor{"config/wordpress_cpu_mem.csv", nil}
	err = m.Load()
	if err != nil {
		log.Println("ERROR: callCapacitorResource unable to start MockExecutor")
		return
	}

	c := capacitor.Capacitor{dspace, m}
	h := capacitor.NewPolicy(&c, config.Configuration, config.WKL)

	wkls := make([]string, len(config.Demand), len(config.Demand))
	for i, d := range config.Demand {
		wkls[i] = strconv.Itoa(d)
	}

	execInfo, dspaceInfo := h.Exec(config.Mode, float32(config.Slo), wkls)

	str := ExecPathSummary(execInfo, wkls, config.Mode, &c)
	str = fmt.Sprintf("%v, \"spaceInfo\":%v}", str[0:len(str)-1], DeploymentSpace(execInfo, wkls, config.Mode, &c, dspaceInfo, m, float32(config.Slo)))

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "%v", str)
}

func DeploymentSpace(winner capacitor.ExecInfo, wkls []string, mode string, c *capacitor.Capacitor, dspaceInfo map[string]capacitor.NodesInfo, executor capacitor.Executor, slo float32) (str string) {
	nodeMap := *c.Dspace.CapacityBy(mode)

	str = "["
	for cat, nodesInfo := range dspaceInfo {
		nodes := nodeMap[cat]
		for level := 1; level <= nodesInfo.Levels; level++ {
			node := nodes.NodeByLevel(level)
			for wkl := 0; wkl < nodesInfo.Workloads; wkl++ {
				str = fmt.Sprintf("%v%v", str, PrintNodeExecInfo(node, wkl, nodesInfo, executor, slo))
			}
			for _, e := range nodes.Equivalents(node) {
				for wkl := 0; wkl < nodesInfo.Workloads; wkl++ {
					str = fmt.Sprintf("%v%v", str, PrintNodeExecInfo(e, wkl, nodesInfo, executor, slo))
				}
			}
		}
	}
	str = fmt.Sprintf("%v]", str[0:len(str)-1])
	return
}

func PrintNodeExecInfo(node *capacitor.Node, wkl int, nodesInfo capacitor.NodesInfo, executor capacitor.Executor, slo float32) (str string) {
	key := capacitor.GetMatrixKey(node.ID, wkl)
	nodeInfo := nodesInfo.Matrix[key]
	if wkl == 0 {
		str = fmt.Sprintf("%v{\"name\":\"%v\", \"size\":%v, \"wkl\":[", str, node.Configs[0].Name, node.Configs[0].Size)
	}
	result := executor.Execute(*node.Configs[0], nodeInfo.WKL)
	metSLO := result.SLO <= slo
	right := nodeInfo.Candidate == metSLO
	str = fmt.Sprintf("%v{\"wkl\":\"%v\", \"when\":%v, \"exec\":%v, \"cadidate\":%v, \"right\":%v},", str, nodeInfo.WKL, nodeInfo.When, nodeInfo.Exec, nodeInfo.Candidate, right)
	if wkl == nodesInfo.Workloads-1 {
		str = fmt.Sprintf("%v]},", str[0:len(str)-1])
	}
	return
}

func ExecPathSummary(winner capacitor.ExecInfo, wkls []string, mode string, c *capacitor.Capacitor) (str string) {
	nos := make([]*capacitor.Node, 0, 28)

	for _, n := range *c.Dspace.CapacityBy(mode) {
		nos = append(nos, n...)
	}
	nodes := capacitor.Nodes(nos)
	execs := 0
	price := float32(0.0)

	path := strings.Split(winner.Path, "->")
	str = "["
	for _, key := range path {
		ID, cWKL := capacitor.SplitMatrixKey(key)
		if cWKL != -1 {
			node := nodes.NodeByID(ID)
			str = fmt.Sprintf("%v{\"key\":\"%v\", \"workload\":%v, \"level\":%v,  \"name\":\"%v\", \"price\":%.2f, \"size\":%v},", str, key, wkls[cWKL], node.Level, node.Configs[0].Name, node.Configs[0].Price(), node.Configs[0].Size)
			execs = execs + len(node.Configs)
			price = price + node.Configs[0].Price()
		}
	}
	//one extra comma
	str = fmt.Sprintf("{\"execs\":%v, \"price\":%.2f, \"path\":%v]}", execs, price, str[0:len(str)-1])
	return str
}
<commit_msg>sum precision lost<commit_after>package api

import (
	"encoding/json"
	"fmt"
	"github.com/mathcunha/CloudCapacitor/capacitor"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
)

func restHandlerV1(w http.ResponseWriter, r *http.Request) {
	a_path := strings.Split(r.URL.Path, "/")
	if "POST" != r.Method {
		http.Error(w, "method not allowed, try curl -X POST https://cloudcapacitor.herokuapp.com/api/v1/capacitor", http.StatusMethodNotAllowed)
		return
	}
	if "capacitor" != a_path[3] {
		http.Error(w, "no handler to path "+r.URL.Path, http.StatusNotFound)
		return
	} else {
		callCapacitorResource(w, r)
	}
}

func StartServer() {
	http.HandleFunc("/webui/", staticHandler)
	http.HandleFunc("/api/v1/", restHandlerV1)
	http.ListenAndServe(getPort(), nil)
}

func staticHandler(w http.ResponseWriter, r *http.Request) {
	//log.Printf("INFO: staticHandler:%v", r.URL.Path[1:])
	http.ServeFile(w, r, r.URL.Path[1:])
}

func getPort() string {
	var port = os.Getenv("PORT")
	// Set a default port if there is nothing in the environment
	if port == "" {
		port = "8080"
		log.Println("INFO: No PORT environment variable detected, defaulting to " + port)
	}
	return ":" + port
}

func callCapacitorResource(w http.ResponseWriter, r *http.Request) {
	price := 7.0
	size := 4
	var config struct {
		Slo           int    `json:"slo"`
		Mode          string `json:"mode"`
		Category      bool   `json:"category"`
		Demand        []int  `json:"demand"`
		WKL           string `json:"wkl"`
		Configuration string `json:"configuration"`
	}

	err := json.NewDecoder(r.Body).Decode(&config)
	r.Body.Close()
	if err != nil {
		log.Printf("ERROR: Parsing request body callCapacitorResource:%v", err)
		return
	}

	vms, err := capacitor.LoadTypes("config/dspace.yml")
	if err != nil {
		log.Println("ERROR: callCapacitorResource loanding vm types")
		return
	}
	dspace := capacitor.NewDeploymentSpace(&vms, float32(price), size)
	m := capacitor.MockExecutor{"config/wordpress_cpu_mem.csv", nil}
	err = m.Load()
	if err != nil {
		log.Println("ERROR: callCapacitorResource unable to start MockExecutor")
		return
	}

	c := capacitor.Capacitor{dspace, m}
	h := capacitor.NewPolicy(&c, config.Configuration, config.WKL)

	wkls := make([]string, len(config.Demand), len(config.Demand))
	for i, d := range config.Demand {
		wkls[i] = strconv.Itoa(d)
	}

	execInfo, dspaceInfo := h.Exec(config.Mode, float32(config.Slo), wkls)

	str := ExecPathSummary(execInfo, wkls, config.Mode, &c)
	str = fmt.Sprintf("%v, \"spaceInfo\":%v}", str[0:len(str)-1], DeploymentSpace(execInfo, wkls, config.Mode, &c, dspaceInfo, m, float32(config.Slo)))

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "%v", str)
}

func DeploymentSpace(winner capacitor.ExecInfo, wkls []string, mode string, c *capacitor.Capacitor, dspaceInfo map[string]capacitor.NodesInfo, executor capacitor.Executor, slo float32) (str string) {
	nodeMap := *c.Dspace.CapacityBy(mode)

	str = "["
	for cat, nodesInfo := range dspaceInfo {
		nodes := nodeMap[cat]
		for level := 1; level <= nodesInfo.Levels; level++ {
			node := nodes.NodeByLevel(level)
			for wkl := 0; wkl < nodesInfo.Workloads; wkl++ {
				str = fmt.Sprintf("%v%v", str, PrintNodeExecInfo(node, wkl, nodesInfo, executor, slo))
			}
			for _, e := range nodes.Equivalents(node) {
				for wkl := 0; wkl < nodesInfo.Workloads; wkl++ {
					str = fmt.Sprintf("%v%v", str, PrintNodeExecInfo(e, wkl, nodesInfo, executor, slo))
				}
			}
		}
	}
	str = fmt.Sprintf("%v]", str[0:len(str)-1])
	return
}

func PrintNodeExecInfo(node *capacitor.Node, wkl int, nodesInfo capacitor.NodesInfo, executor capacitor.Executor, slo float32) (str string) {
	key := capacitor.GetMatrixKey(node.ID, wkl)
	nodeInfo := nodesInfo.Matrix[key]
	if wkl == 0 {
		str = fmt.Sprintf("%v{\"name\":\"%v\", \"size\":%v, \"wkl\":[", str, node.Configs[0].Name, node.Configs[0].Size)
	}
	result := executor.Execute(*node.Configs[0], nodeInfo.WKL)
	metSLO := result.SLO <= slo
	right := nodeInfo.Candidate == metSLO
	str = fmt.Sprintf("%v{\"wkl\":\"%v\", \"when\":%v, \"exec\":%v, \"cadidate\":%v, \"right\":%v},", str, nodeInfo.WKL, nodeInfo.When, nodeInfo.Exec, nodeInfo.Candidate, right)
	if wkl == nodesInfo.Workloads-1 {
		str = fmt.Sprintf("%v]},", str[0:len(str)-1])
	}
	return
}

func ExecPathSummary(winner capacitor.ExecInfo, wkls []string, mode string, c *capacitor.Capacitor) (str string) {
	nos := make([]*capacitor.Node, 0, 28)

	for _, n := range *c.Dspace.CapacityBy(mode) {
		nos = append(nos, n...)
	}
	nodes := capacitor.Nodes(nos)
	execs := 0
	price := 0.0

	path := strings.Split(winner.Path, "->")
	str = "["
	for _, key := range path {
		ID, cWKL := capacitor.SplitMatrixKey(key)
		if cWKL != -1 {
			node := nodes.NodeByID(ID)
			str = fmt.Sprintf("%v{\"key\":\"%v\", \"workload\":%v, \"level\":%v,  \"name\":\"%v\", \"price\":%.2f, \"size\":%v},", str, key, wkls[cWKL], node.Level, node.Configs[0].Name, node.Configs[0].Price(), node.Configs[0].Size)
			execs = execs + len(node.Configs)
			price = price + float64(node.Configs[0].Price())
		}
	}
	//one extra comma
	str = fmt.Sprintf("{\"execs\":%v, \"price\":%.2f, \"path\":%v]}", execs, price, str[0:len(str)-1])
	return str
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"fmt"
	"github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/strava/go.strava"
	sync "github.com/svdberg/syncmysport-runkeeper/sync"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

const startTime = -1 * time.Duration(1) * time.Hour * 24 * 365 //1 year ago
const RkClientId = "73664cff18ed4800aab6cffc7ef8f4e1"

var (
	DbConnectionString string
	RkSecret           string
	StvSecret          string
	RedirectUriRk      string
	RedirectUriStv     string
	authenticator      *strava.OAuthAuthenticator
)

func Start(connString string, port int, secretRk string, redirectRk string, secretStv string, redirectStv string) {
	DbConnectionString = connString
	RkSecret = secretRk
	RedirectUriRk = redirectRk
	RedirectUriStv = redirectStv
	StvSecret = secretStv
	portString := fmt.Sprintf(":%d", port)

	strava.ClientId = 9667
	strava.ClientSecret = StvSecret

	//for strava
	authenticator = &strava.OAuthAuthenticator{
		CallbackURL:            RedirectUriStv,
		RequestClientGenerator: nil,
	}

	log.Printf("callback url: %s", authenticator.AuthorizationURL("state1", strava.Permissions.Public, true))
	router := NewRouter()
	router.Methods("GET").Path("/exchange_token").Name("STVOAuthCallback").Handler(authenticator.HandlerFunc(oAuthSuccess, oAuthFailure))
	router.PathPrefix("/").Handler(http.FileServer(http.Dir("./api/static/")))
	log.Fatal(http.ListenAndServe(portString, router))
}

func oAuthSuccess(auth *strava.AuthorizationResponse, w http.ResponseWriter, r *http.Request) {
	//fmt.Fprintf(w, "SUCCESS:\nAt this point you can use this information to create a new user or link the account to one of your existing users\n")
	//fmt.Fprintf(w, "State: %s\n\n", auth.State)
	//fmt.Fprintf(w, "Access Token: %s\n\n", auth.AccessToken)

	//fmt.Fprintf(w, "The Authenticated Athlete (you):\n")
	//content, _ := json.MarshalIndent(auth.Athlete, "", " ")
	//fmt.Fprint(w, string(content))

	db := sync.CreateSyncDbRepo(DbConnectionString)
	task, err := db.FindSyncTaskByToken(auth.AccessToken)
	if task == nil || err != nil {
		syncTask := sync.CreateSyncTask("", "", -1)
		syncTask.StravaToken = auth.AccessToken
		syncTask.LastSeenTimestamp = nowMinusOneHourInUnix()
		_, _, _, err := db.StoreSyncTask(*syncTask)
		if err != nil {
			cookie := &http.Cookie{Name: "strava", Value: fmt.Sprintf("%s", syncTask.StravaToken), Expires: time.Now().Add(356 * 24 * time.Hour), HttpOnly: false}
			cookie.Domain = "www.syncmysport.com"
			http.SetCookie(w, cookie)
		}

	} else {
		//update cookie
		cookie := &http.Cookie{Name: "strava", Value: fmt.Sprintf("%s", task.StravaToken), Expires: time.Now().Add(356 * 24 * time.Hour), HttpOnly: false}
		cookie.Domain = "www.syncmysport.com"
		http.SetCookie(w, cookie)

		if task.StravaToken != auth.AccessToken {
			task.StravaToken = auth.AccessToken
			db.UpdateSyncTask(*task)
		} else {
			log.Printf("Token %s is already stored for task id: %d", auth.AccessToken, task.Uid)
		}
	}
	//redirect back to connect
	http.Redirect(w, r, "www.syncmysport.com/connect.html", 303)
}

func oAuthFailure(err error, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Authorization Failure:\n")

	// some standard error checking
	if err == strava.OAuthAuthorizationDeniedErr {
		fmt.Fprint(w, "The user clicked the 'Do not Authorize' button on the previous page.\n")
		fmt.Fprint(w, "This is the main error your application should handle.")
	} else if err == strava.OAuthInvalidCredentialsErr {
		fmt.Fprint(w, "You provided an incorrect client_id or client_secret.\nDid you remember to set them at the begininng of this file?")
	} else if err == strava.OAuthInvalidCodeErr {
		fmt.Fprint(w, "The temporary token was not recognized, this shouldn't happen normally")
	} else if err == strava.OAuthServerErr {
		fmt.Fprint(w, "There was some sort of server error, try again to see if the problem continues")
	} else {
		fmt.Fprint(w, err)
	}
}
func OAuthCallback(response http.ResponseWriter, request *http.Request) {
	code := request.URL.Query().Get("code")
	go ObtainBearerToken(code)
	//redirect to sign up page with Acknowledgement of success..
	http.Redirect(response, request, "www.syncmysport.com/connect.html", 303)
}

func ObtainBearerToken(code string) {
	tokenUrl := "https://runkeeper.com/apps/token"
	formData := make(map[string][]string)
	formData["grant_type"] = []string{"authorization_code"}
	formData["code"] = []string{code}
	formData["client_id"] = []string{RkClientId}
	formData["client_secret"] = []string{RkSecret}
	formData["redirect_uri"] = []string{RedirectUriRk}
	client := new(http.Client)
	response, err := client.PostForm(tokenUrl, formData)
	responseJson := make(map[string]string)
	if err == nil {
		responseBody, _ := ioutil.ReadAll(response.Body)
		json.Unmarshal(responseBody, &responseJson)
		token := responseJson["access_token"]
		db := sync.CreateSyncDbRepo(DbConnectionString)
		task, err := db.FindSyncTaskByToken(token)
		if task == nil || err != nil {
			syncTask := sync.CreateSyncTask("", "", -1)
			syncTask.RunkeeperToken = token
			syncTask.LastSeenTimestamp = nowMinusOneHourInUnix()
			db.StoreSyncTask(*syncTask)
		} else {
			if task.RunkeeperToken != token {
				task.RunkeeperToken = token
				db.UpdateSyncTask(*task)
			} else {
				log.Printf("Token %s is already stored for task id: %d", token, task.Uid)
			}
		}
	} else {
		fmt.Print(err)
	}
}

func SyncTaskIndex(response http.ResponseWriter, request *http.Request) {
}

func SyncTaskShow(response http.ResponseWriter, request *http.Request) {
}

func nowMinusOneHourInUnix() int {
	now := time.Now().UTC()
	nowMinusOneHour := now.Add(time.Duration(1) * time.Hour)
	return int(nowMinusOneHour.Unix())
}

func SyncTaskCreate(w http.ResponseWriter, r *http.Request) {
	//TODO. Check if there already is a task with either of the keys
	syncTask := sync.CreateSyncTask("", "", -1)
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &syncTask); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}

	//Creation set the last know timestamp to 1 hour ago
	syncTask.LastSeenTimestamp = nowMinusOneHourInUnix()

	db := sync.CreateSyncDbRepo(DbConnectionString)
	_, _, st, _ := db.StoreSyncTask(*syncTask)

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusCreated)
	if err := json.NewEncoder(w).Encode(st); err != nil {
		panic(err)
	}
}
<commit_msg>Removed Host limitation again<commit_after>package api

import (
	"encoding/json"
	"fmt"
	"github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/strava/go.strava"
	sync "github.com/svdberg/syncmysport-runkeeper/sync"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

const startTime = -1 * time.Duration(1) * time.Hour * 24 * 365 //1 year ago
const RkClientId = "73664cff18ed4800aab6cffc7ef8f4e1"

var (
	DbConnectionString string
	RkSecret           string
	StvSecret          string
	RedirectUriRk      string
	RedirectUriStv     string
	authenticator      *strava.OAuthAuthenticator
)

func Start(connString string, port int, secretRk string, redirectRk string, secretStv string, redirectStv string) {
	DbConnectionString = connString
	RkSecret = secretRk
	RedirectUriRk = redirectRk
	RedirectUriStv = redirectStv
	StvSecret = secretStv
	portString := fmt.Sprintf(":%d", port)

	strava.ClientId = 9667
	strava.ClientSecret = StvSecret

	//for strava
	authenticator = &strava.OAuthAuthenticator{
		CallbackURL:            RedirectUriStv,
		RequestClientGenerator: nil,
	}

	log.Printf("callback url: %s", authenticator.AuthorizationURL("state1", strava.Permissions.Public, true))
	router := NewRouter()
	router.Methods("GET").Path("/exchange_token").Name("STVOAuthCallback").Handler(authenticator.HandlerFunc(oAuthSuccess, oAuthFailure))
	router.PathPrefix("/").Handler(http.FileServer(http.Dir("./api/static/")))
	log.Fatal(http.ListenAndServe(portString, router))
}

func oAuthSuccess(auth *strava.AuthorizationResponse, w http.ResponseWriter, r *http.Request) {
	//fmt.Fprintf(w, "SUCCESS:\nAt this point you can use this information to create a new user or link the account to one of your existing users\n")
	//fmt.Fprintf(w, "State: %s\n\n", auth.State)
	//fmt.Fprintf(w, "Access Token: %s\n\n", auth.AccessToken)

	//fmt.Fprintf(w, "The Authenticated Athlete (you):\n")
	//content, _ := json.MarshalIndent(auth.Athlete, "", " ")
	//fmt.Fprint(w, string(content))

	db := sync.CreateSyncDbRepo(DbConnectionString)
	task, err := db.FindSyncTaskByToken(auth.AccessToken)
	if task == nil || err != nil {
		syncTask := sync.CreateSyncTask("", "", -1)
		syncTask.StravaToken = auth.AccessToken
		syncTask.LastSeenTimestamp = nowMinusOneHourInUnix()
		_, _, _, err := db.StoreSyncTask(*syncTask)
		if err != nil {
			cookie := &http.Cookie{Name: "strava", Value: fmt.Sprintf("%s", syncTask.StravaToken), Expires: time.Now().Add(356 * 24 * time.Hour), HttpOnly: false}
			cookie.Domain = "www.syncmysport.com"
			http.SetCookie(w, cookie)
		}

	} else {
		//update cookie
		cookie := &http.Cookie{Name: "strava", Value: fmt.Sprintf("%s", task.StravaToken), Expires: time.Now().Add(356 * 24 * time.Hour), HttpOnly: false}
		cookie.Domain = "www.syncmysport.com"
		http.SetCookie(w, cookie)

		if task.StravaToken != auth.AccessToken {
			task.StravaToken = auth.AccessToken
			db.UpdateSyncTask(*task)
		} else {
			log.Printf("Token %s is already stored for task id: %d", auth.AccessToken, task.Uid)
		}
	}
	//redirect back to connect
	http.Redirect(w, r, "http://www.syncmysport.com/connect.html", 303)
}

func oAuthFailure(err error, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Authorization Failure:\n")

	// some standard error checking
	if err == strava.OAuthAuthorizationDeniedErr {
		fmt.Fprint(w, "The user clicked the 'Do not Authorize' button on the previous page.\n")
		fmt.Fprint(w, "This is the main error your application should handle.")
	} else if err == strava.OAuthInvalidCredentialsErr {
		fmt.Fprint(w, "You provided an incorrect client_id or client_secret.\nDid you remember to set them at the begininng of this file?")
	} else if err == strava.OAuthInvalidCodeErr {
		fmt.Fprint(w, "The temporary token was not recognized, this shouldn't happen normally")
	} else if err == strava.OAuthServerErr {
		fmt.Fprint(w, "There was some sort of server error, try again to see if the problem continues")
	} else {
		fmt.Fprint(w, err)
	}
}
func OAuthCallback(response http.ResponseWriter, request *http.Request) {
	code := request.URL.Query().Get("code")
	go ObtainBearerToken(code)
	//redirect to sign up page with Acknowledgement of success..
	http.Redirect(response, request, "http://www.syncmysport.com/connect.html", 303)
}

func ObtainBearerToken(code string) {
	tokenUrl := "https://runkeeper.com/apps/token"
	formData := make(map[string][]string)
	formData["grant_type"] = []string{"authorization_code"}
	formData["code"] = []string{code}
	formData["client_id"] = []string{RkClientId}
	formData["client_secret"] = []string{RkSecret}
	formData["redirect_uri"] = []string{RedirectUriRk}
	client := new(http.Client)
	response, err := client.PostForm(tokenUrl, formData)
	responseJson := make(map[string]string)
	if err == nil {
		responseBody, _ := ioutil.ReadAll(response.Body)
		json.Unmarshal(responseBody, &responseJson)
		token := responseJson["access_token"]
		db := sync.CreateSyncDbRepo(DbConnectionString)
		task, err := db.FindSyncTaskByToken(token)
		if task == nil || err != nil {
			syncTask := sync.CreateSyncTask("", "", -1)
			syncTask.RunkeeperToken = token
			syncTask.LastSeenTimestamp = nowMinusOneHourInUnix()
			db.StoreSyncTask(*syncTask)
		} else {
			if task.RunkeeperToken != token {
				task.RunkeeperToken = token
				db.UpdateSyncTask(*task)
			} else {
				log.Printf("Token %s is already stored for task id: %d", token, task.Uid)
			}
		}
	} else {
		fmt.Print(err)
	}
}

func SyncTaskIndex(response http.ResponseWriter, request *http.Request) {
}

func SyncTaskShow(response http.ResponseWriter, request *http.Request) {
}

func nowMinusOneHourInUnix() int {
	now := time.Now().UTC()
	nowMinusOneHour := now.Add(time.Duration(1) * time.Hour)
	return int(nowMinusOneHour.Unix())
}

func SyncTaskCreate(w http.ResponseWriter, r *http.Request) {
	//TODO. Check if there already is a task with either of the keys
	syncTask := sync.CreateSyncTask("", "", -1)
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &syncTask); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}

	//Creation set the last know timestamp to 1 hour ago
	syncTask.LastSeenTimestamp = nowMinusOneHourInUnix()

	db := sync.CreateSyncDbRepo(DbConnectionString)
	_, _, st, _ := db.StoreSyncTask(*syncTask)

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusCreated)
	if err := json.NewEncoder(w).Encode(st); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package api

import (
	"context"

	log "github.com/sirupsen/logrus"

	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/txbuilder"
	"github.com/bytom/crypto/ed25519/chainkd"
)

type createKeyResp struct {
	Xpub     *pseudohsm.XPub `json:"xpub"`
	Mnemonic *string         `json:"mnemonic"`
}

func (a *API) pseudohsmCreateKey(ctx context.Context, in struct {
	Alias    string `json:"alias"`
	Password string `json:"password"`
	Mnemonic string `json:"nnemonic"`
	Language string    `json:"language"`
}) Response {
	if len(in.Mnemonic) > 0 {
		xpub, err := a.wallet.Hsm.ImportKeyFromMnemonic(in.Alias, in.Password, in.Mnemonic, in.Language)
		if err != nil {
			return NewErrorResponse(err)
		}
		return NewSuccessResponse(&createKeyResp{Xpub: xpub})
	}
	xpub, mnemonic, err := a.wallet.Hsm.XCreate(in.Alias, in.Password, in.Language)
	if err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(&createKeyResp{Xpub: xpub, Mnemonic: mnemonic})
}

type importKeyResp struct {
	Xpub *pseudohsm.XPub `json:"xpub"`
}

func (a *API) pseudohsmListKeys(ctx context.Context) Response {
	return NewSuccessResponse(a.wallet.Hsm.ListKeys())
}

func (a *API) pseudohsmDeleteKey(ctx context.Context, x struct {
	Password string       `json:"password"`
	XPub     chainkd.XPub `json:"xpub"`
}) Response {
	if err := a.wallet.Hsm.XDelete(x.XPub, x.Password); err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(nil)
}

type signResp struct {
	Tx           *txbuilder.Template `json:"transaction"`
	SignComplete bool                `json:"sign_complete"`
}

func (a *API) pseudohsmSignTemplates(ctx context.Context, x struct {
	Password string             `json:"password"`
	Txs      txbuilder.Template `json:"transaction"`
}) Response {
	if err := txbuilder.Sign(ctx, &x.Txs, x.Password, a.pseudohsmSignTemplate); err != nil {
		log.WithField("build err", err).Error("fail on sign transaction.")
		return NewErrorResponse(err)
	}
	log.Info("Sign Transaction complete.")
	return NewSuccessResponse(&signResp{Tx: &x.Txs, SignComplete: txbuilder.SignProgress(&x.Txs)})
}

func (a *API) pseudohsmSignTemplate(ctx context.Context, xpub chainkd.XPub, path [][]byte, data [32]byte, password string) ([]byte, error) {
	return a.wallet.Hsm.XSign(xpub, path, data[:], password)
}

// ResetPasswordResp is response for reset key password
type ResetPasswordResp struct {
	Changed bool `json:"changed"`
}

func (a *API) pseudohsmResetPassword(ctx context.Context, ins struct {
	XPub        chainkd.XPub `json:"xpub"`
	OldPassword string       `json:"old_password"`
	NewPassword string       `json:"new_password"`
}) Response {
	resp := &ResetPasswordResp{Changed: false}
	if err := a.wallet.Hsm.ResetPassword(ins.XPub, ins.OldPassword, ins.NewPassword); err != nil {
		return NewSuccessResponse(resp)
	}
	resp.Changed = true
	return NewSuccessResponse(resp)
}

// CheckPasswordResp is response for check key password
type CheckPasswordResp struct {
	CheckResult bool `json:"check_result"`
}

func (a *API) pseudohsmCheckPassword(ctx context.Context, ins struct {
	XPub     chainkd.XPub `json:"xpub"`
	Password string       `json:"password"`
}) Response {
	resp := &CheckPasswordResp{CheckResult: false}
	if _, err := a.wallet.Hsm.LoadChainKDKey(ins.XPub, ins.Password); err != nil {
		return NewSuccessResponse(resp)
	}
	resp.CheckResult = true
	return NewSuccessResponse(resp)
}
<commit_msg>Set the mnemonic default language<commit_after>package api

import (
	"context"

	log "github.com/sirupsen/logrus"

	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/txbuilder"
	"github.com/bytom/crypto/ed25519/chainkd"
)

type createKeyResp struct {
	Xpub     *pseudohsm.XPub `json:"xpub"`
	Mnemonic *string         `json:"mnemonic"`
}

func (a *API) pseudohsmCreateKey(ctx context.Context, in struct {
	Alias    string `json:"alias"`
	Password string `json:"password"`
	Mnemonic string `json:"nnemonic"`
	Language string `json:"language"`
}) Response {
	if in.Language == "" {
		in.Language = "en"
	}
	if len(in.Mnemonic) > 0 {
		xpub, err := a.wallet.Hsm.ImportKeyFromMnemonic(in.Alias, in.Password, in.Mnemonic, in.Language)
		if err != nil {
			return NewErrorResponse(err)
		}
		return NewSuccessResponse(&createKeyResp{Xpub: xpub})
	}
	xpub, mnemonic, err := a.wallet.Hsm.XCreate(in.Alias, in.Password, in.Language)
	if err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(&createKeyResp{Xpub: xpub, Mnemonic: mnemonic})
}

type importKeyResp struct {
	Xpub *pseudohsm.XPub `json:"xpub"`
}

func (a *API) pseudohsmListKeys(ctx context.Context) Response {
	return NewSuccessResponse(a.wallet.Hsm.ListKeys())
}

func (a *API) pseudohsmDeleteKey(ctx context.Context, x struct {
	Password string       `json:"password"`
	XPub     chainkd.XPub `json:"xpub"`
}) Response {
	if err := a.wallet.Hsm.XDelete(x.XPub, x.Password); err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(nil)
}

type signResp struct {
	Tx           *txbuilder.Template `json:"transaction"`
	SignComplete bool                `json:"sign_complete"`
}

func (a *API) pseudohsmSignTemplates(ctx context.Context, x struct {
	Password string             `json:"password"`
	Txs      txbuilder.Template `json:"transaction"`
}) Response {
	if err := txbuilder.Sign(ctx, &x.Txs, x.Password, a.pseudohsmSignTemplate); err != nil {
		log.WithField("build err", err).Error("fail on sign transaction.")
		return NewErrorResponse(err)
	}
	log.Info("Sign Transaction complete.")
	return NewSuccessResponse(&signResp{Tx: &x.Txs, SignComplete: txbuilder.SignProgress(&x.Txs)})
}

func (a *API) pseudohsmSignTemplate(ctx context.Context, xpub chainkd.XPub, path [][]byte, data [32]byte, password string) ([]byte, error) {
	return a.wallet.Hsm.XSign(xpub, path, data[:], password)
}

// ResetPasswordResp is response for reset key password
type ResetPasswordResp struct {
	Changed bool `json:"changed"`
}

func (a *API) pseudohsmResetPassword(ctx context.Context, ins struct {
	XPub        chainkd.XPub `json:"xpub"`
	OldPassword string       `json:"old_password"`
	NewPassword string       `json:"new_password"`
}) Response {
	resp := &ResetPasswordResp{Changed: false}
	if err := a.wallet.Hsm.ResetPassword(ins.XPub, ins.OldPassword, ins.NewPassword); err != nil {
		return NewSuccessResponse(resp)
	}
	resp.Changed = true
	return NewSuccessResponse(resp)
}

// CheckPasswordResp is response for check key password
type CheckPasswordResp struct {
	CheckResult bool `json:"check_result"`
}

func (a *API) pseudohsmCheckPassword(ctx context.Context, ins struct {
	XPub     chainkd.XPub `json:"xpub"`
	Password string       `json:"password"`
}) Response {
	resp := &CheckPasswordResp{CheckResult: false}
	if _, err := a.wallet.Hsm.LoadChainKDKey(ins.XPub, ins.Password); err != nil {
		return NewSuccessResponse(resp)
	}
	resp.CheckResult = true
	return NewSuccessResponse(resp)
}
<|endoftext|>


<commit_before>package app

import (
	"fmt"
	"time"

	"github.com/dcbishop/fileaccessor"
	"github.com/dcbishop/gim/cli"
	"github.com/dcbishop/gim/service"
	"github.com/dcbishop/gim/ui"
)

// App is the main program.
type App struct {
	fa            fileaccessor.FileAccessor
	buffers       []Buffer
	currentBuffer *Buffer
	quit          chan interface{}
	ui            ui.UI
	state         service.State
}

// Buffer contains the text to edit
type Buffer struct {
	filename string
	data     []byte
}

// New constructs a new app from the given options.
func New(fa fileaccessor.FileAccessor) App {
	app := App{
		fa: fa,
	}
	return app
}

// LoadOptions loads the given options.
func (app *App) LoadOptions(options cli.Options) {
	app.OpenFiles(options.FilesToOpen)
}

// OpenFiles opens a list of files into buffers and sets the current buffer to the first of the new buffers.
func (app *App) OpenFiles(filenames []string) {
	for i, filename := range filenames {
		buffer := app.openFile(filename)
		bufferPtr := app.AddBuffer(buffer)

		if i == 0 {
			app.currentBuffer = bufferPtr
		}
	}
}

// openFile reads a file, loads it into a new buffer and adds it to the list of buffers
func (app *App) openFile(filename string) Buffer {
	buffer := NewBuffer()

	buffer.filename = filename

	if data, err := app.fa.ReadFile(filename); err == nil {
		buffer.data = data
	} else {
		// [TODO]: Error handling. Non-existant files shouldn't cause a problem,
		// but ones that do exist but can't open should show an error.
		buffer.data = []byte{}
	}

	return buffer
}

// OpenFile opens a file and sets it to the current buffer.
func (app *App) OpenFile(filename string) {
	app.OpenFiles([]string{filename})
}

// AddBuffer adds a buffer to the list of buffers
func (app *App) AddBuffer(buffer Buffer) *Buffer {
	app.buffers = append(app.buffers, buffer)
	return app.LastBuffer()
}

// LastBuffer returns a pointer to the last buffer in the list of buffers
func (app *App) LastBuffer() *Buffer {
	return &app.buffers[len(app.buffers)-1]
}

// SetCurrentBuffer sets the currently visible buffer
func (app *App) SetCurrentBuffer(buffer *Buffer) {
}

// Run starts the main loop of the app. Will block until finished.
func (app *App) Run() {
	if app.state.SetRunning() != nil {
		panic("App already running.")
	}
	app.initialize()

	go app.ui.Run()
	defer app.ui.Stop()

	app.loopUntilQuit()
	app.state.SetStopped()
}

// Stop shuts everything down and terminates Run(). Blocks untill clean shutdown.
func (app *App) Stop() {
	if app.quit == nil {
		return
	}
	close(app.quit)

	if service.WaitUntilStopped(app.ui, time.Second) != nil {
		fmt.Println("UI service did not stop in under a second.")
	}
	if service.WaitUntilStopped(app, time.Second) != nil {
		fmt.Println("App service did not stop in under a second.")
	}
}

// Running returns true if Run() was called but Stop() hasn't been.
func (app *App) Running() bool {
	return app.state.Running()
}

func (app *App) initialize() {
	app.initializeQuitChannel()
	app.initializeUI()
}

func (app *App) initializeQuitChannel() {
	app.quit = make(chan interface{})
}

func (app *App) initializeUI() {
	if app.ui == nil {
		app.ui = &ui.TermboxUI{}
	}
}

func (app *App) loopUntilQuit() {
loop:
	for {
		select {
		case <-app.quit:
			break loop
		default:
			app.Update()
		}
	}
}

// Update processes input and redraws the app.
func (app *App) Update() {
}

// NewBuffer constructs a new Buffer object containing data.
func NewBuffer() Buffer {
	return Buffer{}
}

// RuneGrid contains the rendered text UI
type RuneGrid struct {
	width  uint
	height uint
	cells  [][]rune
}

// NewRuneGrid constructs a RuneGrid with the given width and height
func NewRuneGrid(width, height uint) RuneGrid {
	grid := RuneGrid{
		width:  width,
		height: height,
		cells:  make([][]rune, height),
	}

	for i := range grid.cells {
		grid.cells[i] = make([]rune, width)
	}

	return grid
}

// RenderBuffer blits the buffer onto the grid.
// wrap sets line wrapping on
// linebrake sets soft wrapping
func (grid *RuneGrid) RenderBuffer(
	x, y, x2, y2 uint,
	buffer *Buffer,
	wrap,
	linebrake,
	breakindent bool,
	showbreak string,
	// [TODO]: Should line numbering be done here?
	// Otherwise how do we communicate the line numbers out. - 2014-09-24 11:50pm
) {
	xPos := x
	yPos := y

	for _, r := range buffer.data {
		if r == '\n' {
			yPos++
			xPos = x
			continue
		}
		if xPos <= x2 && yPos <= y2 {
			grid.SetCell(xPos, yPos, rune(r))
		}
		xPos++
	}
}

// SetCell sets a cell in the RuneGrid to the given rune
func (grid *RuneGrid) SetCell(x, y uint, r rune) {
	if !grid.IsCellValid(x, y) {
		return
	}

	grid.cells[y][x] = r
}

// IsCellValid returns true if the cell coordinates are valid
func (grid *RuneGrid) IsCellValid(x, y uint) bool {
	if x >= grid.width || y >= grid.height {
		return false
	}
	return true
}
<commit_msg>Use/implement SetCurrentBuffer function.<commit_after>package app

import (
	"fmt"
	"time"

	"github.com/dcbishop/fileaccessor"
	"github.com/dcbishop/gim/cli"
	"github.com/dcbishop/gim/service"
	"github.com/dcbishop/gim/ui"
)

// App is the main program.
type App struct {
	fa            fileaccessor.FileAccessor
	buffers       []Buffer
	currentBuffer *Buffer
	quit          chan interface{}
	ui            ui.UI
	state         service.State
}

// Buffer contains the text to edit
type Buffer struct {
	filename string
	data     []byte
}

// New constructs a new app from the given options.
func New(fa fileaccessor.FileAccessor) App {
	app := App{
		fa: fa,
	}
	return app
}

// LoadOptions loads the given options.
func (app *App) LoadOptions(options cli.Options) {
	app.OpenFiles(options.FilesToOpen)
}

// OpenFiles opens a list of files into buffers and sets the current buffer to the first of the new buffers.
func (app *App) OpenFiles(filenames []string) {
	for i, filename := range filenames {
		buffer := app.openFile(filename)
		bufferPtr := app.AddBuffer(buffer)

		if i == 0 {
			app.SetCurrentBuffer(bufferPtr)
		}
	}
}

// openFile reads a file, loads it into a new buffer and adds it to the list of buffers
func (app *App) openFile(filename string) Buffer {
	buffer := NewBuffer()

	buffer.filename = filename

	if data, err := app.fa.ReadFile(filename); err == nil {
		buffer.data = data
	} else {
		// [TODO]: Error handling. Non-existant files shouldn't cause a problem,
		// but ones that do exist but can't open should show an error.
		buffer.data = []byte{}
	}

	return buffer
}

// OpenFile opens a file and sets it to the current buffer.
func (app *App) OpenFile(filename string) {
	app.OpenFiles([]string{filename})
}

// AddBuffer adds a buffer to the list of buffers
func (app *App) AddBuffer(buffer Buffer) *Buffer {
	app.buffers = append(app.buffers, buffer)
	return app.LastBuffer()
}

// LastBuffer returns a pointer to the last buffer in the list of buffers
func (app *App) LastBuffer() *Buffer {
	return &app.buffers[len(app.buffers)-1]
}

// SetCurrentBuffer sets the currently visible buffer
func (app *App) SetCurrentBuffer(buffer *Buffer) {
	app.currentBuffer = buffer
}

// Run starts the main loop of the app. Will block until finished.
func (app *App) Run() {
	if app.state.SetRunning() != nil {
		panic("App already running.")
	}
	app.initialize()

	go app.ui.Run()
	defer app.ui.Stop()

	app.loopUntilQuit()
	app.state.SetStopped()
}

// Stop shuts everything down and terminates Run(). Blocks untill clean shutdown.
func (app *App) Stop() {
	if app.quit == nil {
		return
	}
	close(app.quit)

	if service.WaitUntilStopped(app.ui, time.Second) != nil {
		fmt.Println("UI service did not stop in under a second.")
	}
	if service.WaitUntilStopped(app, time.Second) != nil {
		fmt.Println("App service did not stop in under a second.")
	}
}

// Running returns true if Run() was called but Stop() hasn't been.
func (app *App) Running() bool {
	return app.state.Running()
}

func (app *App) initialize() {
	app.initializeQuitChannel()
	app.initializeUI()
}

func (app *App) initializeQuitChannel() {
	app.quit = make(chan interface{})
}

func (app *App) initializeUI() {
	if app.ui == nil {
		app.ui = &ui.TermboxUI{}
	}
}

func (app *App) loopUntilQuit() {
loop:
	for {
		select {
		case <-app.quit:
			break loop
		default:
			app.Update()
		}
	}
}

// Update processes input and redraws the app.
func (app *App) Update() {
}

// NewBuffer constructs a new Buffer object containing data.
func NewBuffer() Buffer {
	return Buffer{}
}

// RuneGrid contains the rendered text UI
type RuneGrid struct {
	width  uint
	height uint
	cells  [][]rune
}

// NewRuneGrid constructs a RuneGrid with the given width and height
func NewRuneGrid(width, height uint) RuneGrid {
	grid := RuneGrid{
		width:  width,
		height: height,
		cells:  make([][]rune, height),
	}

	for i := range grid.cells {
		grid.cells[i] = make([]rune, width)
	}

	return grid
}

// RenderBuffer blits the buffer onto the grid.
// wrap sets line wrapping on
// linebrake sets soft wrapping
func (grid *RuneGrid) RenderBuffer(
	x, y, x2, y2 uint,
	buffer *Buffer,
	wrap,
	linebrake,
	breakindent bool,
	showbreak string,
	// [TODO]: Should line numbering be done here?
	// Otherwise how do we communicate the line numbers out. - 2014-09-24 11:50pm
) {
	xPos := x
	yPos := y

	for _, r := range buffer.data {
		if r == '\n' {
			yPos++
			xPos = x
			continue
		}
		if xPos <= x2 && yPos <= y2 {
			grid.SetCell(xPos, yPos, rune(r))
		}
		xPos++
	}
}

// SetCell sets a cell in the RuneGrid to the given rune
func (grid *RuneGrid) SetCell(x, y uint, r rune) {
	if !grid.IsCellValid(x, y) {
		return
	}

	grid.cells[y][x] = r
}

// IsCellValid returns true if the cell coordinates are valid
func (grid *RuneGrid) IsCellValid(x, y uint) bool {
	if x >= grid.width || y >= grid.height {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package extra

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

	"github.com/stretchr/testify/require"

	"github.com/algolia/algoliasearch-client-go/v3/algolia/errs"
	"github.com/algolia/algoliasearch-client-go/v3/algolia/opt"
	"github.com/algolia/algoliasearch-client-go/v3/algolia/search"
)

func TestIntermediateErrors(t *testing.T) {
	algoliaErr := errs.AlgoliaErr{
		Status:  500,
		Message: "There was an internal server error",
	}

	client := search.NewClientWithConfig(search.Configuration{
		Requester: &httpNetworkErrorRequester{
			responseErr: algoliaErr,
		},
	})

	_, err := client.ListIndices(opt.ExposeIntermediateNetworkErrors(true))
	require.Error(t, err)

	noMoreHostToTryErr, ok := err.(*errs.NoMoreHostToTryErr)
	require.True(t, ok)
	errors := noMoreHostToTryErr.IntermediateNetworkErrors()
	require.Len(t, errors, 4)

	for _, e := range errors {
		require.Equal(t, algoliaErr.Error(), e.Error())
	}
}

type httpNetworkErrorRequester struct {
	responseErr errs.AlgoliaErr
}

func (r *httpNetworkErrorRequester) Request(req *http.Request) (*http.Response, error) {
	data, _ := json.Marshal(r.responseErr)
	return &http.Response{
		Status:        strconv.Itoa(r.responseErr.Status),
		StatusCode:    r.responseErr.Status,
		Proto:         "HTTP/1.1",
		ProtoMajor:    1,
		ProtoMinor:    1,
		Body:          ioutil.NopCloser(bytes.NewBuffer(data)),
		ContentLength: int64(len(data)),
		Request:       req,
		Header:        make(http.Header, 0),
	}, nil
}
<commit_msg>test(WaitTask): test ExposeIntermediateNetworkErrors on WaitTask<commit_after>package extra

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

	"github.com/stretchr/testify/require"

	"github.com/algolia/algoliasearch-client-go/v3/algolia/errs"
	"github.com/algolia/algoliasearch-client-go/v3/algolia/opt"
	"github.com/algolia/algoliasearch-client-go/v3/algolia/search"
)

func TestIntermediateErrors(t *testing.T) {
	algoliaErr := errs.AlgoliaErr{
		Status:  500,
		Message: "There was an internal server error",
	}

	client := search.NewClientWithConfig(search.Configuration{
		Requester: &httpNetworkErrorRequester{
			responseErr: algoliaErr,
		},
	})

	_, err := client.ListIndices(opt.ExposeIntermediateNetworkErrors(true))
	require.Error(t, err)

	noMoreHostToTryErr, ok := err.(*errs.NoMoreHostToTryErr)
	require.True(t, ok)
	errors := noMoreHostToTryErr.IntermediateNetworkErrors()
	require.Len(t, errors, 4)

	for _, e := range errors {
		require.Equal(t, algoliaErr.Error(), e.Error())
	}
}

func TestIntermediateErrorsOnWaitTask(t *testing.T) {
	algoliaErr := errs.AlgoliaErr{
		Status:  500,
		Message: "There was an internal server error",
	}

	client := search.NewClientWithConfig(search.Configuration{
		Requester: &httpNetworkErrorRequester{
			responseErr: algoliaErr,
		},
	})

	err := client.InitIndex("test").WaitTask(0, opt.ExposeIntermediateNetworkErrors(true))
	require.Error(t, err)

	noMoreHostToTryErr, ok := err.(*errs.NoMoreHostToTryErr)
	require.True(t, ok)
	errors := noMoreHostToTryErr.IntermediateNetworkErrors()
	require.Len(t, errors, 4)

	for _, e := range errors {
		require.Equal(t, algoliaErr.Error(), e.Error())
	}
}

type httpNetworkErrorRequester struct {
	responseErr errs.AlgoliaErr
}

func (r *httpNetworkErrorRequester) Request(req *http.Request) (*http.Response, error) {
	data, _ := json.Marshal(r.responseErr)
	return &http.Response{
		Status:        strconv.Itoa(r.responseErr.Status),
		StatusCode:    r.responseErr.Status,
		Proto:         "HTTP/1.1",
		ProtoMajor:    1,
		ProtoMinor:    1,
		Body:          ioutil.NopCloser(bytes.NewBuffer(data)),
		ContentLength: int64(len(data)),
		Request:       req,
		Header:        make(http.Header, 0),
	}, nil
}
<|endoftext|>