<commit_before>// Package dice utilises the standard "nds" notation where n = number of die and s = number of sides; i.e 1d6, 3d10, 8d8 etc
// in order to create individual sets of a single type of die or bags of mixed collections that can then be manipluated or rolled
package dice

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

var rng = rand.New(rand.NewSource(time.Now().UnixNano()))

// Dice represents a set of 1 type of dice, i.e: 3d20 OR 2d4 OR 1d6
type Dice struct {
	number, sides int
}

// NewDice takes the common notation "nds" where n is the number of dice and s is the number of sides;
// i.e 1d6 and returns a new Dice set. Returns error if s is not a valid dice string
func NewDice(s string) (*Dice, error) {
	number, sides, err := strToVal(s)
	if err != nil {
		return new(Dice), err
	}

	return &Dice{number, sides}, nil
}

// Add adds n die to a single set iff that set is of the same number of sides. Returns error if s is not a valid dice string
func (d *Dice) Add(s string) error {
	number, sides, err := strToVal(s)
	if err != nil {
		return err
	}

	if d.sides == sides {
		d.number += number
	}

	return nil
}

// Remove removes n die from a single set iff that set is of the same number of sides. Returns error if s is not a valid dice string
func (d *Dice) Remove(s string) error {
	number, sides, err := strToVal(s)
	if err != nil {
		return err
	}

	if d.sides == sides {
		if d.number-number < 1 {
			d.number = 0
		} else {
			d.number -= number
		}
	}

	return nil
}

// Roll all dice in set and return the aggregate result
func (d *Dice) Roll() int {
	t := 0

	for i := 0; i < d.number; i++ {
		t += rng.Intn(d.sides) + 1
	}

	return t
}

// String satisfies the Stringer interface for Dice
func (d *Dice) String() string {
	return fmt.Sprintf("%dd%d", d.number, d.sides)
}

// Bag is a collection of different types of Dice; i.e [3d20, 2d4, 1d6]
type Bag struct {
	dice []*Dice
}

// NewBag returns a new Bag object. A bag can be created with a collection of
// dice specified in string form for convenience. I.e b := NewBag("2d20", "1d6", "8d8")
// Returns error if s is not a valid dice string
func NewBag(dice ...string) (*Bag, error) {
	b := new(Bag)

	for _, a := range dice {
		if err := b.Add(a); err != nil {
			return b, err
		}
	}

	return b, nil
}

// Add puts more dice in the bag, adding to existing sets where possible. Returns error if s is not a valid dice string
func (b *Bag) Add(s string) error {
	d, err := NewDice(s)
	if err != nil {
		return err
	}

	// increment existing set if it exists
	for _, set := range b.dice {
		if set.sides == d.sides {
			set.number += d.number
			return nil
		}
	}

	// Otherwise add a new set
	b.dice = append(b.dice, d)
	return nil
}

// Remove reduces the number of dice by the specified s string if s exists in the bag. Returns error if s is not a valid dice string
func (b *Bag) Remove(s string) error {
	number, sides, err := strToVal(s)
	if err != nil {
		return err
	}

	// Remove specified dice from set
	for _, set := range b.dice {
		if set.sides == sides {
			// ensure no < 0 values
			if set.number-number < 0 {
				set.number = 0
			} else {
				set.number -= number
			}
			break
		}
	}

	return nil
}

// Roll returns aggregate rolls of all Dice in the bag
func (b *Bag) Roll() int {
	t := 0

	for _, d := range b.dice {
		t += d.Roll()
	}

	return t
}

// String satisfies the Stringer interface for Bags
func (b *Bag) String() string {
	v := make([]string, len(b.dice))

	for i, d := range b.dice {
		v[i] = fmt.Sprint(d)
	}

	return strings.Join(v, ", ")
}

// returns int values for numbers, sides
func strToVal(a string) (number int, sides int, err error) {
	ns := strings.Split(a, "d")
	if len(ns) == 2 {
		number, _ = strconv.Atoi(ns[0])
		sides, _ = strconv.Atoi(ns[1])
		if number > 0 && sides > 0 {
			return number, sides, nil
		}

		return number, sides, fmt.Errorf("%s is not a valid dice string", a)
	}

	return number, sides, fmt.Errorf("%s is not a valid dice string", a)
}
<commit_msg>lines pedantry<commit_after>// Package dice utilises the standard "nds" notation where n = number of die and s = number of sides; i.e 1d6, 3d10, 8d8 etc
// in order to create individual sets of a single type of die or bags of mixed collections that can then be manipluated or rolled
package dice

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

var rng = rand.New(rand.NewSource(time.Now().UnixNano()))

// Dice represents a set of 1 type of dice, i.e: 3d20 OR 2d4 OR 1d6
type Dice struct {
	number, sides int
}

// NewDice takes the common notation "nds" where n is the number of dice and s is the number of sides;
// i.e 1d6 and returns a new Dice set. Returns error if s is not a valid dice string
func NewDice(s string) (*Dice, error) {
	number, sides, err := strToVal(s)
	if err != nil {
		return new(Dice), err
	}

	return &Dice{number, sides}, nil
}

// Add adds n die to a single set iff that set is of the same number of sides.
// Returns error if s is not a valid dice string
func (d *Dice) Add(s string) error {
	number, sides, err := strToVal(s)
	if err != nil {
		return err
	}

	if d.sides == sides {
		d.number += number
	}

	return nil
}

// Remove removes n die from a single set iff that set is of the same number of sides.
// Returns error if s is not a valid dice string
func (d *Dice) Remove(s string) error {
	number, sides, err := strToVal(s)
	if err != nil {
		return err
	}

	if d.sides == sides {
		if d.number-number < 1 {
			d.number = 0
		} else {
			d.number -= number
		}
	}

	return nil
}

// Roll all dice in set and return the aggregate result
func (d *Dice) Roll() int {
	t := 0

	for i := 0; i < d.number; i++ {
		t += rng.Intn(d.sides) + 1
	}

	return t
}

// String satisfies the Stringer interface for Dice
func (d *Dice) String() string {
	return fmt.Sprintf("%dd%d", d.number, d.sides)
}

// Bag is a collection of different types of Dice; i.e [3d20, 2d4, 1d6]
type Bag struct {
	dice []*Dice
}

// NewBag returns a new Bag object. A bag can be created with a collection of
// dice specified in string form for convenience. I.e b := NewBag("2d20", "1d6", "8d8")
// Returns error if s is not a valid dice string
func NewBag(dice ...string) (*Bag, error) {
	b := new(Bag)

	for _, a := range dice {
		if err := b.Add(a); err != nil {
			return b, err
		}
	}

	return b, nil
}

// Add puts more dice in the bag, adding to existing sets where possible.
// Returns error if s is not a valid dice string
func (b *Bag) Add(s string) error {
	d, err := NewDice(s)
	if err != nil {
		return err
	}

	// increment existing set if it exists
	for _, set := range b.dice {
		if set.sides == d.sides {
			set.number += d.number
			return nil
		}
	}

	// Otherwise add a new set
	b.dice = append(b.dice, d)
	return nil
}

// Remove reduces the number of dice by the specified s string if s exists in the bag.
// Returns error if s is not a valid dice string
func (b *Bag) Remove(s string) error {
	number, sides, err := strToVal(s)
	if err != nil {
		return err
	}

	// Remove specified dice from set
	for _, set := range b.dice {
		if set.sides == sides {
			// ensure no < 0 values
			if set.number-number < 0 {
				set.number = 0
			} else {
				set.number -= number
			}
			break
		}
	}

	return nil
}

// Roll returns aggregate rolls of all Dice in the bag
func (b *Bag) Roll() int {
	t := 0

	for _, d := range b.dice {
		t += d.Roll()
	}

	return t
}

// String satisfies the Stringer interface for Bags
func (b *Bag) String() string {
	v := make([]string, len(b.dice))

	for i, d := range b.dice {
		v[i] = fmt.Sprint(d)
	}

	return strings.Join(v, ", ")
}

// returns int values for numbers, sides
func strToVal(a string) (number int, sides int, err error) {
	ns := strings.Split(a, "d")
	if len(ns) == 2 {
		number, _ = strconv.Atoi(ns[0])
		sides, _ = strconv.Atoi(ns[1])
		if number > 0 && sides > 0 {
			return number, sides, nil
		}

		return number, sides, fmt.Errorf("%s is not a valid dice string", a)
	}

	return number, sides, fmt.Errorf("%s is not a valid dice string", a)
}
<|endoftext|>


<commit_before>package storage

import (
	"io"
	"os"
	"path/filepath"

	"github.com/anacrolix/missinggo"

	"github.com/anacrolix/torrent/metainfo"
)

// File-based storage for torrents, that isn't yet bound to a particular
// torrent.
type fileClientImpl struct {
	baseDir   string
	pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string
	pc        PieceCompletion
}

// The Default path maker just returns the current path
func defaultPathMaker(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string {
	return baseDir
}

func infoHashPathMaker(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string {
	return filepath.Join(baseDir, infoHash.HexString())
}

// All Torrent data stored in this baseDir
func NewFile(baseDir string) ClientImpl {
	return NewFileWithCompletion(baseDir, pieceCompletionForDir(baseDir))
}

func NewFileWithCompletion(baseDir string, completion PieceCompletion) ClientImpl {
	return newFileWithCustomPathMakerAndCompletion(baseDir, nil, completion)
}

// All Torrent data stored in subdirectorys by infohash
func NewFileByInfoHash(baseDir string) ClientImpl {
	return NewFileWithCustomPathMaker(baseDir, infoHashPathMaker)
}

// Allows passing a function to determine the path for storing torrent data
func NewFileWithCustomPathMaker(baseDir string, pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string) ClientImpl {
	return newFileWithCustomPathMakerAndCompletion(baseDir, pathMaker, pieceCompletionForDir(baseDir))
}

func newFileWithCustomPathMakerAndCompletion(baseDir string, pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string, completion PieceCompletion) ClientImpl {
	if pathMaker == nil {
		pathMaker = defaultPathMaker
	}
	return &fileClientImpl{
		baseDir:   baseDir,
		pathMaker: pathMaker,
		pc:        completion,
	}
}

func (me *fileClientImpl) Close() error {
	return me.pc.Close()
}

func (fs *fileClientImpl) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (TorrentImpl, error) {
	dir := fs.pathMaker(fs.baseDir, info, infoHash)
	err := CreateNativeZeroLengthFiles(info, dir)
	if err != nil {
		return nil, err
	}
	return &fileTorrentImpl{
		dir,
		info,
		infoHash,
		fs.pc,
	}, nil
}

// File-based torrent storage, not yet bound to a Torrent.
type fileTorrentImpl struct {
	dir        string
	info       *metainfo.Info
	infoHash   metainfo.Hash
	completion PieceCompletion
}

func (fts *fileTorrentImpl) Piece(p metainfo.Piece) PieceImpl {
	// Create a view onto the file-based torrent storage.
	_io := fileTorrentImplIO{fts}
	// Return the appropriate segments of this.
	return &fileStoragePiece{
		fts,
		p,
		missinggo.NewSectionWriter(_io, p.Offset(), p.Length()),
		io.NewSectionReader(_io, p.Offset(), p.Length()),
	}
}

func (fs *fileTorrentImpl) Close() error {
	return nil
}

// Creates natives files for any zero-length file entries in the info. This is
// a helper for file-based storages, which don't address or write to zero-
// length files because they have no corresponding pieces.
func CreateNativeZeroLengthFiles(info *metainfo.Info, dir string) (err error) {
	for _, fi := range info.UpvertedFiles() {
		if fi.Length != 0 {
			continue
		}
		name := filepath.Join(append([]string{dir, info.Name}, fi.Path...)...)
		os.MkdirAll(filepath.Dir(name), 0750)
		var f io.Closer
		f, err = os.Create(name)
		if err != nil {
			break
		}
		f.Close()
	}
	return
}

// Exposes file-based storage of a torrent, as one big ReadWriterAt.
type fileTorrentImplIO struct {
	fts *fileTorrentImpl
}

// Returns EOF on short or missing file.
func (fst *fileTorrentImplIO) readFileAt(fi metainfo.FileInfo, b []byte, off int64) (n int, err error) {
	f, err := os.Open(fst.fts.fileInfoName(fi))
	if os.IsNotExist(err) {
		// File missing is treated the same as a short file.
		err = io.EOF
		return
	}
	if err != nil {
		return
	}
	defer f.Close()
	// Limit the read to within the expected bounds of this file.
	if int64(len(b)) > fi.Length-off {
		b = b[:fi.Length-off]
	}
	for off < fi.Length && len(b) != 0 {
		n1, err1 := f.ReadAt(b, off)
		b = b[n1:]
		n += n1
		off += int64(n1)
		if n1 == 0 {
			err = err1
			break
		}
	}
	return
}

// Only returns EOF at the end of the torrent. Premature EOF is ErrUnexpectedEOF.
func (fst fileTorrentImplIO) ReadAt(b []byte, off int64) (n int, err error) {
	for _, fi := range fst.fts.info.UpvertedFiles() {
		for off < fi.Length {
			n1, err1 := fst.readFileAt(fi, b, off)
			n += n1
			off += int64(n1)
			b = b[n1:]
			if len(b) == 0 {
				// Got what we need.
				return
			}
			if n1 != 0 {
				// Made progress.
				continue
			}
			err = err1
			if err == io.EOF {
				// Lies.
				err = io.ErrUnexpectedEOF
			}
			return
		}
		off -= fi.Length
	}
	err = io.EOF
	return
}

func (fst fileTorrentImplIO) WriteAt(p []byte, off int64) (n int, err error) {
	for _, fi := range fst.fts.info.UpvertedFiles() {
		if off >= fi.Length {
			off -= fi.Length
			continue
		}
		n1 := len(p)
		if int64(n1) > fi.Length-off {
			n1 = int(fi.Length - off)
		}
		name := fst.fts.fileInfoName(fi)
		os.MkdirAll(filepath.Dir(name), 0770)
		var f *os.File
		f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0660)
		if err != nil {
			return
		}
		n1, err = f.WriteAt(p[:n1], off)
		f.Close()
		if err != nil {
			return
		}
		n += n1
		off = 0
		p = p[n1:]
		if len(p) == 0 {
			break
		}
	}
	return
}

func (fts *fileTorrentImpl) fileInfoName(fi metainfo.FileInfo) string {
	return filepath.Join(append([]string{fts.dir, fts.info.Name}, fi.Path...)...)
}
<commit_msg>storage: Add TODO about handling Close errors<commit_after>package storage

import (
	"io"
	"os"
	"path/filepath"

	"github.com/anacrolix/missinggo"

	"github.com/anacrolix/torrent/metainfo"
)

// File-based storage for torrents, that isn't yet bound to a particular
// torrent.
type fileClientImpl struct {
	baseDir   string
	pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string
	pc        PieceCompletion
}

// The Default path maker just returns the current path
func defaultPathMaker(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string {
	return baseDir
}

func infoHashPathMaker(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string {
	return filepath.Join(baseDir, infoHash.HexString())
}

// All Torrent data stored in this baseDir
func NewFile(baseDir string) ClientImpl {
	return NewFileWithCompletion(baseDir, pieceCompletionForDir(baseDir))
}

func NewFileWithCompletion(baseDir string, completion PieceCompletion) ClientImpl {
	return newFileWithCustomPathMakerAndCompletion(baseDir, nil, completion)
}

// All Torrent data stored in subdirectorys by infohash
func NewFileByInfoHash(baseDir string) ClientImpl {
	return NewFileWithCustomPathMaker(baseDir, infoHashPathMaker)
}

// Allows passing a function to determine the path for storing torrent data
func NewFileWithCustomPathMaker(baseDir string, pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string) ClientImpl {
	return newFileWithCustomPathMakerAndCompletion(baseDir, pathMaker, pieceCompletionForDir(baseDir))
}

func newFileWithCustomPathMakerAndCompletion(baseDir string, pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string, completion PieceCompletion) ClientImpl {
	if pathMaker == nil {
		pathMaker = defaultPathMaker
	}
	return &fileClientImpl{
		baseDir:   baseDir,
		pathMaker: pathMaker,
		pc:        completion,
	}
}

func (me *fileClientImpl) Close() error {
	return me.pc.Close()
}

func (fs *fileClientImpl) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (TorrentImpl, error) {
	dir := fs.pathMaker(fs.baseDir, info, infoHash)
	err := CreateNativeZeroLengthFiles(info, dir)
	if err != nil {
		return nil, err
	}
	return &fileTorrentImpl{
		dir,
		info,
		infoHash,
		fs.pc,
	}, nil
}

// File-based torrent storage, not yet bound to a Torrent.
type fileTorrentImpl struct {
	dir        string
	info       *metainfo.Info
	infoHash   metainfo.Hash
	completion PieceCompletion
}

func (fts *fileTorrentImpl) Piece(p metainfo.Piece) PieceImpl {
	// Create a view onto the file-based torrent storage.
	_io := fileTorrentImplIO{fts}
	// Return the appropriate segments of this.
	return &fileStoragePiece{
		fts,
		p,
		missinggo.NewSectionWriter(_io, p.Offset(), p.Length()),
		io.NewSectionReader(_io, p.Offset(), p.Length()),
	}
}

func (fs *fileTorrentImpl) Close() error {
	return nil
}

// Creates natives files for any zero-length file entries in the info. This is
// a helper for file-based storages, which don't address or write to zero-
// length files because they have no corresponding pieces.
func CreateNativeZeroLengthFiles(info *metainfo.Info, dir string) (err error) {
	for _, fi := range info.UpvertedFiles() {
		if fi.Length != 0 {
			continue
		}
		name := filepath.Join(append([]string{dir, info.Name}, fi.Path...)...)
		os.MkdirAll(filepath.Dir(name), 0750)
		var f io.Closer
		f, err = os.Create(name)
		if err != nil {
			break
		}
		f.Close()
	}
	return
}

// Exposes file-based storage of a torrent, as one big ReadWriterAt.
type fileTorrentImplIO struct {
	fts *fileTorrentImpl
}

// Returns EOF on short or missing file.
func (fst *fileTorrentImplIO) readFileAt(fi metainfo.FileInfo, b []byte, off int64) (n int, err error) {
	f, err := os.Open(fst.fts.fileInfoName(fi))
	if os.IsNotExist(err) {
		// File missing is treated the same as a short file.
		err = io.EOF
		return
	}
	if err != nil {
		return
	}
	defer f.Close()
	// Limit the read to within the expected bounds of this file.
	if int64(len(b)) > fi.Length-off {
		b = b[:fi.Length-off]
	}
	for off < fi.Length && len(b) != 0 {
		n1, err1 := f.ReadAt(b, off)
		b = b[n1:]
		n += n1
		off += int64(n1)
		if n1 == 0 {
			err = err1
			break
		}
	}
	return
}

// Only returns EOF at the end of the torrent. Premature EOF is ErrUnexpectedEOF.
func (fst fileTorrentImplIO) ReadAt(b []byte, off int64) (n int, err error) {
	for _, fi := range fst.fts.info.UpvertedFiles() {
		for off < fi.Length {
			n1, err1 := fst.readFileAt(fi, b, off)
			n += n1
			off += int64(n1)
			b = b[n1:]
			if len(b) == 0 {
				// Got what we need.
				return
			}
			if n1 != 0 {
				// Made progress.
				continue
			}
			err = err1
			if err == io.EOF {
				// Lies.
				err = io.ErrUnexpectedEOF
			}
			return
		}
		off -= fi.Length
	}
	err = io.EOF
	return
}

func (fst fileTorrentImplIO) WriteAt(p []byte, off int64) (n int, err error) {
	for _, fi := range fst.fts.info.UpvertedFiles() {
		if off >= fi.Length {
			off -= fi.Length
			continue
		}
		n1 := len(p)
		if int64(n1) > fi.Length-off {
			n1 = int(fi.Length - off)
		}
		name := fst.fts.fileInfoName(fi)
		os.MkdirAll(filepath.Dir(name), 0770)
		var f *os.File
		f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0660)
		if err != nil {
			return
		}
		n1, err = f.WriteAt(p[:n1], off)
		// TODO: On some systems, write errors can be delayed until the Close.
		f.Close()
		if err != nil {
			return
		}
		n += n1
		off = 0
		p = p[n1:]
		if len(p) == 0 {
			break
		}
	}
	return
}

func (fts *fileTorrentImpl) fileInfoName(fi metainfo.FileInfo) string {
	return filepath.Join(append([]string{fts.dir, fts.info.Name}, fi.Path...)...)
}
<|endoftext|>


<commit_before>// +build darwin

package store

import (
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"encoding/base64"
	"encoding/xml"
	"fmt"
	"io"
	"math/big"
	"os/exec"
	"os/user"
	"path/filepath"
	"reflect"
	"regexp"
	"strings"
	"time"

	"github.com/adamdecaf/cert-manage/tools/pem"
	"github.com/adamdecaf/cert-manage/whitelist"
)

// Docs
// - https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/security.1.html
// - https://github.com/adamdecaf/cert-manage/issues/9#issuecomment-337778241

var (
	plistModDateFormat = "2006-01-02T15:04:05Z"
	systemDirs = []string{
		"/System/Library/Keychains/SystemRootCertificates.keychain",
		"/Library/Keychains/System.keychain",
	}
)

func getUserDirs() ([]string, error) {
	u, err := user.Current()
	if err != nil {
		return nil, err
	}

	return []string{
		filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain"),
		filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain-db"),
	}, nil
}

type darwinStore struct{}

func platform() Store {
	return darwinStore{}
}

func (s darwinStore) Backup() error {
	return nil
}

// List
//
// Note: Currently we are ignoring the login keychain. This is done because those certs are
// typically modified by the user (or an application the user trusts).
func (s darwinStore) List() ([]*x509.Certificate, error) {
	// TODO(adam): Should we call `x509.SystemCertPool()` instead?
	// We need to apply the trust settings anyway..
	return readDarwinCerts(systemDirs...)
}

func readDarwinCerts(paths ...string) ([]*x509.Certificate, error) {
	res := make([]*x509.Certificate, 0)

	args := []string{"find-certificate", "-a", "-p"}
	args = append(args, paths...)

	b, err := exec.Command("/usr/bin/security", args...).Output()
	if err != nil {
		return nil, err
	}

	cs, err := pem.Parse(b)
	if err != nil {
		return nil, err
	}
	for _, c := range cs {
		if c == nil {
			continue
		}
		add := true
		for i := range res {
			if reflect.DeepEqual(c.Signature, res[i].Signature) {
				add = false
				break
			}
		}
		if add {
			res = append(res, c)
		}
	}

	return res, nil
}

// TODO(adam): impl
func (s darwinStore) Remove(wh whitelist.Whitelist) error {
	return nil
}

func (s darwinStore) Restore() error {
	// /usr/bin/security trust-settings-import
	// ^ will prompt users, so I think the 'Restore' should just be
	// outputting what command to run and telling users to run it
	return nil
}

// security remove-trusted-cert <crt-file>
// What does ^ do, exactly?
// How does restore look?

// /usr/bin/security trust-settings-export
// /usr/bin/security trust-settings-import
// Could this be used in as a big batch operation?

// Is there a way to disable a cert? aka mark it as "Never Trust"?
// Otherwise, we'll need to make a full backup of all certs before touching anything.

// xml format, this was generated with the package github.com/gnewton/chidley
// but has also been modified by hand:
// 1. don't export struct names
// 2. remove outermost ChiChidleyRoot314159 wrapper as parsing fails with it
// 3. make `date []*date` rather than `date *date`

type chiPlist struct {
	// AttrVersion string `xml:" version,attr"  json:",omitempty"`
	ChiDict *chiDict `xml:" dict,omitempty" json:"dict,omitempty"`
}

type chiDict struct {
	ChiData []*chiData `xml:" data,omitempty" json:"data,omitempty"`
	ChiDate []*chiDate `xml:" date,omitempty" json:"date,omitempty"`
	ChiDict *chiDict `xml:" dict,omitempty" json:"dict,omitempty"`
	ChiInteger *chiInteger `xml:" integer,omitempty" json:"integer,omitempty"`
	ChiKey []*chiKey `xml:" key,omitempty" json:"key,omitempty"`
}

type chiKey struct {
	Text string `xml:",chardata" json:",omitempty"`
}

type chiData struct {
	Text string `xml:",chardata" json:",omitempty"`
}

type chiDate struct {
	Text string `xml:",chardata" json:",omitempty"`
}

type chiInteger struct {
	Text bool `xml:",chardata" json:",omitempty"`
}

func (p chiPlist) convertToTrustItems() []trustItem {
	out := make([]trustItem, 0)

	// TODO(adam): Add checks to make sure we're on target, and if not panic

	max := len(p.ChiDict.ChiDict.ChiDict.ChiData)
	for i := 0; i < max; i += 2 {
		item := trustItem{}

		// TODO(adam): rename, sha1Fingerprint
		item.key = strings.ToLower(p.ChiDict.ChiDict.ChiKey[i/2].Text)

		// trim whitespace
		r := regexp.MustCompile(`[^a-zA-Z0-9\+\/=]*`)
		r2 := strings.NewReplacer("\t", "", "\n", "", " ", "", "\r", "")

		s1 := r2.Replace(r.ReplaceAllString(p.ChiDict.ChiDict.ChiDict.ChiData[i].Text, ""))
		s2 := r2.Replace(r.ReplaceAllString(p.ChiDict.ChiDict.ChiDict.ChiData[i+1].Text, ""))

		bs1, _ := base64.StdEncoding.DecodeString(s1)
		bs2, _ := base64.StdEncoding.DecodeString(s2)

		// The issuerName's <data></data> block is only under asn1 encoding for the
		// issuerName field from 4.1.2.4 (https://tools.ietf.org/rfc/rfc5280)
		var issuer pkix.RDNSequence
		_, err := asn1.Unmarshal(bs1, &issuer)
		if err == nil {
			name := pkix.Name{}
			name.FillFromRDNSequence(&issuer)
			item.issuerName = name
		}

		dt := p.ChiDict.ChiDict.ChiDict.ChiDate[i/2].Text
		t, err := time.ParseInLocation(plistModDateFormat, dt, time.UTC)
		if err == nil {
			item.modDate = t
		}

		// serialNumber is just a base64 encoded big endian (big) int
		item.serialNumber = bs2

		out = append(out, item)
	}

	return out
}

func parsePlist(in io.Reader) (chiPlist, error) {
	dec := xml.NewDecoder(in)
	var out chiPlist
	err := dec.Decode(&out)
	return out, err
}

// The human readable struct
type trustItem struct {
	// required
	key          string
	issuerName   pkix.Name
	modDate      time.Time
	serialNumber []byte

	// optional
	kSecTrustSettingsResult int32
}

func (t trustItem) Serial() *big.Int {
	serial := big.NewInt(0)
	serial.SetBytes(t.serialNumber)
	return serial
}

func (t trustItem) String() string {
	modDate := t.modDate.Format(plistModDateFormat)

	name := fmt.Sprintf("O=%s", strings.Join(t.issuerName.Organization, " "))
	if t.issuerName.CommonName != "" {
		name = fmt.Sprintf("CN=%s", t.issuerName.CommonName)
	}

	country := strings.Join(t.issuerName.Country, " ")

	return fmt.Sprintf("SHA1 Fingerprint: %s\n %s (%s)\n modDate: %s\n serialNumber: %d", t.key, name, country, modDate, t.Serial())
}
<commit_msg>store/darwin: go fmt<commit_after>// +build darwin

package store

import (
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"encoding/base64"
	"encoding/xml"
	"fmt"
	"io"
	"math/big"
	"os/exec"
	"os/user"
	"path/filepath"
	"reflect"
	"regexp"
	"strings"
	"time"

	"github.com/adamdecaf/cert-manage/tools/pem"
	"github.com/adamdecaf/cert-manage/whitelist"
)

// Docs
// - https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/security.1.html
// - https://github.com/adamdecaf/cert-manage/issues/9#issuecomment-337778241

var (
	plistModDateFormat = "2006-01-02T15:04:05Z"
	systemDirs         = []string{
		"/System/Library/Keychains/SystemRootCertificates.keychain",
		"/Library/Keychains/System.keychain",
	}
)

func getUserDirs() ([]string, error) {
	u, err := user.Current()
	if err != nil {
		return nil, err
	}

	return []string{
		filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain"),
		filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain-db"),
	}, nil
}

type darwinStore struct{}

func platform() Store {
	return darwinStore{}
}

func (s darwinStore) Backup() error {
	return nil
}

// List
//
// Note: Currently we are ignoring the login keychain. This is done because those certs are
// typically modified by the user (or an application the user trusts).
func (s darwinStore) List() ([]*x509.Certificate, error) {
	// TODO(adam): Should we call `x509.SystemCertPool()` instead?
	// We need to apply the trust settings anyway..
	return readDarwinCerts(systemDirs...)
}

func readDarwinCerts(paths ...string) ([]*x509.Certificate, error) {
	res := make([]*x509.Certificate, 0)

	args := []string{"find-certificate", "-a", "-p"}
	args = append(args, paths...)

	b, err := exec.Command("/usr/bin/security", args...).Output()
	if err != nil {
		return nil, err
	}

	cs, err := pem.Parse(b)
	if err != nil {
		return nil, err
	}
	for _, c := range cs {
		if c == nil {
			continue
		}
		add := true
		for i := range res {
			if reflect.DeepEqual(c.Signature, res[i].Signature) {
				add = false
				break
			}
		}
		if add {
			res = append(res, c)
		}
	}

	return res, nil
}

// TODO(adam): impl
func (s darwinStore) Remove(wh whitelist.Whitelist) error {
	return nil
}

func (s darwinStore) Restore() error {
	// /usr/bin/security trust-settings-import
	// ^ will prompt users, so I think the 'Restore' should just be
	// outputting what command to run and telling users to run it
	return nil
}

// security remove-trusted-cert <crt-file>
// What does ^ do, exactly?
// How does restore look?

// /usr/bin/security trust-settings-export
// /usr/bin/security trust-settings-import
// Could this be used in as a big batch operation?

// Is there a way to disable a cert? aka mark it as "Never Trust"?
// Otherwise, we'll need to make a full backup of all certs before touching anything.

// xml format, this was generated with the package github.com/gnewton/chidley
// but has also been modified by hand:
// 1. don't export struct names
// 2. remove outermost ChiChidleyRoot314159 wrapper as parsing fails with it
// 3. make `date []*date` rather than `date *date`

type chiPlist struct {
	// AttrVersion string `xml:" version,attr"  json:",omitempty"`
	ChiDict *chiDict `xml:" dict,omitempty" json:"dict,omitempty"`
}

type chiDict struct {
	ChiData    []*chiData  `xml:" data,omitempty" json:"data,omitempty"`
	ChiDate    []*chiDate  `xml:" date,omitempty" json:"date,omitempty"`
	ChiDict    *chiDict    `xml:" dict,omitempty" json:"dict,omitempty"`
	ChiInteger *chiInteger `xml:" integer,omitempty" json:"integer,omitempty"`
	ChiKey     []*chiKey   `xml:" key,omitempty" json:"key,omitempty"`
}

type chiKey struct {
	Text string `xml:",chardata" json:",omitempty"`
}

type chiData struct {
	Text string `xml:",chardata" json:",omitempty"`
}

type chiDate struct {
	Text string `xml:",chardata" json:",omitempty"`
}

type chiInteger struct {
	Text bool `xml:",chardata" json:",omitempty"`
}

func (p chiPlist) convertToTrustItems() []trustItem {
	out := make([]trustItem, 0)

	// TODO(adam): Add checks to make sure we're on target, and if not panic

	max := len(p.ChiDict.ChiDict.ChiDict.ChiData)
	for i := 0; i < max; i += 2 {
		item := trustItem{}

		// TODO(adam): rename, sha1Fingerprint
		item.key = strings.ToLower(p.ChiDict.ChiDict.ChiKey[i/2].Text)

		// trim whitespace
		r := regexp.MustCompile(`[^a-zA-Z0-9\+\/=]*`)
		r2 := strings.NewReplacer("\t", "", "\n", "", " ", "", "\r", "")

		s1 := r2.Replace(r.ReplaceAllString(p.ChiDict.ChiDict.ChiDict.ChiData[i].Text, ""))
		s2 := r2.Replace(r.ReplaceAllString(p.ChiDict.ChiDict.ChiDict.ChiData[i+1].Text, ""))

		bs1, _ := base64.StdEncoding.DecodeString(s1)
		bs2, _ := base64.StdEncoding.DecodeString(s2)

		// The issuerName's <data></data> block is only under asn1 encoding for the
		// issuerName field from 4.1.2.4 (https://tools.ietf.org/rfc/rfc5280)
		var issuer pkix.RDNSequence
		_, err := asn1.Unmarshal(bs1, &issuer)
		if err == nil {
			name := pkix.Name{}
			name.FillFromRDNSequence(&issuer)
			item.issuerName = name
		}

		dt := p.ChiDict.ChiDict.ChiDict.ChiDate[i/2].Text
		t, err := time.ParseInLocation(plistModDateFormat, dt, time.UTC)
		if err == nil {
			item.modDate = t
		}

		// serialNumber is just a base64 encoded big endian (big) int
		item.serialNumber = bs2

		out = append(out, item)
	}

	return out
}

func parsePlist(in io.Reader) (chiPlist, error) {
	dec := xml.NewDecoder(in)
	var out chiPlist
	err := dec.Decode(&out)
	return out, err
}

// The human readable struct
type trustItem struct {
	// required
	key          string
	issuerName   pkix.Name
	modDate      time.Time
	serialNumber []byte

	// optional
	kSecTrustSettingsResult int32
}

func (t trustItem) Serial() *big.Int {
	serial := big.NewInt(0)
	serial.SetBytes(t.serialNumber)
	return serial
}

func (t trustItem) String() string {
	modDate := t.modDate.Format(plistModDateFormat)

	name := fmt.Sprintf("O=%s", strings.Join(t.issuerName.Organization, " "))
	if t.issuerName.CommonName != "" {
		name = fmt.Sprintf("CN=%s", t.issuerName.CommonName)
	}

	country := strings.Join(t.issuerName.Country, " ")

	return fmt.Sprintf("SHA1 Fingerprint: %s\n %s (%s)\n modDate: %s\n serialNumber: %d", t.key, name, country, modDate, t.Serial())
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2016 VMware, Inc. All Rights Reserved.
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package utils

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"

	"github.com/vmware/harbor/utils/log"
)

// BuildRegistryURL ...
func BuildRegistryURL(segments ...string) string {
	registryURL := os.Getenv("REGISTRY_URL")
	if registryURL == "" {
		registryURL = "http://localhost:5000"
	}
	url := registryURL + "/v2"
	for _, s := range segments {
		if s == "v2" {
			log.Debugf("unnecessary v2 in %v", segments)
			continue
		}
		url += "/" + s
	}
	return url
}

// RegistryAPIGet triggers GET request to the URL which is the endpoint of registry and returns the response body.
// It will attach a valid jwt token to the request if registry requires.
func RegistryAPIGet(url, username string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	if response.StatusCode == http.StatusOK {
		return result, nil
	} else if response.StatusCode == http.StatusUnauthorized {
		authenticate := response.Header.Get("WWW-Authenticate")
		str := strings.Split(authenticate, " ")[1]
		log.Debugf("url: %s", url)
		var service string
		var scope string
		strs := strings.Split(str, ",")
		for _, s := range strs {
			if strings.Contains(s, "service") {
				service = s
			} else if strings.Contains(s, "scope") {
				scope = s
			}
		}
		service = strings.Split(service, "\"")[1]
		scope = strings.Split(scope, "\"")[1]
		token, err := GenTokenForUI(username, service, scope)
		if err != nil {
			return nil, err
		}
		request, err := http.NewRequest("GET", url, nil)
		if err != nil {
			return nil, err
		}
		request.Header.Add("Authorization", "Bearer "+token)
		client := &http.Client{}
		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
			//	log.Infof("via length: %d\n", len(via))
			if len(via) >= 10 {
				return fmt.Errorf("too many redirects")
			}
			for k, v := range via[0].Header {
				if _, ok := req.Header[k]; !ok {
					req.Header[k] = v
				}
			}
			return nil
		}
		response, err = client.Do(request)
		if err != nil {
			return nil, err
		}
		if response.StatusCode != http.StatusOK {
			errMsg := fmt.Sprintf("Unexpected return code from registry: %d", response.StatusCode)
			log.Error(errMsg)
			return nil, fmt.Errorf(errMsg)
		}
		result, err = ioutil.ReadAll(response.Body)
		if err != nil {
			return nil, err
		}
		defer response.Body.Close()
		return result, nil
	} else {
		return nil, errors.New(string(result))
	}
}
<commit_msg>fix potential index out of range error<commit_after>/*
   Copyright (c) 2016 VMware, Inc. All Rights Reserved.
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package utils

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"

	"github.com/vmware/harbor/utils/log"
)

// BuildRegistryURL ...
func BuildRegistryURL(segments ...string) string {
	registryURL := os.Getenv("REGISTRY_URL")
	if registryURL == "" {
		registryURL = "http://localhost:5000"
	}
	url := registryURL + "/v2"
	for _, s := range segments {
		if s == "v2" {
			log.Debugf("unnecessary v2 in %v", segments)
			continue
		}
		url += "/" + s
	}
	return url
}

// RegistryAPIGet triggers GET request to the URL which is the endpoint of registry and returns the response body.
// It will attach a valid jwt token to the request if registry requires.
func RegistryAPIGet(url, username string) ([]byte, error) {

	log.Debugf("Registry API url: %s", url)
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	if response.StatusCode == http.StatusOK {
		return result, nil
	} else if response.StatusCode == http.StatusUnauthorized {
		authenticate := response.Header.Get("WWW-Authenticate")
		log.Debugf("authenticate header: %s", authenticate)
		str := strings.Split(authenticate, " ")[1]
		var service string
		var scope string
		strs := strings.Split(str, ",")
		for _, s := range strs {
			if strings.Contains(s, "service") {
				service = s
			} else if strings.Contains(s, "scope") {
				scope = s
			}
		}
		if arr := strings.Split(service, "\""); len(arr) > 1 {
			service = arr[1]
		}
		if arr := strings.Split(scope, "\""); len(arr) > 1 {
			scope = arr[1]
		}
		token, err := GenTokenForUI(username, service, scope)
		if err != nil {
			return nil, err
		}
		request, err := http.NewRequest("GET", url, nil)
		if err != nil {
			return nil, err
		}
		request.Header.Add("Authorization", "Bearer "+token)
		client := &http.Client{}
		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
			//	log.Infof("via length: %d\n", len(via))
			if len(via) >= 10 {
				return fmt.Errorf("too many redirects")
			}
			for k, v := range via[0].Header {
				if _, ok := req.Header[k]; !ok {
					req.Header[k] = v
				}
			}
			return nil
		}
		response, err = client.Do(request)
		if err != nil {
			return nil, err
		}
		if response.StatusCode != http.StatusOK {
			errMsg := fmt.Sprintf("Unexpected return code from registry: %d", response.StatusCode)
			log.Error(errMsg)
			return nil, fmt.Errorf(errMsg)
		}
		result, err = ioutil.ReadAll(response.Body)
		if err != nil {
			return nil, err
		}
		defer response.Body.Close()
		return result, nil
	} else {
		return nil, errors.New(string(result))
	}
}
<|endoftext|>


<commit_before>package etcd

import (
	"context"
	"fmt"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	"github.com/prometheus/common/model"

	"github.com/openshift/origin/test/extended/prometheus/client"
	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[sig-etcd] etcd", func() {
	defer g.GinkgoRecover()
	oc := exutil.NewCLIWithoutNamespace("etcd-leader-change").AsAdmin()
	g.It("leader changes are not excessive [Late]", func() {
		prometheus, err := client.NewE2EPrometheusRouterClient(oc)
		o.Expect(err).ToNot(o.HaveOccurred())

		// we only consider series sent since the beginning of the test
		testDuration := exutil.DurationSinceStartInSeconds().String()

		g.By("Examining the number of etcd leadership changes over the run")
		result, _, err := prometheus.Query(context.Background(), fmt.Sprintf("max(max by (pod,job) (increase(etcd_server_leader_changes_seen_total[%s])))", testDuration), time.Now())
		o.Expect(err).ToNot(o.HaveOccurred())

		vec, ok := result.(model.Vector)
		if !ok {
			o.Expect(fmt.Errorf("expecting Prometheus query to return a vector, got %s instead", vec.Type())).ToNot(o.HaveOccurred())
		}

		if len(vec) == 0 {
			o.Expect(fmt.Errorf("expecting Prometheus query to return at least one item, got 0 instead")).ToNot(o.HaveOccurred())
		}

		leaderChanges := vec[0].Value
		if leaderChanges != 0 {
			o.Expect(fmt.Errorf("Observed %s leader changes (expected 0) in %s: Leader changes are a result of stopping the etcd leader process or from latency (disk or network), review etcd performance metrics", leaderChanges, testDuration)).ToNot(o.HaveOccurred())
		}
	})
})
<commit_msg>Fix etcd leader changes are not excessive for Hypershift<commit_after>package etcd

import (
	"context"
	"fmt"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	"github.com/prometheus/common/model"

	configv1 "github.com/openshift/api/config/v1"
	"github.com/openshift/origin/test/extended/prometheus/client"
	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[sig-etcd] etcd", func() {
	defer g.GinkgoRecover()
	oc := exutil.NewCLIWithoutNamespace("etcd-leader-change").AsAdmin()
	g.It("leader changes are not excessive [Late]", func() {
		controlPlaneTopology, err := exutil.GetControlPlaneTopology(oc)
		o.Expect(err).NotTo(o.HaveOccurred())
		if *controlPlaneTopology == configv1.ExternalTopologyMode {
			oc = exutil.NewHypershiftManagementCLI("default").AsAdmin().WithoutNamespace()
		}

		prometheus, err := client.NewE2EPrometheusRouterClient(oc)
		o.Expect(err).ToNot(o.HaveOccurred())

		// we only consider series sent since the beginning of the test
		testDuration := exutil.DurationSinceStartInSeconds().String()

		g.By("Examining the number of etcd leadership changes over the run")
		etcdNamespace := "openshift-etcd"
		if *controlPlaneTopology == configv1.ExternalTopologyMode {
			etcdNamespace = "clusters-.*"
		}
		result, _, err := prometheus.Query(context.Background(), fmt.Sprintf(`max(max by (pod,job) (increase(etcd_server_leader_changes_seen_total{namespace=~"%s"}[%s])))`, etcdNamespace, testDuration), time.Now())
		o.Expect(err).ToNot(o.HaveOccurred())

		vec, ok := result.(model.Vector)
		if !ok {
			o.Expect(fmt.Errorf("expecting Prometheus query to return a vector, got %s instead", vec.Type())).ToNot(o.HaveOccurred())
		}

		if len(vec) == 0 {
			o.Expect(fmt.Errorf("expecting Prometheus query to return at least one item, got 0 instead")).ToNot(o.HaveOccurred())
		}

		leaderChanges := vec[0].Value
		if leaderChanges != 0 {
			o.Expect(fmt.Errorf("Observed %s leader changes (expected 0) in %s: Leader changes are a result of stopping the etcd leader process or from latency (disk or network), review etcd performance metrics", leaderChanges, testDuration)).ToNot(o.HaveOccurred())
		}
	})
})
<|endoftext|>


<commit_before>package services

import (
	"encoding/json"
	"html"

	"github.com/khades/servbot/httpclient"
	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

type tdjTrack struct {
	Title string
}

// CheckTwitchDJTrack checks last playing track
func CheckTwitchDJTrack() {
	channels, error := repos.GetTwitchDJEnabledChannels()
	if error != nil {
		return
	}
	for _, channel := range *channels {
		checkOneTwitchDJTrack(&channel)
	}
}

func checkOneTwitchDJTrack(channel *models.ChannelInfo) {

	status := models.TwitchDJ{ID: channel.TwitchDJ.ID}
	defer repos.PushTwitchDJ(&channel.ChannelID, &status)
	//log.Printf("Checking %s twitchDj track \n", channel.Channel)
	resp, error := httpclient.Get("https://twitch-dj.ru/includes/back.php?func=get_track&channel=" + channel.TwitchDJ.ID)

	if error != nil {
		//log.Println(error)
		return
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	track := tdjTrack{}
	marshallError := json.NewDecoder(resp.Body).Decode(&track)
	if marshallError != nil {
		//log.Println(marshallError)
		return
	}
	if track.Title != "" {
		status.Playing = true
		status.Track = html.UnescapeString(track.Title)
	}
}
<commit_msg>Feature: Auto notify in chat on track change<commit_after>package services

import (
	"encoding/json"
	"html"

	"github.com/khades/servbot/bot"
	"github.com/khades/servbot/httpclient"
	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

type tdjTrack struct {
	Title string
}

// CheckTwitchDJTrack checks last playing track
func CheckTwitchDJTrack() {
	channels, error := repos.GetTwitchDJEnabledChannels()
	if error != nil {
		return
	}
	for _, channel := range *channels {
		checkOneTwitchDJTrack(&channel)
	}
}

func checkOneTwitchDJTrack(channel *models.ChannelInfo) {

	status := models.TwitchDJ{ID: channel.TwitchDJ.ID}
	defer repos.PushTwitchDJ(&channel.ChannelID, &status)
	//log.Printf("Checking %s twitchDj track \n", channel.Channel)
	resp, error := httpclient.Get("https://twitch-dj.ru/includes/back.php?func=get_track&channel=" + channel.TwitchDJ.ID)

	if error != nil {
		//log.Println(error)
		return
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	track := tdjTrack{}
	marshallError := json.NewDecoder(resp.Body).Decode(&track)
	if marshallError != nil {
		//log.Println(marshallError)
		return
	}
	if track.Title != "" {
		status.Playing = true
		status.Track = html.UnescapeString(track.Title)
	}
	if status.Playing == false {
		return
	}
	if channel.TwitchDJ.NotifyOnUpdate == true {
		channelName, channelNameError := repos.GetUsernameByID(&channel.ChannelID)
		if channelNameError == nil && *channelName != "" && status.Playing == true && channel.TwitchDJ.Track != status.Track {
			bot.IrcClientInstance.SendPublic(&models.OutgoingMessage{
				Channel: *channelName,
				Body:    "[TwitchDJ] Now Playing: " + status.Track})
		}
	}
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package server

import (
	"testing"

	srvconfig "github.com/containerd/containerd/services/server/config"
	"gotest.tools/assert"
	is "gotest.tools/assert/cmp"
)

func TestCreateTopLevelDirectoriesErrorsWithSamePathForRootAndState(t *testing.T) {
	path := "/tmp/path/for/testing"
	err := CreateTopLevelDirectories(&srvconfig.Config{
		Root:  path,
		State: path,
	})
	assert.Check(t, is.Error(err, "root and state must be different paths"))
}
<commit_msg>add tests to server_test<commit_after>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package server

import (
	"testing"

	srvconfig "github.com/containerd/containerd/services/server/config"
	"gotest.tools/assert"
	is "gotest.tools/assert/cmp"
)

func TestCreateTopLevelDirectoriesErrorsWithSamePathForRootAndState(t *testing.T) {
	path := "/tmp/path/for/testing"
	err := CreateTopLevelDirectories(&srvconfig.Config{
		Root:  path,
		State: path,
	})
	assert.Check(t, is.Error(err, "root and state must be different paths"))
}

func TestCreateTopLevelDirectoriesWithEmptyStatePath(t *testing.T) {
	statePath := ""
	rootPath := "/tmp/path/for/testing"
	err := CreateTopLevelDirectories(&srvconfig.Config{
		Root:  rootPath,
		State: statePath,
	})
	assert.Check(t, is.Error(err, "state must be specified"))
}

func TestCreateTopLevelDirectoriesWithEmptyRootPath(t *testing.T) {
	statePath := "/tmp/path/for/testing"
	rootPath := ""
	err := CreateTopLevelDirectories(&srvconfig.Config{
		Root:  rootPath,
		State: statePath,
	})
	assert.Check(t, is.Error(err, "root must be specified"))
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, 2016 Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package jsonresponse // import "resenje.org/jsonresponse"

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

var (
	// DefaultContentTypeHeader is the value of if "Content-Type" header
	// in HTTP response.
	DefaultContentTypeHeader = "application/json; charset=utf-8"
)

// MessageResponse is the response structure that will be written by
// Respond function if respond argument is nil.
type MessageResponse struct {
	Message string `json:"message,omitempty"`
	Code    int    `json:"code,omitempty"`
}

// NewMessage returns MessageResponse with a provided textual message.
func NewMessage(message string) *MessageResponse {
	return &MessageResponse{
		Message: message,
	}
}

// Respond writes a JSON-encoded body to http.ResponseWriter.
func Respond(w http.ResponseWriter, statusCode int, response interface{}) {
	if response == nil {
		response = &MessageResponse{}
	} else if r, ok := response.(MessageResponse); ok {
		response = &r
	}
	if r, ok := response.(*MessageResponse); ok {
		if r.Code == 0 {
			r.Code = statusCode
		}
		if r.Message == "" {
			r.Message = http.StatusText(statusCode)
		}
	}
	b, err := json.Marshal(response)
	if err != nil {
		panic(err)
	}
	if DefaultContentTypeHeader != "" {
		w.Header().Set("Content-Type", DefaultContentTypeHeader)
	}
	w.WriteHeader(statusCode)
	fmt.Fprint(w, string(b)+"\n")
}

// Continue writes a response with status code 100.
func Continue(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusContinue, response)
}

// SwitchingProtocols writes a response with status code 101.
func SwitchingProtocols(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusSwitchingProtocols, response)
}

// OK writes a response with status code 200.
func OK(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusOK, response)
}

// Created writes a response with status code 201.
func Created(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusCreated, response)
}

// Accepted writes a response with status code 202.
func Accepted(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusAccepted, response)
}

// NonAuthoritativeInfo writes a response with status code 203.
func NonAuthoritativeInfo(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNonAuthoritativeInfo, response)
}

// ResetContent writes a response with status code 205.
func ResetContent(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusResetContent, response)
}

// PartialContent writes a response with status code 206.
func PartialContent(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPartialContent, response)
}

// MultipleChoices writes a response with status code 300.
func MultipleChoices(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusMultipleChoices, response)
}

// MovedPermanently writes a response with status code 301.
func MovedPermanently(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusMovedPermanently, response)
}

// Found writes a response with status code 302.
func Found(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusFound, response)
}

// SeeOther writes a response with status code 303.
func SeeOther(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusSeeOther, response)
}

// NotModified writes a response with status code 304.
func NotModified(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotModified, response)
}

// UseProxy writes a response with status code 305.
func UseProxy(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUseProxy, response)
}

// TemporaryRedirect writes a response with status code 307.
func TemporaryRedirect(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusTemporaryRedirect, response)
}

// PermanentRedirect writes a response with status code 308.
func PermanentRedirect(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPermanentRedirect, response)
}

// BadRequest writes a response with status code 400.
func BadRequest(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusBadRequest, response)
}

// Unauthorized writes a response with status code 401.
func Unauthorized(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUnauthorized, response)
}

// PaymentRequired writes a response with status code 402.
func PaymentRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPaymentRequired, response)
}

// Forbidden writes a response with status code 403.
func Forbidden(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusForbidden, response)
}

// NotFound writes a response with status code 404.
func NotFound(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotFound, response)
}

// MethodNotAllowed writes a response with status code 405.
func MethodNotAllowed(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusMethodNotAllowed, response)
}

// NotAcceptable writes a response with status code 406.
func NotAcceptable(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotAcceptable, response)
}

// ProxyAuthRequired writes a response with status code 407.
func ProxyAuthRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusProxyAuthRequired, response)
}

// RequestTimeout writes a response with status code 408.
func RequestTimeout(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestTimeout, response)
}

// Conflict writes a response with status code 409.
func Conflict(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusConflict, response)
}

// Gone writes a response with status code 410.
func Gone(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusGone, response)
}

// LengthRequired writes a response with status code 411.
func LengthRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusLengthRequired, response)
}

// PreconditionFailed writes a response with status code 412.
func PreconditionFailed(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPreconditionFailed, response)
}

// RequestEntityTooLarge writes a response with status code 413.
func RequestEntityTooLarge(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestEntityTooLarge, response)
}

// RequestURITooLong writes a response with status code 414.
func RequestURITooLong(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestURITooLong, response)
}

// UnsupportedMediaType writes a response with status code 415.
func UnsupportedMediaType(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUnsupportedMediaType, response)
}

// RequestedRangeNotSatisfiable writes a response with status code 416.
func RequestedRangeNotSatisfiable(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestedRangeNotSatisfiable, response)
}

// ExpectationFailed writes a response with status code 417.
func ExpectationFailed(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusExpectationFailed, response)
}

// Teapot writes a response with status code 418.
func Teapot(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusTeapot, response)
}

// UpgradeRequired writes a response with status code 426.
func UpgradeRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUpgradeRequired, response)
}

// PreconditionRequired writes a response with status code 428.
func PreconditionRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPreconditionRequired, response)
}

// TooManyRequests writes a response with status code 429.
func TooManyRequests(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusTooManyRequests, response)
}

// RequestHeaderFieldsTooLarge writes a response with status code 431.
func RequestHeaderFieldsTooLarge(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestHeaderFieldsTooLarge, response)
}

// UnavailableForLegalReasons writes a response with status code 451.
func UnavailableForLegalReasons(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUnavailableForLegalReasons, response)
}

// InternalServerError writes a response with status code 500.
func InternalServerError(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusInternalServerError, response)
}

// NotImplemented writes a response with status code 501.
func NotImplemented(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotImplemented, response)
}

// BadGateway writes a response with status code 502.
func BadGateway(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusBadGateway, response)
}

// ServiceUnavailable writes a response with status code 503.
func ServiceUnavailable(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusServiceUnavailable, response)
}

// GatewayTimeout writes a response with status code 504.
func GatewayTimeout(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusGatewayTimeout, response)
}

// HTTPVersionNotSupported writes a response with status code 505.
func HTTPVersionNotSupported(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusHTTPVersionNotSupported, response)
}
<commit_msg>Set SetEscapeHTML to false by default<commit_after>// Copyright (c) 2015, 2016 Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package jsonresponse // import "resenje.org/jsonresponse"

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

var (
	// DefaultContentTypeHeader is the value of if "Content-Type" header
	// in HTTP response.
	DefaultContentTypeHeader = "application/json; charset=utf-8"
	// EscapeHTML specifies whether problematic HTML characters
	// should be escaped inside JSON quoted strings.
	EscapeHTML = false
)

// MessageResponse is the response structure that will be written by
// Respond function if respond argument is nil.
type MessageResponse struct {
	Message string `json:"message,omitempty"`
	Code    int    `json:"code,omitempty"`
}

// NewMessage returns MessageResponse with a provided textual message.
func NewMessage(message string) *MessageResponse {
	return &MessageResponse{
		Message: message,
	}
}

// Respond writes a JSON-encoded body to http.ResponseWriter.
func Respond(w http.ResponseWriter, statusCode int, response interface{}) {
	if response == nil {
		response = &MessageResponse{}
	} else if r, ok := response.(MessageResponse); ok {
		response = &r
	}
	if r, ok := response.(*MessageResponse); ok {
		if r.Code == 0 {
			r.Code = statusCode
		}
		if r.Message == "" {
			r.Message = http.StatusText(statusCode)
		}
	}
	var b bytes.Buffer
	enc := json.NewEncoder(&b)
	enc.SetEscapeHTML(EscapeHTML)
	if err := enc.Encode(response); err != nil {
		panic(err)
	}
	if DefaultContentTypeHeader != "" {
		w.Header().Set("Content-Type", DefaultContentTypeHeader)
	}
	w.WriteHeader(statusCode)
	fmt.Fprintln(w, b.String())
}

// Continue writes a response with status code 100.
func Continue(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusContinue, response)
}

// SwitchingProtocols writes a response with status code 101.
func SwitchingProtocols(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusSwitchingProtocols, response)
}

// OK writes a response with status code 200.
func OK(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusOK, response)
}

// Created writes a response with status code 201.
func Created(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusCreated, response)
}

// Accepted writes a response with status code 202.
func Accepted(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusAccepted, response)
}

// NonAuthoritativeInfo writes a response with status code 203.
func NonAuthoritativeInfo(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNonAuthoritativeInfo, response)
}

// ResetContent writes a response with status code 205.
func ResetContent(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusResetContent, response)
}

// PartialContent writes a response with status code 206.
func PartialContent(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPartialContent, response)
}

// MultipleChoices writes a response with status code 300.
func MultipleChoices(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusMultipleChoices, response)
}

// MovedPermanently writes a response with status code 301.
func MovedPermanently(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusMovedPermanently, response)
}

// Found writes a response with status code 302.
func Found(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusFound, response)
}

// SeeOther writes a response with status code 303.
func SeeOther(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusSeeOther, response)
}

// NotModified writes a response with status code 304.
func NotModified(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotModified, response)
}

// UseProxy writes a response with status code 305.
func UseProxy(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUseProxy, response)
}

// TemporaryRedirect writes a response with status code 307.
func TemporaryRedirect(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusTemporaryRedirect, response)
}

// PermanentRedirect writes a response with status code 308.
func PermanentRedirect(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPermanentRedirect, response)
}

// BadRequest writes a response with status code 400.
func BadRequest(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusBadRequest, response)
}

// Unauthorized writes a response with status code 401.
func Unauthorized(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUnauthorized, response)
}

// PaymentRequired writes a response with status code 402.
func PaymentRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPaymentRequired, response)
}

// Forbidden writes a response with status code 403.
func Forbidden(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusForbidden, response)
}

// NotFound writes a response with status code 404.
func NotFound(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotFound, response)
}

// MethodNotAllowed writes a response with status code 405.
func MethodNotAllowed(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusMethodNotAllowed, response)
}

// NotAcceptable writes a response with status code 406.
func NotAcceptable(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotAcceptable, response)
}

// ProxyAuthRequired writes a response with status code 407.
func ProxyAuthRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusProxyAuthRequired, response)
}

// RequestTimeout writes a response with status code 408.
func RequestTimeout(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestTimeout, response)
}

// Conflict writes a response with status code 409.
func Conflict(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusConflict, response)
}

// Gone writes a response with status code 410.
func Gone(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusGone, response)
}

// LengthRequired writes a response with status code 411.
func LengthRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusLengthRequired, response)
}

// PreconditionFailed writes a response with status code 412.
func PreconditionFailed(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPreconditionFailed, response)
}

// RequestEntityTooLarge writes a response with status code 413.
func RequestEntityTooLarge(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestEntityTooLarge, response)
}

// RequestURITooLong writes a response with status code 414.
func RequestURITooLong(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestURITooLong, response)
}

// UnsupportedMediaType writes a response with status code 415.
func UnsupportedMediaType(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUnsupportedMediaType, response)
}

// RequestedRangeNotSatisfiable writes a response with status code 416.
func RequestedRangeNotSatisfiable(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestedRangeNotSatisfiable, response)
}

// ExpectationFailed writes a response with status code 417.
func ExpectationFailed(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusExpectationFailed, response)
}

// Teapot writes a response with status code 418.
func Teapot(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusTeapot, response)
}

// UpgradeRequired writes a response with status code 426.
func UpgradeRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUpgradeRequired, response)
}

// PreconditionRequired writes a response with status code 428.
func PreconditionRequired(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusPreconditionRequired, response)
}

// TooManyRequests writes a response with status code 429.
func TooManyRequests(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusTooManyRequests, response)
}

// RequestHeaderFieldsTooLarge writes a response with status code 431.
func RequestHeaderFieldsTooLarge(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusRequestHeaderFieldsTooLarge, response)
}

// UnavailableForLegalReasons writes a response with status code 451.
func UnavailableForLegalReasons(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusUnavailableForLegalReasons, response)
}

// InternalServerError writes a response with status code 500.
func InternalServerError(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusInternalServerError, response)
}

// NotImplemented writes a response with status code 501.
func NotImplemented(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusNotImplemented, response)
}

// BadGateway writes a response with status code 502.
func BadGateway(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusBadGateway, response)
}

// ServiceUnavailable writes a response with status code 503.
func ServiceUnavailable(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusServiceUnavailable, response)
}

// GatewayTimeout writes a response with status code 504.
func GatewayTimeout(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusGatewayTimeout, response)
}

// HTTPVersionNotSupported writes a response with status code 505.
func HTTPVersionNotSupported(w http.ResponseWriter, response interface{}) {
	Respond(w, http.StatusHTTPVersionNotSupported, response)
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom_test

import (
	"bytes"
	"encoding/json"
	"fmt"
	. "github.com/FactomProject/factom"
	"testing"
)

var _ = fmt.Sprint("testing")

func TestNewJSON2Request(t *testing.T) {
	type t1 struct {
		A int
		B string
	}
	//removed because this test was failing when running ack tests. should be made stateless.
	/*
		x1 := &t1{A: 1, B: "hello"}
		j1 := NewJSON2Request("testing", APICounter(), x1)
		r1 := `{"jsonrpc":"2.0","id":1,"params":{"A":1,"B":"hello"},"method":"testing"}`
		if p, err := json.Marshal(j1); err != nil {
			t.Error(err)
		} else if string(p) != r1 {
			t.Errorf(string(p))
		}

		x2 := "hello"
		j2 := NewJSON2Request("testing", APICounter(), x2)
		r2 := `{"jsonrpc":"2.0","id":2,"params":"hello","method":"testing"}`
		if p, err := json.Marshal(j2); err != nil {
			t.Error(err)
		} else if string(p) != r2 {
			t.Errorf(string(p))
		}

		x3 := new(Entry)
		x3.ChainID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		x3.ExtIDs = append(x3.ExtIDs, []byte("test01"))
		x3.Content = []byte("hello factom")
		j3 := NewJSON2Request("testing", APICounter(), x3)
		r3 := `{"jsonrpc":"2.0","id":3,"params":{"chainid":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","extids":["746573743031"],"content":"68656c6c6f20666163746f6d"},"method":"testing"}`
		if p, err := json.Marshal(j3); err != nil {
			t.Error(err)
		} else if string(p) != r3 {
			t.Errorf(string(p))
		}*/
}

func TestJSON2Response(t *testing.T) {
	j1 := []byte(`{"jsonrpc":"2.0","id":2,"result":"hello"}`)
	j2 := []byte(`{"jsonrpc":"2.0","id":3,"result":{"ChainID":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","ExtIDs":["746573743031"],"Content":"68656c6c6f20666163746f6d"},"method":"testing"}`)
	r1 := `"hello"`
	r2 := Entry{ChainID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", ExtIDs: [][]byte{[]byte("test01")}, Content: []byte("hello factom")}

	resp := NewJSON2Response()
	if err := json.Unmarshal(j1, resp); err != nil {
		t.Error(err)
	} else if string(resp.JSONResult()) != r1 {
		t.Errorf("%s is not equal to %s", resp.JSONResult(), r1)
	}

	resp = NewJSON2Response()
	if err := json.Unmarshal(j2, resp); err != nil {
		t.Error(err)
	}
	e := new(Entry)
	e.UnmarshalJSON(resp.JSONResult())

	if e.ChainID != r2.ChainID {
		t.Error(e)
	}
	for i, v := range e.ExtIDs {
		if !bytes.Equal(v, r2.ExtIDs[i]) {
			t.Error(e)
		}
	}
	if !bytes.Equal(e.Content, r2.Content) {
		t.Error(e)
	}
}
<commit_msg>minor updates for jsonrpc test<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom_test

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

	. "github.com/FactomProject/factom"

	"testing"
)

var _ = fmt.Sprint("testing")

func TestNewJSON2Request(t *testing.T) {
	type t1 struct {
		A int
		B string
	}

	x1 := &t1{A: 1, B: "hello"}
	j1 := NewJSON2Request("testing", APICounter(), x1)
	r1 := `{"jsonrpc":"2.0","id":1,"params":{"A":1,"B":"hello"},"method":"testing"}`
	if p, err := json.Marshal(j1); err != nil {
		t.Error(err)
	} else if string(p) != r1 {
		t.Errorf(string(p))
	}

	x2 := "hello"
	j2 := NewJSON2Request("testing", APICounter(), x2)
	r2 := `{"jsonrpc":"2.0","id":2,"params":"hello","method":"testing"}`
	if p, err := json.Marshal(j2); err != nil {
		t.Error(err)
	} else if string(p) != r2 {
		t.Errorf(string(p))
	}

	x3 := new(Entry)
	x3.ChainID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
	x3.ExtIDs = append(x3.ExtIDs, []byte("test01"))
	x3.Content = []byte("hello factom")
	j3 := NewJSON2Request("testing", APICounter(), x3)
	r3 := `{"jsonrpc":"2.0","id":3,"params":{"chainid":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","extids":["746573743031"],"content":"68656c6c6f20666163746f6d"},"method":"testing"}`
	if p, err := json.Marshal(j3); err != nil {
		t.Error(err)
	} else if string(p) != r3 {
		t.Errorf(string(p))
	}
}

func TestJSON2Response(t *testing.T) {
	j1 := []byte(`{"jsonrpc":"2.0","id":2,"result":"hello"}`)
	j2 := []byte(`{"jsonrpc":"2.0","id":3,"result":{"ChainID":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","ExtIDs":["746573743031"],"Content":"68656c6c6f20666163746f6d"},"method":"testing"}`)
	r1 := `"hello"`
	r2 := Entry{ChainID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", ExtIDs: [][]byte{[]byte("test01")}, Content: []byte("hello factom")}

	resp := NewJSON2Response()
	if err := json.Unmarshal(j1, resp); err != nil {
		t.Error(err)
	} else if string(resp.JSONResult()) != r1 {
		t.Errorf("%s is not equal to %s", resp.JSONResult(), r1)
	}

	resp = NewJSON2Response()
	if err := json.Unmarshal(j2, resp); err != nil {
		t.Error(err)
	}
	e := new(Entry)
	e.UnmarshalJSON(resp.JSONResult())

	if e.ChainID != r2.ChainID {
		t.Error(e)
	}
	for i, v := range e.ExtIDs {
		if !bytes.Equal(v, r2.ExtIDs[i]) {
			t.Error(e)
		}
	}
	if !bytes.Equal(e.Content, r2.Content) {
		t.Error(e)
	}
}
<|endoftext|>


<commit_before>package main

import "fmt"

type Node struct {
	int name `noder`
}

func main() {
	x := Node{}

	fmt.Println(x)
}
<commit_msg>Fix mini prob<commit_after>package main

import "fmt"

type Node struct {
	name int `noder`
}

func main() {
	x := Node{}

	fmt.Println(x)
}
<|endoftext|>


<commit_before>package osarch

import (
	"fmt"
)

const (
	ARCH_UNKNOWN                     = 0
	ARCH_32BIT_INTEL_X86             = 1
	ARCH_64BIT_INTEL_X86             = 2
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN   = 3
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN   = 4
	ARCH_32BIT_POWERPC_BIG_ENDIAN    = 5
	ARCH_64BIT_POWERPC_BIG_ENDIAN    = 6
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN = 7
	ARCH_64BIT_S390_BIG_ENDIAN       = 8
	ARCH_32BIT_MIPS_BIG_ENDIAN       = 9
	ARCH_32BIT_MIPS_LITTLE_ENDIAN    = 10
	ARCH_64BIT_MIPS64_BIG_ENDIAN     = 11
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN  = 12
)

var architectureNames = map[int]string{
	ARCH_32BIT_INTEL_X86:             "i686",
	ARCH_64BIT_INTEL_X86:             "x86_64",
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   "armv7l",
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   "aarch64",
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    "ppc",
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    "ppc64",
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: "ppc64le",
	ARCH_64BIT_S390_BIG_ENDIAN:       "s390x",
	ARCH_32BIT_MIPS_BIG_ENDIAN:       "mips",
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    "mipsle",
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     "mips64",
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  "mips64le",
}

var architectureAliases = map[int][]string{
	ARCH_32BIT_INTEL_X86:             {"i386", "i586", "386", "x86", "generic_32"},
	ARCH_64BIT_INTEL_X86:             {"amd64", "generic_64"},
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   {"armel", "armhf", "arm", "armhfp", "armv7a_hardfp", "armv7", "armv7a_vfpv3_hardfp"},
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   {"arm64", "arm64_generic"},
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    {"powerpc"},
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    {"powerpc64", "ppc64"},
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: {"ppc64el"},
	ARCH_32BIT_MIPS_BIG_ENDIAN:       {"mips"},
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    {"mipsle"},
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     {"mips64"},
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  {"mips64le"},
}

var architecturePersonalities = map[int]string{
	ARCH_32BIT_INTEL_X86:             "linux32",
	ARCH_64BIT_INTEL_X86:             "linux64",
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   "linux32",
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   "linux64",
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    "linux32",
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    "linux64",
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: "linux64",
	ARCH_64BIT_S390_BIG_ENDIAN:       "linux64",
	ARCH_32BIT_MIPS_BIG_ENDIAN:       "linux32",
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    "linux32",
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     "linux64",
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  "linux64",
}

var architectureSupportedPersonalities = map[int][]int{
	ARCH_32BIT_INTEL_X86:             {},
	ARCH_64BIT_INTEL_X86:             {ARCH_32BIT_INTEL_X86},
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   {},
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   {ARCH_32BIT_ARMV7_LITTLE_ENDIAN},
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    {},
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    {ARCH_32BIT_POWERPC_BIG_ENDIAN},
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: {},
	ARCH_64BIT_S390_BIG_ENDIAN:       {},
	ARCH_32BIT_MIPS_BIG_ENDIAN:       {},
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    {},
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     {ARCH_32BIT_MIPS_BIG_ENDIAN},
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  {ARCH_32BIT_MIPS_LITTLE_ENDIAN},
}

const ArchitectureDefault = "x86_64"

func ArchitectureName(arch int) (string, error) {
	arch_name, exists := architectureNames[arch]
	if exists {
		return arch_name, nil
	}

	return "unknown", fmt.Errorf("Architecture isn't supported: %d", arch)
}

func ArchitectureId(arch string) (int, error) {
	for arch_id, arch_name := range architectureNames {
		if arch_name == arch {
			return arch_id, nil
		}
	}

	for arch_id, arch_aliases := range architectureAliases {
		for _, arch_name := range arch_aliases {
			if arch_name == arch {
				return arch_id, nil
			}
		}
	}

	return 0, fmt.Errorf("Architecture isn't supported: %s", arch)
}

func ArchitecturePersonality(arch int) (string, error) {
	arch_personality, exists := architecturePersonalities[arch]
	if exists {
		return arch_personality, nil
	}

	return "", fmt.Errorf("Architecture isn't supported: %d", arch)
}

func ArchitecturePersonalities(arch int) ([]int, error) {
	personalities, exists := architectureSupportedPersonalities[arch]
	if exists {
		return personalities, nil
	}

	return []int{}, fmt.Errorf("Architecture isn't supported: %d", arch)
}

// ArchitectureGetLocalID returns the local hardware architecture ID
func ArchitectureGetLocalID() (int, error) {
	name, err := ArchitectureGetLocal()
	if err != nil {
		return -1, err
	}
	id, err := ArchitectureId(name)
	if err != nil {
		return -1, err
	}
	return id, nil
}
<commit_msg>add riscv architecture definitions<commit_after>package osarch

import (
	"fmt"
)

const (
	ARCH_UNKNOWN                     = 0
	ARCH_32BIT_INTEL_X86             = 1
	ARCH_64BIT_INTEL_X86             = 2
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN   = 3
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN   = 4
	ARCH_32BIT_POWERPC_BIG_ENDIAN    = 5
	ARCH_64BIT_POWERPC_BIG_ENDIAN    = 6
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN = 7
	ARCH_64BIT_S390_BIG_ENDIAN       = 8
	ARCH_32BIT_MIPS_BIG_ENDIAN       = 9
	ARCH_32BIT_MIPS_LITTLE_ENDIAN    = 10
	ARCH_64BIT_MIPS64_BIG_ENDIAN     = 11
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN  = 12
	ARCH_32BIT_RISCV_LITTLE_ENDIAN   = 13
	ARCH_64BIT_RISCV_LITTLE_ENDIAN   = 14
)

var architectureNames = map[int]string{
	ARCH_32BIT_INTEL_X86:             "i686",
	ARCH_64BIT_INTEL_X86:             "x86_64",
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   "armv7l",
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   "aarch64",
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    "ppc",
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    "ppc64",
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: "ppc64le",
	ARCH_64BIT_S390_BIG_ENDIAN:       "s390x",
	ARCH_32BIT_MIPS_BIG_ENDIAN:       "mips",
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    "mipsle",
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     "mips64",
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  "mips64le",
	ARCH_32BIT_RISCV_LITTLE_ENDIAN:   "rv32",
	ARCH_64BIT_RISCV_LITTLE_ENDIAN:   "rv64",
}

var architectureAliases = map[int][]string{
	ARCH_32BIT_INTEL_X86:             {"i386", "i586", "386", "x86", "generic_32"},
	ARCH_64BIT_INTEL_X86:             {"amd64", "generic_64"},
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   {"armel", "armhf", "arm", "armhfp", "armv7a_hardfp", "armv7", "armv7a_vfpv3_hardfp"},
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   {"arm64", "arm64_generic"},
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    {"powerpc"},
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    {"powerpc64", "ppc64"},
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: {"ppc64el"},
	ARCH_32BIT_MIPS_BIG_ENDIAN:       {"mips"},
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    {"mipsle"},
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     {"mips64"},
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  {"mips64le"},
	ARCH_32BIT_RISCV_LITTLE_ENDIAN:   {"rv32", "riscv32"},
	ARCH_64BIT_RISCV_LITTLE_ENDIAN:   {"rv64", "riscv64"},
}

var architecturePersonalities = map[int]string{
	ARCH_32BIT_INTEL_X86:             "linux32",
	ARCH_64BIT_INTEL_X86:             "linux64",
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   "linux32",
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   "linux64",
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    "linux32",
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    "linux64",
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: "linux64",
	ARCH_64BIT_S390_BIG_ENDIAN:       "linux64",
	ARCH_32BIT_MIPS_BIG_ENDIAN:       "linux32",
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    "linux32",
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     "linux64",
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  "linux64",
	ARCH_32BIT_RISCV_LITTLE_ENDIAN:   "linux32",
	ARCH_64BIT_RISCV_LITTLE_ENDIAN:   "linux64",
}

var architectureSupportedPersonalities = map[int][]int{
	ARCH_32BIT_INTEL_X86:             {},
	ARCH_64BIT_INTEL_X86:             {ARCH_32BIT_INTEL_X86},
	ARCH_32BIT_ARMV7_LITTLE_ENDIAN:   {},
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN:   {ARCH_32BIT_ARMV7_LITTLE_ENDIAN},
	ARCH_32BIT_POWERPC_BIG_ENDIAN:    {},
	ARCH_64BIT_POWERPC_BIG_ENDIAN:    {ARCH_32BIT_POWERPC_BIG_ENDIAN},
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN: {},
	ARCH_64BIT_S390_BIG_ENDIAN:       {},
	ARCH_32BIT_MIPS_BIG_ENDIAN:       {},
	ARCH_32BIT_MIPS_LITTLE_ENDIAN:    {},
	ARCH_64BIT_MIPS64_BIG_ENDIAN:     {ARCH_32BIT_MIPS_BIG_ENDIAN},
	ARCH_64BIT_MIPS64_LITTLE_ENDIAN:  {ARCH_32BIT_MIPS_LITTLE_ENDIAN},
	ARCH_32BIT_RISCV_LITTLE_ENDIAN:   {},
	ARCH_64BIT_RISCV_LITTLE_ENDIAN:   {},
}

const ArchitectureDefault = "x86_64"

func ArchitectureName(arch int) (string, error) {
	arch_name, exists := architectureNames[arch]
	if exists {
		return arch_name, nil
	}

	return "unknown", fmt.Errorf("Architecture isn't supported: %d", arch)
}

func ArchitectureId(arch string) (int, error) {
	for arch_id, arch_name := range architectureNames {
		if arch_name == arch {
			return arch_id, nil
		}
	}

	for arch_id, arch_aliases := range architectureAliases {
		for _, arch_name := range arch_aliases {
			if arch_name == arch {
				return arch_id, nil
			}
		}
	}

	return 0, fmt.Errorf("Architecture isn't supported: %s", arch)
}

func ArchitecturePersonality(arch int) (string, error) {
	arch_personality, exists := architecturePersonalities[arch]
	if exists {
		return arch_personality, nil
	}

	return "", fmt.Errorf("Architecture isn't supported: %d", arch)
}

func ArchitecturePersonalities(arch int) ([]int, error) {
	personalities, exists := architectureSupportedPersonalities[arch]
	if exists {
		return personalities, nil
	}

	return []int{}, fmt.Errorf("Architecture isn't supported: %d", arch)
}

// ArchitectureGetLocalID returns the local hardware architecture ID
func ArchitectureGetLocalID() (int, error) {
	name, err := ArchitectureGetLocal()
	if err != nil {
		return -1, err
	}
	id, err := ArchitectureId(name)
	if err != nil {
		return -1, err
	}
	return id, nil
}
<|endoftext|>


<commit_before>//go:build !windows
// +build !windows

package subprocess

import (
	"io"
	"os"
	"strings"
	"testing"
	"time"
)

func TestSignalHandling(t *testing.T) {
	var a []string
	a = append(a, "testscript/signal.sh")
	var file *os.File
	p, err := NewProcess("sh", a, "testscript/signal_out.txt", "")

	if err != nil {
		t.Error("Failed process creation: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process ", err)
	}

	time.Sleep(2 * time.Second)
	err = p.Reload()
	if err != nil {
		t.Error("Unable to Reload process: ", err)
	}

	time.Sleep(2 * time.Second)
	err = p.Signal(10)
	if err != nil {
		t.Error("Unable to Signal process: ", err)
	}

	ecode, err := p.Wait()
	if err == nil {
		t.Error("Did not exit with an error")
	} else if ecode != 1 {
		t.Error("Exit code is not 1: ", ecode)
	}

	file, err = os.OpenFile("testscript/signal_out.txt", os.O_RDWR, 0644)
	if err != nil {
		t.Error("Could not open file ", err)
	}
	defer file.Close()

	var text = make([]byte, 1024)
	for {
		_, err = file.Read(text)
		// Break if finally arrived at end of file
		if err == io.EOF {
			break
		}

		// Break if error occurred
		if err != nil && err != io.EOF {
			t.Error("Error in reading file ", err)
		}
	}

	if !strings.Contains(string(text), "Called with signal 1") {
		t.Errorf("Reload failed. File output mismatch. Got %s", string(text))
	}

	if !strings.Contains(string(text), "Called with signal 10") {
		t.Errorf("Signal failed. File output mismatch. Got %s", string(text))
	}

	err = os.Remove("testscript/signal_out.txt")
	if err != nil {
		t.Error("Could not delete file ", err)
	}
}

//tests newprocess, start, stop, save, import, restart, wait
func TestStopRestart(t *testing.T) {
	var a []string
	a = append(a, "testscript/stoprestart.sh")

	p, err := NewProcess("sh", a, "", "")
	if err != nil {
		t.Error("Failed process creation: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process: ", err)
	}

	err = p.Stop()
	if err != nil {
		t.Error("Failed to stop process: ", err)
	}

	err = p.Save("testscript/test2.yaml")
	if err != nil {
		t.Error("Failed to save process: ", err)
	}

	p, err = ImportProcess("testscript/test2.yaml")
	if err != nil {
		t.Error("Failed to import process: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process: ", err)
	}

	err = p.Restart()
	if err != nil {
		t.Error("Failed to restart process: ", err)
	}

	exitcode, err := p.Wait()
	if err != nil {
		t.Error("Could not wait for process: ", err)
	} else if exitcode != 0 {
		t.Errorf("Exit code expected to be 0 but got %d", exitcode)
	}

	err = os.Remove("testscript/test2.yaml")
	if err != nil {
		t.Error("Could not delete file: ", err)
	}
}

func TestProcessStartWaitExit(t *testing.T) {
	var a []string
	var file *os.File
	var exp string
	var text []byte
	a = append(a, "testscript/exit1.sh")
	p, err := NewProcess("sh", a, "testscript/out.txt", "")
	if err != nil {
		t.Error("Failed process creation: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process: ", err)
	}

	ecode, err := p.Wait()
	if err == nil {
		t.Error("Did not exit with an error")
	} else if ecode != 1 {
		t.Error("Exit code is not 1: ", ecode)
	}

	file, err = os.OpenFile("testscript/out.txt", os.O_RDWR, 0644)
	if err != nil {
		t.Error("Could not open file: ", err)
	}
	defer file.Close()

	exp = "hello again\nwaiting now\n"
	// Read file, line by line
	text = make([]byte, len(exp))
	for {
		_, err = file.Read(text)
		// Break if finally arrived at end of file
		if err == io.EOF {
			break
		}
		// Break if error occurred
		if err != nil && err != io.EOF {
			t.Error("Error reading file: ", err)
		}
	}

	if string(text) != exp {
		t.Errorf("File output mismatch Expected %s got %s", "hello again\nwaiting now\n", string(text))
	}

	// Cleanup
	err = os.Remove("testscript/out.txt")
	if err != nil {
		t.Error("Could not delete file: ", err)
	}
}
<commit_msg>shared/subprocess: Fix tests to use p.Wait() with context<commit_after>//go:build !windows
// +build !windows

package subprocess

import (
	"context"
	"io"
	"os"
	"strings"
	"testing"
	"time"
)

func TestSignalHandling(t *testing.T) {
	var a []string
	a = append(a, "testscript/signal.sh")
	var file *os.File
	p, err := NewProcess("sh", a, "testscript/signal_out.txt", "")

	if err != nil {
		t.Error("Failed process creation: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process ", err)
	}

	time.Sleep(2 * time.Second)
	err = p.Reload()
	if err != nil {
		t.Error("Unable to Reload process: ", err)
	}

	time.Sleep(2 * time.Second)
	err = p.Signal(10)
	if err != nil {
		t.Error("Unable to Signal process: ", err)
	}

	ecode, err := p.Wait(context.Background())
	if err == nil {
		t.Error("Did not exit with an error")
	} else if ecode != 1 {
		t.Error("Exit code is not 1: ", ecode)
	}

	file, err = os.OpenFile("testscript/signal_out.txt", os.O_RDWR, 0644)
	if err != nil {
		t.Error("Could not open file ", err)
	}
	defer file.Close()

	var text = make([]byte, 1024)
	for {
		_, err = file.Read(text)
		// Break if finally arrived at end of file
		if err == io.EOF {
			break
		}

		// Break if error occurred
		if err != nil && err != io.EOF {
			t.Error("Error in reading file ", err)
		}
	}

	if !strings.Contains(string(text), "Called with signal 1") {
		t.Errorf("Reload failed. File output mismatch. Got %s", string(text))
	}

	if !strings.Contains(string(text), "Called with signal 10") {
		t.Errorf("Signal failed. File output mismatch. Got %s", string(text))
	}

	err = os.Remove("testscript/signal_out.txt")
	if err != nil {
		t.Error("Could not delete file ", err)
	}
}

//tests newprocess, start, stop, save, import, restart, wait
func TestStopRestart(t *testing.T) {
	var a []string
	a = append(a, "testscript/stoprestart.sh")

	p, err := NewProcess("sh", a, "", "")
	if err != nil {
		t.Error("Failed process creation: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process: ", err)
	}

	err = p.Stop()
	if err != nil {
		t.Error("Failed to stop process: ", err)
	}

	err = p.Save("testscript/test2.yaml")
	if err != nil {
		t.Error("Failed to save process: ", err)
	}

	p, err = ImportProcess("testscript/test2.yaml")
	if err != nil {
		t.Error("Failed to import process: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process: ", err)
	}

	err = p.Restart()
	if err != nil {
		t.Error("Failed to restart process: ", err)
	}

	exitcode, err := p.Wait(context.Background())
	if err != nil {
		t.Error("Could not wait for process: ", err)
	} else if exitcode != 0 {
		t.Errorf("Exit code expected to be 0 but got %d", exitcode)
	}

	err = os.Remove("testscript/test2.yaml")
	if err != nil {
		t.Error("Could not delete file: ", err)
	}
}

func TestProcessStartWaitExit(t *testing.T) {
	var a []string
	var file *os.File
	var exp string
	var text []byte
	a = append(a, "testscript/exit1.sh")
	p, err := NewProcess("sh", a, "testscript/out.txt", "")
	if err != nil {
		t.Error("Failed process creation: ", err)
	}

	err = p.Start()
	if err != nil {
		t.Error("Failed to start process: ", err)
	}

	ecode, err := p.Wait(context.Background())
	if err == nil {
		t.Error("Did not exit with an error")
	} else if ecode != 1 {
		t.Error("Exit code is not 1: ", ecode)
	}

	file, err = os.OpenFile("testscript/out.txt", os.O_RDWR, 0644)
	if err != nil {
		t.Error("Could not open file: ", err)
	}
	defer file.Close()

	exp = "hello again\nwaiting now\n"
	// Read file, line by line
	text = make([]byte, len(exp))
	for {
		_, err = file.Read(text)
		// Break if finally arrived at end of file
		if err == io.EOF {
			break
		}
		// Break if error occurred
		if err != nil && err != io.EOF {
			t.Error("Error reading file: ", err)
		}
	}

	if string(text) != exp {
		t.Errorf("File output mismatch Expected %s got %s", "hello again\nwaiting now\n", string(text))
	}

	// Cleanup
	err = os.Remove("testscript/out.txt")
	if err != nil {
		t.Error("Could not delete file: ", err)
	}
}
<|endoftext|>


<commit_before>package ebuf

import (
	"github.com/reusee/rope"
)

type Buffer struct {
	rope        *rope.Rope
	savedStates []*rope.Rope
	savingState bool
}

func New() *Buffer {
	return &Buffer{
		rope:        rope.NewFromBytes(nil),
		savingState: true,
	}
}

func (b *Buffer) SetBytes(bs []byte) {
	if b.savingState {
		b.savedStates = append(b.savedStates, b.rope)
	}
	b.rope = rope.NewFromBytes(bs)
}

func (b *Buffer) Bytes() []byte {
	return b.rope.Bytes()
}

func (b *Buffer) Action(fn func()) {
	b.savingState = false
	fn()
	b.savingState = true
}
<commit_msg>add Cursor and State types<commit_after>package ebuf

import (
	"github.com/reusee/rope"
)

type Buffer struct {
	rope        *rope.Rope
	cursors     []Cursor
	savedStates []State
	savingState bool
}

type Cursor int

type State struct {
	rope    *rope.Rope
	cursors []Cursor
}

func New() *Buffer {
	return &Buffer{
		rope:        rope.NewFromBytes(nil),
		savingState: true,
		cursors:     []Cursor{0},
	}
}

func (b *Buffer) saveState() {
	if !b.savingState {
		return
	}
	state := State{
		rope:    b.rope,
		cursors: make([]Cursor, len(b.cursors)),
	}
	copy(state.cursors[:], b.cursors[:])
	b.savedStates = append(b.savedStates, state)
}

func (b *Buffer) SetBytes(bs []byte) {
	b.saveState()
	b.rope = rope.NewFromBytes(bs)
}

func (b *Buffer) Bytes() []byte {
	return b.rope.Bytes()
}

func (b *Buffer) Action(fn func()) {
	b.savingState = false
	fn()
	b.savingState = true
}
<|endoftext|>