<commit_before>package glutton

import (
	"bufio"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"math/rand"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/kung-foo/freki"
)

// Mirai botnet  - https://github.com/CymmetriaResearch/MTPot/blob/master/mirai_conf.json
// Hajime botnet - https://security.rapiditynetworks.com/publications/2016-10-16/hajime.pdf
var miraiCom = map[string][]string{
	"ps":                          []string{"1 pts/21   00:00:00 init"},
	"cat /proc/mounts":            []string{"rootfs / rootfs rw 0 0\r\n/dev/root / ext2 rw,relatime,errors=continue 0 0\r\nproc /proc proc rw,relatime 0 0\r\nsysfs /sys sysfs rw,relatime 0 0\r\nudev /dev tmpfs rw,relatime 0 0\r\ndevpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0\r\n/dev/mtdblock1 /home/hik jffs2 rw,relatime 0 0\r\ntmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0\r\n"},
	"(cat .s || cp /bin/echo .s)": []string{"cat: .s: No such file or directory"},
	"nc":   []string{"nc: command not found"},
	"wget": []string{"wget: missing URL"},
	"(dd bs=52 count=1 if=.s || cat .s)": []string{"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\xbc\x14\x01\x00\x34\x00\x00\x00"},
	"sh": []string{"$"},
	"echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon":              []string{""},
	"cat /dev/.nippon":                                             []string{"kami/dev"},
	"rm /dev/.nippon":                                              []string{""},
	"echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon":              []string{""},
	"cat /run/.nippon":                                             []string{"kami/run"},
	"rm /run/.nippon":                                              []string{""},
	"cat /bin/sh":                                                  []string{""},
	"/bin/busybox ps":                                              []string{"1 pts/21   00:00:00 init"},
	"/bin/busybox cat /proc/mounts":                                []string{"tmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0"},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon": []string{""},
	"/bin/busybox cat /dev/.nippon":                                []string{"kami/dev"},
	"/bin/busybox rm /dev/.nippon":                                 []string{""},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon": []string{""},
	"/bin/busybox cat /run/.nippon":                                []string{"kami/run"},
	"/bin/busybox rm /run/.nippon":                                 []string{""},
	"/bin/busybox cat /bin/sh":                                     []string{""},
	"/bin/busybox cat /bin/echo":                                   []string{"/bin/busybox cat /bin/echo\r\n\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\x6c\xb9\x00\x00\x34\x00\x00\x00"},
	"rm /dev/.human":                                               []string{"rm: can't remove '/.t': No such file or directory\r\nrm: can't remove '/.sh': No such file or directory\r\nrm: can't remove '/.human': No such file or directory\r\ncd /dev"},
}

func writeMsg(conn net.Conn, msg string, g *Glutton) error {
	_, err := conn.Write([]byte(msg))
	g.logger.Infof("[telnet  ] send: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "write")
	return err
}

func readMsg(conn net.Conn, g *Glutton) (msg string, err error) {
	msg, err = bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return "", err
	}
	g.logger.Infof("[telnet  ] recv: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "read")
	return msg, err
}

func getSample(cmd string, g *Glutton) error {
	parts := strings.Split(cmd, " ")
	if len(parts) < 2 {
		return nil
	}
	url := parts[1]
	timeout := time.Duration(5 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(url)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	defer resp.Body.Close()
	p := new([]byte)
	resp.Body.Read(*p)
	sum := sha256.Sum256(*p)
	// Ignoring errors for if the folder already exists
	os.MkdirAll("samples", os.ModePerm)
	sha256Hash := hex.EncodeToString(sum[:])
	path := filepath.Join("samples", sha256Hash)
	out, err := os.Create(path)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	g.logger.Infof("[telnet  ] getSample succcess: %s", path)
	return nil
}

// HandleTelnet handles telnet communication on a connection
func (g *Glutton) HandleTelnet(conn net.Conn) {
	defer conn.Close()

	// TODO (glaslos): Add device banner

	// telnet window size negotiation response
	writeMsg(conn, "\xff\xfd\x18\xff\xfd\x20\xff\xfd\x23\xff\xfd\x27", g)

	// User name prompt
	writeMsg(conn, "Username: ", g)
	_, err := readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}
	writeMsg(conn, "Password: ", g)
	_, err = readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}

	writeMsg(conn, "welcome\r\n> ", g)
	for {
		msg, err := readMsg(conn, g)
		if err != nil {
			g.logger.Errorf("[telnet  ] %v", err)
			return
		}
		for _, cmd := range strings.Split(msg, ";") {
			if strings.HasPrefix(strings.Trim(cmd, " "), "wget http") {
				go getSample(cmd, g)
			}
			if strings.TrimRight(cmd, "") == " rm /dev/.t" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == " rm /dev/.sh" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == "cd /dev/" {
				writeMsg(conn, "ECCHI: applet not found\r\n", g)
				writeMsg(conn, "\r\nBusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-it shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				continue
			}

			if resp := miraiCom[strings.TrimSpace(cmd)]; len(resp) > 0 {
				writeMsg(conn, resp[rand.Intn(len(resp))]+"\r\n", g)
			} else {
				// /bin/busybox YDKBI
				re := regexp.MustCompile(`\/bin\/busybox (?P<applet>[A-Z]+)`)
				match := re.FindStringSubmatch(cmd)
				if len(match) > 1 {
					writeMsg(conn, match[1]+": applet not found\r\n", g)
					writeMsg(conn, "BusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-in shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				}
			}
		}
		writeMsg(conn, "> ", g)
	}
}
<commit_msg>fixed param<commit_after>package glutton

import (
	"bufio"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"math/rand"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/kung-foo/freki"
)

// Mirai botnet  - https://github.com/CymmetriaResearch/MTPot/blob/master/mirai_conf.json
// Hajime botnet - https://security.rapiditynetworks.com/publications/2016-10-16/hajime.pdf
var miraiCom = map[string][]string{
	"ps":                          []string{"1 pts/21   00:00:00 init"},
	"cat /proc/mounts":            []string{"rootfs / rootfs rw 0 0\r\n/dev/root / ext2 rw,relatime,errors=continue 0 0\r\nproc /proc proc rw,relatime 0 0\r\nsysfs /sys sysfs rw,relatime 0 0\r\nudev /dev tmpfs rw,relatime 0 0\r\ndevpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0\r\n/dev/mtdblock1 /home/hik jffs2 rw,relatime 0 0\r\ntmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0\r\n"},
	"(cat .s || cp /bin/echo .s)": []string{"cat: .s: No such file or directory"},
	"nc":   []string{"nc: command not found"},
	"wget": []string{"wget: missing URL"},
	"(dd bs=52 count=1 if=.s || cat .s)": []string{"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\xbc\x14\x01\x00\x34\x00\x00\x00"},
	"sh": []string{"$"},
	"echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon":              []string{""},
	"cat /dev/.nippon":                                             []string{"kami/dev"},
	"rm /dev/.nippon":                                              []string{""},
	"echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon":              []string{""},
	"cat /run/.nippon":                                             []string{"kami/run"},
	"rm /run/.nippon":                                              []string{""},
	"cat /bin/sh":                                                  []string{""},
	"/bin/busybox ps":                                              []string{"1 pts/21   00:00:00 init"},
	"/bin/busybox cat /proc/mounts":                                []string{"tmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0"},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon": []string{""},
	"/bin/busybox cat /dev/.nippon":                                []string{"kami/dev"},
	"/bin/busybox rm /dev/.nippon":                                 []string{""},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon": []string{""},
	"/bin/busybox cat /run/.nippon":                                []string{"kami/run"},
	"/bin/busybox rm /run/.nippon":                                 []string{""},
	"/bin/busybox cat /bin/sh":                                     []string{""},
	"/bin/busybox cat /bin/echo":                                   []string{"/bin/busybox cat /bin/echo\r\n\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\x6c\xb9\x00\x00\x34\x00\x00\x00"},
	"rm /dev/.human":                                               []string{"rm: can't remove '/.t': No such file or directory\r\nrm: can't remove '/.sh': No such file or directory\r\nrm: can't remove '/.human': No such file or directory\r\ncd /dev"},
}

func writeMsg(conn net.Conn, msg string, g *Glutton) error {
	_, err := conn.Write([]byte(msg))
	g.logger.Infof("[telnet  ] send: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "write")
	return err
}

func readMsg(conn net.Conn, g *Glutton) (msg string, err error) {
	msg, err = bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return "", err
	}
	g.logger.Infof("[telnet  ] recv: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "read")
	return msg, err
}

func getSample(cmd string, g *Glutton) error {
	parts := strings.Split(cmd, " ")
	if len(parts) < 2 {
		return nil
	}
	url := parts[1]
	timeout := time.Duration(5 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(url)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	defer resp.Body.Close()
	p := new([]byte)
	resp.Body.Read(*p)
	sum := sha256.Sum256(*p)
	// Ignoring errors for if the folder already exists
	os.MkdirAll("samples", os.ModePerm)
	sha256Hash := hex.EncodeToString(sum[:])
	path := filepath.Join("samples", sha256Hash)
	out, err := os.Create(path)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	g.logger.Infof("[telnet  ] getSample succcess: %s", path)
	return nil
}

// HandleTelnet handles telnet communication on a connection
func (g *Glutton) HandleTelnet(conn net.Conn) {
	defer conn.Close()

	// TODO (glaslos): Add device banner

	// telnet window size negotiation response
	writeMsg(conn, "\xff\xfd\x18\xff\xfd\x20\xff\xfd\x23\xff\xfd\x27", g)

	// User name prompt
	writeMsg(conn, "Username: ", g)
	_, err := readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}
	writeMsg(conn, "Password: ", g)
	_, err = readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}

	writeMsg(conn, "welcome\r\n> ", g)
	for {
		msg, err := readMsg(conn, g)
		if err != nil {
			g.logger.Errorf("[telnet  ] %v", err)
			return
		}
		for _, cmd := range strings.Split(msg, ";") {
			if strings.HasPrefix(strings.Trim(cmd, " "), "wget http") {
				go getSample(strings.Trim(cmd, " "), g)
			}
			if strings.TrimRight(cmd, "") == " rm /dev/.t" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == " rm /dev/.sh" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == "cd /dev/" {
				writeMsg(conn, "ECCHI: applet not found\r\n", g)
				writeMsg(conn, "\r\nBusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-it shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				continue
			}

			if resp := miraiCom[strings.TrimSpace(cmd)]; len(resp) > 0 {
				writeMsg(conn, resp[rand.Intn(len(resp))]+"\r\n", g)
			} else {
				// /bin/busybox YDKBI
				re := regexp.MustCompile(`\/bin\/busybox (?P<applet>[A-Z]+)`)
				match := re.FindStringSubmatch(cmd)
				if len(match) > 1 {
					writeMsg(conn, match[1]+": applet not found\r\n", g)
					writeMsg(conn, "BusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-in shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				}
			}
		}
		writeMsg(conn, "> ", g)
	}
}
<|endoftext|>


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

// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05.
package ed25519

// This code is a port of the public domain, “ref10” implementation of ed25519
// from SUPERCOP.

import (
	"bytes"
	"crypto"
	cryptorand "crypto/rand"
	"crypto/sha512"
	"errors"
	"io"
	"strconv"

	"golang.org/x/crypto/ed25519/internal/edwards25519"
)

const (
	// PublicKeySize is the size, in bytes, of public keys as used in this package.
	PublicKeySize = 32
	// PrivateKeySize is the size, in bytes, of private keys as used in this package.
	PrivateKeySize = 64
	// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
	SignatureSize = 64
)

// PublicKey is the type of Ed25519 public keys.
type PublicKey []byte

// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
type PrivateKey []byte

// Public returns the PublicKey corresponding to priv.
func (priv PrivateKey) Public() crypto.PublicKey {
	publicKey := make([]byte, PublicKeySize)
	copy(publicKey, priv[32:])
	return PublicKey(publicKey)
}

// Sign signs the given message with priv.
// Ed25519 performs two passes over messages to be signed and therefore cannot
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
// indicate the message hasn't been hashed. This can be achieved by passing
// crypto.Hash(0) as the value for opts.
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
	if opts.HashFunc() != crypto.Hash(0) {
		return nil, errors.New("ed25519: cannot sign hashed message")
	}

	return Sign(priv, message), nil
}

// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
	if rand == nil {
		rand = cryptorand.Reader
	}

	privateKey = make([]byte, PrivateKeySize)
	publicKey = make([]byte, PublicKeySize)
	_, err = io.ReadFull(rand, privateKey[:32])
	if err != nil {
		return nil, nil, err
	}

	digest := sha512.Sum512(privateKey[:32])
	digest[0] &= 248
	digest[31] &= 127
	digest[31] |= 64

	var A edwards25519.ExtendedGroupElement
	var hBytes [32]byte
	copy(hBytes[:], digest[:])
	edwards25519.GeScalarMultBase(&A, &hBytes)
	var publicKeyBytes [32]byte
	A.ToBytes(&publicKeyBytes)

	copy(privateKey[32:], publicKeyBytes[:])
	copy(publicKey, publicKeyBytes[:])

	return publicKey, privateKey, nil
}

// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
	if l := len(privateKey); l != PrivateKeySize {
		panic("ed25519: bad private key length: " + strconv.Itoa(l))
	}

	h := sha512.New()
	h.Write(privateKey[:32])

	var digest1, messageDigest, hramDigest [64]byte
	var expandedSecretKey [32]byte
	h.Sum(digest1[:0])
	copy(expandedSecretKey[:], digest1[:])
	expandedSecretKey[0] &= 248
	expandedSecretKey[31] &= 63
	expandedSecretKey[31] |= 64

	h.Reset()
	h.Write(digest1[32:])
	h.Write(message)
	h.Sum(messageDigest[:0])

	var messageDigestReduced [32]byte
	edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
	var R edwards25519.ExtendedGroupElement
	edwards25519.GeScalarMultBase(&R, &messageDigestReduced)

	var encodedR [32]byte
	R.ToBytes(&encodedR)

	h.Reset()
	h.Write(encodedR[:])
	h.Write(privateKey[32:])
	h.Write(message)
	h.Sum(hramDigest[:0])
	var hramDigestReduced [32]byte
	edwards25519.ScReduce(&hramDigestReduced, &hramDigest)

	var s [32]byte
	edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)

	signature := make([]byte, SignatureSize)
	copy(signature[:], encodedR[:])
	copy(signature[32:], s[:])

	return signature
}

// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
	if l := len(publicKey); l != PublicKeySize {
		panic("ed25519: bad public key length: " + strconv.Itoa(l))
	}

	if len(sig) != SignatureSize || sig[63]&224 != 0 {
		return false
	}

	var A edwards25519.ExtendedGroupElement
	var publicKeyBytes [32]byte
	copy(publicKeyBytes[:], publicKey)
	if !A.FromBytes(&publicKeyBytes) {
		return false
	}
	edwards25519.FeNeg(&A.X, &A.X)
	edwards25519.FeNeg(&A.T, &A.T)

	h := sha512.New()
	h.Write(sig[:32])
	h.Write(publicKey[:])
	h.Write(message)
	var digest [64]byte
	h.Sum(digest[:0])

	var hReduced [32]byte
	edwards25519.ScReduce(&hReduced, &digest)

	var R edwards25519.ProjectiveGroupElement
	var b [32]byte
	copy(b[:], sig[32:])
	edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)

	var checkR [32]byte
	R.ToBytes(&checkR)
	return bytes.Equal(sig[:32], checkR[:])
}
<commit_msg>ed25519: update document to mention RFC 8032<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032.
package ed25519

// This code is a port of the public domain, “ref10” implementation of ed25519
// from SUPERCOP.

import (
	"bytes"
	"crypto"
	cryptorand "crypto/rand"
	"crypto/sha512"
	"errors"
	"io"
	"strconv"

	"golang.org/x/crypto/ed25519/internal/edwards25519"
)

const (
	// PublicKeySize is the size, in bytes, of public keys as used in this package.
	PublicKeySize = 32
	// PrivateKeySize is the size, in bytes, of private keys as used in this package.
	PrivateKeySize = 64
	// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
	SignatureSize = 64
)

// PublicKey is the type of Ed25519 public keys.
type PublicKey []byte

// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
type PrivateKey []byte

// Public returns the PublicKey corresponding to priv.
func (priv PrivateKey) Public() crypto.PublicKey {
	publicKey := make([]byte, PublicKeySize)
	copy(publicKey, priv[32:])
	return PublicKey(publicKey)
}

// Sign signs the given message with priv.
// Ed25519 performs two passes over messages to be signed and therefore cannot
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
// indicate the message hasn't been hashed. This can be achieved by passing
// crypto.Hash(0) as the value for opts.
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
	if opts.HashFunc() != crypto.Hash(0) {
		return nil, errors.New("ed25519: cannot sign hashed message")
	}

	return Sign(priv, message), nil
}

// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
	if rand == nil {
		rand = cryptorand.Reader
	}

	privateKey = make([]byte, PrivateKeySize)
	publicKey = make([]byte, PublicKeySize)
	_, err = io.ReadFull(rand, privateKey[:32])
	if err != nil {
		return nil, nil, err
	}

	digest := sha512.Sum512(privateKey[:32])
	digest[0] &= 248
	digest[31] &= 127
	digest[31] |= 64

	var A edwards25519.ExtendedGroupElement
	var hBytes [32]byte
	copy(hBytes[:], digest[:])
	edwards25519.GeScalarMultBase(&A, &hBytes)
	var publicKeyBytes [32]byte
	A.ToBytes(&publicKeyBytes)

	copy(privateKey[32:], publicKeyBytes[:])
	copy(publicKey, publicKeyBytes[:])

	return publicKey, privateKey, nil
}

// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
	if l := len(privateKey); l != PrivateKeySize {
		panic("ed25519: bad private key length: " + strconv.Itoa(l))
	}

	h := sha512.New()
	h.Write(privateKey[:32])

	var digest1, messageDigest, hramDigest [64]byte
	var expandedSecretKey [32]byte
	h.Sum(digest1[:0])
	copy(expandedSecretKey[:], digest1[:])
	expandedSecretKey[0] &= 248
	expandedSecretKey[31] &= 63
	expandedSecretKey[31] |= 64

	h.Reset()
	h.Write(digest1[32:])
	h.Write(message)
	h.Sum(messageDigest[:0])

	var messageDigestReduced [32]byte
	edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
	var R edwards25519.ExtendedGroupElement
	edwards25519.GeScalarMultBase(&R, &messageDigestReduced)

	var encodedR [32]byte
	R.ToBytes(&encodedR)

	h.Reset()
	h.Write(encodedR[:])
	h.Write(privateKey[32:])
	h.Write(message)
	h.Sum(hramDigest[:0])
	var hramDigestReduced [32]byte
	edwards25519.ScReduce(&hramDigestReduced, &hramDigest)

	var s [32]byte
	edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)

	signature := make([]byte, SignatureSize)
	copy(signature[:], encodedR[:])
	copy(signature[32:], s[:])

	return signature
}

// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
	if l := len(publicKey); l != PublicKeySize {
		panic("ed25519: bad public key length: " + strconv.Itoa(l))
	}

	if len(sig) != SignatureSize || sig[63]&224 != 0 {
		return false
	}

	var A edwards25519.ExtendedGroupElement
	var publicKeyBytes [32]byte
	copy(publicKeyBytes[:], publicKey)
	if !A.FromBytes(&publicKeyBytes) {
		return false
	}
	edwards25519.FeNeg(&A.X, &A.X)
	edwards25519.FeNeg(&A.T, &A.T)

	h := sha512.New()
	h.Write(sig[:32])
	h.Write(publicKey[:])
	h.Write(message)
	var digest [64]byte
	h.Sum(digest[:0])

	var hReduced [32]byte
	edwards25519.ScReduce(&hReduced, &digest)

	var R edwards25519.ProjectiveGroupElement
	var b [32]byte
	copy(b[:], sig[32:])
	edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)

	var checkR [32]byte
	R.ToBytes(&checkR)
	return bytes.Equal(sig[:32], checkR[:])
}
<|endoftext|>


<commit_before>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package execution

import (
	"errors"
	"fmt"
	"strings"

	"github.com/getgauge/gauge/execution/event"
	"github.com/getgauge/gauge/execution/result"
	"github.com/getgauge/gauge/gauge"
	"github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/logger"
	"github.com/getgauge/gauge/parser"
	"github.com/getgauge/gauge/plugin"
	"github.com/getgauge/gauge/runner"
	"github.com/getgauge/gauge/validation"
	"github.com/golang/protobuf/proto"
)

type specExecutor struct {
	specification        *gauge.Specification
	dataTableIndex       indexRange
	runner               runner.Runner
	pluginHandler        *plugin.Handler
	currentExecutionInfo *gauge_messages.ExecutionInfo
	specResult           *result.SpecResult
	currentTableRow      int
	errMap               *validation.ValidationErrMaps
	stream               int
}

type indexRange struct {
	start int
	end   int
}

func newSpecExecutor(s *gauge.Specification, r runner.Runner, ph *plugin.Handler, tr indexRange, e *validation.ValidationErrMaps, stream int) *specExecutor {
	return &specExecutor{specification: s, runner: r, pluginHandler: ph, dataTableIndex: tr, errMap: e, stream: stream}
}

func (e *specExecutor) execute() *result.SpecResult {
	specInfo := &gauge_messages.SpecInfo{Name: proto.String(e.specification.Heading.Value),
		FileName: proto.String(e.specification.FileName),
		IsFailed: proto.Bool(false), Tags: getTagValue(e.specification.Tags)}
	e.currentExecutionInfo = &gauge_messages.ExecutionInfo{CurrentSpec: specInfo}
	e.specResult = gauge.NewSpecResult(e.specification)

	resolvedSpecItems := e.resolveItems(e.specification.GetSpecItems())
	e.specResult.AddSpecItems(resolvedSpecItems)
	if _, ok := e.errMap.SpecErrs[e.specification]; ok {
		e.skipSpec()
		return e.specResult
	}

	if e.dataTableIndex.start < 0 {
		e.skipSpecForError(fmt.Errorf("Data Table doesn't match the given range in spec: %s\n", e.specification.FileName))
		return e.specResult
	}

	if len(e.specification.Scenarios) == 0 {
		e.skipSpecForError(fmt.Errorf("%s: No scenarios found in spec\n", e.specification.FileName))
		return e.specResult
	}

	event.Notify(event.NewExecutionEvent(event.SpecStart, e.specification, nil, e.stream, *e.currentExecutionInfo))
	defer event.Notify(event.NewExecutionEvent(event.SpecEnd, nil, e.specResult, e.stream, *e.currentExecutionInfo))

	res := e.initSpecDataStore()
	if res.GetFailed() {
		e.skipSpecForError(fmt.Errorf("Failed to initialize spec datastore. Error: %s", res.GetErrorMessage()))
		return e.specResult
	}

	e.notifyBeforeSpecHook()
	if !e.specResult.GetFailed() {
		if e.specification.DataTable.Table.GetRowCount() == 0 {
			scenarioResults := e.executeScenarios()
			e.specResult.AddScenarioResults(scenarioResults)
		} else {
			e.executeTableDrivenSpec()
		}
	}
	e.notifyAfterSpecHook()

	e.specResult.SetSkipped(e.specResult.ScenarioSkippedCount == len(e.specification.Scenarios))
	return e.specResult
}

func (e *specExecutor) executeTableDrivenSpec() {
	var res [][]result.Result
	for e.currentTableRow = e.dataTableIndex.start; e.currentTableRow <= e.dataTableIndex.end; e.currentTableRow++ {
		res = append(res, e.executeScenarios())
	}
	e.specResult.AddTableDrivenScenarioResult(res)
}

func (e *specExecutor) resolveItems(items []gauge.Item) []*gauge_messages.ProtoItem {
	var protoItems []*gauge_messages.ProtoItem
	for _, item := range items {
		if item.Kind() != gauge.TearDownKind {
			protoItems = append(protoItems, e.resolveToProtoItem(item))
		}
	}
	return protoItems
}

func (e *specExecutor) resolveToProtoItem(item gauge.Item) *gauge_messages.ProtoItem {
	var protoItem *gauge_messages.ProtoItem
	switch item.Kind() {
	case gauge.StepKind:
		if (item.(*gauge.Step)).IsConcept {
			concept := item.(*gauge.Step)
			protoItem = e.resolveToProtoConceptItem(*concept)
		} else {
			protoItem = e.resolveToProtoStepItem(item.(*gauge.Step))
		}
		break

	default:
		protoItem = gauge.ConvertToProtoItem(item)
	}
	return protoItem
}

// Not passing pointer as we cannot modify the original concept step's lookup. This has to be populated for each iteration over data table.
func (e *specExecutor) resolveToProtoConceptItem(concept gauge.Step) *gauge_messages.ProtoItem {
	paramResolver := new(parser.ParamResolver)

	parser.PopulateConceptDynamicParams(&concept, e.dataTableLookup())
	protoConceptItem := gauge.ConvertToProtoItem(&concept)
	protoConceptItem.Concept.ConceptStep.StepExecutionResult = &gauge_messages.ProtoStepExecutionResult{}
	for stepIndex, step := range concept.ConceptSteps {
		// Need to reset parent as the step.parent is pointing to a concept whose lookup is not populated yet
		if step.IsConcept {
			step.Parent = &concept
			protoConceptItem.GetConcept().GetSteps()[stepIndex] = e.resolveToProtoConceptItem(*step)
		} else {
			stepParameters := paramResolver.GetResolvedParams(step, &concept, e.dataTableLookup())
			updateProtoStepParameters(protoConceptItem.Concept.Steps[stepIndex].Step, stepParameters)
			e.setSkipInfo(protoConceptItem.Concept.Steps[stepIndex].Step, step)
		}
	}
	protoConceptItem.Concept.ConceptStep.StepExecutionResult.Skipped = proto.Bool(false)
	return protoConceptItem
}

func (e *specExecutor) resolveToProtoStepItem(step *gauge.Step) *gauge_messages.ProtoItem {
	protoStepItem := gauge.ConvertToProtoItem(step)
	paramResolver := new(parser.ParamResolver)
	parameters := paramResolver.GetResolvedParams(step, nil, e.dataTableLookup())
	updateProtoStepParameters(protoStepItem.Step, parameters)
	e.setSkipInfo(protoStepItem.Step, step)
	return protoStepItem
}

func (e *specExecutor) initSpecDataStore() *gauge_messages.ProtoExecutionResult {
	initSpecDataStoreMessage := &gauge_messages.Message{MessageType: gauge_messages.Message_SpecDataStoreInit.Enum(),
		SpecDataStoreInitRequest: &gauge_messages.SpecDataStoreInitRequest{}}
	return e.runner.ExecuteAndGetStatus(initSpecDataStoreMessage)
}

func (e *specExecutor) notifyBeforeSpecHook() {
	m := &gauge_messages.Message{MessageType: gauge_messages.Message_SpecExecutionStarting.Enum(),
		SpecExecutionStartingRequest: &gauge_messages.SpecExecutionStartingRequest{CurrentExecutionInfo: e.currentExecutionInfo}}
	res := executeHook(m, e.specResult, e.runner, e.pluginHandler)
	if res.GetFailed() {
		setSpecFailure(e.currentExecutionInfo)
		handleHookFailure(e.specResult, res, result.AddPreHook)
	}
}

func (e *specExecutor) notifyAfterSpecHook() {
	m := &gauge_messages.Message{MessageType: gauge_messages.Message_SpecExecutionEnding.Enum(),
		SpecExecutionEndingRequest: &gauge_messages.SpecExecutionEndingRequest{CurrentExecutionInfo: e.currentExecutionInfo}}
	res := executeHook(m, e.specResult, e.runner, e.pluginHandler)
	if res.GetFailed() {
		setSpecFailure(e.currentExecutionInfo)
		handleHookFailure(e.specResult, res, result.AddPostHook)
	}
}

func executeHook(message *gauge_messages.Message, execTimeTracker result.ExecTimeTracker, r runner.Runner, ph *plugin.Handler) *gauge_messages.ProtoExecutionResult {
	ph.NotifyPlugins(message)
	executionResult := r.ExecuteAndGetStatus(message)
	execTimeTracker.AddExecTime(executionResult.GetExecutionTime())
	return executionResult
}

func (e *specExecutor) skipSpecForError(err error) {
	logger.Errorf(err.Error())
	validationError := validation.NewValidationError(&gauge.Step{LineNo: e.specification.Heading.LineNo, LineText: e.specification.Heading.Value},
		err.Error(), e.specification.FileName, nil)
	for _, scenario := range e.specification.Scenarios {
		e.errMap.ScenarioErrs[scenario] = []*validation.StepValidationError{validationError}
	}
	e.errMap.SpecErrs[e.specification] = []*validation.StepValidationError{validationError}
	e.skipSpec()
}

func (e *specExecutor) skipSpec() {
	var scenarioResults []result.Result
	for _, scenario := range e.specification.Scenarios {
		scenarioResults = append(scenarioResults, e.getSkippedScenarioResult(scenario))
	}
	e.specResult.AddScenarioResults(scenarioResults)
	e.specResult.Skipped = true
}

func (e *specExecutor) setSkipInfo(protoStep *gauge_messages.ProtoStep, step *gauge.Step) {
	protoStep.StepExecutionResult = &gauge_messages.ProtoStepExecutionResult{}
	protoStep.StepExecutionResult.Skipped = proto.Bool(false)
	if _, ok := e.errMap.StepErrs[step]; ok {
		protoStep.StepExecutionResult.Skipped = proto.Bool(true)
		protoStep.StepExecutionResult.SkippedReason = proto.String("Step implemenatation not found")
	}
}

func (e *specExecutor) getItemsForScenarioExecution(steps []*gauge.Step) []*gauge_messages.ProtoItem {
	items := make([]gauge.Item, len(steps))
	for i, context := range steps {
		items[i] = context
	}
	return e.resolveItems(items)
}

func (e *specExecutor) dataTableLookup() *gauge.ArgLookup {
	return new(gauge.ArgLookup).FromDataTableRow(&e.specification.DataTable.Table, e.currentTableRow)
}

func (e *specExecutor) getCurrentDataTableValueFor(columnName string) string {
	return e.specification.DataTable.Table.Get(columnName)[e.currentTableRow].Value
}

func (e *specExecutor) executeScenarios() []result.Result {
	var scenarioResults []result.Result
	for _, scenario := range e.specification.Scenarios {
		scenarioResults = append(scenarioResults, e.executeScenario(scenario))
	}
	return scenarioResults
}

func (e *specExecutor) executeScenario(scenario *gauge.Scenario) *result.ScenarioResult {
	e.currentExecutionInfo.CurrentScenario = &gauge_messages.ScenarioInfo{
		Name:     proto.String(scenario.Heading.Value),
		Tags:     getTagValue(scenario.Tags),
		IsFailed: proto.Bool(false),
	}

	scenarioResult := result.NewScenarioResult(gauge.NewProtoScenario(scenario))

	// TODO: During data driven execution, scenario holds the last row of datatable in scenario.DataTableRow.
	// This can be eliminated by creating a new scenario instance for each of the table row execution.
	if e.specification.DataTable.Table.GetRowCount() != 0 {
		var dataTable gauge.Table
		dataTable.AddHeaders(e.specification.DataTable.Table.Headers)
		dataTable.AddRowValues(e.specification.DataTable.Table.Rows()[e.currentTableRow])
		scenario.DataTableRow = dataTable
		scenario.DataTableRowIndex = e.currentTableRow
	}

	e.addAllItemsForScenarioExecution(scenario, scenarioResult)

	scenarioExec := newScenarioExecutor(e.runner, e.pluginHandler, e.currentExecutionInfo, e.errMap, e.stream)
	scenarioExec.execute(scenarioResult, scenario, e.specification.Contexts, e.specification.TearDownSteps)
	if scenarioResult.ProtoScenario.GetSkipped() {
		e.specResult.ScenarioSkippedCount++
	}
	return scenarioResult
}

func (e *specExecutor) addAllItemsForScenarioExecution(scenario *gauge.Scenario, scenarioResult *result.ScenarioResult) {
	scenarioResult.AddContexts(e.getItemsForScenarioExecution(e.specification.Contexts))
	scenarioResult.AddTearDownSteps(e.getItemsForScenarioExecution(e.specification.TearDownSteps))
	scenarioResult.AddItems(e.resolveItems(scenario.Items))
}

func (e *specExecutor) getSkippedScenarioResult(scenario *gauge.Scenario) *result.ScenarioResult {
	scenarioResult := &result.ScenarioResult{ProtoScenario: gauge.NewProtoScenario(scenario)}
	e.addAllItemsForScenarioExecution(scenario, scenarioResult)
	setSkipInfoInResult(scenarioResult, scenario, e.errMap)
	e.specResult.ScenarioSkippedCount++
	return scenarioResult
}

func updateProtoStepParameters(protoStep *gauge_messages.ProtoStep, parameters []*gauge_messages.Parameter) {
	paramIndex := 0
	for fragmentIndex, fragment := range protoStep.Fragments {
		if fragment.GetFragmentType() == gauge_messages.Fragment_Parameter {
			protoStep.Fragments[fragmentIndex].Parameter = parameters[paramIndex]
			paramIndex++
		}
	}
}

func getTagValue(tags *gauge.Tags) []string {
	var tagValues []string
	if tags != nil {
		tagValues = append(tagValues, tags.Values...)
	}
	return tagValues
}

func setSpecFailure(executionInfo *gauge_messages.ExecutionInfo) {
	executionInfo.CurrentSpec.IsFailed = proto.Bool(true)
}

func getDataTableRowsRange(tableRows string, rowCount int) (indexRange, error) {
	var startIndex, endIndex int
	var err error
	indexRanges := strings.Split(tableRows, "-")
	if len(indexRanges) == 2 {
		startIndex, endIndex, err = validation.ValidateTableRowsRange(indexRanges[0], indexRanges[1], rowCount)
	} else if len(indexRanges) == 1 {
		startIndex, endIndex, err = validation.ValidateTableRowsRange(tableRows, tableRows, rowCount)
	} else {
		return indexRange{start: 0, end: 0}, errors.New("Table rows range validation failed.")
	}
	if err != nil {
		return indexRange{start: 0, end: 0}, err
	}
	return indexRange{start: startIndex, end: endIndex}, nil
}
<commit_msg>Fixing typo in messaging | fixes #517<commit_after>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package execution

import (
	"errors"
	"fmt"
	"strings"

	"github.com/getgauge/gauge/execution/event"
	"github.com/getgauge/gauge/execution/result"
	"github.com/getgauge/gauge/gauge"
	"github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/logger"
	"github.com/getgauge/gauge/parser"
	"github.com/getgauge/gauge/plugin"
	"github.com/getgauge/gauge/runner"
	"github.com/getgauge/gauge/validation"
	"github.com/golang/protobuf/proto"
)

type specExecutor struct {
	specification        *gauge.Specification
	dataTableIndex       indexRange
	runner               runner.Runner
	pluginHandler        *plugin.Handler
	currentExecutionInfo *gauge_messages.ExecutionInfo
	specResult           *result.SpecResult
	currentTableRow      int
	errMap               *validation.ValidationErrMaps
	stream               int
}

type indexRange struct {
	start int
	end   int
}

func newSpecExecutor(s *gauge.Specification, r runner.Runner, ph *plugin.Handler, tr indexRange, e *validation.ValidationErrMaps, stream int) *specExecutor {
	return &specExecutor{specification: s, runner: r, pluginHandler: ph, dataTableIndex: tr, errMap: e, stream: stream}
}

func (e *specExecutor) execute() *result.SpecResult {
	specInfo := &gauge_messages.SpecInfo{Name: proto.String(e.specification.Heading.Value),
		FileName: proto.String(e.specification.FileName),
		IsFailed: proto.Bool(false), Tags: getTagValue(e.specification.Tags)}
	e.currentExecutionInfo = &gauge_messages.ExecutionInfo{CurrentSpec: specInfo}
	e.specResult = gauge.NewSpecResult(e.specification)

	resolvedSpecItems := e.resolveItems(e.specification.GetSpecItems())
	e.specResult.AddSpecItems(resolvedSpecItems)
	if _, ok := e.errMap.SpecErrs[e.specification]; ok {
		e.skipSpec()
		return e.specResult
	}

	if e.dataTableIndex.start < 0 {
		e.skipSpecForError(fmt.Errorf("Data Table doesn't match the given range in spec: %s\n", e.specification.FileName))
		return e.specResult
	}

	if len(e.specification.Scenarios) == 0 {
		e.skipSpecForError(fmt.Errorf("%s: No scenarios found in spec\n", e.specification.FileName))
		return e.specResult
	}

	event.Notify(event.NewExecutionEvent(event.SpecStart, e.specification, nil, e.stream, *e.currentExecutionInfo))
	defer event.Notify(event.NewExecutionEvent(event.SpecEnd, nil, e.specResult, e.stream, *e.currentExecutionInfo))

	res := e.initSpecDataStore()
	if res.GetFailed() {
		e.skipSpecForError(fmt.Errorf("Failed to initialize spec datastore. Error: %s", res.GetErrorMessage()))
		return e.specResult
	}

	e.notifyBeforeSpecHook()
	if !e.specResult.GetFailed() {
		if e.specification.DataTable.Table.GetRowCount() == 0 {
			scenarioResults := e.executeScenarios()
			e.specResult.AddScenarioResults(scenarioResults)
		} else {
			e.executeTableDrivenSpec()
		}
	}
	e.notifyAfterSpecHook()

	e.specResult.SetSkipped(e.specResult.ScenarioSkippedCount == len(e.specification.Scenarios))
	return e.specResult
}

func (e *specExecutor) executeTableDrivenSpec() {
	var res [][]result.Result
	for e.currentTableRow = e.dataTableIndex.start; e.currentTableRow <= e.dataTableIndex.end; e.currentTableRow++ {
		res = append(res, e.executeScenarios())
	}
	e.specResult.AddTableDrivenScenarioResult(res)
}

func (e *specExecutor) resolveItems(items []gauge.Item) []*gauge_messages.ProtoItem {
	var protoItems []*gauge_messages.ProtoItem
	for _, item := range items {
		if item.Kind() != gauge.TearDownKind {
			protoItems = append(protoItems, e.resolveToProtoItem(item))
		}
	}
	return protoItems
}

func (e *specExecutor) resolveToProtoItem(item gauge.Item) *gauge_messages.ProtoItem {
	var protoItem *gauge_messages.ProtoItem
	switch item.Kind() {
	case gauge.StepKind:
		if (item.(*gauge.Step)).IsConcept {
			concept := item.(*gauge.Step)
			protoItem = e.resolveToProtoConceptItem(*concept)
		} else {
			protoItem = e.resolveToProtoStepItem(item.(*gauge.Step))
		}
		break

	default:
		protoItem = gauge.ConvertToProtoItem(item)
	}
	return protoItem
}

// Not passing pointer as we cannot modify the original concept step's lookup. This has to be populated for each iteration over data table.
func (e *specExecutor) resolveToProtoConceptItem(concept gauge.Step) *gauge_messages.ProtoItem {
	paramResolver := new(parser.ParamResolver)

	parser.PopulateConceptDynamicParams(&concept, e.dataTableLookup())
	protoConceptItem := gauge.ConvertToProtoItem(&concept)
	protoConceptItem.Concept.ConceptStep.StepExecutionResult = &gauge_messages.ProtoStepExecutionResult{}
	for stepIndex, step := range concept.ConceptSteps {
		// Need to reset parent as the step.parent is pointing to a concept whose lookup is not populated yet
		if step.IsConcept {
			step.Parent = &concept
			protoConceptItem.GetConcept().GetSteps()[stepIndex] = e.resolveToProtoConceptItem(*step)
		} else {
			stepParameters := paramResolver.GetResolvedParams(step, &concept, e.dataTableLookup())
			updateProtoStepParameters(protoConceptItem.Concept.Steps[stepIndex].Step, stepParameters)
			e.setSkipInfo(protoConceptItem.Concept.Steps[stepIndex].Step, step)
		}
	}
	protoConceptItem.Concept.ConceptStep.StepExecutionResult.Skipped = proto.Bool(false)
	return protoConceptItem
}

func (e *specExecutor) resolveToProtoStepItem(step *gauge.Step) *gauge_messages.ProtoItem {
	protoStepItem := gauge.ConvertToProtoItem(step)
	paramResolver := new(parser.ParamResolver)
	parameters := paramResolver.GetResolvedParams(step, nil, e.dataTableLookup())
	updateProtoStepParameters(protoStepItem.Step, parameters)
	e.setSkipInfo(protoStepItem.Step, step)
	return protoStepItem
}

func (e *specExecutor) initSpecDataStore() *gauge_messages.ProtoExecutionResult {
	initSpecDataStoreMessage := &gauge_messages.Message{MessageType: gauge_messages.Message_SpecDataStoreInit.Enum(),
		SpecDataStoreInitRequest: &gauge_messages.SpecDataStoreInitRequest{}}
	return e.runner.ExecuteAndGetStatus(initSpecDataStoreMessage)
}

func (e *specExecutor) notifyBeforeSpecHook() {
	m := &gauge_messages.Message{MessageType: gauge_messages.Message_SpecExecutionStarting.Enum(),
		SpecExecutionStartingRequest: &gauge_messages.SpecExecutionStartingRequest{CurrentExecutionInfo: e.currentExecutionInfo}}
	res := executeHook(m, e.specResult, e.runner, e.pluginHandler)
	if res.GetFailed() {
		setSpecFailure(e.currentExecutionInfo)
		handleHookFailure(e.specResult, res, result.AddPreHook)
	}
}

func (e *specExecutor) notifyAfterSpecHook() {
	m := &gauge_messages.Message{MessageType: gauge_messages.Message_SpecExecutionEnding.Enum(),
		SpecExecutionEndingRequest: &gauge_messages.SpecExecutionEndingRequest{CurrentExecutionInfo: e.currentExecutionInfo}}
	res := executeHook(m, e.specResult, e.runner, e.pluginHandler)
	if res.GetFailed() {
		setSpecFailure(e.currentExecutionInfo)
		handleHookFailure(e.specResult, res, result.AddPostHook)
	}
}

func executeHook(message *gauge_messages.Message, execTimeTracker result.ExecTimeTracker, r runner.Runner, ph *plugin.Handler) *gauge_messages.ProtoExecutionResult {
	ph.NotifyPlugins(message)
	executionResult := r.ExecuteAndGetStatus(message)
	execTimeTracker.AddExecTime(executionResult.GetExecutionTime())
	return executionResult
}

func (e *specExecutor) skipSpecForError(err error) {
	logger.Errorf(err.Error())
	validationError := validation.NewValidationError(&gauge.Step{LineNo: e.specification.Heading.LineNo, LineText: e.specification.Heading.Value},
		err.Error(), e.specification.FileName, nil)
	for _, scenario := range e.specification.Scenarios {
		e.errMap.ScenarioErrs[scenario] = []*validation.StepValidationError{validationError}
	}
	e.errMap.SpecErrs[e.specification] = []*validation.StepValidationError{validationError}
	e.skipSpec()
}

func (e *specExecutor) skipSpec() {
	var scenarioResults []result.Result
	for _, scenario := range e.specification.Scenarios {
		scenarioResults = append(scenarioResults, e.getSkippedScenarioResult(scenario))
	}
	e.specResult.AddScenarioResults(scenarioResults)
	e.specResult.Skipped = true
}

func (e *specExecutor) setSkipInfo(protoStep *gauge_messages.ProtoStep, step *gauge.Step) {
	protoStep.StepExecutionResult = &gauge_messages.ProtoStepExecutionResult{}
	protoStep.StepExecutionResult.Skipped = proto.Bool(false)
	if _, ok := e.errMap.StepErrs[step]; ok {
		protoStep.StepExecutionResult.Skipped = proto.Bool(true)
		protoStep.StepExecutionResult.SkippedReason = proto.String("Step implementation not found")
	}
}

func (e *specExecutor) getItemsForScenarioExecution(steps []*gauge.Step) []*gauge_messages.ProtoItem {
	items := make([]gauge.Item, len(steps))
	for i, context := range steps {
		items[i] = context
	}
	return e.resolveItems(items)
}

func (e *specExecutor) dataTableLookup() *gauge.ArgLookup {
	return new(gauge.ArgLookup).FromDataTableRow(&e.specification.DataTable.Table, e.currentTableRow)
}

func (e *specExecutor) getCurrentDataTableValueFor(columnName string) string {
	return e.specification.DataTable.Table.Get(columnName)[e.currentTableRow].Value
}

func (e *specExecutor) executeScenarios() []result.Result {
	var scenarioResults []result.Result
	for _, scenario := range e.specification.Scenarios {
		scenarioResults = append(scenarioResults, e.executeScenario(scenario))
	}
	return scenarioResults
}

func (e *specExecutor) executeScenario(scenario *gauge.Scenario) *result.ScenarioResult {
	e.currentExecutionInfo.CurrentScenario = &gauge_messages.ScenarioInfo{
		Name:     proto.String(scenario.Heading.Value),
		Tags:     getTagValue(scenario.Tags),
		IsFailed: proto.Bool(false),
	}

	scenarioResult := result.NewScenarioResult(gauge.NewProtoScenario(scenario))

	// TODO: During data driven execution, scenario holds the last row of datatable in scenario.DataTableRow.
	// This can be eliminated by creating a new scenario instance for each of the table row execution.
	if e.specification.DataTable.Table.GetRowCount() != 0 {
		var dataTable gauge.Table
		dataTable.AddHeaders(e.specification.DataTable.Table.Headers)
		dataTable.AddRowValues(e.specification.DataTable.Table.Rows()[e.currentTableRow])
		scenario.DataTableRow = dataTable
		scenario.DataTableRowIndex = e.currentTableRow
	}

	e.addAllItemsForScenarioExecution(scenario, scenarioResult)

	scenarioExec := newScenarioExecutor(e.runner, e.pluginHandler, e.currentExecutionInfo, e.errMap, e.stream)
	scenarioExec.execute(scenarioResult, scenario, e.specification.Contexts, e.specification.TearDownSteps)
	if scenarioResult.ProtoScenario.GetSkipped() {
		e.specResult.ScenarioSkippedCount++
	}
	return scenarioResult
}

func (e *specExecutor) addAllItemsForScenarioExecution(scenario *gauge.Scenario, scenarioResult *result.ScenarioResult) {
	scenarioResult.AddContexts(e.getItemsForScenarioExecution(e.specification.Contexts))
	scenarioResult.AddTearDownSteps(e.getItemsForScenarioExecution(e.specification.TearDownSteps))
	scenarioResult.AddItems(e.resolveItems(scenario.Items))
}

func (e *specExecutor) getSkippedScenarioResult(scenario *gauge.Scenario) *result.ScenarioResult {
	scenarioResult := &result.ScenarioResult{ProtoScenario: gauge.NewProtoScenario(scenario)}
	e.addAllItemsForScenarioExecution(scenario, scenarioResult)
	setSkipInfoInResult(scenarioResult, scenario, e.errMap)
	e.specResult.ScenarioSkippedCount++
	return scenarioResult
}

func updateProtoStepParameters(protoStep *gauge_messages.ProtoStep, parameters []*gauge_messages.Parameter) {
	paramIndex := 0
	for fragmentIndex, fragment := range protoStep.Fragments {
		if fragment.GetFragmentType() == gauge_messages.Fragment_Parameter {
			protoStep.Fragments[fragmentIndex].Parameter = parameters[paramIndex]
			paramIndex++
		}
	}
}

func getTagValue(tags *gauge.Tags) []string {
	var tagValues []string
	if tags != nil {
		tagValues = append(tagValues, tags.Values...)
	}
	return tagValues
}

func setSpecFailure(executionInfo *gauge_messages.ExecutionInfo) {
	executionInfo.CurrentSpec.IsFailed = proto.Bool(true)
}

func getDataTableRowsRange(tableRows string, rowCount int) (indexRange, error) {
	var startIndex, endIndex int
	var err error
	indexRanges := strings.Split(tableRows, "-")
	if len(indexRanges) == 2 {
		startIndex, endIndex, err = validation.ValidateTableRowsRange(indexRanges[0], indexRanges[1], rowCount)
	} else if len(indexRanges) == 1 {
		startIndex, endIndex, err = validation.ValidateTableRowsRange(tableRows, tableRows, rowCount)
	} else {
		return indexRange{start: 0, end: 0}, errors.New("Table rows range validation failed.")
	}
	if err != nil {
		return indexRange{start: 0, end: 0}, err
	}
	return indexRange{start: startIndex, end: endIndex}, nil
}
<|endoftext|>


<commit_before>package test

import (
	"strings"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
)

func TestResourceDefaults_basic(t *testing.T) {
	resource.UnitTest(t, resource.TestCase{
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckResourceDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
}
				`),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_string", "default string",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_bool", "1",
					),
					resource.TestCheckNoResourceAttr(
						"test_resource_defaults.foo", "nested.#",
					),
				),
			},
		},
	})
}

func TestResourceDefaults_inSet(t *testing.T) {
	resource.UnitTest(t, resource.TestCase{
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckResourceDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
	nested {
		optional = "val"
	}
}
				`),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_string", "default string",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_bool", "1",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.2826070548.optional", "val",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.2826070548.string", "default nested",
					),
				),
			},
		},
	})
}

func TestResourceDefaults_import(t *testing.T) {
	// FIXME: The ReadResource after ImportResourceState sin't returning the
	// complete state, yet the later refresh does.
	return

	resource.UnitTest(t, resource.TestCase{
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckResourceDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
	nested {
		optional = "val"
	}
}
				`),
			},
			{
				ImportState:       true,
				ImportStateVerify: true,
				ResourceName:      "test_resource_defaults.foo",
			},
		},
	})
}
<commit_msg>add more tests<commit_after>package test

import (
	"strings"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
)

func TestResourceDefaults_basic(t *testing.T) {
	resource.UnitTest(t, resource.TestCase{
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckResourceDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
}
				`),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_string", "default string",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_bool", "1",
					),
					resource.TestCheckNoResourceAttr(
						"test_resource_defaults.foo", "nested.#",
					),
				),
			},
		},
	})
}

func TestResourceDefaults_change(t *testing.T) {
	resource.UnitTest(t, resource.TestCase{
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckResourceDestroy,
		Steps: []resource.TestStep{
			{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
}
				`),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_string", "default string",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_bool", "1",
					),
					resource.TestCheckNoResourceAttr(
						"test_resource_defaults.foo", "nested.#",
					),
				),
			},
			{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
	default_string = "new"
	default_bool = false
	nested {
		optional = "nested"
	}
}
				`),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_string", "new",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_bool", "false",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.#", "1",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.2950978312.optional", "nested",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.2950978312.string", "default nested",
					),
				),
			},
			{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
	default_string = "new"
	default_bool = false
	nested {
		optional = "nested"
		string = "new"
	}
}
				`),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_string", "new",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_bool", "false",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.#", "1",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.782850362.optional", "nested",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.782850362.string", "new",
					),
				),
			},
		},
	})
}

func TestResourceDefaults_inSet(t *testing.T) {
	resource.UnitTest(t, resource.TestCase{
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckResourceDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
	nested {
		optional = "val"
	}
}
				`),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_string", "default string",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "default_bool", "1",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.2826070548.optional", "val",
					),
					resource.TestCheckResourceAttr(
						"test_resource_defaults.foo", "nested.2826070548.string", "default nested",
					),
				),
			},
		},
	})
}

func TestResourceDefaults_import(t *testing.T) {
	// FIXME: The ReadResource after ImportResourceState sin't returning the
	// complete state, yet the later refresh does.
	return

	resource.UnitTest(t, resource.TestCase{
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckResourceDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: strings.TrimSpace(`
resource "test_resource_defaults" "foo" {
	nested {
		optional = "val"
	}
}
				`),
			},
			{
				ImportState:       true,
				ImportStateVerify: true,
				ResourceName:      "test_resource_defaults.foo",
			},
		},
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"gopkg.in/src-d/go-kallax.v1/generator"

	"gopkg.in/urfave/cli.v1"
)

func main() {
	app := cli.NewApp()
	app.Name = "kallax"
	app.Version = "1.0.0"
	app.Usage = "generate kallax models"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "input",
			Value: ".",
			Usage: "Input package directory",
		},
		cli.StringFlag{
			Name:  "output",
			Value: "kallax.go",
			Usage: "Output file name",
		},
		cli.StringSliceFlag{
			Name:  "exclude, e",
			Usage: "List of excluded files from the package when generating the code for your models. Use this to exclude files in your package that uses the generated code. You can use this flag as many times as you want.",
		},
	}
	app.Action = generateModels
	app.Commands = []cli.Command{
		{
			Name:   "gen",
			Usage:  "Generate kallax models",
			Action: app.Action,
			Flags:  app.Flags,
		},
	}

	app.Run(os.Args)
}

func generateModels(c *cli.Context) error {
	input := c.String("input")
	output := c.String("output")
	excluded := c.StringSlice("exclude")

	if !isDirectory(input) {
		return fmt.Errorf("kallax: Input path should be a directory %s", input)
	}

	p := generator.NewProcessor(input, excluded)
	pkg, err := p.Do()
	if err != nil {
		return err
	}

	gen := generator.NewGenerator(filepath.Join(input, output))
	err = gen.Generate(pkg)
	if err != nil {
		return err
	}

	return nil
}

func isDirectory(name string) bool {
	info, err := os.Stat(name)
	if err != nil {
		log.Fatal(err)
	}

	return info.IsDir()
}
<commit_msg>update command version<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"gopkg.in/src-d/go-kallax.v1/generator"

	"gopkg.in/urfave/cli.v1"
)

func main() {
	app := cli.NewApp()
	app.Name = "kallax"
	app.Version = "1.1.0"
	app.Usage = "generate kallax models"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "input",
			Value: ".",
			Usage: "Input package directory",
		},
		cli.StringFlag{
			Name:  "output",
			Value: "kallax.go",
			Usage: "Output file name",
		},
		cli.StringSliceFlag{
			Name:  "exclude, e",
			Usage: "List of excluded files from the package when generating the code for your models. Use this to exclude files in your package that uses the generated code. You can use this flag as many times as you want.",
		},
	}
	app.Action = generateModels
	app.Commands = []cli.Command{
		{
			Name:   "gen",
			Usage:  "Generate kallax models",
			Action: app.Action,
			Flags:  app.Flags,
		},
	}

	app.Run(os.Args)
}

func generateModels(c *cli.Context) error {
	input := c.String("input")
	output := c.String("output")
	excluded := c.StringSlice("exclude")

	if !isDirectory(input) {
		return fmt.Errorf("kallax: Input path should be a directory %s", input)
	}

	p := generator.NewProcessor(input, excluded)
	pkg, err := p.Do()
	if err != nil {
		return err
	}

	gen := generator.NewGenerator(filepath.Join(input, output))
	err = gen.Generate(pkg)
	if err != nil {
		return err
	}

	return nil
}

func isDirectory(name string) bool {
	info, err := os.Stat(name)
	if err != nil {
		log.Fatal(err)
	}

	return info.IsDir()
}
<|endoftext|>


<commit_before>package effects

import "github.com/faiface/beep"

// Doppler simulates a "sound at a distance". If the sound starts at a far distance,
// it'll take some time to reach the ears of the listener.
//
// The distance of the sound can change dynamically. Doppler adjusts the density of
// the sound (affecting its speed) to remain consistent with the distance. This is called
// the Doppler effect.
//
// The arguments are:
//
//   quality:         the quality of the underlying resampler (1 or 2 is usually okay)
//   samplesPerMeter: sample rate / speed of sound
//   s:               the source streamer
//   distance:        a function to calculate the current distance; takes number of
//                    samples Doppler wants to stream at the moment
//
// This API is experimental and may change any time!
func Doppler(quality int, samplesPerMeter float64, s beep.Streamer, distance func(delta int) float64) beep.Streamer {
	return &doppler{
		r:               beep.ResampleRatio(quality, 1, s),
		distance:        distance,
		space:           make([][2]float64, int(distance(0)*samplesPerMeter)),
		samplesPerMeter: samplesPerMeter,
	}
}

type doppler struct {
	r               *beep.Resampler
	distance        func(delta int) float64
	space           [][2]float64
	samplesPerMeter float64
}

func (d *doppler) Stream(samples [][2]float64) (n int, ok bool) {
	distance := d.distance(len(samples))
	currentSpaceLen := int(distance * d.samplesPerMeter)
	difference := currentSpaceLen - len(d.space)

	d.r.SetRatio(float64(len(samples)) / float64(len(samples)+difference))

	d.space = append(d.space, make([][2]float64, len(samples)+difference)...)
	rn, _ := d.r.Stream(d.space[len(d.space)-len(samples)-difference:])
	d.space = d.space[:len(d.space)-len(samples)-difference+rn]
	for i := len(d.space) - rn; i < len(d.space); i++ {
		d.space[i][0] /= distance * distance
		d.space[i][1] /= distance * distance
	}

	if len(d.space) == 0 {
		return 0, false
	}
	n = copy(samples, d.space)
	d.space = d.space[n:]
	return n, true
}

func (d *doppler) Err() error {
	return d.r.Err()
}
<commit_msg>effects: wording<commit_after>package effects

import "github.com/faiface/beep"

// Doppler simulates a "sound at a distance". If the sound starts at a far distance,
// it'll take some time to reach the ears of the listener.
//
// The distance of the sound can change dynamically. Doppler adjusts the density of
// the sound (affecting its speed) to remain consistent with the distance. This is called
// the Doppler effect.
//
// The arguments are:
//
//   quality:         the quality of the underlying resampler (1 or 2 is usually okay)
//   samplesPerMeter: sample rate / speed of sound
//   s:               the source streamer
//   distance:        a function to calculate the current distance; takes number of
//                    samples Doppler wants to stream at the moment
//
// This function is experimental and may change any time!
func Doppler(quality int, samplesPerMeter float64, s beep.Streamer, distance func(delta int) float64) beep.Streamer {
	return &doppler{
		r:               beep.ResampleRatio(quality, 1, s),
		distance:        distance,
		space:           make([][2]float64, int(distance(0)*samplesPerMeter)),
		samplesPerMeter: samplesPerMeter,
	}
}

type doppler struct {
	r               *beep.Resampler
	distance        func(delta int) float64
	space           [][2]float64
	samplesPerMeter float64
}

func (d *doppler) Stream(samples [][2]float64) (n int, ok bool) {
	distance := d.distance(len(samples))
	currentSpaceLen := int(distance * d.samplesPerMeter)
	difference := currentSpaceLen - len(d.space)

	d.r.SetRatio(float64(len(samples)) / float64(len(samples)+difference))

	d.space = append(d.space, make([][2]float64, len(samples)+difference)...)
	rn, _ := d.r.Stream(d.space[len(d.space)-len(samples)-difference:])
	d.space = d.space[:len(d.space)-len(samples)-difference+rn]
	for i := len(d.space) - rn; i < len(d.space); i++ {
		d.space[i][0] /= distance * distance
		d.space[i][1] /= distance * distance
	}

	if len(d.space) == 0 {
		return 0, false
	}
	n = copy(samples, d.space)
	d.space = d.space[n:]
	return n, true
}

func (d *doppler) Err() error {
	return d.r.Err()
}
<|endoftext|>


<commit_before>package driver

import (
	"database/sql/driver"
	"io"
	"sort"
)

// Rows is an iterator over an executed query's results.
// It implements sort and driver.Rows interfaces.
type Rows struct {
	data      [][]driver.Value
	less      []lessFunc
	cols      []string
	size, pos int
}

// Len
func (r *Rows) Len() int {
	return r.size
}

// Less
func (r *Rows) Less(i, j int) bool {
	// Extracts data to compare.
	p, q := r.data[i], r.data[j]
	// Sets the number of iterations to do to compare.
	// Subtraction of 1 because a final comparison is done if all checks said "equal".
	b := len(r.less) - 1
	// Try all but the last comparison.
	var k int
	for k = 0; k < b; k++ {
		less := r.less[k]
		switch {
		case less(p, q):
			// p < q, so we have a decision.
			return true
		case less(q, p):
			// p > q, so we have a decision.
			return false
		}
		// p == q; try the next comparison.
	}
	return r.less[k](p, q)
}

// Swap
func (r *Rows) Swap(i, j int) {
	r.data[i], r.data[j] = r.data[j], r.data[i]
}

// Columns returns the names of the columns.
func (r *Rows) Columns() []string {
	return r.cols
}

// Close closes the rows iterator.
func (r *Rows) Close() error {
	return nil
}

// Next is called to populate the next row of data into the provided slice.
func (r *Rows) Next(dest []driver.Value) error {
	if r.pos == r.size {
		return io.EOF
	}
	for i := 0; i < len(r.cols); i++ {
		// todo Improves with Scanner interface.
		switch r.data[r.pos][i].(type) {
		case AutoNullInt64:
			dest[i], _ = r.data[r.pos][i].(AutoNullInt64).Value()
		case AutoNullFloat64:
			dest[i], _ = r.data[r.pos][i].(AutoNullFloat64).Value()
		case Float64:
			dest[i], _ = r.data[r.pos][i].(Float64).Value()
		case Time:
			dest[i], _ = r.data[r.pos][i].(Time).Value()
		case NullString:
			dest[i], _ = r.data[r.pos][i].(NullString).Value()
		default:
			dest[i] = r.data[r.pos][i]
		}
	}
	r.pos++

	return nil
}

// Limit bounds the slice of rows.
func (r *Rows) Limit(offset, rowCount int) {
	if offset < 0 {
		offset = 0
	}
	r.pos = offset

	rowCount += offset
	if rowCount >= r.size {
		rowCount = r.size - 1
	}
	r.size = rowCount
}

// Sort sorts rows as expected by less functions.
func (r *Rows) Sort() {
	sort.Sort(r)
}
<commit_msg>Removes header line in case of zero result with ascii table<commit_after>package driver

import (
	"database/sql/driver"
	"io"
	"sort"
)

// Rows is an iterator over an executed query's results.
// It implements sort and driver.Rows interfaces.
type Rows struct {
	data      [][]driver.Value
	less      []lessFunc
	cols      []string
	size, pos int
}

// Len
func (r *Rows) Len() int {
	return r.size
}

// Less
func (r *Rows) Less(i, j int) bool {
	// Extracts data to compare.
	p, q := r.data[i], r.data[j]
	// Sets the number of iterations to do to compare.
	// Subtraction of 1 because a final comparison is done if all checks said "equal".
	b := len(r.less) - 1
	// Try all but the last comparison.
	var k int
	for k = 0; k < b; k++ {
		less := r.less[k]
		switch {
		case less(p, q):
			// p < q, so we have a decision.
			return true
		case less(q, p):
			// p > q, so we have a decision.
			return false
		}
		// p == q; try the next comparison.
	}
	return r.less[k](p, q)
}

// Swap
func (r *Rows) Swap(i, j int) {
	r.data[i], r.data[j] = r.data[j], r.data[i]
}

// Columns returns the names of the columns.
func (r *Rows) Columns() []string {
	if r.size == 0 {
		return nil
	}
	return r.cols
}

// Close closes the rows iterator.
func (r *Rows) Close() error {
	return nil
}

// Next is called to populate the next row of data into the provided slice.
func (r *Rows) Next(dest []driver.Value) error {
	if r.pos == r.size {
		return io.EOF
	}
	for i := 0; i < len(r.cols); i++ {
		// todo Improves with Scanner interface.
		switch r.data[r.pos][i].(type) {
		case AutoNullInt64:
			dest[i], _ = r.data[r.pos][i].(AutoNullInt64).Value()
		case AutoNullFloat64:
			dest[i], _ = r.data[r.pos][i].(AutoNullFloat64).Value()
		case Float64:
			dest[i], _ = r.data[r.pos][i].(Float64).Value()
		case Time:
			dest[i], _ = r.data[r.pos][i].(Time).Value()
		case NullString:
			dest[i], _ = r.data[r.pos][i].(NullString).Value()
		default:
			dest[i] = r.data[r.pos][i]
		}
	}
	r.pos++

	return nil
}

// Limit bounds the slice of rows.
func (r *Rows) Limit(offset, rowCount int) {
	if offset < 0 {
		offset = 0
	}
	r.pos = offset

	rowCount += offset
	if rowCount >= r.size {
		rowCount = r.size - 1
	}
	r.size = rowCount
}

// Sort sorts rows as expected by less functions.
func (r *Rows) Sort() {
	sort.Sort(r)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
)

type EmbedTransport struct {
	http.RoundTripper
}

func (e *EmbedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	log.Printf("uri: %s", req.URL.String())

	base := e.RoundTripper
	if base == nil {
		base = http.DefaultTransport
	}

	r, spec, err := stripSpec(req)
	if err != nil {
		return nil, err
	}

	resp, err := base.RoundTrip(r)
	if err != nil {
		return resp, err
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return resp, err

	}

	if err := resp.Body.Close(); err != nil {
		return resp, err
	}

	var data map[string]interface{}
	if err := json.Unmarshal(b, &data); err != nil {
		log.Fatalf("json.Unmarshal() failed: %v", err)
	}

	links, ok := data["_links"].(map[string]interface{})
	if !ok {
		return resp, nil
	}

	embedded, ok := data["_embedded"].(map[string]interface{})
	if !ok {
		m := make(map[string]interface{})
		data["_embedded"] = m
		embedded = m
	}

	for k, v := range links {
		if k != spec[0] {
			continue
		}

		switch v := v.(type) {
		case map[string]interface{}:
			data, err := e.embed(req, v)
			if err != nil {
				continue
			}

			embedded[k] = data
		case []interface{}:
			var arr []map[string]interface{}
			for _, v := range v {
				data, err := e.embed(req, v.(map[string]interface{}))
				if err != nil {
					continue
				}

				arr = append(arr, data)
			}
			embedded[k] = arr
		default:
			continue
		}
	}

	b, err = json.Marshal(data)
	if err != nil {
		return resp, err
	}

	resp.Body = ioutil.NopCloser(bytes.NewReader(b))

	return resp, nil
}

func stripSpec(req *http.Request) (*http.Request, []string, error) {
	with := req.URL.Query().Get("with")
	spec := strings.Split(with, ".")

	q := req.URL.Query()
	q.Del("with")
	u := url.URL{
		Scheme:   req.URL.Scheme,
		Opaque:   req.URL.Opaque,
		User:     req.URL.User,
		Host:     req.URL.Host,
		Path:     req.URL.Path,
		RawQuery: q.Encode(),
		Fragment: req.URL.Fragment,
	}

	r, err := http.NewRequest(req.Method, u.String(), nil)
	if err != nil {
		return r, spec, err
	}
	r.Header = req.Header

	return r, spec, nil
}

func (e *EmbedTransport) embed(parent *http.Request, link map[string]interface{}) (map[string]interface{}, error) {
	href, ok := link["href"].(string)
	if !ok {
		return nil, errors.New("href not found")
	}

	uri, err := url.Parse(href)
	if err != nil {
		return nil, err
	}

	_, spec, err := stripSpec(parent)
	if err != nil {
		return nil, err
	}

	q := uri.Query()
	q["with"] = spec[1:]
	uri.RawQuery = q.Encode()

	req, err := http.NewRequest(http.MethodGet, parent.URL.ResolveReference(uri).String(), nil)
	if err != nil {
		return nil, err
	}
	req.Header = parent.Header

	resp, err := e.RoundTrip(req)
	if err != nil {
		return nil, err
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var data map[string]interface{}
	if err := json.Unmarshal(b, &data); err != nil {
		return nil, err
	}

	return data, nil
}
<commit_msg>spec based fetch<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
)

type EmbedTransport struct {
	http.RoundTripper
}

func (e *EmbedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	log.Printf("uri: %s", req.URL.String())

	base := e.RoundTripper
	if base == nil {
		base = http.DefaultTransport
	}

	if req.Method != http.MethodGet {
		return base.RoundTrip(req)
	}

	r, spec, err := stripSpec(req)
	if err != nil {
		return nil, err
	}

	resp, err := base.RoundTrip(r)
	if err != nil {
		return resp, err
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return resp, err

	}

	if err := resp.Body.Close(); err != nil {
		return resp, err
	}

	var data map[string]interface{}
	if err := json.Unmarshal(b, &data); err != nil {
		log.Fatalf("json.Unmarshal() failed: %v", err)
	}

	links, ok := data["_links"].(map[string]interface{})
	if !ok {
		return resp, nil
	}

	embedded, ok := data["_embedded"].(map[string]interface{})
	if !ok {
		m := make(map[string]interface{})
		data["_embedded"] = m
		embedded = m
	}

	current := []map[string]interface{}{data}
	for i := 0; i < len(spec); i++ {
		for _, c := range current {
			links, ok = c["_links"].(map[string]interface{})
			if !ok {
				break
			}

			link, ok := links[spec[i]]
			if !ok {
				break
			}

			embedded, ok = c["_embedded"].(map[string]interface{})
			if !ok {
				m := make(map[string]interface{})
				c["_embedded"] = m
				embedded = m
			}

			switch link := link.(type) {
			case map[string]interface{}:
				embed, err := e.get(req, link)
				if err != nil {
					log.Fatal(err)
					continue
				}

				embedded[spec[i]] = embed

				current = []map[string]interface{}{embed}
			case []interface{}:
				result := []map[string]interface{}{}

				for _, l := range link {
					embed, err := e.get(req, l.(map[string]interface{}))
					if err != nil {
						log.Fatal(err)
						continue
					}

					result = append(result, embed)
				}

				embedded[spec[i]] = result
				current = result
			default:
				continue
			}
		}
	}

	b, err = json.Marshal(data)
	if err != nil {
		return resp, err
	}

	resp.Body = ioutil.NopCloser(bytes.NewReader(b))

	return resp, nil
}

func stripSpec(req *http.Request) (*http.Request, []string, error) {
	with := req.URL.Query().Get("with")
	spec := strings.Split(with, ".")

	q := req.URL.Query()
	q.Del("with")
	u := url.URL{
		Scheme:   req.URL.Scheme,
		Opaque:   req.URL.Opaque,
		User:     req.URL.User,
		Host:     req.URL.Host,
		Path:     req.URL.Path,
		RawQuery: q.Encode(),
		Fragment: req.URL.Fragment,
	}

	r, err := http.NewRequest(req.Method, u.String(), nil)
	if err != nil {
		return r, spec, err
	}
	r.Header = req.Header

	return r, spec, nil
}

func (e *EmbedTransport) get(base *http.Request, link map[string]interface{}) (map[string]interface{}, error) {
	transport := e.RoundTripper
	if transport == nil {
		transport = http.DefaultTransport
	}

	href, ok := link["href"].(string)
	if !ok {
		return nil, errors.New("href not found")
	}

	uri, err := url.Parse(href)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest(http.MethodGet, base.URL.ResolveReference(uri).String(), nil)
	if err != nil {
		return nil, err
	}
	req.Header = base.Header

	resp, err := transport.RoundTrip(req)
	if err != nil {
		return nil, err
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var data map[string]interface{}
	if err := json.Unmarshal(b, &data); err != nil {
		return nil, err
	}

	return data, nil
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Jennal(jennalcn@gmail.com). All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// 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 encode

import (
	"github.com/golang/protobuf/proto"
	"github.com/jennal/goplay/log"
)

//Protobuf encoder/decoder
type Protobuf struct {
}

func (self Protobuf) Marshal(obj interface{}) ([]byte, error) {
	pb, ok := obj.(proto.Message)
	if !ok {
		return nil, log.NewErrorf("protobuf: convert on wrong type value: %#v", obj)
	}
	return proto.Marshal(pb)
}

func (self Protobuf) Unmarshal(data []byte, content interface{}) error {
	pb, ok := content.(proto.Message)
	if !ok {
		return log.NewErrorf("protobuf: convert on wrong type value: %#v", content)
	}
	return proto.Unmarshal(data, pb)
}

func NewProtobuf() EncodeDecoder {
	return &Base{
		child: Protobuf{},
	}
}
<commit_msg>hack oneof encode/decode on protobuf<commit_after>// Copyright (C) 2017 Jennal(jennalcn@gmail.com). All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// 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 encode

import (
	"github.com/golang/protobuf/proto"
	"github.com/jennal/goplay/log"
)

//Protobuf encoder/decoder
type Protobuf struct {
}

type oneOfMarshaler interface {
	MarshalOneOf() ([]byte, error)
	UnmarshalOneOf(buf []byte) error
}

func (self Protobuf) Marshal(obj interface{}) ([]byte, error) {
	if oneOf, ok := obj.(oneOfMarshaler); ok {
		return oneOf.MarshalOneOf()
	}

	pb, ok := obj.(proto.Message)
	if !ok {
		return nil, log.NewErrorf("protobuf: convert on wrong type value: %#v", obj)
	}
	return proto.Marshal(pb)
}

func (self Protobuf) Unmarshal(data []byte, content interface{}) error {
	if oneOf, ok := content.(oneOfMarshaler); ok {
		return oneOf.UnmarshalOneOf(data)
	}

	pb, ok := content.(proto.Message)
	if !ok {
		return log.NewErrorf("protobuf: convert on wrong type value: %#v", content)
	}
	return proto.Unmarshal(data, pb)
}

func NewProtobuf() EncodeDecoder {
	return &Base{
		child: Protobuf{},
	}
}
<|endoftext|>


<commit_before>package encoding

import (
	"errors"
	"fmt"
	"io"
)

var (
	errNoData    = errors.New("no data")
	errBadPrefix = errors.New("could not read full length prefix")
)

// ReadPrefix reads an 8-byte length prefixes, followed by the number of bytes
// specified in the prefix. The operation is aborted if the prefix exceeds a
// specified maximum length.
func ReadPrefix(r io.Reader, maxLen uint64) ([]byte, error) {
	prefix := make([]byte, 8)
	if n, err := io.ReadFull(r, prefix); n == 0 {
		return nil, errNoData
	} else if err != nil {
		return nil, errBadPrefix
	}
	dataLen := DecUint64(prefix)
	if dataLen > maxLen {
		return nil, fmt.Errorf("length %d exceeds maxLen of %d", dataLen, maxLen)
	}
	// read dataLen bytes
	data := make([]byte, dataLen)
	_, err := io.ReadFull(r, data)
	return data, err
}

// ReadObject reads and decodes a length-prefixed and marshalled object.
func ReadObject(r io.Reader, obj interface{}, maxLen uint64) error {
	data, err := ReadPrefix(r, maxLen)
	if err != nil {
		return err
	}
	return Unmarshal(data, obj)
}

// WritePrefix writes a length-prefixed byte slice to w.
func WritePrefix(w io.Writer, data []byte) error {
	n, err := w.Write(append(EncUint64(uint64(len(data))), data...))
	if n != len(data)+8 {
		return io.ErrShortWrite
	}
	return err
}

// WriteObject writes a length-prefixed object to w.
func WriteObject(w io.Writer, v interface{}) error {
	return WritePrefix(w, Marshal(v))
}
<commit_msg>add AddPrefix method to encoding<commit_after>package encoding

import (
	"errors"
	"fmt"
	"io"
)

var (
	errNoData    = errors.New("no data")
	errBadPrefix = errors.New("could not read full length prefix")
)

// ReadPrefix reads an 8-byte length prefixes, followed by the number of bytes
// specified in the prefix. The operation is aborted if the prefix exceeds a
// specified maximum length.
func ReadPrefix(r io.Reader, maxLen uint64) ([]byte, error) {
	prefix := make([]byte, 8)
	if n, err := io.ReadFull(r, prefix); n == 0 {
		return nil, errNoData
	} else if err != nil {
		return nil, errBadPrefix
	}
	dataLen := DecUint64(prefix)
	if dataLen > maxLen {
		return nil, fmt.Errorf("length %d exceeds maxLen of %d", dataLen, maxLen)
	}
	// read dataLen bytes
	data := make([]byte, dataLen)
	_, err := io.ReadFull(r, data)
	return data, err
}

// ReadObject reads and decodes a length-prefixed and marshalled object.
func ReadObject(r io.Reader, obj interface{}, maxLen uint64) error {
	data, err := ReadPrefix(r, maxLen)
	if err != nil {
		return err
	}
	return Unmarshal(data, obj)
}

// AddPrefix prepends b with an 8-byte length prefix.
func AddPrefix(b []byte) []byte {
	return append(EncUint64(uint64(len(b))), b...)
}

// WritePrefix writes a length-prefixed byte slice to w.
func WritePrefix(w io.Writer, data []byte) error {
	n, err := w.Write(AddPrefix(data))
	if n != len(data)+8 {
		return io.ErrShortWrite
	}
	return err
}

// WriteObject writes a length-prefixed object to w.
func WriteObject(w io.Writer, v interface{}) error {
	return WritePrefix(w, Marshal(v))
}
<|endoftext|>