<commit_before>package shell

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// NoClobber is the switch to forbide to overwrite the exist file.
var NoClobber = false

type _Redirecter struct {
	path     string
	isAppend bool
	no       int
	dupFrom  int
	force    bool
}

func newRedirecter(no int) *_Redirecter {
	return &_Redirecter{
		path:     "",
		isAppend: false,
		no:       no,
		dupFrom:  -1}
}

func (r *_Redirecter) FileNo() int {
	return r.no
}

func (r *_Redirecter) DupFrom(fileno int) {
	r.dupFrom = fileno
}

func (r *_Redirecter) SetPath(path string) {
	r.path = path
}

func (r *_Redirecter) SetAppend() {
	r.isAppend = true
}

var deviceName = map[string]struct{}{
	"AUX":    {},
	"CON":    {},
	"NUL":    {},
	"PRN":    {},
	"CLOCK$": {},
	"COM1":   {},
	"COM2":   {},
	"COM3":   {},
	"COM4":   {},
	"COM5":   {},
	"COM6":   {},
	"COM7":   {},
	"COM8":   {},
	"COM9":   {},
	"LPT1":   {},
	"LPT2":   {},
	"LPT3":   {},
	"LPT4":   {},
	"LPT5":   {},
	"LPT6":   {},
	"LPT7":   {},
	"LPT8":   {},
	"LPT9":   {},
}

func (r *_Redirecter) open() (*os.File, error) {
	if r.path == "" {
		return nil, errors.New("_Redirecter.open(): path=\"\"")
	}
	if r.no == 0 {
		return os.Open(r.path)
	} else if r.isAppend {
		return os.OpenFile(r.path, os.O_APPEND|os.O_CREATE, 0666)
	} else {
		if NoClobber && !r.force {
			_, err := os.Stat(r.path)
			if err == nil {
				name := strings.ToUpper(filepath.Base(r.path))
				if pos := strings.IndexRune(name, '.'); pos >= 0 {
					name = name[:pos]
				}
				if _, ok := deviceName[name]; !ok {
					return nil, fmt.Errorf("%s: cannot overwrite existing file", r.path)
				}
			}
		}
		return os.Create(r.path)
	}
}

func (r *_Redirecter) OpenOn(cmd *Cmd) (*os.File, error) {
	var fd *os.File
	var err error

	switch r.dupFrom {
	case 0:
		fd = cmd.Stdin
	case 1:
		fd = cmd.Stdout
	case 2:
		fd = cmd.Stderr
	default:
		fd, err = r.open()
		if err != nil {
			return nil, err
		}
	}
	switch r.FileNo() {
	case 0:
		cmd.Stdin = fd
	case 1:
		cmd.Stdout = fd
	case 2:
		cmd.Stderr = fd
	default:
		panic("Assertion failed: _Redirecter.OpenAs: r.no not in (0,1,2)")
	}
	return fd, nil
}
<commit_msg>on linux: regard 'nul' as /dev/null<commit_after>package shell

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// NoClobber is the switch to forbide to overwrite the exist file.
var NoClobber = false

type _Redirecter struct {
	path     string
	isAppend bool
	no       int
	dupFrom  int
	force    bool
}

func newRedirecter(no int) *_Redirecter {
	return &_Redirecter{
		path:     "",
		isAppend: false,
		no:       no,
		dupFrom:  -1}
}

func (r *_Redirecter) FileNo() int {
	return r.no
}

func (r *_Redirecter) DupFrom(fileno int) {
	r.dupFrom = fileno
}

func (r *_Redirecter) SetPath(path string) {
	r.path = path
}

func (r *_Redirecter) SetAppend() {
	r.isAppend = true
}

var deviceName = map[string]struct{}{
	"AUX":    {},
	"CON":    {},
	"NUL":    {},
	"PRN":    {},
	"CLOCK$": {},
	"COM1":   {},
	"COM2":   {},
	"COM3":   {},
	"COM4":   {},
	"COM5":   {},
	"COM6":   {},
	"COM7":   {},
	"COM8":   {},
	"COM9":   {},
	"LPT1":   {},
	"LPT2":   {},
	"LPT3":   {},
	"LPT4":   {},
	"LPT5":   {},
	"LPT6":   {},
	"LPT7":   {},
	"LPT8":   {},
	"LPT9":   {},
}

func (r *_Redirecter) open() (*os.File, error) {
	if r.path == "" {
		return nil, errors.New("_Redirecter.open(): path=\"\"")
	}
	if strings.EqualFold(r.path, "nul") {
		r.path = os.DevNull
	}
	if r.no == 0 {
		return os.Open(r.path)
	} else if r.isAppend {
		return os.OpenFile(r.path, os.O_APPEND|os.O_CREATE, 0666)
	} else {
		if NoClobber && !r.force {
			_, err := os.Stat(r.path)
			if err == nil {
				name := strings.ToUpper(filepath.Base(r.path))
				if pos := strings.IndexRune(name, '.'); pos >= 0 {
					name = name[:pos]
				}
				if _, ok := deviceName[name]; !ok {
					return nil, fmt.Errorf("%s: cannot overwrite existing file", r.path)
				}
			}
		}
		return os.Create(r.path)
	}
}

func (r *_Redirecter) OpenOn(cmd *Cmd) (*os.File, error) {
	var fd *os.File
	var err error

	switch r.dupFrom {
	case 0:
		fd = cmd.Stdin
	case 1:
		fd = cmd.Stdout
	case 2:
		fd = cmd.Stderr
	default:
		fd, err = r.open()
		if err != nil {
			return nil, err
		}
	}
	switch r.FileNo() {
	case 0:
		cmd.Stdin = fd
	case 1:
		cmd.Stdout = fd
	case 2:
		cmd.Stderr = fd
	default:
		panic("Assertion failed: _Redirecter.OpenAs: r.no not in (0,1,2)")
	}
	return fd, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"fmt"
	"net"
	"os"
	"runtime"
	"strings"
)

const (
	REQUEST  = "request"
	RESPONSE = "response"
)

func makeResponse(sipHeaders map[string]string, code string, reasonPhrase string, method string) []byte {
	var response bytes.Buffer
	response.WriteString("SIP/2.0 " + code + " " + reasonPhrase + "\r\n")
	response.WriteString("Via: " + sipHeaders["Via"] + "\r\n")
	response.WriteString("To: " + sipHeaders["To"] + "\r\n")
	response.WriteString("From: " + sipHeaders["From"] + "\r\n")
	response.WriteString("Call-ID: " + sipHeaders["Call-ID"] + "\r\n")
	response.WriteString("CSeq: " + sipHeaders["CSeq"] + "\r\n")
	response.WriteString("Content-Length: 0\r\n")
	if method != "BYE" && code != "100" {
		response.WriteString("Contact: sip:bob@localhost:5060\r\n")
	}
	response.WriteString("Max-Forwards: " + sipHeaders["Max-Forwards"] + "\r\n" + "\r\n")
	return response.Bytes()
}

func parseFirstLine(ruriOrStatusLine string) (string, string, error) {
	firstLine := strings.Fields(ruriOrStatusLine)
	if firstLine[2] == "SIP/2.0" {
		return REQUEST, firstLine[0], nil
	} else if firstLine[0] == "SIP/2.0" {
		return RESPONSE, firstLine[1], nil
	} else {
		return "", "", errors.New("Incoming datagram doesn't look like a SIP message: " + ruriOrStatusLine)
	}
}

//func parseHeaders(

func handleIncomingPacket(buf []byte, addr *net.UDPAddr, packetSize int, connection *net.UDPConn) {
	sipHeaders := make(map[string]string)
	payload := string(buf[0:packetSize])
	lines := strings.Split(payload, "\n")
	mType, mValue, err := parseFirstLine(lines[0])
	fmt.Println(mType, " ", mValue, " received")
	if err != nil {
		fmt.Println(err)
	}

	for _, value := range lines[1:] {
		header := strings.SplitN(value, ":", 2)
		// Ignoring body after headers are processed
		if len(header) != 2 {
			break
		}
		sipHeaders[strings.TrimSpace(header[0])] = strings.TrimSpace(header[1])
	}

	if mValue == "INVITE" {
		outboundTrying := makeResponse(sipHeaders, "100", "Trying", mValue)
		outboundOK := makeResponse(sipHeaders, "200", "", mValue)
		_, err := connection.WriteToUDP(outboundTrying, addr)
		if err != nil {
			fmt.Println("Error: ", err)
			os.Exit(0)
		}
		_, err = connection.WriteToUDP(outboundOK, addr)
		if err != nil {
			fmt.Println("Error: ", err)
			os.Exit(0)
		}
	} else if mValue == "BYE" {
		outboundOK := makeResponse(sipHeaders, "200", "OK", mValue)
		_, err := connection.WriteToUDP(outboundOK, addr)
		if err != nil {
			fmt.Println("Error: ", err)
			os.Exit(0)
		}
	} else {
	}
}

func listen(connection *net.UDPConn, quit chan struct{}) {
	buffer := make([]byte, 4096)
	n, remoteAddr, err := 0, new(net.UDPAddr), error(nil)
	for err == nil {
		n, remoteAddr, err = connection.ReadFromUDP(buffer)
		packet := buffer
		go handleIncomingPacket(packet, remoteAddr, n, connection)
	}
	fmt.Println("listener failed - ", err)
	quit <- struct{}{}
}

func main() {
	addr := net.UDPAddr{
		Port: 5060,
		IP:   net.IP{127, 0, 0, 1},
	}
	connection, err := net.ListenUDP("udp", &addr)
	if err != nil {
		panic(err)
	}
	quit := make(chan struct{})
	for i := 0; i < runtime.NumCPU(); i++ {
		fmt.Println(runtime.NumCPU(), " processor(s) started")
		go listen(connection, quit)
	}
	<-quit
}
<commit_msg>changed API for building response<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"net"
	"os"
	"runtime"
	"strings"
)

const (
	REQUEST  = "request"
	RESPONSE = "response"
)

// Prepare a response to incoming request
func prepareResponse(sipHeaders map[string]string, code string, reasonPhrase string) string {
	var response string
	response += "SIP/2.0 " + code + " " + reasonPhrase + "\r\n"
	response += "Via: " + sipHeaders["Via"] + "\r\n"
	response += "To: " + sipHeaders["To"] + "\r\n"
	response += "From: " + sipHeaders["From"] + "\r\n"
	response += "Call-ID: " + sipHeaders["Call-ID"] + "\r\n"
	response += "CSeq: " + sipHeaders["CSeq"] + "\r\n"
	response += "Max-Forwards: " + sipHeaders["Max-Forwards"] + "\r\n"
	return response
}

// Adding header to response, should be called after prepareResponse to add non-mandatory headers
func addHeader(responseHeaders string, newHeaderName string, newHeaderValue string) string {
	responseHeaders += newHeaderName + ": " + newHeaderValue + "\r\n"
	return responseHeaders
}

// Finalizing response and putting it on the wire
func sendResponse(responseHeaders string, addr *net.UDPAddr, connection *net.UDPConn) {
	var payload bytes.Buffer
	responseHeaders += "\r\n"
	payload.WriteString(responseHeaders)
	_, err := connection.WriteToUDP(payload.Bytes(), addr)
	if err != nil {
		fmt.Println("Error: ", err)
		os.Exit(0)
	}
}

// Parse first line to determine whether incoming message is a response or a request
func parseFirstLine(ruriOrStatusLine string) (string, string, error) {
	firstLine := strings.Fields(ruriOrStatusLine)
	if firstLine[2] == "SIP/2.0" {
		return REQUEST, firstLine[0], nil
	} else if firstLine[0] == "SIP/2.0" {
		return RESPONSE, firstLine[1], nil
	} else {
		return "", "", errors.New("Incoming datagram doesn't look like a SIP message: " + ruriOrStatusLine)
	}
}

// Parsing headers, so far SDP is not processed in any way
func parseHeaders(headers []string) map[string]string {
	sipHeaders := make(map[string]string)
	for _, value := range headers {
		header := strings.SplitN(value, ":", 2)
		if len(header) != 2 {
			// TODO: processing of SDP body
			break
		}
		sipHeaders[strings.TrimSpace(header[0])] = strings.TrimSpace(header[1])
	}
	return sipHeaders
}

func handleIncomingPacket(buf []byte, addr *net.UDPAddr, packetSize int, connection *net.UDPConn) {
	payload := string(buf[0:packetSize])
	lines := strings.Split(payload, "\n")
	_, mValue, err := parseFirstLine(lines[0])
	//fmt.Println(mType, " ", mValue, " received")
	if err != nil {
		fmt.Println(err)
	}

	sipHeaders := parseHeaders(lines[1:])
	if mValue == "INVITE" {
		outboundTrying := prepareResponse(sipHeaders, "100", "Trying")
		outboundOK := prepareResponse(sipHeaders, "200", "OK")
		outboundOK = addHeader(outboundOK, "Contact", "sip:bob@localhost:5060")
		sendResponse(outboundTrying, addr, connection)
		sendResponse(outboundOK, addr, connection)

	} else if mValue == "BYE" {
		outboundOK := prepareResponse(sipHeaders, "200", "OK")
		sendResponse(outboundOK, addr, connection)
	} else {
	}
}

func listen(connection *net.UDPConn, quit chan struct{}) {
	// 4 Kb seems sufficient for SIP packet
	buffer := make([]byte, 4096)
	n, remoteAddr, err := 0, new(net.UDPAddr), error(nil)
	for err == nil {
		n, remoteAddr, err = connection.ReadFromUDP(buffer)
		packet := buffer
		go handleIncomingPacket(packet, remoteAddr, n, connection)
	}
	fmt.Println("listener failed - ", err)
	quit <- struct{}{}
}

func main() {
	addr := net.UDPAddr{
		Port: 5060,
		IP:   net.IP{127, 0, 0, 1},
	}
	connection, err := net.ListenUDP("udp", &addr)
	if err != nil {
		panic(err)
	}
	quit := make(chan struct{})
	for i := 0; i < runtime.NumCPU(); i++ {
		fmt.Println(runtime.NumCPU(), " listener(s) started as determined by runtime.NumCPU()")
		go listen(connection, quit)
	}
	<-quit
}
<|endoftext|>


<commit_before>// TBD: should rename this module

package smartbus

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"github.com/contactless/wbgo"
	"io"
	"sync"
)

const (
	MIN_FRAME_SIZE = 11 // excluding sync
)

const (
	BROADCAST_SUBNET = 0xff
	BROADCAST_DEVICE = 0xff
)

type MessageHeader struct {
	OrigSubnetID   uint8
	OrigDeviceID   uint8
	OrigDeviceType uint16
	Opcode         uint16
	TargetSubnetID uint8
	TargetDeviceID uint8
}

type MutexLike interface {
	Lock()
	Unlock()
}

type SmartbusMessage struct {
	Header  MessageHeader
	Message interface{}
}

func WritePreBuiltFrame(writer io.Writer, frame []byte) {
	// writing the buffer in parts may cause missed frames
	bs := make([]byte, len(frame)+2)
	bs[0] = 0xaa
	bs[1] = 0xaa
	copy(bs[2:], frame)
	writer.Write(bs)
}

func WriteFrameRaw(writer io.Writer, header MessageHeader, writeMsg func(writer io.Writer)) {
	buf := bytes.NewBuffer(make([]byte, 0, 128))
	binary.Write(buf, binary.BigEndian, uint16(0xaaaa)) // signature
	binary.Write(buf, binary.BigEndian, uint8(0))       // len placeholder
	binary.Write(buf, binary.BigEndian, header)
	writeMsg(buf)
	bs := buf.Bytes()
	bs[2] = uint8(len(bs)) // minus 2 bytes of signature, but plus 2 bytes of crc
	binary.Write(buf, binary.BigEndian, crc16(bs[2:]))
	wbgo.Debug.Printf("sending frame:\n%s", hex.Dump(buf.Bytes()))
	// writing the buffer in parts may cause missed frames
	writer.Write(buf.Bytes())
}

func WriteFrame(writer io.Writer, fullMsg SmartbusMessage) {
	header := fullMsg.Header // make a copy because Opcode field is modified
	msg := fullMsg.Message.(Message)
	header.Opcode = msg.Opcode()

	WriteFrameRaw(writer, header, func(writer io.Writer) {
		var err error
		var preprocessed interface{}
		preprocess, hasPreprocess := msg.(PreprocessedMessage)
		if hasPreprocess {
			preprocessed, err = preprocess.ToRaw()
			if err == nil {
				err = WriteMessage(writer, preprocessed)
			}
		} else {
			err = WriteMessage(writer, msg)
		}
		if err != nil {
			panic(fmt.Sprintf("WriteMessage() failed: %v", err))
		}
	})
}

func ReadSync(reader io.Reader, mutex MutexLike) error {
	var b byte
	for {
		if err := binary.Read(reader, binary.BigEndian, &b); err != nil {
			return err
		}
		if b != 0xaa {
			wbgo.Debug.Printf("unsync byte 0: %02x", b)
			continue
		}

		mutex.Lock()
		if err := binary.Read(reader, binary.BigEndian, &b); err != nil {
			mutex.Unlock()
			return err
		}
		if b == 0xaa {
			break
		}

		wbgo.Debug.Printf("unsync byte 1: %02x", b)
		mutex.Unlock()
	}
	// the mutex is locked here
	return nil
}

func ParseFrame(frame []byte) (*SmartbusMessage, error) {
	wbgo.Debug.Printf("parsing frame:\n%s", hex.Dump(frame))
	buf := bytes.NewBuffer(frame[1 : len(frame)-2]) // skip len
	var header MessageHeader
	if err := binary.Read(buf, binary.BigEndian, &header); err != nil {
		return nil, err
	}
	msgParser, found := recognizedMessages[header.Opcode]
	if !found {
		return nil, fmt.Errorf("opcode %04x not recognized", header.Opcode)
	}

	if msg, err := msgParser(buf); err != nil {
		return nil, err
	} else {
		return &SmartbusMessage{header, msg}, nil
	}
}

func ReadSmartbusFrame(reader io.Reader) ([]byte, bool) {
	var l byte
	if err := binary.Read(reader, binary.BigEndian, &l); err != nil {
		wbgo.Error.Printf("error reading frame length: %v", err)
		return nil, false
	}
	if l < MIN_FRAME_SIZE {
		wbgo.Error.Printf("frame too short")
		return nil, true
	}
	var frame []byte = make([]byte, l)
	frame[0] = l
	if _, err := io.ReadFull(reader, frame[1:]); err != nil {
		wbgo.Error.Printf("error reading frame body (%d bytes): %v", l, err)
		return nil, false
	}

	crc := crc16(frame[:len(frame)-2])
	if crc != binary.BigEndian.Uint16(frame[len(frame)-2:]) {
		wbgo.Error.Printf("bad crc")
		return nil, true
	}

	return frame, true
}

func ReadSmartbusRaw(reader io.Reader, mutex MutexLike, frameHandler func(frame []byte)) {
	var err error
	defer func() {
		switch {
		case err == io.EOF || err == io.ErrUnexpectedEOF:
			wbgo.Error.Printf("eof reached")
			return
		case err != nil:
			wbgo.Error.Printf("NOTE: connection error: %s", err)
			return
		}
	}()
	for {
		if err = ReadSync(reader, mutex); err != nil {
			wbgo.Error.Printf("ReadSync error: %v", err)
			// the mutex is not locked if ReadSync failed
			break
		}

		// the mutex is locked here
		frame, cont := ReadSmartbusFrame(reader)
		mutex.Unlock()
		if frame != nil {
			frameHandler(frame)
		}
		if !cont {
			break
		}
	}
}

func ReadSmartbus(reader io.Reader, mutex MutexLike, ch chan *SmartbusMessage, rawReadCh chan []byte) {
	ReadSmartbusRaw(reader, mutex, func(frame []byte) {
		if rawReadCh != nil {
			rawReadCh <- frame
		}
		if msg, err := ParseFrame(frame); err != nil {
			wbgo.Error.Printf("failed to parse smartbus frame: %s", err)
		} else {
			ch <- msg
		}
	})
	close(ch)
}

func WriteSmartbus(writer io.Writer, mutex MutexLike, ch chan interface{}) {
	for msg := range ch {
		mutex.Lock()
		switch msg.(type) {
		case SmartbusMessage:
			WriteFrame(writer, msg.(SmartbusMessage))
		case []byte:
			WritePreBuiltFrame(writer, msg.([]byte))
		default:
			panic("unsupported message object type")
		}
		mutex.Unlock()
	}
}

type SmartbusIO interface {
	Start() chan *SmartbusMessage
	Send(msg SmartbusMessage)
	Stop()
}

type SmartbusStreamIO struct {
	stream    io.ReadWriteCloser
	readCh    chan *SmartbusMessage
	writeCh   chan interface{}
	rawReadCh chan []byte
	mutex     sync.Mutex
}

func NewStreamIO(stream io.ReadWriteCloser, rawReadCh chan []byte) *SmartbusStreamIO {
	return &SmartbusStreamIO{
		stream:    stream,
		readCh:    make(chan *SmartbusMessage),
		writeCh:   make(chan interface{}),
		rawReadCh: rawReadCh,
	}
}

func (streamIO *SmartbusStreamIO) Start() chan *SmartbusMessage {
	go ReadSmartbus(streamIO.stream, &streamIO.mutex, streamIO.readCh, streamIO.rawReadCh)
	go WriteSmartbus(streamIO.stream, &streamIO.mutex, streamIO.writeCh)
	return streamIO.readCh
}

func (streamIO *SmartbusStreamIO) Send(msg SmartbusMessage) {
	streamIO.writeCh <- msg
}

func (streamIO *SmartbusStreamIO) SendRaw(msg []byte) {
	streamIO.writeCh <- msg
}

func (streamIO *SmartbusStreamIO) Stop() {
	close(streamIO.writeCh) // this kills WriteSmartbus goroutine
	streamIO.stream.Close() // this kills ReadSmartbus goroutine by causing read error
}
<commit_msg>Don't show error messages in case of non-error EOF & related conditions.<commit_after>// TBD: should rename this module

package smartbus

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"github.com/contactless/wbgo"
	"io"
	"sync"
)

const (
	MIN_FRAME_SIZE = 11 // excluding sync
)

const (
	BROADCAST_SUBNET = 0xff
	BROADCAST_DEVICE = 0xff
)

type MessageHeader struct {
	OrigSubnetID   uint8
	OrigDeviceID   uint8
	OrigDeviceType uint16
	Opcode         uint16
	TargetSubnetID uint8
	TargetDeviceID uint8
}

type MutexLike interface {
	Lock()
	Unlock()
}

type SmartbusMessage struct {
	Header  MessageHeader
	Message interface{}
}

func WritePreBuiltFrame(writer io.Writer, frame []byte) {
	// writing the buffer in parts may cause missed frames
	bs := make([]byte, len(frame)+2)
	bs[0] = 0xaa
	bs[1] = 0xaa
	copy(bs[2:], frame)
	writer.Write(bs)
}

func WriteFrameRaw(writer io.Writer, header MessageHeader, writeMsg func(writer io.Writer)) {
	buf := bytes.NewBuffer(make([]byte, 0, 128))
	binary.Write(buf, binary.BigEndian, uint16(0xaaaa)) // signature
	binary.Write(buf, binary.BigEndian, uint8(0))       // len placeholder
	binary.Write(buf, binary.BigEndian, header)
	writeMsg(buf)
	bs := buf.Bytes()
	bs[2] = uint8(len(bs)) // minus 2 bytes of signature, but plus 2 bytes of crc
	binary.Write(buf, binary.BigEndian, crc16(bs[2:]))
	wbgo.Debug.Printf("sending frame:\n%s", hex.Dump(buf.Bytes()))
	// writing the buffer in parts may cause missed frames
	writer.Write(buf.Bytes())
}

func WriteFrame(writer io.Writer, fullMsg SmartbusMessage) {
	header := fullMsg.Header // make a copy because Opcode field is modified
	msg := fullMsg.Message.(Message)
	header.Opcode = msg.Opcode()

	WriteFrameRaw(writer, header, func(writer io.Writer) {
		var err error
		var preprocessed interface{}
		preprocess, hasPreprocess := msg.(PreprocessedMessage)
		if hasPreprocess {
			preprocessed, err = preprocess.ToRaw()
			if err == nil {
				err = WriteMessage(writer, preprocessed)
			}
		} else {
			err = WriteMessage(writer, msg)
		}
		if err != nil {
			panic(fmt.Sprintf("WriteMessage() failed: %v", err))
		}
	})
}

func ReadSync(reader io.Reader, mutex MutexLike) error {
	var b byte
	for {
		if err := binary.Read(reader, binary.BigEndian, &b); err != nil {
			return err
		}
		if b != 0xaa {
			wbgo.Debug.Printf("unsync byte 0: %02x", b)
			continue
		}

		mutex.Lock()
		if err := binary.Read(reader, binary.BigEndian, &b); err != nil {
			mutex.Unlock()
			return err
		}
		if b == 0xaa {
			break
		}

		wbgo.Debug.Printf("unsync byte 1: %02x", b)
		mutex.Unlock()
	}
	// the mutex is locked here
	return nil
}

func ParseFrame(frame []byte) (*SmartbusMessage, error) {
	wbgo.Debug.Printf("parsing frame:\n%s", hex.Dump(frame))
	buf := bytes.NewBuffer(frame[1 : len(frame)-2]) // skip len
	var header MessageHeader
	if err := binary.Read(buf, binary.BigEndian, &header); err != nil {
		return nil, err
	}
	msgParser, found := recognizedMessages[header.Opcode]
	if !found {
		return nil, fmt.Errorf("opcode %04x not recognized", header.Opcode)
	}

	if msg, err := msgParser(buf); err != nil {
		return nil, err
	} else {
		return &SmartbusMessage{header, msg}, nil
	}
}

func ReadSmartbusFrame(reader io.Reader) ([]byte, bool) {
	var l byte
	if err := binary.Read(reader, binary.BigEndian, &l); err != nil {
		wbgo.Error.Printf("error reading frame length: %v", err)
		return nil, false
	}
	if l < MIN_FRAME_SIZE {
		wbgo.Error.Printf("frame too short")
		return nil, true
	}
	var frame []byte = make([]byte, l)
	frame[0] = l
	if _, err := io.ReadFull(reader, frame[1:]); err != nil {
		wbgo.Error.Printf("error reading frame body (%d bytes): %v", l, err)
		return nil, false
	}

	crc := crc16(frame[:len(frame)-2])
	if crc != binary.BigEndian.Uint16(frame[len(frame)-2:]) {
		wbgo.Error.Printf("bad crc")
		return nil, true
	}

	return frame, true
}

func ReadSmartbusRaw(reader io.Reader, mutex MutexLike, frameHandler func(frame []byte)) {
	var err error
	defer func() {
		switch {
		case err == io.EOF || err == io.ErrUnexpectedEOF:
			wbgo.Debug.Printf("eof reached")
			return
		case err == io.ErrClosedPipe:
			wbgo.Debug.Printf("pipe closed")
			return
		case err != nil:
			wbgo.Error.Printf("NOTE: connection error: %s", err)
			return
		}
	}()
	for {
		if err = ReadSync(reader, mutex); err != nil {
			wbgo.Debug.Printf("ReadSync error: %v", err)
			// the mutex is not locked if ReadSync failed
			break
		}

		// the mutex is locked here
		frame, cont := ReadSmartbusFrame(reader)
		mutex.Unlock()
		if frame != nil {
			frameHandler(frame)
		}
		if !cont {
			break
		}
	}
}

func ReadSmartbus(reader io.Reader, mutex MutexLike, ch chan *SmartbusMessage, rawReadCh chan []byte) {
	ReadSmartbusRaw(reader, mutex, func(frame []byte) {
		if rawReadCh != nil {
			rawReadCh <- frame
		}
		if msg, err := ParseFrame(frame); err != nil {
			wbgo.Error.Printf("failed to parse smartbus frame: %s", err)
		} else {
			ch <- msg
		}
	})
	close(ch)
}

func WriteSmartbus(writer io.Writer, mutex MutexLike, ch chan interface{}) {
	for msg := range ch {
		mutex.Lock()
		switch msg.(type) {
		case SmartbusMessage:
			WriteFrame(writer, msg.(SmartbusMessage))
		case []byte:
			WritePreBuiltFrame(writer, msg.([]byte))
		default:
			panic("unsupported message object type")
		}
		mutex.Unlock()
	}
}

type SmartbusIO interface {
	Start() chan *SmartbusMessage
	Send(msg SmartbusMessage)
	Stop()
}

type SmartbusStreamIO struct {
	stream    io.ReadWriteCloser
	readCh    chan *SmartbusMessage
	writeCh   chan interface{}
	rawReadCh chan []byte
	mutex     sync.Mutex
}

func NewStreamIO(stream io.ReadWriteCloser, rawReadCh chan []byte) *SmartbusStreamIO {
	return &SmartbusStreamIO{
		stream:    stream,
		readCh:    make(chan *SmartbusMessage),
		writeCh:   make(chan interface{}),
		rawReadCh: rawReadCh,
	}
}

func (streamIO *SmartbusStreamIO) Start() chan *SmartbusMessage {
	go ReadSmartbus(streamIO.stream, &streamIO.mutex, streamIO.readCh, streamIO.rawReadCh)
	go WriteSmartbus(streamIO.stream, &streamIO.mutex, streamIO.writeCh)
	return streamIO.readCh
}

func (streamIO *SmartbusStreamIO) Send(msg SmartbusMessage) {
	streamIO.writeCh <- msg
}

func (streamIO *SmartbusStreamIO) SendRaw(msg []byte) {
	streamIO.writeCh <- msg
}

func (streamIO *SmartbusStreamIO) Stop() {
	close(streamIO.writeCh) // this kills WriteSmartbus goroutine
	streamIO.stream.Close() // this kills ReadSmartbus goroutine by causing read error
}
<|endoftext|>


<commit_before>package smtp

import (
	"testing"

	"github.com/xuqingfeng/mailman/util"
)

var (
	testSMTPServer = SMTPServer{
		"@example.com",
		"smtp.example.com",
		"25",
	}
)

func TestGetSMTPServer(t *testing.T) {

	fakeEmailAddress := "test@example.com"
	_, err := GetSMTPServer(fakeEmailAddress)
	if util.SMTPServerNotFoundErr != err {
		t.Error("@example.com SMTP Server exist")
	}
	SaveSMTPServer(testSMTPServer)
	_, err = GetSMTPServer(fakeEmailAddress)
	if err != nil {
		t.Errorf("GetSMTPServer() fail %v", err)
	}
	DeleteSMTPServer(testSMTPServer.Address)
}

func TestSaveSMTPServer(t *testing.T) {

	err := SaveSMTPServer(testSMTPServer)
	if err != nil {
		t.Errorf("SaveSMTPServer() fail %v", err)
	}
}

func TestGetCustomSMTPServer(t *testing.T) {

	customSMTPServerList, err := GetCustomSMTPServer()
	if err != nil {
		t.Errorf("GetCustomSMTPServer() fail %v", err)
	}
	if len(customSMTPServerList) < 1 {
		t.Error("GetCustomSMTPServer() fail")
	}
}

func TestDeleteSMTPServer(t *testing.T) {

	err := DeleteSMTPServer(testSMTPServer.Address)
	if err != nil {
		t.Errorf("DeleteSMTPServer() fail %v", err)
	}
}
<commit_msg>Change test domain to avoid go concurrent test (#7)<commit_after>package smtp

import (
	"testing"

	"github.com/xuqingfeng/mailman/util"
)

var (
	testSMTPServer = SMTPServer{
		"@example.com",
		"smtp.example.com",
		"25",
	}
)

func TestGetSMTPServer(t *testing.T) {

	fakeEmailAddress0 := "test@example.net"
	_, err := GetSMTPServer(fakeEmailAddress0)
	if util.SMTPServerNotFoundErr != err {
		t.Error("@example.net SMTP Server exists")
	}

	fakeEmailAddress1 := "test@example.com"
	SaveSMTPServer(testSMTPServer)
	_, err = GetSMTPServer(fakeEmailAddress1)
	if err != nil {
		t.Errorf("GetSMTPServer() fail %v", err)
	}
	DeleteSMTPServer(testSMTPServer.Address)
}

func TestSaveSMTPServer(t *testing.T) {

	err := SaveSMTPServer(testSMTPServer)
	if err != nil {
		t.Errorf("SaveSMTPServer() fail %v", err)
	}
}

func TestGetCustomSMTPServer(t *testing.T) {

	customSMTPServerList, err := GetCustomSMTPServer()
	if err != nil {
		t.Errorf("GetCustomSMTPServer() fail %v", err)
	}
	if len(customSMTPServerList) < 1 {
		t.Error("GetCustomSMTPServer() fail")
	}
}

func TestDeleteSMTPServer(t *testing.T) {

	err := DeleteSMTPServer(testSMTPServer.Address)
	if err != nil {
		t.Errorf("DeleteSMTPServer() fail %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"time"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/mitchellh/cli"
"errors"
)

type CreateCommand struct {
	Ui 		cli.Ui
	AwsRegion 	string
	InstanceId 	string
	Name 		string
	DryRun		bool
	NoReboot	bool
}

// descriptions for args
var createDscrAwsRegion = "The AWS region to use (e.g. us-west-2)"
var createDscrInstanceId = "The instance from which to create the AMI"
var createDscrName = "The name of the AMI; the current timestamp will be automatically appended"
var createDscrDryRun = "Execute a simulated run"
var createDscrNoReboot = "If true, do not reboot the instance before creating the AMI. It is preferable to reboot the instance to guarantee a consistent filesystem when taking the snapshot, but the likelihood of an inconsistent snapshot is very low."

func (c *CreateCommand) Help() string {
	return `ec2-snapper create <args> [--help]

Create an AMI of the given EC2 instance.

Available args are:
--region      ` + createDscrAwsRegion + `
--instance      ` + createDscrInstanceId + `
--name          ` + createDscrName + `
--dry-run       ` + createDscrDryRun + `
--no-reboot     ` + createDscrNoReboot
}

func (c *CreateCommand) Synopsis() string {
	return "Create an AMI of the given EC2 instance"
}

func (c *CreateCommand) Run(args []string) int {

	// Handle the command-line args
	cmdFlags := flag.NewFlagSet("create", flag.ExitOnError)
	cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }

	cmdFlags.StringVar(&c.AwsRegion, "region", "", createDscrAwsRegion)
	cmdFlags.StringVar(&c.InstanceId, "instance", "", createDscrInstanceId)
	cmdFlags.StringVar(&c.Name, "name", "", createDscrName)
	cmdFlags.BoolVar(&c.DryRun, "dry-run", false, createDscrDryRun)
	cmdFlags.BoolVar(&c.NoReboot, "no-reboot", true, createDscrNoReboot)

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if _, err := create(*c); err != nil {
		c.Ui.Error(err.Error())
		return 1
	}

	return 0
}

func create(c CreateCommand) (string, error) {
	snapshotId := ""

	// Check for required command-line args
	if c.AwsRegion == "" {
		return snapshotId, errors.New("ERROR: The argument '--region' is required.")
	}

	if c.InstanceId == "" {
		return snapshotId, errors.New("ERROR: The argument '--instance' is required.")
	}

	if c.Name == "" {
		return snapshotId, errors.New("ERROR: The argument '--name' is required.")
	}

	// Create an EC2 service object; AWS region is picked up from the "AWS_REGION" env var.
	session := session.New(&aws.Config{Region: &c.AwsRegion})
	svc := ec2.New(session)

	// Generate a nicely formatted timestamp for right now
	const dateLayoutForAmiName = "2006-01-02 at 15_04_05 (MST)"
	t := time.Now()

	// Create the AMI Snapshot
	name := c.Name + " - " + t.Format(dateLayoutForAmiName)

	c.Ui.Output("==> Creating AMI for " + c.InstanceId + "...")

	resp, err := svc.CreateImage(&ec2.CreateImageInput{
		Name: &name,
		InstanceId: &c.InstanceId,
		DryRun: &c.DryRun,
		NoReboot: &c.NoReboot })
	if err != nil && strings.Contains(err.Error(), "NoCredentialProviders") {
		return snapshotId, errors.New("ERROR: No AWS credentials were found.  Either set the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or run this program on an EC2 instance that has an IAM Role with the appropriate permissions.")
	} else if err != nil {
		return snapshotId, err
	}

	// Sleep here to give time for AMI to get found
	time.Sleep(3000 * time.Millisecond)

	// Assign tags to this AMI.  We'll use these when it comes time to delete the AMI
	snapshotId = *resp.ImageId
	c.Ui.Output("==> Adding tags to AMI " + snapshotId + "...")

	_, tagsErr := svc.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{&snapshotId},
		Tags: []*ec2.Tag{
			&ec2.Tag{ Key: aws.String("ec2-snapper-instance-id"), Value: &c.InstanceId },
			&ec2.Tag{ Key: aws.String("Name"), Value: &c.Name },
		},
	})

	if tagsErr != nil {
		return snapshotId, tagsErr
	}

	// Check the status of the AMI
	respDscrImages, err := svc.DescribeImages(&ec2.DescribeImagesInput{
		Filters: []*ec2.Filter{
			&ec2.Filter{
				Name: aws.String("image-id"),
				Values: []*string{&snapshotId},
			},
		},
	})
	if err != nil {
		return snapshotId, err
	}

	// If no AMI at all was found, throw an error
	if len(respDscrImages.Images) == 0 {
		return snapshotId, errors.New("ERROR: Could not find the AMI just created.")
	}

	// If the AMI's status is failed throw an error
	if *respDscrImages.Images[0].State == "failed" {
		return snapshotId, errors.New("ERROR: AMI was created but entered a state of 'failed'. This is an AWS issue. Please re-run this command.  Note that you will need to manually de-register the AMI in the AWS console or via the API.")
	}

	// Announce success
	c.Ui.Info("==> Success! Created " + snapshotId + " named \"" + name + "\"")
	return snapshotId, nil
}
<commit_msg>Fix indentation<commit_after>package main

import (
	"flag"
	"time"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/mitchellh/cli"
	"errors"
)

type CreateCommand struct {
	Ui 		cli.Ui
	AwsRegion 	string
	InstanceId 	string
	Name 		string
	DryRun		bool
	NoReboot	bool
}

// descriptions for args
var createDscrAwsRegion = "The AWS region to use (e.g. us-west-2)"
var createDscrInstanceId = "The instance from which to create the AMI"
var createDscrName = "The name of the AMI; the current timestamp will be automatically appended"
var createDscrDryRun = "Execute a simulated run"
var createDscrNoReboot = "If true, do not reboot the instance before creating the AMI. It is preferable to reboot the instance to guarantee a consistent filesystem when taking the snapshot, but the likelihood of an inconsistent snapshot is very low."

func (c *CreateCommand) Help() string {
	return `ec2-snapper create <args> [--help]

Create an AMI of the given EC2 instance.

Available args are:
--region      ` + createDscrAwsRegion + `
--instance      ` + createDscrInstanceId + `
--name          ` + createDscrName + `
--dry-run       ` + createDscrDryRun + `
--no-reboot     ` + createDscrNoReboot
}

func (c *CreateCommand) Synopsis() string {
	return "Create an AMI of the given EC2 instance"
}

func (c *CreateCommand) Run(args []string) int {

	// Handle the command-line args
	cmdFlags := flag.NewFlagSet("create", flag.ExitOnError)
	cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }

	cmdFlags.StringVar(&c.AwsRegion, "region", "", createDscrAwsRegion)
	cmdFlags.StringVar(&c.InstanceId, "instance", "", createDscrInstanceId)
	cmdFlags.StringVar(&c.Name, "name", "", createDscrName)
	cmdFlags.BoolVar(&c.DryRun, "dry-run", false, createDscrDryRun)
	cmdFlags.BoolVar(&c.NoReboot, "no-reboot", true, createDscrNoReboot)

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if _, err := create(*c); err != nil {
		c.Ui.Error(err.Error())
		return 1
	}

	return 0
}

func create(c CreateCommand) (string, error) {
	snapshotId := ""

	// Check for required command-line args
	if c.AwsRegion == "" {
		return snapshotId, errors.New("ERROR: The argument '--region' is required.")
	}

	if c.InstanceId == "" {
		return snapshotId, errors.New("ERROR: The argument '--instance' is required.")
	}

	if c.Name == "" {
		return snapshotId, errors.New("ERROR: The argument '--name' is required.")
	}

	// Create an EC2 service object; AWS region is picked up from the "AWS_REGION" env var.
	session := session.New(&aws.Config{Region: &c.AwsRegion})
	svc := ec2.New(session)

	// Generate a nicely formatted timestamp for right now
	const dateLayoutForAmiName = "2006-01-02 at 15_04_05 (MST)"
	t := time.Now()

	// Create the AMI Snapshot
	name := c.Name + " - " + t.Format(dateLayoutForAmiName)

	c.Ui.Output("==> Creating AMI for " + c.InstanceId + "...")

	resp, err := svc.CreateImage(&ec2.CreateImageInput{
		Name: &name,
		InstanceId: &c.InstanceId,
		DryRun: &c.DryRun,
		NoReboot: &c.NoReboot })
	if err != nil && strings.Contains(err.Error(), "NoCredentialProviders") {
		return snapshotId, errors.New("ERROR: No AWS credentials were found.  Either set the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or run this program on an EC2 instance that has an IAM Role with the appropriate permissions.")
	} else if err != nil {
		return snapshotId, err
	}

	// Sleep here to give time for AMI to get found
	time.Sleep(3000 * time.Millisecond)

	// Assign tags to this AMI.  We'll use these when it comes time to delete the AMI
	snapshotId = *resp.ImageId
	c.Ui.Output("==> Adding tags to AMI " + snapshotId + "...")

	_, tagsErr := svc.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{&snapshotId},
		Tags: []*ec2.Tag{
			&ec2.Tag{ Key: aws.String("ec2-snapper-instance-id"), Value: &c.InstanceId },
			&ec2.Tag{ Key: aws.String("Name"), Value: &c.Name },
		},
	})

	if tagsErr != nil {
		return snapshotId, tagsErr
	}

	// Check the status of the AMI
	respDscrImages, err := svc.DescribeImages(&ec2.DescribeImagesInput{
		Filters: []*ec2.Filter{
			&ec2.Filter{
				Name: aws.String("image-id"),
				Values: []*string{&snapshotId},
			},
		},
	})
	if err != nil {
		return snapshotId, err
	}

	// If no AMI at all was found, throw an error
	if len(respDscrImages.Images) == 0 {
		return snapshotId, errors.New("ERROR: Could not find the AMI just created.")
	}

	// If the AMI's status is failed throw an error
	if *respDscrImages.Images[0].State == "failed" {
		return snapshotId, errors.New("ERROR: AMI was created but entered a state of 'failed'. This is an AWS issue. Please re-run this command.  Note that you will need to manually de-register the AMI in the AWS console or via the API.")
	}

	// Announce success
	c.Ui.Info("==> Success! Created " + snapshotId + " named \"" + name + "\"")
	return snapshotId, nil
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2017, AverageSecurityGuy
# All rights reserved.

Complete challenge 6 from Cryptopals set 1.
http://cryptopals.com/sets/1

Usage:

$ go run cryptopals-1-6.go
*/

package main

import (
    "os"
    "fmt"
    "bufio"
    "crypto/aes"
    "encoding/base64"
)

func check(e error) {
	if e != nil {
		fmt.Printf("Error: %s\n", e.Error())
		os.Exit(0)
	}
}

func get_data(filename string) []byte {
    file, err := os.Open(filename)
    check(err)

    var temp []byte
    scan := bufio.NewScanner(file)
	for scan.Scan() {
        temp = append(temp, []byte(scan.Text())...)
    }

    data := make([]byte, base64.StdEncoding.DecodedLen(len(temp)))
    _, err = base64.StdEncoding.Decode(data, temp)
    check(err)

    return data
}

func chunk(data []byte, size int) [][]byte {
    var chunks [][]byte

    for i:=0; i<len(data); i=i+size {
        chunks = append(chunks, data[i:i+size])
    }

    return chunks
}

func pad(data []byte, size int) []byte {
    if len(data) < size {
        pad := size - len(data)
        for i:=0; i<pad; i++ {
            data = append(data, byte(pad))
        }
    }

    return data
}

func main() {
    fmt.Println("Cryptopals Set 1")
    fmt.Println("================")

    fmt.Println("Challenge 7")
    fmt.Println("-----------")

    block_size := 16
    ecb, err := aes.NewCipher([]byte("YELLOW SUBMARINE"))
    check(err)

    ciphertext := get_data("data/7.txt")
    plaintext := make([]byte, 0)
    chunks := chunk(ciphertext, block_size)

    for _, chunk := range chunks {
        chunk = pad(chunk, block_size)
        temp := make([]byte, block_size)

        ecb.Decrypt(temp, chunk)

        plaintext = append(plaintext, temp...)
    }

    fmt.Println(string(plaintext))
}
<commit_msg>Day 29<commit_after>/*
Copyright (c) 2017, AverageSecurityGuy
# All rights reserved.

Complete challenge 7 from Cryptopals set 1.
http://cryptopals.com/sets/1

Usage:

$ go run cryptopals-1-7.go
*/

package main

import (
    "os"
    "fmt"
    "bufio"
    "crypto/aes"
    "encoding/base64"
)

func check(e error) {
	if e != nil {
		fmt.Printf("Error: %s\n", e.Error())
		os.Exit(0)
	}
}

func get_data(filename string) []byte {
    file, err := os.Open(filename)
    check(err)

    var temp []byte
    scan := bufio.NewScanner(file)
	for scan.Scan() {
        temp = append(temp, []byte(scan.Text())...)
    }

    data := make([]byte, base64.StdEncoding.DecodedLen(len(temp)))
    _, err = base64.StdEncoding.Decode(data, temp)
    check(err)

    return data
}

func chunk(data []byte, size int) [][]byte {
    var chunks [][]byte

    for i:=0; i<len(data); i=i+size {
        chunks = append(chunks, data[i:i+size])
    }

    return chunks
}

func pad(data []byte, size int) []byte {
    if len(data) < size {
        pad := size - len(data)
        for i:=0; i<pad; i++ {
            data = append(data, byte(pad))
        }
    }

    return data
}

func main() {
    fmt.Println("Cryptopals Set 1")
    fmt.Println("================")

    fmt.Println("Challenge 7")
    fmt.Println("-----------")

    block_size := 16
    ecb, err := aes.NewCipher([]byte("YELLOW SUBMARINE"))
    check(err)

    ciphertext := get_data("data/7.txt")
    plaintext := make([]byte, 0)
    chunks := chunk(ciphertext, block_size)

    for _, chunk := range chunks {
        chunk = pad(chunk, block_size)
        temp := make([]byte, block_size)

        ecb.Decrypt(temp, chunk)

        plaintext = append(plaintext, temp...)
    }

    fmt.Println(string(plaintext))
}
<|endoftext|>


<commit_before>package csv

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/frictionlessdata/tableschema-go/schema"
)

type csvRow struct {
	Name string
}

func ExampleTable_Iter() {
	tab, _ := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
	tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
	iter, _ := tab.Iter()
	for iter.Next() {
		var data csvRow
		iter.CastRow(&data)
		fmt.Println(data.Name)
	}
	// Output:foo
	// bar
}

func ExampleTable_Infer() {
	tab, _ := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
	iter, _ := tab.Iter()
	for iter.Next() {
		var data csvRow
		iter.CastRow(&data)
		fmt.Println(data.Name)
	}
	// Output:foo
	// bar
}

func TestLoadHeaders(t *testing.T) {
	t.Run("EmptyString", func(t *testing.T) {
		tab, err := New(StringSource(""), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if len(tab.Headers) != 0 {
			t.Fatalf("len(headers) want:0 got:%v", len(tab.Headers))
		}
	})
	t.Run("SimpleCase", func(t *testing.T) {
		in := `"name"
"bar"`
		tab, err := New(StringSource(in), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		want := []string{"name"}
		if !reflect.DeepEqual(want, tab.Headers) {
			t.Fatalf("headers want:%v got:%v", want, tab.Headers)
		}
		tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
		var out []csvRow
		if err := tab.CastAll(&out); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if len(out) != 1 {
			t.Fatalf("LoadHeaders content must skip first row")
		}
	})
}

func TestNew(t *testing.T) {
	t.Run("ErrorOpts", func(t *testing.T) {
		tab, err := New(StringSource(""), errorOpts())
		if tab != nil {
			t.Fatalf("tab want:nil got:%v", tab)
		}
		if err == nil {
			t.Fatalf("err want:error got:nil")
		}
	})
	t.Run("ErrorSource", func(t *testing.T) {
		_, err := New(errorSource(), LoadHeaders())
		if err == nil {
			t.Fatalf("want:err got:nil")
		}
	})
}

func TestSetHeaders(t *testing.T) {
	in := "Foo"
	tab, err := New(StringSource(in), SetHeaders("name"))
	if err != nil {
		t.Fatalf("err want:nil got:%q", err)
	}
	want := []string{"name"}
	if !reflect.DeepEqual(want, tab.Headers) {
		t.Fatalf("val want:%v got:%v", want, tab.Headers)
	}
	tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
	var out []csvRow
	if err := tab.CastAll(&out); err != nil {
		t.Fatalf("err want:nil got:%q", err)
	}
	if len(out) == 0 {
		t.Fatalf("CSVHeaders must not skip first row")
	}
}

func TestTable_Infer(t *testing.T) {
	t.Run("SimpleCase", func(t *testing.T) {
		tab, err := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.Infer(); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		var got []csvRow
		if err := tab.CastAll(&got); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		want := []csvRow{{"foo"}, {"bar"}}
		if !reflect.DeepEqual(want, got) {
			t.Fatalf("val want:%v got:%v", want, got)
		}
	})
	t.Run("WithErrorSource", func(t *testing.T) {
		tab, err := New(errorSource())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.Infer(); err == nil {
			t.Fatalf("want:err got:nil")
		}
	})
}

func TestTable_Iter(t *testing.T) {
	t.Run("SimpleCase", func(t *testing.T) {
		tab, err := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.Infer(); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		iter, err := tab.Iter()
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		want := [][]string{{"foo"}, {"bar"}}
		for i := range want {
			if !iter.Next() {
				t.Fatalf("want more values")
			}
			if !reflect.DeepEqual(want[i], iter.Row()) {
				t.Fatalf("val want:%v got:%v", want[i], iter.Row())
			}
			if iter.Err() != nil {
				t.Fatalf("err want:nil got:%q", err)
			}
		}
	})
	t.Run("WithErrorSource", func(t *testing.T) {
		tab, err := New(errorSource())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		_, err = tab.Iter()
		if err == nil {
			t.Fatalf("want:err got:nil")
		}
	})
}

func TestTable_CastAll(t *testing.T) {
	data := []struct {
		desc string
		got  []csvRow
	}{
		{"OutEmpty", []csvRow{}},
		{"OutNil", nil},
		{"OutInitialized", []csvRow{{"fooooo"}}},
	}
	for _, d := range data {
		t.Run(d.desc, func(t *testing.T) {
			tab, err := New(StringSource("name\nfoo\nbar"))
			if err != nil {
				t.Fatalf("err want:nil got:%q", err)
			}
			tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
			if err := tab.CastAll(&d.got); err != nil {
				t.Fatalf("err want:nil got:%q", err)
			}
			want := []csvRow{{"name"}, {"foo"}, {"bar"}}
			if !reflect.DeepEqual(want, d.got) {
				t.Fatalf("val want:%v got:%v", want, d.got)
			}
		})
	}
	t.Run("EmptyString", func(t *testing.T) {
		tab, err := New(StringSource(""))
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
		var got []csvRow
		if err := tab.CastAll(&got); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if len(got) != 0 {
			t.Fatalf("len(got) want:0 got:%v", len(got))
		}
	})
	t.Run("Error_TableWithNoSchema", func(t *testing.T) {
		tab, err := New(StringSource("name"))
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.CastAll(&[]csvRow{}); err == nil {
			t.Fatalf("err want:err got:nil")
		}
	})
	t.Run("Error_OutNotAPointerToSlice", func(t *testing.T) {
		tab, err := New(StringSource("name"))
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
		if err := tab.CastAll([]csvRow{}); err == nil {
			t.Fatalf("err want:err got:nil")
		}
	})
}
<commit_msg>Adding a line that was removed by mistake<commit_after>package csv

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/frictionlessdata/tableschema-go/schema"
)

type csvRow struct {
	Name string
}

func ExampleTable_Iter() {
	tab, _ := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
	tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
	iter, _ := tab.Iter()
	for iter.Next() {
		var data csvRow
		iter.CastRow(&data)
		fmt.Println(data.Name)
	}
	// Output:foo
	// bar
}

func ExampleTable_Infer() {
	tab, _ := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
	tab.Infer()
	iter, _ := tab.Iter()
	for iter.Next() {
		var data csvRow
		iter.CastRow(&data)
		fmt.Println(data.Name)
	}
	// Output:foo
	// bar
}

func TestLoadHeaders(t *testing.T) {
	t.Run("EmptyString", func(t *testing.T) {
		tab, err := New(StringSource(""), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if len(tab.Headers) != 0 {
			t.Fatalf("len(headers) want:0 got:%v", len(tab.Headers))
		}
	})
	t.Run("SimpleCase", func(t *testing.T) {
		in := `"name"
"bar"`
		tab, err := New(StringSource(in), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		want := []string{"name"}
		if !reflect.DeepEqual(want, tab.Headers) {
			t.Fatalf("headers want:%v got:%v", want, tab.Headers)
		}
		tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
		var out []csvRow
		if err := tab.CastAll(&out); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if len(out) != 1 {
			t.Fatalf("LoadHeaders content must skip first row")
		}
	})
}

func TestNew(t *testing.T) {
	t.Run("ErrorOpts", func(t *testing.T) {
		tab, err := New(StringSource(""), errorOpts())
		if tab != nil {
			t.Fatalf("tab want:nil got:%v", tab)
		}
		if err == nil {
			t.Fatalf("err want:error got:nil")
		}
	})
	t.Run("ErrorSource", func(t *testing.T) {
		_, err := New(errorSource(), LoadHeaders())
		if err == nil {
			t.Fatalf("want:err got:nil")
		}
	})
}

func TestSetHeaders(t *testing.T) {
	in := "Foo"
	tab, err := New(StringSource(in), SetHeaders("name"))
	if err != nil {
		t.Fatalf("err want:nil got:%q", err)
	}
	want := []string{"name"}
	if !reflect.DeepEqual(want, tab.Headers) {
		t.Fatalf("val want:%v got:%v", want, tab.Headers)
	}
	tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
	var out []csvRow
	if err := tab.CastAll(&out); err != nil {
		t.Fatalf("err want:nil got:%q", err)
	}
	if len(out) == 0 {
		t.Fatalf("CSVHeaders must not skip first row")
	}
}

func TestTable_Infer(t *testing.T) {
	t.Run("SimpleCase", func(t *testing.T) {
		tab, err := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.Infer(); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		var got []csvRow
		if err := tab.CastAll(&got); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		want := []csvRow{{"foo"}, {"bar"}}
		if !reflect.DeepEqual(want, got) {
			t.Fatalf("val want:%v got:%v", want, got)
		}
	})
	t.Run("WithErrorSource", func(t *testing.T) {
		tab, err := New(errorSource())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.Infer(); err == nil {
			t.Fatalf("want:err got:nil")
		}
	})
}

func TestTable_Iter(t *testing.T) {
	t.Run("SimpleCase", func(t *testing.T) {
		tab, err := New(StringSource("\"name\"\nfoo\nbar"), LoadHeaders())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.Infer(); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		iter, err := tab.Iter()
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		want := [][]string{{"foo"}, {"bar"}}
		for i := range want {
			if !iter.Next() {
				t.Fatalf("want more values")
			}
			if !reflect.DeepEqual(want[i], iter.Row()) {
				t.Fatalf("val want:%v got:%v", want[i], iter.Row())
			}
			if iter.Err() != nil {
				t.Fatalf("err want:nil got:%q", err)
			}
		}
	})
	t.Run("WithErrorSource", func(t *testing.T) {
		tab, err := New(errorSource())
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		_, err = tab.Iter()
		if err == nil {
			t.Fatalf("want:err got:nil")
		}
	})
}

func TestTable_CastAll(t *testing.T) {
	data := []struct {
		desc string
		got  []csvRow
	}{
		{"OutEmpty", []csvRow{}},
		{"OutNil", nil},
		{"OutInitialized", []csvRow{{"fooooo"}}},
	}
	for _, d := range data {
		t.Run(d.desc, func(t *testing.T) {
			tab, err := New(StringSource("name\nfoo\nbar"))
			if err != nil {
				t.Fatalf("err want:nil got:%q", err)
			}
			tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
			if err := tab.CastAll(&d.got); err != nil {
				t.Fatalf("err want:nil got:%q", err)
			}
			want := []csvRow{{"name"}, {"foo"}, {"bar"}}
			if !reflect.DeepEqual(want, d.got) {
				t.Fatalf("val want:%v got:%v", want, d.got)
			}
		})
	}
	t.Run("EmptyString", func(t *testing.T) {
		tab, err := New(StringSource(""))
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
		var got []csvRow
		if err := tab.CastAll(&got); err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if len(got) != 0 {
			t.Fatalf("len(got) want:0 got:%v", len(got))
		}
	})
	t.Run("Error_TableWithNoSchema", func(t *testing.T) {
		tab, err := New(StringSource("name"))
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		if err := tab.CastAll(&[]csvRow{}); err == nil {
			t.Fatalf("err want:err got:nil")
		}
	})
	t.Run("Error_OutNotAPointerToSlice", func(t *testing.T) {
		tab, err := New(StringSource("name"))
		if err != nil {
			t.Fatalf("err want:nil got:%q", err)
		}
		tab.Schema = &schema.Schema{Fields: []schema.Field{{Name: "name", Type: schema.StringType}}}
		if err := tab.CastAll([]csvRow{}); err == nil {
			t.Fatalf("err want:err got:nil")
		}
	})
}
<|endoftext|>


<commit_before>package util

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net"
	"os/user"
	"strconv"
	"strings"
	"sync"
	"time"

	"code.google.com/p/go.crypto/ssh"
	"github.com/skia-dev/glog"
	"go.skia.org/infra/go/util"
)

const (
	KEY_FILE           = "id_rsa"
	WORKER_NUM_KEYWORD = "{{worker_num}}"
)

type workerResp struct {
	hostname string
	output   string
}

func executeCmd(cmd, hostname string, config *ssh.ClientConfig, timeout time.Duration) (string, error) {
	// Dial up TCP connection to remote machine.
	conn, err := net.Dial("tcp", hostname+":22")
	if err != nil {
		return "", fmt.Errorf("Failed to ssh connect to %s. Make sure \"PubkeyAuthentication yes\" is in your sshd_config: %s", hostname, err)
	}
	defer util.Close(conn)
	util.LogErr(conn.SetDeadline(time.Now().Add(timeout)))

	// Create new SSH client connection.
	sshConn, sshChan, req, err := ssh.NewClientConn(conn, hostname+":22", config)
	if err != nil {
		return "", fmt.Errorf("Failed to ssh connect to %s: %s", hostname, err)
	}
	// Use client connection to create new client.
	client := ssh.NewClient(sshConn, sshChan, req)
	defer util.Close(client)

	// Client connections can support multiple interactive sessions.
	session, err := client.NewSession()
	if err != nil {
		return "", fmt.Errorf("Failed to ssh connect to %s: %s", hostname, err)
	}
	defer util.Close(session)

	var stdoutBuf bytes.Buffer
	session.Stdout = &stdoutBuf
	if err := session.Run(cmd); err != nil {
		return "", fmt.Errorf("Errored or Timeout out while running \"%s\" on %s: %s", cmd, hostname, err)
	}
	return stdoutBuf.String(), nil
}

func getKeyFile() (key ssh.Signer, err error) {
	usr, _ := user.Current()
	file := usr.HomeDir + "/.ssh/" + KEY_FILE
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	key, err = ssh.ParsePrivateKey(buf)
	if err != nil {
		return
	}
	return
}

// SSH connects to the specified workers and runs the specified command. If the
// command does not complete in the given duration then all remaining workers are
// considered timed out. SSH also automatically substitutes the sequential number
// of the worker for the WORKER_NUM_KEYWORD since it is a common use case.
func SSH(cmd string, workers []string, timeout time.Duration) (map[string]string, error) {
	glog.Infof("Running \"%s\" on %s with timeout of %s", cmd, workers, timeout)

	// Ensure that the key file exists.
	key, err := getKeyFile()
	if err != nil {
		return nil, fmt.Errorf("Failed to get key file: %s", err)
	}

	// Initialize the structure with the configuration for ssh.
	config := &ssh.ClientConfig{
		User: CT_USER,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(key),
		},
	}

	var wg sync.WaitGroup
	// Will be populated and returned by this function.
	workersWithOutputs := map[string]string{}
	// Keeps track of which workers are still pending.
	remainingWorkers := map[string]int{}

	// Kick off a goroutine on all workers.
	for i, hostname := range workers {
		wg.Add(1)
		remainingWorkers[hostname] = 1
		go func(index int, hostname string) {
			defer wg.Done()
			updatedCmd := strings.Replace(cmd, WORKER_NUM_KEYWORD, strconv.Itoa(index+1), -1)
			output, err := executeCmd(updatedCmd, hostname, config, timeout)
			if err != nil {
				glog.Errorf("Could not execute ssh cmd: %s", err)
			}
			workersWithOutputs[hostname] = output
			delete(remainingWorkers, hostname)
			glog.Infof("Worker %s has completed execution", hostname)
			glog.Infof("Remaining workers: %s", remainingWorkers)
		}(i, hostname)
	}

	wg.Wait()

	return workersWithOutputs, nil
}

// RebootWorkers reboots all CT workers and waits for 4 mins before returning.
func RebootWorkers() {
	if _, err := SSH("sudo reboot", Slaves, 5*time.Minute); err != nil {
		glog.Errorf("Got error while rebooting workers: %v", err)
	}
	// Sleep for 4 mins for all slaves to come back.
	time.Sleep(4 * time.Minute)
}
<commit_msg>Do not close client and session because connection is already closed<commit_after>package util

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net"
	"os/user"
	"strconv"
	"strings"
	"sync"
	"time"

	"code.google.com/p/go.crypto/ssh"
	"github.com/skia-dev/glog"
	"go.skia.org/infra/go/util"
)

const (
	KEY_FILE           = "id_rsa"
	WORKER_NUM_KEYWORD = "{{worker_num}}"
)

type workerResp struct {
	hostname string
	output   string
}

func executeCmd(cmd, hostname string, config *ssh.ClientConfig, timeout time.Duration) (string, error) {
	// Dial up TCP connection to remote machine.
	conn, err := net.Dial("tcp", hostname+":22")
	if err != nil {
		return "", fmt.Errorf("Failed to ssh connect to %s. Make sure \"PubkeyAuthentication yes\" is in your sshd_config: %s", hostname, err)
	}
	defer util.Close(conn)
	util.LogErr(conn.SetDeadline(time.Now().Add(timeout)))

	// Create new SSH client connection.
	sshConn, sshChan, req, err := ssh.NewClientConn(conn, hostname+":22", config)
	if err != nil {
		return "", fmt.Errorf("Failed to ssh connect to %s: %s", hostname, err)
	}
	// Use client connection to create new client.
	client := ssh.NewClient(sshConn, sshChan, req)

	// Client connections can support multiple interactive sessions.
	session, err := client.NewSession()
	if err != nil {
		return "", fmt.Errorf("Failed to ssh connect to %s: %s", hostname, err)
	}

	var stdoutBuf bytes.Buffer
	session.Stdout = &stdoutBuf
	if err := session.Run(cmd); err != nil {
		return "", fmt.Errorf("Errored or Timeout out while running \"%s\" on %s: %s", cmd, hostname, err)
	}
	return stdoutBuf.String(), nil
}

func getKeyFile() (key ssh.Signer, err error) {
	usr, _ := user.Current()
	file := usr.HomeDir + "/.ssh/" + KEY_FILE
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	key, err = ssh.ParsePrivateKey(buf)
	if err != nil {
		return
	}
	return
}

// SSH connects to the specified workers and runs the specified command. If the
// command does not complete in the given duration then all remaining workers are
// considered timed out. SSH also automatically substitutes the sequential number
// of the worker for the WORKER_NUM_KEYWORD since it is a common use case.
func SSH(cmd string, workers []string, timeout time.Duration) (map[string]string, error) {
	glog.Infof("Running \"%s\" on %s with timeout of %s", cmd, workers, timeout)

	// Ensure that the key file exists.
	key, err := getKeyFile()
	if err != nil {
		return nil, fmt.Errorf("Failed to get key file: %s", err)
	}

	// Initialize the structure with the configuration for ssh.
	config := &ssh.ClientConfig{
		User: CT_USER,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(key),
		},
	}

	var wg sync.WaitGroup
	// Will be populated and returned by this function.
	workersWithOutputs := map[string]string{}
	// Keeps track of which workers are still pending.
	remainingWorkers := map[string]int{}

	// Kick off a goroutine on all workers.
	for i, hostname := range workers {
		wg.Add(1)
		remainingWorkers[hostname] = 1
		go func(index int, hostname string) {
			defer wg.Done()
			updatedCmd := strings.Replace(cmd, WORKER_NUM_KEYWORD, strconv.Itoa(index+1), -1)
			output, err := executeCmd(updatedCmd, hostname, config, timeout)
			if err != nil {
				glog.Errorf("Could not execute ssh cmd: %s", err)
			}
			workersWithOutputs[hostname] = output
			delete(remainingWorkers, hostname)
			glog.Infof("Worker %s has completed execution", hostname)
			glog.Infof("Remaining workers: %s", remainingWorkers)
		}(i, hostname)
	}

	wg.Wait()

	return workersWithOutputs, nil
}

// RebootWorkers reboots all CT workers and waits for 4 mins before returning.
func RebootWorkers() {
	if _, err := SSH("sudo reboot", Slaves, 5*time.Minute); err != nil {
		glog.Errorf("Got error while rebooting workers: %v", err)
	}
	// Sleep for 4 mins for all slaves to come back.
	time.Sleep(4 * time.Minute)
}
<|endoftext|>


<commit_before>package daemon

import (
	"log"
	"math"
	"time"

	"github.com/larsth/go-gpsfix"
	"github.com/larsth/go-rmsggpsbinmsg"
	"github.com/larsth/rmsggpsd-gpspipe/errors"
)

/*
calcBearing is a function that calculates the _inital_ bearing
from point p1(lat1, lon1) to point p2(lat2, lon2) by using the
haversine algorithm.

The bearing changes at any point between point 1 to
point 2 and vise versa.

The returned float64 value is the initial bearing in radians (not degrees).
*/
func calcBearing(this, other *binmsg.Message) (float64, error) {
	/*
		tc1=mod(atan2(sin(lon2-lon1)*cos(lat2),
		   	cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1)), 2*pi)

		Algorithm is from:
		    http://mathforum.org/library/drmath/view/55417.html : Post #2

		The algorithm had been translated to this pseudo code:
		   	dlon = lon2 -lon1
		   	sin_dlon = sin(dlon)
		   	cos_lat2 = cos(lat2)
		   	cos_lat1 = cos(lat1)
		   	sin_lat2 = sin(lat2)
		   	sin_lat1 = sin(lat1)
		   	cos_dlon = cos(dlon)
		   	atan2_x = sin_dlon*cos_lat2
		   	atan2_y1 = cos_lat1*sin_lat2
		   	atan2_y2 = sin_lat1*cos_lat2*cos_dlon
		   	atan2_y = atan2_y1 - atan2_y2
		    mod_x = atan2(atan2_x, atan2_y)
		    mod_y = 2*pi
		   	bearing=mod(mod_x, mod_y)
	*/
	var (
		lon1, lat1, lon2, lat2           float64
		dLon                             float64
		sinLat2, sinLat1, sinDlon        float64
		cosLat2, cosLat1, cosDlon        float64
		atan2x, atan2y1, atan2y2, atan2y float64
		modX, modY, bearing              float64
		err                              error
	)

	lat1 = this.Gps.Lat()
	lat2 = other.Gps.Lat()
	lon1 = this.Gps.Lon()
	lon2 = other.Gps.Lon()

	dLon = lon2 - lon1

	sinDlon = math.Sin(dLon)
	cosLat2 = math.Cos(lat2)
	cosLat1 = math.Cos(lat1)
	sinLat2 = math.Sin(lat2)
	sinLat1 = math.Sin(lat1)
	cosDlon = math.Cos(dLon)

	atan2x = sinDlon * cosLat2
	atan2y1 = cosLat1 * sinLat2
	atan2y2 = sinLat1 * cosLat2 * cosDlon
	atan2y = atan2y1 - atan2y2

	if modX, err = atan2(atan2x, atan2y); err != nil {
		return math.NaN(), errors.Trace(err)
	}
	modY = math.Pi * 2

	bearing = math.Mod(modX, modY)

	return bearing, nil
}

func updateBearingCache(this, other *binmsg.Message, logger *log.Logger) {
	var (
		useTime    time.Time
		a, b, c, d bool
		bearing    float64
		err        error
	)

	if this.TimeStamp.Time.Before(other.TimeStamp.Time) {
		useTime = this.TimeStamp.Time
	} else {
		useTime = other.TimeStamp.Time
	}

	a = this.Gps.FixMode == gpsfix.FixNotSeen
	b = this.Gps.FixMode == gpsfix.FixNone
	c = this.Gps.FixMode == gpsfix.FixNotSeen
	d = this.Gps.FixMode == gpsfix.FixNone

	if a || b || c || d {
		bearing = math.NaN()
	} else {
		//FIXME
		/* Also use sentinel values?, ie. : special float64 values outside 360
		   degrees (2*Pi rad) to give extra information to http request functions?
		*/
		bearing, err = calcBearing(this, other)
		if err != nil {
			logger.Println(err)
		}
	}
	bearingCache.Put(bearing, useTime)
}

func bearingGoRoutine(logger *log.Logger) {
	var (
		this  = binmsg.MkFixNotSeenMessage()
		other = binmsg.MkFixNotSeenMessage()
	)

	updateBearingCache(this, other, logger)
	for {
		select {
		case this = <-thisChan:
			updateBearingCache(this, other, logger)
		case other = <-otherChan:
			updateBearingCache(this, other, logger)
		}
	}
}
<commit_msg>Made it easy to test function updateBearingCache in package "github.com/larsth/rmsggpsd-gpspipe/daemon" 	modified:   daemon/bearing.go<commit_after>package daemon

import (
	"log"
	"math"
	"time"

	"github.com/larsth/go-gpsfix"
	"github.com/larsth/go-rmsggpsbinmsg"
	"github.com/larsth/rmsggpsd-gpspipe/cache"
	"github.com/larsth/rmsggpsd-gpspipe/errors"
)

/*
calcBearing is a function that calculates the _inital_ bearing
from point p1(lat1, lon1) to point p2(lat2, lon2) by using the
haversine algorithm.

The bearing changes at any point between point 1 to
point 2 and vise versa.

The returned float64 value is the initial bearing in radians (not degrees).
*/
func calcBearing(this, other *binmsg.Message) (float64, error) {
	/*
		tc1=mod(atan2(sin(lon2-lon1)*cos(lat2),
		   	cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1)), 2*pi)

		Algorithm is from:
		    http://mathforum.org/library/drmath/view/55417.html : Post #2

		The algorithm had been translated to this pseudo code:
		   	dlon = lon2 -lon1
		   	sin_dlon = sin(dlon)
		   	cos_lat2 = cos(lat2)
		   	cos_lat1 = cos(lat1)
		   	sin_lat2 = sin(lat2)
		   	sin_lat1 = sin(lat1)
		   	cos_dlon = cos(dlon)
		   	atan2_x = sin_dlon*cos_lat2
		   	atan2_y1 = cos_lat1*sin_lat2
		   	atan2_y2 = sin_lat1*cos_lat2*cos_dlon
		   	atan2_y = atan2_y1 - atan2_y2
		    mod_x = atan2(atan2_x, atan2_y)
		    mod_y = 2*pi
		   	bearing=mod(mod_x, mod_y)
	*/
	var (
		lon1, lat1, lon2, lat2           float64
		dLon                             float64
		sinLat2, sinLat1, sinDlon        float64
		cosLat2, cosLat1, cosDlon        float64
		atan2x, atan2y1, atan2y2, atan2y float64
		modX, modY, bearing              float64
		err                              error
	)

	lat1 = this.Gps.Lat()
	lat2 = other.Gps.Lat()
	lon1 = this.Gps.Lon()
	lon2 = other.Gps.Lon()

	dLon = lon2 - lon1

	sinDlon = math.Sin(dLon)
	cosLat2 = math.Cos(lat2)
	cosLat1 = math.Cos(lat1)
	sinLat2 = math.Sin(lat2)
	sinLat1 = math.Sin(lat1)
	cosDlon = math.Cos(dLon)

	atan2x = sinDlon * cosLat2
	atan2y1 = cosLat1 * sinLat2
	atan2y2 = sinLat1 * cosLat2 * cosDlon
	atan2y = atan2y1 - atan2y2

	if modX, err = atan2(atan2x, atan2y); err != nil {
		return math.NaN(), errors.Trace(err)
	}
	modY = math.Pi * 2

	bearing = math.Mod(modX, modY)

	return bearing, nil
}

func updateBearingCache(this, other *binmsg.Message, logger *log.Logger, bc *cache.Bearing) {
	var (
		useTime    time.Time
		a, b, c, d bool
		bearing    float64
		err        error
	)

	if this.TimeStamp.Time.Before(other.TimeStamp.Time) {
		useTime = this.TimeStamp.Time
	} else {
		useTime = other.TimeStamp.Time
	}

	a = this.Gps.FixMode == gpsfix.FixNotSeen
	b = this.Gps.FixMode == gpsfix.FixNone
	c = this.Gps.FixMode == gpsfix.FixNotSeen
	d = this.Gps.FixMode == gpsfix.FixNone

	if a || b || c || d {
		bearing = math.NaN()
	} else {
		//FIXME
		/* Also use sentinel values?, ie. : special float64 values outside 360
		   degrees (2*Pi rad) to give extra information to http request functions?
		*/
		bearing, err = calcBearing(this, other)
		if err != nil {
			logger.Println(err)
		}
	}
	bc.Put(bearing, useTime)
}

func bearingGoRoutine(logger *log.Logger) {
	var (
		this  = binmsg.MkFixNotSeenMessage()
		other = binmsg.MkFixNotSeenMessage()
	)

	updateBearingCache(this, other, logger, bearingCache)
	for {
		select {
		case this = <-thisChan:
			updateBearingCache(this, other, logger, bearingCache)
		case other = <-otherChan:
			updateBearingCache(this, other, logger, bearingCache)
		}
	}
}
<|endoftext|>


<commit_before>package dal

import (
	"os"
	"testing"

	_ "github.com/lib/pq"
)

func newCheckForTest(t *testing.T) *Check {
	return NewCheck(newDbForTest(t))
}

func TestCheckCRUD(t *testing.T) {
	u := newUserForTest(t)

	// Signup
	userRow, err := u.Signup(nil, newEmailForTest(), "abc123", "abc123")
	if err != nil {
		t.Errorf("Signing up user should work. Error: %v", err)
	}
	if userRow == nil {
		t.Fatal("Signing up user should work.")
	}
	if userRow.ID <= 0 {
		t.Fatal("Signing up user should work.")
	}

	// Create cluster for user
	clusterRow, err := newClusterForTest(t).Create(nil, userRow.ID, "cluster-name")
	if err != nil {
		t.Fatalf("Creating a cluster for user should work. Error: %v", err)
	}
	if clusterRow.ID <= 0 {
		t.Fatalf("Cluster ID should be assign properly. clusterRow.ID: %v", clusterRow.ID)
	}

	hostname, _ := os.Hostname()

	// Create Check
	data := make(map[string]interface{})
	data["name"] = "check-name"
	data["interval"] = "60s"
	data["hosts_query"] = ""
	data["hosts_list"] = []byte("[\"" + hostname + "\"]")
	data["expressions"] = []byte("[]")
	data["triggers"] = []byte("[]")
	data["last_result_hosts"] = []byte("[]")
	data["last_result_expressions"] = []byte("[]")

	checkRow, err := newCheckForTest(t).Create(nil, clusterRow.ID, data)
	if err != nil {
		t.Fatalf("Creating a Check should not fail. Error: %v", err)
	}
	if checkRow.ID <= 0 {
		t.Fatalf("Check ID should be assign properly. CheckRow.ID: %v", checkRow.ID)
	}

	// DELETE FROM Checks WHERE id=...
	_, err = NewCheck(u.db).DeleteByID(nil, checkRow.ID)
	if err != nil {
		t.Fatalf("Deleting Checks by id should not fail. Error: %v", err)
	}

	// DELETE FROM users WHERE id=...
	_, err = u.DeleteByID(nil, userRow.ID)
	if err != nil {
		t.Fatalf("Deleting user by id should not fail. Error: %v", err)
	}
}

func TestCheckEvalRawHostDataExpression(t *testing.T) {
	u := newUserForTest(t)

	// Signup
	userRow, err := u.Signup(nil, newEmailForTest(), "abc123", "abc123")
	if err != nil {
		t.Errorf("Signing up user should work. Error: %v", err)
	}
	if userRow == nil {
		t.Fatal("Signing up user should work.")
	}
	if userRow.ID <= 0 {
		t.Fatal("Signing up user should work.")
	}

	// Create cluster for user
	clusterRow, err := newClusterForTest(t).Create(nil, userRow.ID, "cluster-name")
	if err != nil {
		t.Fatalf("Creating a cluster for user should work. Error: %v", err)
	}
	if clusterRow.ID <= 0 {
		t.Fatalf("Cluster ID should be assign properly. clusterRow.ID: %v", clusterRow.ID)
	}

	hostname, _ := os.Hostname()

	// Create Check
	data := make(map[string]interface{})
	data["name"] = "check-name"
	data["interval"] = "60s"
	data["hosts_query"] = ""
	data["hosts_list"] = []byte("[\"" + hostname + "\"]")
	data["expressions"] = []byte("[]")
	data["triggers"] = []byte("[]")
	data["last_result_hosts"] = []byte("[]")
	data["last_result_expressions"] = []byte("[]")

	checkRow, err := newCheckForTest(t).Create(nil, clusterRow.ID, data)
	if err != nil {
		t.Fatalf("Creating a Check should not fail. Error: %v", err)
	}
	if checkRow.ID <= 0 {
		t.Fatalf("Check ID should be assign properly. CheckRow.ID: %v", checkRow.ID)
	}

	// EvalRawHostDataExpression where hosts list is nil
	// The result should be true, which means that this expression is a fail.
	expression := checkRow.EvalRawHostDataExpression(nil, CheckExpression{})
	if expression.Result.Value != true {
		t.Fatalf("Expression result is not true")
	}

	at := newAccessTokenForTest(t)

	// Create access token
	tokenRow, err := at.Create(nil, userRow.ID, clusterRow.ID, "execute")
	if err != nil {
		t.Fatalf("Creating a token should work. Error: %v", err)
	}
	if tokenRow.ID <= 0 {
		t.Fatalf("AccessToken ID should be assign properly. tokenRow.ID: %v", tokenRow.ID)
	}

	// Create host
	hostRow, err := newHostForTest(t).CreateOrUpdate(nil, tokenRow, []byte(`{"/stuff": {"Data": {"Score": 100}, "Host": {"Name": "localhost", "Tags": {"aaa": "bbb"}}}}`))
	if err != nil {
		t.Errorf("Creating a new host should work. Error: %v", err)
	}
	if hostRow.ID <= 0 {
		t.Fatalf("Host ID should be assign properly. hostRow.ID: %v", hostRow.ID)
	}

	// EvalRawHostDataExpression where hosts list is not nil and valid expression.
	// This is a basic happy path test.
	// Host data is 100, and we set check to fail at 101.
	// The result should be false, 100 is not greater than 101, which means that this expression does not fail.
	hosts := make([]*HostRow, 1)
	hosts[0] = hostRow

	expression = CheckExpression{}
	expression.Metric = "/stuff.Score"
	expression.Operator = ">"
	expression.MinHost = 1
	expression.Value = float64(101)

	expression = checkRow.EvalRawHostDataExpression(hosts, expression)
	if expression.Result.Value != false {
		t.Fatalf("Expression result is not false. %v > %v", hostRow.DataAsFlatKeyValue()["/stuff"]["Score"], expression.Value)
	}

	// DELETE FROM hosts WHERE id=...
	_, err = newHostForTest(t).DeleteByID(nil, hostRow.ID)
	if err != nil {
		t.Fatalf("Deleting access_tokens by id should not fail. Error: %v", err)
	}

	// DELETE FROM access_tokens WHERE id=...
	_, err = at.DeleteByID(nil, tokenRow.ID)
	if err != nil {
		t.Fatalf("Deleting access_tokens by id should not fail. Error: %v", err)
	}

	// DELETE FROM Checks WHERE id=...
	_, err = NewCheck(u.db).DeleteByID(nil, checkRow.ID)
	if err != nil {
		t.Fatalf("Deleting Checks by id should not fail. Error: %v", err)
	}

	// DELETE FROM users WHERE id=...
	_, err = u.DeleteByID(nil, userRow.ID)
	if err != nil {
		t.Fatalf("Deleting user by id should not fail. Error: %v", err)
	}
}
<commit_msg>Arithmetic comparison tests on RawHostData.<commit_after>package dal

import (
	"os"
	"testing"

	_ "github.com/lib/pq"
)

func newCheckForTest(t *testing.T) *Check {
	return NewCheck(newDbForTest(t))
}

func TestCheckCRUD(t *testing.T) {
	u := newUserForTest(t)

	// Signup
	userRow, err := u.Signup(nil, newEmailForTest(), "abc123", "abc123")
	if err != nil {
		t.Errorf("Signing up user should work. Error: %v", err)
	}
	if userRow == nil {
		t.Fatal("Signing up user should work.")
	}
	if userRow.ID <= 0 {
		t.Fatal("Signing up user should work.")
	}

	// Create cluster for user
	clusterRow, err := newClusterForTest(t).Create(nil, userRow.ID, "cluster-name")
	if err != nil {
		t.Fatalf("Creating a cluster for user should work. Error: %v", err)
	}
	if clusterRow.ID <= 0 {
		t.Fatalf("Cluster ID should be assign properly. clusterRow.ID: %v", clusterRow.ID)
	}

	// ----------------------------------------------------------------------
	// Real test begins here

	hostname, _ := os.Hostname()

	// Create Check
	data := make(map[string]interface{})
	data["name"] = "check-name"
	data["interval"] = "60s"
	data["hosts_query"] = ""
	data["hosts_list"] = []byte("[\"" + hostname + "\"]")
	data["expressions"] = []byte("[]")
	data["triggers"] = []byte("[]")
	data["last_result_hosts"] = []byte("[]")
	data["last_result_expressions"] = []byte("[]")

	checkRow, err := newCheckForTest(t).Create(nil, clusterRow.ID, data)
	if err != nil {
		t.Fatalf("Creating a Check should not fail. Error: %v", err)
	}
	if checkRow.ID <= 0 {
		t.Fatalf("Check ID should be assign properly. CheckRow.ID: %v", checkRow.ID)
	}

	// DELETE FROM Checks WHERE id=...
	_, err = NewCheck(u.db).DeleteByID(nil, checkRow.ID)
	if err != nil {
		t.Fatalf("Deleting Checks by id should not fail. Error: %v", err)
	}

	// ----------------------------------------------------------------------

	// DELETE FROM users WHERE id=...
	_, err = u.DeleteByID(nil, userRow.ID)
	if err != nil {
		t.Fatalf("Deleting user by id should not fail. Error: %v", err)
	}
}

func TestCheckEvalRawHostDataExpression(t *testing.T) {
	u := newUserForTest(t)

	// Signup
	userRow, err := u.Signup(nil, newEmailForTest(), "abc123", "abc123")
	if err != nil {
		t.Errorf("Signing up user should work. Error: %v", err)
	}
	if userRow == nil {
		t.Fatal("Signing up user should work.")
	}
	if userRow.ID <= 0 {
		t.Fatal("Signing up user should work.")
	}

	// Create cluster for user
	clusterRow, err := newClusterForTest(t).Create(nil, userRow.ID, "cluster-name")
	if err != nil {
		t.Fatalf("Creating a cluster for user should work. Error: %v", err)
	}
	if clusterRow.ID <= 0 {
		t.Fatalf("Cluster ID should be assign properly. clusterRow.ID: %v", clusterRow.ID)
	}

	at := newAccessTokenForTest(t)

	// Create access token
	tokenRow, err := at.Create(nil, userRow.ID, clusterRow.ID, "execute")
	if err != nil {
		t.Fatalf("Creating a token should work. Error: %v", err)
	}
	if tokenRow.ID <= 0 {
		t.Fatalf("AccessToken ID should be assign properly. tokenRow.ID: %v", tokenRow.ID)
	}

	// Create host
	hostRow, err := newHostForTest(t).CreateOrUpdate(nil, tokenRow, []byte(`{"/stuff": {"Data": {"Score": 100}, "Host": {"Name": "localhost", "Tags": {"aaa": "bbb"}}}}`))
	if err != nil {
		t.Errorf("Creating a new host should work. Error: %v", err)
	}

	// ----------------------------------------------------------------------
	// Real test begins here

	hostname, _ := os.Hostname()

	// Create Check
	data := make(map[string]interface{})
	data["name"] = "check-name"
	data["interval"] = "60s"
	data["hosts_query"] = ""
	data["hosts_list"] = []byte("[\"" + hostname + "\"]")
	data["expressions"] = []byte("[]")
	data["triggers"] = []byte("[]")
	data["last_result_hosts"] = []byte("[]")
	data["last_result_expressions"] = []byte("[]")

	checkRow, err := newCheckForTest(t).Create(nil, clusterRow.ID, data)
	if err != nil {
		t.Fatalf("Creating a Check should not fail. Error: %v", err)
	}
	if checkRow.ID <= 0 {
		t.Fatalf("Check ID should be assign properly. CheckRow.ID: %v", checkRow.ID)
	}

	hosts := make([]*HostRow, 1)
	hosts[0] = hostRow

	// EvalRawHostDataExpression where hosts list is nil
	// The result should be true, which means that this expression is a fail.
	expression := checkRow.EvalRawHostDataExpression(nil, CheckExpression{})
	if expression.Result.Value != true {
		t.Fatalf("Expression result is not true")
	}

	// EvalRawHostDataExpression where hosts list is not nil and valid expression.
	// This is a basic happy path test.
	// Host data is 100, and we set check to fail at 101.
	// The result should be false, 100 is not greater than 101, which means that this expression does not fail.
	expression = CheckExpression{}
	expression.Metric = "/stuff.Score"
	expression.Operator = ">"
	expression.MinHost = 1
	expression.Value = float64(101)

	expression = checkRow.EvalRawHostDataExpression(hosts, expression)
	if expression.Result.Value != false {
		t.Fatalf("Expression result is not false. %v %v %v", hostRow.DataAsFlatKeyValue()["/stuff"]["Score"], expression.Operator, expression.Value)
	}

	// Arithmetic expression test.
	// Host data is 100, see if the arithmetic comparison works.
	// Greater than is already tested, above.
	expression = CheckExpression{}
	expression.Metric = "/stuff.Score"
	expression.Operator = ">="
	expression.MinHost = 1
	expression.Value = float64(100)

	expression = checkRow.EvalRawHostDataExpression(hosts, expression)
	if expression.Result.Value != true {
		// The result should be true, 100 is greater than or equal to 100, which means that this expression fails.
		t.Fatalf("Expression result should be true. %v %v %v", hostRow.DataAsFlatKeyValue()["/stuff"]["Score"], expression.Operator, expression.Value)
	}

	expression = CheckExpression{}
	expression.Metric = "/stuff.Score"
	expression.Operator = "="
	expression.MinHost = 1
	expression.Value = float64(100)

	expression = checkRow.EvalRawHostDataExpression(hosts, expression)
	if expression.Result.Value != true {
		// The result should be true, 100 is equal to 100, which means that this expression fails.
		t.Fatalf("Expression result should be true. %v %v %v", hostRow.DataAsFlatKeyValue()["/stuff"]["Score"], expression.Operator, expression.Value)
	}

	expression = CheckExpression{}
	expression.Metric = "/stuff.Score"
	expression.Operator = "<"
	expression.MinHost = 1
	expression.Value = float64(200)

	expression = checkRow.EvalRawHostDataExpression(hosts, expression)
	if expression.Result.Value != true {
		// The result should be true, 100 is less than 200, which means that this expression fails.
		t.Fatalf("Expression result should be true. %v %v %v", hostRow.DataAsFlatKeyValue()["/stuff"]["Score"], expression.Operator, expression.Value)
	}

	expression = CheckExpression{}
	expression.Metric = "/stuff.Score"
	expression.Operator = "<="
	expression.MinHost = 1
	expression.Value = float64(100)

	expression = checkRow.EvalRawHostDataExpression(hosts, expression)
	if expression.Result.Value != true {
		// The result should be true, 100 is less than or equal to 100, which means that this expression fails.
		t.Fatalf("Expression result should be true. %v %v %v", hostRow.DataAsFlatKeyValue()["/stuff"]["Score"], expression.Operator, expression.Value)
	}

	// ----------------------------------------------------------------------

	// DELETE FROM hosts WHERE id=...
	_, err = newHostForTest(t).DeleteByID(nil, hostRow.ID)
	if err != nil {
		t.Fatalf("Deleting access_tokens by id should not fail. Error: %v", err)
	}

	// DELETE FROM access_tokens WHERE id=...
	_, err = at.DeleteByID(nil, tokenRow.ID)
	if err != nil {
		t.Fatalf("Deleting access_tokens by id should not fail. Error: %v", err)
	}

	// DELETE FROM Checks WHERE id=...
	_, err = NewCheck(u.db).DeleteByID(nil, checkRow.ID)
	if err != nil {
		t.Fatalf("Deleting Checks by id should not fail. Error: %v", err)
	}

	// DELETE FROM users WHERE id=...
	_, err = u.DeleteByID(nil, userRow.ID)
	if err != nil {
		t.Fatalf("Deleting user by id should not fail. Error: %v", err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// package dashboard defines data structures used in dashboard communication
// and provides client interface.
package dashboard

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

type Dashboard struct {
	Addr   string
	Client string
	Key    string
}

type Crash struct {
	Tag    string
	Desc   string
	Log    []byte
	Report []byte
}

type Repro struct {
	Crash      Crash
	Reproduced bool
	Opts       string
	Prog       []byte
	CProg      []byte
}

type Patch struct {
	Title string
	Diff  []byte
}

func (dash *Dashboard) ReportCrash(crash *Crash) error {
	return dash.query("add_crash", crash, nil)
}

func (dash *Dashboard) ReportRepro(repro *Repro) error {
	return dash.query("add_repro", repro, nil)
}

func (dash *Dashboard) PollPatches() (string, error) {
	hash := ""
	err := dash.query("poll_patches", nil, &hash)
	return hash, err
}

func (dash *Dashboard) GetPatches() ([]Patch, error) {
	var patches []Patch
	err := dash.query("get_patches", nil, &patches)
	return patches, err
}

func (dash *Dashboard) query(method string, req, reply interface{}) error {
	values := make(url.Values)
	values.Add("client", dash.Client)
	values.Add("key", dash.Key)
	values.Add("method", method)
	var body io.Reader
	if req != nil {
		data, err := json.Marshal(req)
		if err != nil {
			return fmt.Errorf("failed to marshal request: %v", err)
		}
		body = bytes.NewReader(data)
	}
	resp, err := http.Post(fmt.Sprintf("%v/api?%v", dash.Addr, values.Encode()), "application/json", body)
	if err != nil {
		return fmt.Errorf("http request failed: %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		data, _ := ioutil.ReadAll(resp.Body)
		return fmt.Errorf("request failed with %v: %s", resp.Status, data)
	}
	if reply != nil {
		if err := json.NewDecoder(resp.Body).Decode(reply); err != nil {
			return fmt.Errorf("failed to unmarshal response: %v", err)
		}
	}
	return nil
}
<commit_msg>dashboard: add New function<commit_after>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// package dashboard defines data structures used in dashboard communication
// and provides client interface.
package dashboard

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

type Dashboard struct {
	Addr   string
	Client string
	Key    string
}

type Crash struct {
	Tag    string
	Desc   string
	Log    []byte
	Report []byte
}

type Repro struct {
	Crash      Crash
	Reproduced bool
	Opts       string
	Prog       []byte
	CProg      []byte
}

type Patch struct {
	Title string
	Diff  []byte
}

func New(client, addr, key string) (*Dashboard, error) {
	dash := &Dashboard{
		Client: client,
		Addr:   addr,
		Key:    key,
	}
	return dash, nil
}

func (dash *Dashboard) ReportCrash(crash *Crash) error {
	return dash.query("add_crash", crash, nil)
}

func (dash *Dashboard) ReportRepro(repro *Repro) error {
	return dash.query("add_repro", repro, nil)
}

func (dash *Dashboard) PollPatches() (string, error) {
	hash := ""
	err := dash.query("poll_patches", nil, &hash)
	return hash, err
}

func (dash *Dashboard) GetPatches() ([]Patch, error) {
	var patches []Patch
	err := dash.query("get_patches", nil, &patches)
	return patches, err
}

func (dash *Dashboard) query(method string, req, reply interface{}) error {
	values := make(url.Values)
	values.Add("client", dash.Client)
	values.Add("key", dash.Key)
	values.Add("method", method)
	var body io.Reader
	if req != nil {
		data, err := json.Marshal(req)
		if err != nil {
			return fmt.Errorf("failed to marshal request: %v", err)
		}
		body = bytes.NewReader(data)
	}
	resp, err := http.Post(fmt.Sprintf("%v/api?%v", dash.Addr, values.Encode()), "application/json", body)
	if err != nil {
		return fmt.Errorf("http request failed: %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		data, _ := ioutil.ReadAll(resp.Body)
		return fmt.Errorf("request failed with %v: %s", resp.Status, data)
	}
	if reply != nil {
		if err := json.NewDecoder(resp.Body).Decode(reply); err != nil {
			return fmt.Errorf("failed to unmarshal response: %v", err)
		}
	}
	return nil
}
<|endoftext|>


<commit_before><commit_msg>dwsdss<commit_after><|endoftext|>


<commit_before><commit_msg>removed test print statement<commit_after><|endoftext|>


<commit_before>package databoard

import (
	"context"
	"net/http"

	"golang.org/x/oauth2"

	"github.com/google/go-github/github"
)

type Databoard struct {
	c     *github.Client
	Owner string
	Repo  string
}

func New(hc *http.Client, token string) *Databoard {
	if hc == nil {
		hc = &http.Client{}
	}
	hc.Transport = &oauth2.Transport{
		Base: hc.Transport,
		Source: oauth2.ReuseTokenSource(nil, oauth2.StaticTokenSource(
			&oauth2.Token{AccessToken: token},
		)),
	}

	client := github.NewClient(hc)

	return &Databoard{
		c: client,
	}
}

func (d *Databoard) GetLatestRelease(ctx context.Context) (*github.RepositoryRelease, error) {
	ret, _, err := d.c.Repositories.GetLatestRelease(ctx, d.Owner, d.Repo)
	return ret, err
}
<commit_msg>add Databoard.GetReleases()<commit_after>package databoard

import (
	"context"
	"net/http"

	"golang.org/x/oauth2"

	"github.com/google/go-github/github"
)

type Databoard struct {
	c     *github.Client
	Owner string
	Repo  string
}

func New(hc *http.Client, token string) *Databoard {
	if hc == nil {
		hc = &http.Client{}
	}
	hc.Transport = &oauth2.Transport{
		Base: hc.Transport,
		Source: oauth2.ReuseTokenSource(nil, oauth2.StaticTokenSource(
			&oauth2.Token{AccessToken: token},
		)),
	}

	client := github.NewClient(hc)

	return &Databoard{
		c: client,
	}
}

func (d *Databoard) GetLatestRelease(ctx context.Context) (*github.RepositoryRelease, error) {
	ret, _, err := d.c.Repositories.GetLatestRelease(ctx, d.Owner, d.Repo)
	return ret, err
}

func (d *Databoard) GetReleases(ctx context.Context) (<-chan *github.RepositoryRelease, error) {
	ch := make(chan *github.RepositoryRelease)

	go func(ch chan<- *github.RepositoryRelease) {
		defer close(ch)
		listOptions := &github.ListOptions{
			Page:    1,
			PerPage: 1,
		}
		for {
			releases, resp, err := d.c.Repositories.ListReleases(ctx, d.Owner, d.Repo, listOptions)
			if err != nil {
				return
			}

			for _, rel := range releases {
				select {
				case <-ctx.Done():
					return
				case ch <- rel:
				}
			}

			if resp.NextPage == 0 {
				return
			}

			listOptions.Page = resp.NextPage
		}
	}(ch)
	return ch, nil
}
<|endoftext|>