<commit_before>package util

import (
	"github.com/ghts/ghts/lib"
	"github.com/ghts/ghts/lib/daily_price_data"
	_ "github.com/go-sql-driver/mysql"

	"database/sql"
	"sort"
	"time"
)

func New개장일_모음(db *sql.DB) (개장일_모음 *S개장일_모음, 에러 error) {
	defer lib.S예외처리{M에러: &에러}.S실행()

	일일_가격정보_모음_KODEX200 := lib.F확인2(daily_price_data.New종목별_일일_가격정보_모음_DB읽기(db, "069500"))
	일일_가격정보_모음_삼성전자 := lib.F확인2(daily_price_data.New종목별_일일_가격정보_모음_DB읽기(db, "005930"))
	개장일_맵 := make(map[uint32]int)

	for _, 일일_정보 := range 일일_가격정보_모음_KODEX200.M저장소 {
		개장일_맵[일일_정보.M일자] = -1
	}

	for _, 일일_정보 := range 일일_가격정보_모음_삼성전자.M저장소 {
		개장일_맵[일일_정보.M일자] = -1
	}

	개장일_슬라이스 := make([]int, len(개장일_맵))

	i := 0
	for 개장일 := range 개장일_맵 {
		개장일_슬라이스[i] = int(개장일)
		i++
	}

	// 개장일 정렬
	sort.Ints(개장일_슬라이스)

	개장일_모음 = new(S개장일_모음)
	개장일_모음.M저장소 = make([]uint32, len(개장일_맵))
	개장일_모음.인덱스_맵 = make(map[uint32]int)

	for i, 개장일 := range 개장일_슬라이스 {
		개장일_모음.M저장소[i] = uint32(개장일)
		개장일_모음.인덱스_맵[uint32(개장일)] = i
	}

	return 개장일_모음, nil
}

type S개장일_모음 struct {
	M저장소  []uint32
	인덱스_맵 map[uint32]int
}

func (s S개장일_모음) G인덱스(일자 uint32) int {
	if 인덱스, 존재함 := s.인덱스_맵[일자]; 존재함 {
		return 인덱스
	} else {
		return -1
	}
}

func (s S개장일_모음) G인덱스2(일자 time.Time) int {
	return s.G인덱스(lib.F일자2정수(일자))
}

func (s S개장일_모음) G증분_개장일(일자 uint32, 증분 int) (uint32, error) {
	if 인덱스 := s.G인덱스(일자); 인덱스 < 0 {
		return 0, lib.New에러("존재하지 않는 일자 : '%v'", 일자)
	} else if 인덱스+증분 < 0 || 인덱스+증분 >= len(s.M저장소) {
		return 0, lib.New에러("범위를 벗어난 증분 : '%v' '%v'", 인덱스+증분, len(s.M저장소))
	} else {
		return s.M저장소[인덱스+증분], nil
	}
}

func (s S개장일_모음) G이전_개장일(기간 int) (이전_개장일 uint32, 에러 error) {
	defer lib.S예외처리{M에러: &에러, M함수: func() { 이전_개장일 = 0 }}.S실행()

	return s.M저장소[len(s.M저장소)-기간-1], nil
}
<commit_msg>S개장일_모음.G복사본() 추가<commit_after>package util

import (
	"github.com/ghts/ghts/lib"
	"github.com/ghts/ghts/lib/daily_price_data"
	_ "github.com/go-sql-driver/mysql"

	"database/sql"
	"sort"
	"time"
)

func New개장일_모음(db *sql.DB) (개장일_모음 *S개장일_모음, 에러 error) {
	defer lib.S예외처리{M에러: &에러}.S실행()

	일일_가격정보_모음_KODEX200 := lib.F확인2(daily_price_data.New종목별_일일_가격정보_모음_DB읽기(db, "069500"))
	일일_가격정보_모음_삼성전자 := lib.F확인2(daily_price_data.New종목별_일일_가격정보_모음_DB읽기(db, "005930"))
	개장일_맵 := make(map[uint32]int)

	for _, 일일_정보 := range 일일_가격정보_모음_KODEX200.M저장소 {
		개장일_맵[일일_정보.M일자] = -1
	}

	for _, 일일_정보 := range 일일_가격정보_모음_삼성전자.M저장소 {
		개장일_맵[일일_정보.M일자] = -1
	}

	개장일_슬라이스 := make([]int, len(개장일_맵))

	i := 0
	for 개장일 := range 개장일_맵 {
		개장일_슬라이스[i] = int(개장일)
		i++
	}

	// 개장일 정렬
	sort.Ints(개장일_슬라이스)

	개장일_모음 = new(S개장일_모음)
	개장일_모음.M저장소 = make([]uint32, len(개장일_맵))
	개장일_모음.인덱스_맵 = make(map[uint32]int)

	for i, 개장일 := range 개장일_슬라이스 {
		개장일_모음.M저장소[i] = uint32(개장일)
	}

	개장일_모음.S인덱스_맵_설정()

	return 개장일_모음, nil
}

type S개장일_모음 struct {
	M저장소  []uint32
	인덱스_맵 map[uint32]int
}

func (s *S개장일_모음) S인덱스_맵_설정() {
	s.인덱스_맵 = make(map[uint32]int)

	for i, 개장일 := range s.M저장소 {
		s.인덱스_맵[uint32(개장일)] = i
	}
}

func (s S개장일_모음) G인덱스(일자 uint32) int {
	if 인덱스, 존재함 := s.인덱스_맵[일자]; 존재함 {
		return 인덱스
	} else {
		return -1
	}
}

func (s S개장일_모음) G인덱스2(일자 time.Time) int {
	return s.G인덱스(lib.F일자2정수(일자))
}

func (s S개장일_모음) G증분_개장일(일자 uint32, 증분 int) (uint32, error) {
	if 인덱스 := s.G인덱스(일자); 인덱스 < 0 {
		return 0, lib.New에러("존재하지 않는 일자 : '%v'", 일자)
	} else if 인덱스+증분 < 0 || 인덱스+증분 >= len(s.M저장소) {
		return 0, lib.New에러("범위를 벗어난 증분 : '%v' '%v'", 인덱스+증분, len(s.M저장소))
	} else {
		return s.M저장소[인덱스+증분], nil
	}
}

func (s S개장일_모음) G이전_개장일(기간 int) (이전_개장일 uint32, 에러 error) {
	defer lib.S예외처리{M에러: &에러, M함수: func() { 이전_개장일 = 0 }}.S실행()

	return s.M저장소[len(s.M저장소)-기간-1], nil
}

func (s S개장일_모음) G복사본() *S개장일_모음 {
	s2 := new(S개장일_모음)
	s2.M저장소 = make([]uint32, len(s.M저장소))

	for i, 값 := range s.M저장소 {
		s2.M저장소[i] = 값
	}

	s2.S인덱스_맵_설정()

	return s2f
}<|endoftext|>


<commit_before>package txdb

import (
	"database/sql"

	"golang.org/x/net/context"

	"chain/crypto/hash256"
	"chain/database/pg"
	"chain/errors"
	"chain/fedchain/bc"
	"chain/net/trace/span"
)

func AssetDefinition(ctx context.Context, assetID string) (string, []byte, error) {
	const q = `
		SELECT hash, definition
		FROM asset_definition_pointers adp
		JOIN asset_definitions ON asset_definition_hash=hash
		WHERE asset_id=$1
	`
	var (
		hash     string
		defBytes []byte
	)
	err := pg.FromContext(ctx).QueryRow(ctx, q, assetID).Scan(&hash, &defBytes)
	if err == sql.ErrNoRows {
		err = pg.ErrUserInputNotFound
	}
	if err != nil {
		return "", nil, errors.WithDetailf(err, "asset=%s", assetID)
	}
	return hash, defBytes, nil
}

func DefinitionHashByAssetID(ctx context.Context, assetID string) (string, error) {
	const q = `
		SELECT asset_definition_hash FROM asset_definition_pointers WHERE asset_id=$1
	`

	var hash string
	err := pg.FromContext(ctx).QueryRow(ctx, q, assetID).Scan(&hash)
	if err != nil {
		return "", errors.Wrapf(err, "fetching definition for asset %s", assetID)
	}

	return hash, nil
}

// InsertAssetDefinitionPointers writes the and asset id and the definition hash,
// to the asset_definition_pointers table.
func InsertAssetDefinitionPointers(ctx context.Context, adps map[bc.AssetID]*bc.AssetDefinitionPointer) error {
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	for _, adp := range adps {
		err := insertADP(ctx, adp)
		if err != nil {
			return errors.Wrapf(err, "inserting adp for asset %s", adp.AssetID)
		}
	}

	return nil
}

func insertADP(ctx context.Context, adp *bc.AssetDefinitionPointer) error {
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	aid := adp.AssetID.String()
	hash := bc.Hash(adp.DefinitionHash).String()

	const updateQ = `
		UPDATE asset_definition_pointers
		SET asset_definition_hash=$2
		WHERE asset_id=$1
	`

	res, err := pg.FromContext(ctx).Exec(ctx, updateQ, aid, hash)
	if err != nil {
		return errors.Wrap(err, "updateQ setting asset definition pointer")
	}

	affected, err := res.RowsAffected()
	if err != nil {
		return errors.Wrap(err, "checking rows affected, setting asset definition pointer")
	}

	if affected == 0 {
		const insertQ = `
			INSERT INTO asset_definition_pointers (asset_id, asset_definition_hash)
			VALUES ($1, $2)
		`

		_, err = pg.FromContext(ctx).Exec(ctx, insertQ, aid, hash)
		if err != nil {
			return errors.Wrap(err, "insertQ setting asset definition pointer")
		}

	}

	return nil
}

// InsertAssetDefinitions inserts a record for each asset definition
// in block. The record maps the hash to the data of the definition.
func InsertAssetDefinitions(ctx context.Context, block *bc.Block) error {
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	var (
		seen = map[bc.Hash]bool{}
		hash []string
		defn [][]byte
	)
	for _, tx := range block.Transactions {
		for _, in := range tx.Inputs {
			if in.IsIssuance() && len(in.AssetDefinition) > 0 {
				var h bc.Hash = hash256.Sum(in.AssetDefinition)
				if seen[h] {
					continue
				}
				seen[h] = true
				hash = append(hash, h.String())
				defn = append(defn, in.AssetDefinition)
			}
		}
	}

	const q = `
		WITH defs AS (
			SELECT * FROM unnest($1::text[]) h, unnest($2::bytea[]) d
			WHERE NOT EXISTS (
				SELECT hash from asset_definitions
				WHERE h=hash
			)
		)
		INSERT INTO asset_definitions (hash, definition) TABLE defs
	`
	_, err := pg.FromContext(ctx).Exec(ctx, q, pg.Strings(hash), pg.Byteas(defn))
	return errors.Wrap(err)
}
<commit_msg>api/txdb: update ADPs in a batch<commit_after>package txdb

import (
	"database/sql"

	"golang.org/x/net/context"

	"chain/crypto/hash256"
	"chain/database/pg"
	"chain/errors"
	"chain/fedchain/bc"
	"chain/net/trace/span"
)

func AssetDefinition(ctx context.Context, assetID string) (string, []byte, error) {
	const q = `
		SELECT hash, definition
		FROM asset_definition_pointers adp
		JOIN asset_definitions ON asset_definition_hash=hash
		WHERE asset_id=$1
	`
	var (
		hash     string
		defBytes []byte
	)
	err := pg.FromContext(ctx).QueryRow(ctx, q, assetID).Scan(&hash, &defBytes)
	if err == sql.ErrNoRows {
		err = pg.ErrUserInputNotFound
	}
	if err != nil {
		return "", nil, errors.WithDetailf(err, "asset=%s", assetID)
	}
	return hash, defBytes, nil
}

func DefinitionHashByAssetID(ctx context.Context, assetID string) (string, error) {
	const q = `
		SELECT asset_definition_hash FROM asset_definition_pointers WHERE asset_id=$1
	`

	var hash string
	err := pg.FromContext(ctx).QueryRow(ctx, q, assetID).Scan(&hash)
	if err != nil {
		return "", errors.Wrapf(err, "fetching definition for asset %s", assetID)
	}

	return hash, nil
}

// InsertAssetDefinitionPointers writes the and asset id and the definition hash,
// to the asset_definition_pointers table.
func InsertAssetDefinitionPointers(ctx context.Context, adps map[bc.AssetID]*bc.AssetDefinitionPointer) error {
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	/*
		TODO(erykwalder): do it in a single query,
		something like this:

		WITH adps AS (
			SELECT unnest($1::text[]) h, unnest($2::text[]) id
		), updates AS (
			UPDATE asset_definition_pointers
			SET asset_definition_hash=h
			FROM adps
			WHERE asset_id=id
			RETURNING asset_id
		)
		INSERT INTO asset_definition_pointers (asset_id, asset_definition_hash)
		SELECT * FROM adps
		WHERE id NOT IN (TABLE updates)
	*/

	var aids, ptrs []string
	for id, p := range adps {
		aids = append(aids, id.String())
		ptrs = append(ptrs, bc.Hash(p.DefinitionHash).String())
	}
	updated, err := updateADPs(ctx, aids, ptrs)
	if err != nil {
		return errors.Wrap(err)
	}

	var aidsNew, ptrsNew []string
	for i := range aids {
		if updated[aids[i]] {
			continue
		}
		aidsNew = append(aidsNew, aids[i])
		ptrsNew = append(ptrsNew, ptrs[i])
	}
	err = insertADPs(ctx, aidsNew, ptrsNew)
	if err != nil {
		return errors.Wrap(err)
	}

	return nil
}

func updateADPs(ctx context.Context, aids, ptrs []string) (updated map[string]bool, err error) {
	const q = `
		WITH adps AS (
			SELECT unnest($1::text[]) h, unnest($2::text[]) id
		)
		UPDATE asset_definition_pointers
		SET asset_definition_hash=h
		FROM adps
		WHERE asset_id=id
		RETURNING asset_id
	`
	rows, err := pg.FromContext(ctx).Query(ctx, q, pg.Strings(aids), pg.Strings(ptrs))
	if err != nil {
		return nil, errors.Wrap(err)
	}
	defer rows.Close()
	updated = make(map[string]bool)
	for rows.Next() {
		var h bc.Hash
		err = rows.Scan(&h)
		if err != nil {
			return nil, errors.Wrap(err)
		}
		updated[h.String()] = true
	}
	if rows.Err() != nil {
		return nil, errors.Wrap(rows.Err())
	}
	return updated, nil
}

func insertADPs(ctx context.Context, aids, ptrs []string) error {
	const q = `
		WITH adps AS (SELECT unnest($1::text[]) id, unnest($2::text[]))
		INSERT INTO asset_definition_pointers (asset_id, asset_definition_hash)
		SELECT * FROM adps
		WHERE NOT EXISTS (
			SELECT 1 from asset_definition_pointers
			WHERE id=asset_id
		)
	`
	_, err := pg.FromContext(ctx).Exec(ctx, q, pg.Strings(aids), pg.Strings(ptrs))
	return errors.Wrap(err)
}

// InsertAssetDefinitions inserts a record for each asset definition
// in block. The record maps the hash to the data of the definition.
func InsertAssetDefinitions(ctx context.Context, block *bc.Block) error {
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	var (
		seen = map[bc.Hash]bool{}
		hash []string
		defn [][]byte
	)
	for _, tx := range block.Transactions {
		for _, in := range tx.Inputs {
			if in.IsIssuance() && len(in.AssetDefinition) > 0 {
				var h bc.Hash = hash256.Sum(in.AssetDefinition)
				if seen[h] {
					continue
				}
				seen[h] = true
				hash = append(hash, h.String())
				defn = append(defn, in.AssetDefinition)
			}
		}
	}

	const q = `
		WITH defs AS (
			SELECT * FROM unnest($1::text[]) h, unnest($2::bytea[]) d
			WHERE NOT EXISTS (
				SELECT hash from asset_definitions
				WHERE h=hash
			)
		)
		INSERT INTO asset_definitions (hash, definition) TABLE defs
	`
	_, err := pg.FromContext(ctx).Exec(ctx, q, pg.Strings(hash), pg.Byteas(defn))
	return errors.Wrap(err)
}
<|endoftext|>


<commit_before>package snapshot

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/docker/containerd"
)

func TestBtrfs(t *testing.T) {
	// SORRY(stevvooe): This is where I mount a btrfs loopback. We can probably
	// set this up as part of the test.
	root, err := ioutil.TempDir("/tmp/snapshots", "TestBtrfsPrepare-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(root)
	// TODO(stevvooe): Cleanup subvolumes

	sm, err := NewBtrfs("/dev/loop0", root)
	if err != nil {
		t.Fatal(err)
	}
	mounts, err := sm.Prepare(filepath.Join(root, "test"), "")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(mounts)

	for _, mount := range mounts {
		if mount.Type != "btrfs" {
			t.Fatalf("wrong mount type: %v != btrfs", mount.Type)
		}

		// assumes the first, maybe incorrect in the future
		if !strings.HasPrefix(mount.Options[0], "subvolid=") {
			t.Fatalf("no subvolid option in %v", mount.Options)
		}
	}

	if err := os.MkdirAll(mounts[0].Target, 0755); err != nil {
		t.Fatal(err)
	}
	if err := containerd.MountAll(mounts...); err != nil {
		t.Fatal(err)
	}

	// write in some data
	if err := ioutil.WriteFile(filepath.Join(mounts[0].Target, "foo"), []byte("content"), 0777); err != nil {
		t.Fatal(err)
	}

	// TODO(stevvooe): We don't really make this with the driver, but that
	// might prove annoying in practice.
	if err := os.MkdirAll(filepath.Join(root, "snapshots"), 0755); err != nil {
		t.Fatal(err)
	}

	if err := sm.Commit(filepath.Join(root, "snapshots/committed"), filepath.Join(root, "test")); err != nil {
		t.Fatal(err)
	}

	mounts, err = sm.Prepare(filepath.Join(root, "test2"), filepath.Join(root, "snapshots/committed"))
	if err != nil {
		t.Fatal(err)
	}

	if err := os.MkdirAll(filepath.Join(root, "test2"), 0755); err != nil {
		t.Fatal(err)
	}

	if err := containerd.MountAll(mounts...); err != nil {
		t.Fatal(err)
	}

	// TODO(stevvooe): Verify contents of "foo"
	if err := ioutil.WriteFile(filepath.Join(mounts[0].Target, "bar"), []byte("content"), 0777); err != nil {
		t.Fatal(err)
	}

	if err := sm.Commit(filepath.Join(root, "snapshots/committed2"), filepath.Join(root, "test2")); err != nil {
		t.Fatal(err)
	}
}
<commit_msg>snapshot: automate btrfs test setup<commit_after>package snapshot

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"

	"github.com/docker/containerd"
	btrfs "github.com/stevvooe/go-btrfs"
)

const (
	mib = 1024 * 1024
)

func TestBtrfs(t *testing.T) {
	device := setupBtrfsLoopbackDevice(t)
	defer removeBtrfsLoopbackDevice(t, device)
	root, err := ioutil.TempDir(device.mountPoint, "TestBtrfsPrepare-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(root)

	sm, err := NewBtrfs(device.deviceName, root)
	if err != nil {
		t.Fatal(err)
	}
	mounts, err := sm.Prepare(filepath.Join(root, "test"), "")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(mounts)

	for _, mount := range mounts {
		if mount.Type != "btrfs" {
			t.Fatalf("wrong mount type: %v != btrfs", mount.Type)
		}

		// assumes the first, maybe incorrect in the future
		if !strings.HasPrefix(mount.Options[0], "subvolid=") {
			t.Fatalf("no subvolid option in %v", mount.Options)
		}
	}

	if err := os.MkdirAll(mounts[0].Target, 0755); err != nil {
		t.Fatal(err)
	}
	if err := containerd.MountAll(mounts...); err != nil {
		t.Fatal(err)
	}
	defer func(mounts []containerd.Mount) {
		for _, mount := range mounts {
			unmount(t, mount.Target)
		}
	}(mounts)

	// write in some data
	if err := ioutil.WriteFile(filepath.Join(mounts[0].Target, "foo"), []byte("content"), 0777); err != nil {
		t.Fatal(err)
	}

	// TODO(stevvooe): We don't really make this with the driver, but that
	// might prove annoying in practice.
	if err := os.MkdirAll(filepath.Join(root, "snapshots"), 0755); err != nil {
		t.Fatal(err)
	}

	if err := sm.Commit(filepath.Join(root, "snapshots/committed"), filepath.Join(root, "test")); err != nil {
		t.Fatal(err)
	}
	defer func() {
		t.Log("Delete snapshot 1")
		err := btrfs.SubvolDelete(filepath.Join(root, "snapshots/committed"))
		if err != nil {
			t.Error("snapshot delete failed", err)
		}
	}()

	mounts, err = sm.Prepare(filepath.Join(root, "test2"), filepath.Join(root, "snapshots/committed"))
	if err != nil {
		t.Fatal(err)
	}

	if err := os.MkdirAll(filepath.Join(root, "test2"), 0755); err != nil {
		t.Fatal(err)
	}

	if err := containerd.MountAll(mounts...); err != nil {
		t.Fatal(err)
	}
	defer func(mounts []containerd.Mount) {
		for _, mount := range mounts {
			unmount(t, mount.Target)
		}
	}(mounts)

	// TODO(stevvooe): Verify contents of "foo"
	if err := ioutil.WriteFile(filepath.Join(mounts[0].Target, "bar"), []byte("content"), 0777); err != nil {
		t.Fatal(err)
	}

	if err := sm.Commit(filepath.Join(root, "snapshots/committed2"), filepath.Join(root, "test2")); err != nil {
		t.Fatal(err)
	}
	defer func() {
		t.Log("Delete snapshot 2")
		err := btrfs.SubvolDelete(filepath.Join(root, "snapshots/committed2"))
		if err != nil {
			t.Error("snapshot delete failed", err)
		}
	}()
}

type testDevice struct {
	mountPoint string
	fileName   string
	deviceName string
}

// setupBtrfsLoopbackDevice creates a file, mounts it as a loopback device, and
// formats it as btrfs.  The device should be cleaned up by calling
// removeBtrfsLoopbackDevice.
func setupBtrfsLoopbackDevice(t *testing.T) *testDevice {
	// create temporary directory for mount point
	mountPoint, err := ioutil.TempDir("", "containerd-btrfs-test")
	if err != nil {
		t.Fatal("Could not create mount point for btrfs test", err)
	}
	t.Log("Temporary mount point created", mountPoint)

	// create temporary file for the disk image
	file, err := ioutil.TempFile("", "containerd-btrfs-test")
	if err != nil {
		t.Fatal("Could not create temporary file for btrfs test", err)
	}
	t.Log("Temporary file created", file.Name())

	// initialize file with 100 MiB
	zero := [mib]byte{}
	for i := 0; i < 100; i++ {
		_, err = file.Write(zero[:])
		if err != nil {
			t.Fatal("Could not write to btrfs file", err)
		}
	}
	file.Close()

	// create device
	losetup := exec.Command("losetup", "--find", "--show", file.Name())
	var stdout, stderr bytes.Buffer
	losetup.Stdout = &stdout
	losetup.Stderr = &stderr
	err = losetup.Run()
	if err != nil {
		t.Log(stderr.String())
		t.Fatal("Could not run losetup", err)
	}
	deviceName := strings.TrimSpace(stdout.String())
	t.Log("Created loop device", deviceName)

	// format
	t.Log("Creating btrfs filesystem")
	mkfs := exec.Command("mkfs.btrfs", deviceName)
	err = mkfs.Run()
	if err != nil {
		t.Fatal("Could not run mkfs.btrfs", err)
	}

	// mount
	t.Logf("Mounting %s at %s", deviceName, mountPoint)
	mount := exec.Command("mount", deviceName, mountPoint)
	err = mount.Run()
	if err != nil {
		t.Fatal("Could not mount", err)
	}

	return &testDevice{
		mountPoint: mountPoint,
		fileName:   file.Name(),
		deviceName: deviceName,
	}
}

// removeBtrfsLoopbackDevice unmounts the loopback device and deletes the
// file holding the disk image.
func removeBtrfsLoopbackDevice(t *testing.T, device *testDevice) {
	// unmount
	unmount(t, device.mountPoint)

	// detach device
	t.Log("Removing loop device")
	losetup := exec.Command("losetup", "--detach", device.deviceName)
	err := losetup.Run()
	if err != nil {
		t.Error("Could not remove loop device", device.deviceName, err)
	}

	// remove file
	t.Log("Removing temporary file")
	err = os.Remove(device.fileName)
	if err != nil {
		t.Error(err)
	}

	// remove mount point
	t.Log("Removing temporary mount point")
	err = os.RemoveAll(device.mountPoint)
	if err != nil {
		t.Error(err)
	}
}

func unmount(t *testing.T, mountPoint string) {
	t.Log("unmount", mountPoint)
	umount := exec.Command("umount", mountPoint)
	err := umount.Run()
	if err != nil {

		t.Error("Could not umount", mountPoint, err)
	}
}
<|endoftext|>


<commit_before>package http

import (
	"fmt"
	"time"

	"github.com/alauda/bergamot/log"

	"gopkg.in/kataras/iris.v6"
	"gopkg.in/kataras/iris.v6/adaptors/cors"
	"gopkg.in/kataras/iris.v6/adaptors/httprouter"
)

// Router interface for http endpoints
type Router interface {
	AddRoutes(router *iris.Router)
}

// Middleware adding middleware
type Middleware interface {
	Serve(ctx *iris.Context)
}

// Config configuration for the HTTP server
type Config struct {
	Host           string
	Port           string
	AddLog         bool
	AddHealthCheck bool
	Component      string
}

// Server Full HTTP server
type Server struct {
	config      Config
	start       time.Time
	log         log.Logger
	iris        *iris.Framework
	versions    map[int]*iris.Router
	middlewares map[string][]Middleware
}

// NewServer constructor function for the HTTP server
func NewServer(config Config, log log.Logger) *Server {
	return &Server{
		config:      config,
		log:         log,
		iris:        iris.New(),
		versions:    map[int]*iris.Router{},
		middlewares: map[string][]Middleware{MiddlewareTypeAll: []Middleware{}},
	}
}

// Init will setup any necessary data
func (h *Server) Init() *Server {
	h.iris.Adapt(
		// Logging all errors
		iris.DevLogger(),
		// adding router
		httprouter.New(),

		// Cors wrapper to the entire application, allow all origins.
		cors.New(cors.Options{AllowedOrigins: []string{"*"}}),
	)

	if h.config.AddHealthCheck {
		// adding health check
		h.iris.Any("/", h.Healthcheck)
		h.iris.Any("/_ping", h.Healthcheck)
	}

	if h.config.AddLog {
		// Adding request logger middleware
		h.iris.Use(h)
		// default error when requesting unexistent route
		h.iris.OnError(iris.StatusNotFound, func(ctx *iris.Context) {
			// print method and stuff
			h.Serve(ctx)
		})
	}

	return h
}

// AddVersion Adds a version number to the API route
func (h *Server) AddVersion(version int) *Server {
	if _, ok := h.versions[version]; !ok {
		// adds /v1 or /v2 route
		h.versions[version] = h.iris.Party(fmt.Sprintf("/v%d", version))
	}
	return h
}

// AddEndpoint ands a handler for the given relative path
// should be executed before the Start method and after the Init method
func (h *Server) AddEndpoint(relativePath string, handler Router) *Server {
	router := h.iris.Party(relativePath)
	handler.AddRoutes(router)

	return h
}

// AddVersionEndpoint add a root endpoint to a version specific API
// Used like AddEndpoint but will add on a specific version instead.
// If the version was not created previously will then be created automatically
func (h *Server) AddVersionEndpoint(version int, relativePath string, handler Router) *Server {
	h.AddVersion(version)
	handler.AddRoutes(h.versions[version].Party(relativePath))
	return h
}

// Serve will log all the requests
func (h *Server) Serve(ctx *iris.Context) {
	// logging all requests
	h.log.Infof("---- [%s] %s  - args: %s ", ctx.Method(), ctx.Path(), ctx.ParamsSentence())
	ctx.Next()
}

// Healthcheck healthcheck endpoint
func (h *Server) Healthcheck(ctx *iris.Context) {
	ctx.WriteString(fmt.Sprintf("%s:%s", h.config.Component, time.Since(h.start)))
}

// GetApp returns the iris app, used for testing
func (h *Server) GetApp() *iris.Framework {
	return h.iris
}

// Start will start serving the http server
// this method will block while serving http
func (h *Server) Start() {
	h.start = time.Now()
	h.iris.Listen(h.config.Host + ":" + h.config.Port)
}

const (
	// MiddlewareTypeAll special type
	MiddlewareTypeAll = "*"
)

// AddMiddleware adds a middleware for the given types
func (h *Server) AddMiddleware(mw Middleware, kinds ...string) *Server {
	var (
		collection []Middleware
		ok         bool
	)
	kinds = append(kinds, MiddlewareTypeAll)
	for _, k := range kinds {
		if collection, ok = h.middlewares[k]; !ok {
			collection = make([]Middleware, 0, 2)
		}
		collection = append(collection, mw)
		h.middlewares[k] = collection
	}
	return h
}

// GetMiddlewares get all midlewares of a kind
func (h *Server) GetMiddlewares(kind string) []Middleware {
	return h.middlewares[kind]
}

// GetMiddlewareHandlerFun returns all the handler functions of a middleware kind
func (h *Server) GetMiddlewareHandlerFun(kind string) []iris.HandlerFunc {
	var funcs []iris.HandlerFunc
	mws := h.GetMiddlewares(kind)
	funcs = make([]iris.HandlerFunc, len(mws), len(mws)+1)
	for i, mw := range mws {
		funcs[i] = mw.Serve
	}
	return funcs
}

// GetMiddlewaresDecorated gets all the handler functions of a kind and decorate the target function
func (h *Server) GetMiddlewaresDecorated(kind string, handlerFunc iris.HandlerFunc) []iris.HandlerFunc {
	funcs := h.GetMiddlewareHandlerFun(kind)
	return append(funcs, handlerFunc)
}
<commit_msg>fix: Added multiple middlewares functions<commit_after>package http

import (
	"fmt"
	"time"

	"github.com/alauda/bergamot/log"

	"gopkg.in/kataras/iris.v6"
	"gopkg.in/kataras/iris.v6/adaptors/cors"
	"gopkg.in/kataras/iris.v6/adaptors/httprouter"
)

// Router interface for http endpoints
type Router interface {
	AddRoutes(router *iris.Router)
}

// Middleware adding middleware
type Middleware interface {
	Serve(ctx *iris.Context)
}

// Config configuration for the HTTP server
type Config struct {
	Host           string
	Port           string
	AddLog         bool
	AddHealthCheck bool
	Component      string
}

// Server Full HTTP server
type Server struct {
	config      Config
	start       time.Time
	log         log.Logger
	iris        *iris.Framework
	versions    map[int]*iris.Router
	middlewares map[string][]Middleware
}

// NewServer constructor function for the HTTP server
func NewServer(config Config, log log.Logger) *Server {
	return &Server{
		config:      config,
		log:         log,
		iris:        iris.New(),
		versions:    map[int]*iris.Router{},
		middlewares: map[string][]Middleware{MiddlewareTypeAll: []Middleware{}},
	}
}

// Init will setup any necessary data
func (h *Server) Init() *Server {
	h.iris.Adapt(
		// Logging all errors
		iris.DevLogger(),
		// adding router
		httprouter.New(),

		// Cors wrapper to the entire application, allow all origins.
		cors.New(cors.Options{AllowedOrigins: []string{"*"}}),
	)

	if h.config.AddHealthCheck {
		// adding health check
		h.iris.Any("/", h.Healthcheck)
		h.iris.Any("/_ping", h.Healthcheck)
	}

	if h.config.AddLog {
		// Adding request logger middleware
		h.iris.Use(h)
		// default error when requesting unexistent route
		h.iris.OnError(iris.StatusNotFound, func(ctx *iris.Context) {
			// print method and stuff
			h.Serve(ctx)
		})
	}

	return h
}

// AddVersion Adds a version number to the API route
func (h *Server) AddVersion(version int) *Server {
	if _, ok := h.versions[version]; !ok {
		// adds /v1 or /v2 route
		h.versions[version] = h.iris.Party(fmt.Sprintf("/v%d", version))
	}
	return h
}

// AddEndpoint ands a handler for the given relative path
// should be executed before the Start method and after the Init method
func (h *Server) AddEndpoint(relativePath string, handler Router) *Server {
	router := h.iris.Party(relativePath)
	handler.AddRoutes(router)

	return h
}

// AddVersionEndpoint add a root endpoint to a version specific API
// Used like AddEndpoint but will add on a specific version instead.
// If the version was not created previously will then be created automatically
func (h *Server) AddVersionEndpoint(version int, relativePath string, handler Router) *Server {
	h.AddVersion(version)
	handler.AddRoutes(h.versions[version].Party(relativePath))
	return h
}

// Serve will log all the requests
func (h *Server) Serve(ctx *iris.Context) {
	// logging all requests
	h.log.Infof("---- [%s] %s  - args: %s ", ctx.Method(), ctx.Path(), ctx.ParamsSentence())
	ctx.Next()
}

// Healthcheck healthcheck endpoint
func (h *Server) Healthcheck(ctx *iris.Context) {
	ctx.WriteString(fmt.Sprintf("%s:%s", h.config.Component, time.Since(h.start)))
}

// GetApp returns the iris app, used for testing
func (h *Server) GetApp() *iris.Framework {
	return h.iris
}

// Start will start serving the http server
// this method will block while serving http
func (h *Server) Start() {
	h.start = time.Now()
	h.iris.Listen(h.config.Host + ":" + h.config.Port)
}

const (
	// MiddlewareTypeAll special type
	MiddlewareTypeAll = "*"
)

// AddMiddleware adds a middleware for the given types
func (h *Server) AddMiddleware(mw Middleware, kinds ...string) *Server {
	var (
		collection []Middleware
		ok         bool
	)
	kinds = append(kinds, MiddlewareTypeAll)
	for _, k := range kinds {
		if collection, ok = h.middlewares[k]; !ok {
			collection = make([]Middleware, 0, 2)
		}
		collection = append(collection, mw)
		h.middlewares[k] = collection
	}
	return h
}

// AddMiddlewares adds a middleware for the given types
func (h *Server) AddMiddlewares(mws []Middleware, kinds ...string) *Server {
	for _, mw := range mws {
		h.AddMiddleware(mw, kinds...)
	}
	return h
}

// GetMiddlewares get all midlewares of a kind
func (h *Server) GetMiddlewares(kind string) []Middleware {
	return h.middlewares[kind]
}

// GetMiddlewareHandlerFun returns all the handler functions of a middleware kind
func (h *Server) GetMiddlewareHandlerFun(kind string) []iris.HandlerFunc {
	var funcs []iris.HandlerFunc
	mws := h.GetMiddlewares(kind)
	funcs = make([]iris.HandlerFunc, len(mws), len(mws)+1)
	for i, mw := range mws {
		funcs[i] = mw.Serve
	}
	return funcs
}

// GetMiddlewaresDecorated gets all the handler functions of a collection of kinds and decorate the target function
func (h *Server) GetMiddlewaresDecorated(handlerFunc iris.HandlerFunc, kinds ...string) []iris.HandlerFunc {
	var mws []iris.HandlerFunc
	for _, k := range kinds {
		mws = append(mws, h.GetMiddlewareHandlerFun(k)...)
	}
	mws = append(mws, handlerFunc)
	return mws
}
<|endoftext|>


<commit_before>package sudoku

import (
	"strconv"
	"testing"
	"time"
)

func BenchmarkHumanSolve(b *testing.B) {
	for i := 0; i < b.N; i++ {
		grid := NewGrid()
		defer grid.Done()
		grid.Load(TEST_GRID)
		grid.HumanSolve(nil)
	}
}

func TestHumanSolve(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	steps := grid.HumanSolution(nil)

	if steps == nil {
		t.Log("Human solution returned 0 techniques.")
		t.Fail()
	}

	if grid.Solved() {
		t.Log("Human Solutions mutated the grid.")
		t.Fail()
	}

	steps = grid.HumanSolve(nil)
	//TODO: test to make sure that we use a wealth of different techniques. This will require a cooked random for testing.
	if steps == nil {
		t.Log("Human solve returned 0 techniques")
		t.Fail()
	}
	if !grid.Solved() {
		t.Log("Human solve failed to solve the simple grid.")
		t.Fail()
	}

	//TODO: figure out a better way to test that non-default options to HumanSolution
	//are actually honored. This is hacky and cheap. :-/
	weirdOptions := HumanSolveOptions{
		justReturnInvalidGuess: true,
	}

	steps = grid.HumanSolve(&weirdOptions)

	if steps == nil {
		t.Fatal("Weird human solve options returned nothing")
	}
	if len(steps) != 1 {
		t.Fatal("Wrong number of weird steps returned")
	}
	if steps[0].Technique != GuessTechnique {
		t.Fatal("Weird solve options didn't return Guess.")
	}

	shortTechniqueOptions := defaultHumanSolveOptions()
	shortTechniqueOptions.TechniquesToUse = Techniques[0:5]

	steps = grid.HumanSolve(shortTechniqueOptions)

	if steps == nil {
		t.Fatal("Short technique Options returned nothing")
	}

}

func TestHint(t *testing.T) {

	//This is still flaky, but at least it's a little more likely to catch problems. :-/
	for i := 0; i < 10; i++ {
		hintTestHelper(t, nil, "base case"+strconv.Itoa(i))
	}

	options := defaultHumanSolveOptions()
	options.justReturnValidGuess = true

	hintTestHelper(t, options, "guess")
}

func hintTestHelper(t *testing.T, options *HumanSolveOptions, description string) {
	grid := NewGrid()
	defer grid.Done()

	grid.Load(TEST_GRID)

	steps := grid.Hint(options)

	if steps == nil || len(steps) == 0 {
		t.Error("No steps returned from Hint", description)
	}

	for count, step := range steps {
		if count == len(steps)-1 {
			//Last one
			if !step.Technique.IsFill() {
				t.Error("Non-fill step as last step in Hint: ", step.Technique.Name(), description)
			}
		} else {
			//Not last one
			if step.Technique.IsFill() {
				t.Error("Fill step as non-last step in Hint: ", count, step.Technique.Name(), description)
			}
		}
	}
}

func TestHumanSolveWithGuess(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	if !grid.LoadFromFile(puzzlePath("harddifficulty.sdk")) {
		t.Fatal("harddifficulty.sdk wasn't loaded")
	}

	steps := grid.HumanSolution(nil)

	if steps == nil {
		t.Fatal("Didn't find a solution to a grid that should have needed a guess")
	}

	foundGuess := false
	for i, step := range steps {
		if step.Technique.Name() == "Guess" {
			foundGuess = true
		}
		step.Apply(grid)
		if grid.Invalid() {
			t.Fatal("A solution with a guess in it got us into an invalid grid state. step", i)
		}
	}

	if !foundGuess {
		t.Error("Solution that should have used guess didn't have any guess.")
	}

	if !grid.Solved() {
		t.Error("A solution with a guess said it should solve the puzzle, but it didn't.")
	}

}

func TestStepsDescription(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	//It's really brittle that we load techniques in this way... it changes every time we add a new early technique!
	steps := SolveDirections{
		&SolveStep{
			techniquesByName["Only Legal Number"],
			CellSlice{
				grid.Cell(0, 0),
			},
			IntSlice{1},
			nil,
			nil,
			nil,
		},
		&SolveStep{
			techniquesByName["Pointing Pair Col"],
			CellSlice{
				grid.Cell(1, 0),
				grid.Cell(1, 1),
			},
			IntSlice{1, 2},
			CellSlice{
				grid.Cell(1, 3),
				grid.Cell(1, 4),
			},
			nil,
			nil,
		},
		&SolveStep{
			techniquesByName["Only Legal Number"],
			CellSlice{
				grid.Cell(2, 0),
			},
			IntSlice{2},
			nil,
			nil,
			nil,
		},
	}

	descriptions := steps.Description()

	GOLDEN_DESCRIPTIONS := []string{
		"First, we put 1 in cell (0,0) because 1 is the only remaining valid number for that cell.",
		"Next, we remove the possibilities 1 and 2 from cells (1,0) and (1,1) because 1 is only possible in column 0 of block 1, which means it can't be in any other cell in that column not in that block.",
		"Finally, we put 2 in cell (2,0) because 2 is the only remaining valid number for that cell.",
	}

	for i := 0; i < len(GOLDEN_DESCRIPTIONS); i++ {
		if descriptions[i] != GOLDEN_DESCRIPTIONS[i] {
			t.Log("Got wrong human solve description: ", descriptions[i])
			t.Fail()
		}
	}
}

//TODO: this is useful. Should we use this in other tests?
func cellRefsToCells(refs []cellRef, grid *Grid) CellSlice {
	var result CellSlice
	for _, ref := range refs {
		result = append(result, ref.Cell(grid))
	}
	return result
}

func TestTweakChainedStepsWeights(t *testing.T) {

	//TODO: test other, harder cases as well.
	grid := NewGrid()
	lastStep := &SolveStep{
		nil,
		cellRefsToCells([]cellRef{
			{0, 0},
		}, grid),
		nil,
		nil,
		nil,
		nil,
	}
	possibilities := []*SolveStep{
		{
			nil,
			cellRefsToCells([]cellRef{
				{1, 0},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
		{
			nil,
			cellRefsToCells([]cellRef{
				{2, 2},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
		{
			nil,
			cellRefsToCells([]cellRef{
				{7, 7},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
	}
	weights := []float64{
		10.0,
		10.0,
		10.0,
	}

	tweakChainedStepsWeights(lastStep, possibilities, weights)

	lastWeight := 0.0
	for i, weight := range weights {
		if weight <= lastWeight {
			t.Error("Tweak Chained Steps Weights didn't tweak things in the right direction: ", weights, "at", i)
		}
		lastWeight = weight
	}
}

func TestPuzzleDifficulty(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	//We use the cheaper one for testing so it completes faster.
	difficulty := grid.calcluateDifficulty(false)

	if grid.Solved() {
		t.Log("Difficulty shouldn't have changed the underlying grid, but it did.")
		t.Fail()
	}

	if difficulty < 0.0 || difficulty > 1.0 {
		t.Log("The grid's difficulty was outside of allowed bounds.")
		t.Fail()
	}

	puzzleFilenames := []string{"harddifficulty.sdk", "harddifficulty2.sdk"}

	for _, filename := range puzzleFilenames {
		puzzleDifficultyHelper(filename, t)
	}
}

func puzzleDifficultyHelper(filename string, t *testing.T) {
	otherGrid := NewGrid()
	if !otherGrid.LoadFromFile(puzzlePath(filename)) {
		t.Log("Whoops, couldn't load the file to test:", filename)
		t.Fail()
	}

	after := time.After(time.Second * 60)

	done := make(chan bool)

	go func() {
		//We use the cheaper one for testing so it completes faster
		_ = otherGrid.calcluateDifficulty(false)
		done <- true
	}()

	select {
	case <-done:
		//totally fine.
	case <-after:
		//Uh oh.
		t.Log("We never finished solving the hard difficulty puzzle: ", filename)
		t.Fail()
	}
}
<commit_msg>Fixed it so all tests pass. I was trying to solve a solved grid in that new test :-)<commit_after>package sudoku

import (
	"strconv"
	"testing"
	"time"
)

func BenchmarkHumanSolve(b *testing.B) {
	for i := 0; i < b.N; i++ {
		grid := NewGrid()
		defer grid.Done()
		grid.Load(TEST_GRID)
		grid.HumanSolve(nil)
	}
}

func TestHumanSolve(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	steps := grid.HumanSolution(nil)

	if steps == nil {
		t.Log("Human solution returned 0 techniques.")
		t.Fail()
	}

	if grid.Solved() {
		t.Log("Human Solutions mutated the grid.")
		t.Fail()
	}

	steps = grid.HumanSolve(nil)
	//TODO: test to make sure that we use a wealth of different techniques. This will require a cooked random for testing.
	if steps == nil {
		t.Log("Human solve returned 0 techniques")
		t.Fail()
	}
	if !grid.Solved() {
		t.Log("Human solve failed to solve the simple grid.")
		t.Fail()
	}

	//TODO: figure out a better way to test that non-default options to HumanSolution
	//are actually honored. This is hacky and cheap. :-/
	weirdOptions := HumanSolveOptions{
		justReturnInvalidGuess: true,
	}

	steps = grid.HumanSolve(&weirdOptions)

	if steps == nil {
		t.Fatal("Weird human solve options returned nothing")
	}
	if len(steps) != 1 {
		t.Fatal("Wrong number of weird steps returned")
	}
	if steps[0].Technique != GuessTechnique {
		t.Fatal("Weird solve options didn't return Guess.")
	}
}

func TestShortTechniquesToUseHumanSolveOptions(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	shortTechniqueOptions := defaultHumanSolveOptions()
	shortTechniqueOptions.TechniquesToUse = Techniques[0:5]

	steps := grid.HumanSolution(shortTechniqueOptions)

	if steps == nil {
		t.Fatal("Short technique Options returned nothing")
	}
}

func TestHint(t *testing.T) {

	//This is still flaky, but at least it's a little more likely to catch problems. :-/
	for i := 0; i < 10; i++ {
		hintTestHelper(t, nil, "base case"+strconv.Itoa(i))
	}

	options := defaultHumanSolveOptions()
	options.justReturnValidGuess = true

	hintTestHelper(t, options, "guess")
}

func hintTestHelper(t *testing.T, options *HumanSolveOptions, description string) {
	grid := NewGrid()
	defer grid.Done()

	grid.Load(TEST_GRID)

	steps := grid.Hint(options)

	if steps == nil || len(steps) == 0 {
		t.Error("No steps returned from Hint", description)
	}

	for count, step := range steps {
		if count == len(steps)-1 {
			//Last one
			if !step.Technique.IsFill() {
				t.Error("Non-fill step as last step in Hint: ", step.Technique.Name(), description)
			}
		} else {
			//Not last one
			if step.Technique.IsFill() {
				t.Error("Fill step as non-last step in Hint: ", count, step.Technique.Name(), description)
			}
		}
	}
}

func TestHumanSolveWithGuess(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	if !grid.LoadFromFile(puzzlePath("harddifficulty.sdk")) {
		t.Fatal("harddifficulty.sdk wasn't loaded")
	}

	steps := grid.HumanSolution(nil)

	if steps == nil {
		t.Fatal("Didn't find a solution to a grid that should have needed a guess")
	}

	foundGuess := false
	for i, step := range steps {
		if step.Technique.Name() == "Guess" {
			foundGuess = true
		}
		step.Apply(grid)
		if grid.Invalid() {
			t.Fatal("A solution with a guess in it got us into an invalid grid state. step", i)
		}
	}

	if !foundGuess {
		t.Error("Solution that should have used guess didn't have any guess.")
	}

	if !grid.Solved() {
		t.Error("A solution with a guess said it should solve the puzzle, but it didn't.")
	}

}

func TestStepsDescription(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	//It's really brittle that we load techniques in this way... it changes every time we add a new early technique!
	steps := SolveDirections{
		&SolveStep{
			techniquesByName["Only Legal Number"],
			CellSlice{
				grid.Cell(0, 0),
			},
			IntSlice{1},
			nil,
			nil,
			nil,
		},
		&SolveStep{
			techniquesByName["Pointing Pair Col"],
			CellSlice{
				grid.Cell(1, 0),
				grid.Cell(1, 1),
			},
			IntSlice{1, 2},
			CellSlice{
				grid.Cell(1, 3),
				grid.Cell(1, 4),
			},
			nil,
			nil,
		},
		&SolveStep{
			techniquesByName["Only Legal Number"],
			CellSlice{
				grid.Cell(2, 0),
			},
			IntSlice{2},
			nil,
			nil,
			nil,
		},
	}

	descriptions := steps.Description()

	GOLDEN_DESCRIPTIONS := []string{
		"First, we put 1 in cell (0,0) because 1 is the only remaining valid number for that cell.",
		"Next, we remove the possibilities 1 and 2 from cells (1,0) and (1,1) because 1 is only possible in column 0 of block 1, which means it can't be in any other cell in that column not in that block.",
		"Finally, we put 2 in cell (2,0) because 2 is the only remaining valid number for that cell.",
	}

	for i := 0; i < len(GOLDEN_DESCRIPTIONS); i++ {
		if descriptions[i] != GOLDEN_DESCRIPTIONS[i] {
			t.Log("Got wrong human solve description: ", descriptions[i])
			t.Fail()
		}
	}
}

//TODO: this is useful. Should we use this in other tests?
func cellRefsToCells(refs []cellRef, grid *Grid) CellSlice {
	var result CellSlice
	for _, ref := range refs {
		result = append(result, ref.Cell(grid))
	}
	return result
}

func TestTweakChainedStepsWeights(t *testing.T) {

	//TODO: test other, harder cases as well.
	grid := NewGrid()
	lastStep := &SolveStep{
		nil,
		cellRefsToCells([]cellRef{
			{0, 0},
		}, grid),
		nil,
		nil,
		nil,
		nil,
	}
	possibilities := []*SolveStep{
		{
			nil,
			cellRefsToCells([]cellRef{
				{1, 0},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
		{
			nil,
			cellRefsToCells([]cellRef{
				{2, 2},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
		{
			nil,
			cellRefsToCells([]cellRef{
				{7, 7},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
	}
	weights := []float64{
		10.0,
		10.0,
		10.0,
	}

	tweakChainedStepsWeights(lastStep, possibilities, weights)

	lastWeight := 0.0
	for i, weight := range weights {
		if weight <= lastWeight {
			t.Error("Tweak Chained Steps Weights didn't tweak things in the right direction: ", weights, "at", i)
		}
		lastWeight = weight
	}
}

func TestPuzzleDifficulty(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	//We use the cheaper one for testing so it completes faster.
	difficulty := grid.calcluateDifficulty(false)

	if grid.Solved() {
		t.Log("Difficulty shouldn't have changed the underlying grid, but it did.")
		t.Fail()
	}

	if difficulty < 0.0 || difficulty > 1.0 {
		t.Log("The grid's difficulty was outside of allowed bounds.")
		t.Fail()
	}

	puzzleFilenames := []string{"harddifficulty.sdk", "harddifficulty2.sdk"}

	for _, filename := range puzzleFilenames {
		puzzleDifficultyHelper(filename, t)
	}
}

func puzzleDifficultyHelper(filename string, t *testing.T) {
	otherGrid := NewGrid()
	if !otherGrid.LoadFromFile(puzzlePath(filename)) {
		t.Log("Whoops, couldn't load the file to test:", filename)
		t.Fail()
	}

	after := time.After(time.Second * 60)

	done := make(chan bool)

	go func() {
		//We use the cheaper one for testing so it completes faster
		_ = otherGrid.calcluateDifficulty(false)
		done <- true
	}()

	select {
	case <-done:
		//totally fine.
	case <-after:
		//Uh oh.
		t.Log("We never finished solving the hard difficulty puzzle: ", filename)
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package test

import (
	"sync"
	"testing"

	"github.com/titan-x/titan/client"
)

func TestSendEcho(t *testing.T) {
	sh := NewServerHelper(t).SeedDB()
	defer sh.ListenAndServe().CloseWait()

	ch := sh.GetClientHelper().AsUser(&sh.SeedData.User1)
	defer ch.Connect().CloseWait()

	var wg sync.WaitGroup
	wg.Add(1)
	m := "Ola!"
	ch.Client.Echo(map[string]string{"message": m, "token": sh.SeedData.User1.JWTToken}, func(msg *client.Message) error {
		defer wg.Done()
		if msg.Message != m {
			t.Fatalf("expected: %v, got: %v", m, msg.Message)
		}
		return nil
	})

	wg.Wait()

	// t.Fatal("Failed to send a message to the echo user")
	// t.Fatal("Failed to send batch message to the echo user")
	// t.Fatal("Failed to send large message to the echo user")
	// t.Fatal("Did not receive ACK for a message sent")
	// t.Fatal("Failed to receive a response from echo user")
	// t.Fatal("Could not send an ACK for an incoming message")
}

func TestSendMsgOnline(t *testing.T) {
	sh := NewServerHelper(t).SeedDB()
	defer sh.ListenAndServe().CloseWait()

	ch1 := sh.GetClientHelper().AsUser(&sh.SeedData.User1)
	defer ch1.Connect().CloseWait()

	ch2 := sh.GetClientHelper().AsUser(&sh.SeedData.User2)
	defer ch2.Connect().CloseWait()

	var wg sync.WaitGroup

	// send client.info request from user 1 & 2 to server, to announce availability and get authenticated
	wg.Add(2)
	ch1.Client.GetClientInfo(sh.SeedData.User1.JWTToken, func(m string) error {
		defer wg.Done()
		if m != "ACK" {
			t.Fatal("failed to send client.info request from client 1 to server:", m)
		}
		return nil
	})
	ch2.Client.GetClientInfo(sh.SeedData.User2.JWTToken, func(m string) error {
		defer wg.Done()
		if m != "ACK" {
			t.Fatal("failed to send client.info request from client 2 to server:", m)
		}
		return nil
	})

	wg.Wait()

	// todo: authomate authentication with Client.UseJWT & Client.AuthHandler & Client.Authenticated = true ?

	// send a hello message from user 1 to user 2
	wg.Add(1)
	ch1.Client.SendMessages([]client.Message{client.Message{To: "2", Message: "Hello, how are you?"}}, func(ack string) error {
		defer wg.Done()
		if ack != "ACK" {
			t.Fatal("failed to send hello message to user 2:", ack)
		}
		return nil
	})

	//
	// // receive the hello message from user 1 (online) as user 2 (online)
	// var c2r recvMsgReq
	// c2req := c2.ReadReq(&c2r)
	// if c2r.From != "1" {
	// 	t.Fatal("Received message from wrong sender instead of 1:", c2r.From)
	// } else if c2r.Message != "Hello, how are you?" {
	// 	t.Fatal("Received wrong message content:", c2r.Message)
	// }
	//
	// c2.WriteResponse(c2req.ID, "ACK", nil)
	//
	// // send back a hello response to user 1 (online) as user 2 (online)
	// c2.WriteRequest("msg.send", sendMsgReq{To: "1", Message: "I'm fine, thank you."})
	// res = c2.ReadRes(nil)
	// if res.Result != "ACK" {
	// 	t.Fatal("Failed to send message to user 1:", res)
	// }
	//
	// // receive hello response from user 1 (online) as user 2 (online)
	// var c1r recvMsgReq
	// c1req := c1.ReadReq(&c1r)
	// if c1r.From != "2" {
	// 	t.Fatal("Received message from wrong sender instead of 2:", c1r.From)
	// } else if c1r.Message != "I'm fine, thank you." {
	// 	t.Fatal("Received wrong message content:", c1r.Message)
	// }
	//
	// c1.WriteResponse(c1req.ID, "ACK", nil)
	//
	// // todo: verify that there are no pending requests for either user 1 or 2
	// // todo: below is a placeholder since writing last ACK response will never finish as we never wait for it
	// c1.WriteRequest("msg.echo", map[string]string{"echo": "echo"})
	// resfin := c1.ReadRes(nil).Result.(map[string]interface{})["echo"]
	// if resfin != "echo" {
	// 	t.Fatal("Last echo did return an invalid response:", resfin)
	// }

	wg.Wait()
}

//
// func TestSendMsgOffline(t *testing.T) {
// 	s := NewServerHelper(t).SeedDB()
// 	defer s.Stop()
// 	c1 := NewConnHelper(t, s).AsUser(&s.SeedData.User1).Dial()
// 	defer c1.Close()
//
// 	// send message to user 2 with a basic hello message
// 	c1.WriteRequest("msg.send", sendMsgReq{To: "2", Message: "Hello, how are you?"})
// 	res := c1.ReadRes(nil)
// 	if res.Result != "ACK" {
// 		t.Fatal("Failed to send message to user 2:", res)
// 	}
//
// 	// connect as user 2 and send msg.recv request to announce availability and complete client-cert auth
// 	c2 := NewConnHelper(t, s).AsUser(&s.SeedData.User2).Dial()
// 	defer c2.Close()
//
// 	c2.WriteRequest("msg.recv", nil)
// 	res = c2.ReadRes(nil)
// 	if res.Result != "ACK" {
// 		t.Fatal("Failed to send msg.recv request from client 2 to server:", res)
// 	}
//
// 	// receive the hello message from user 1 (online) as user 2 (was offline at the time message was sent)
// 	var c2r recvMsgReq
// 	c2req := c2.ReadReq(&c2r)
// 	if c2r.From != "1" {
// 		t.Fatal("Received message from wrong sender instead of 1:", c2r.From)
// 	} else if c2r.Message != "Hello, how are you?" {
// 		t.Fatal("Received wrong message content:", c2r.Message)
// 	}
//
// 	c2.WriteResponse(c2req.ID, "ACK", nil)
//
// 	// todo: verify that there are no pending requests for either user 1 or 2
// 	// todo: below is a placeholder since writing last ACK response will never finish as we never wait for it
// 	c1.WriteRequest("msg.echo", map[string]string{"echo": "echo"})
// 	resfin := c1.ReadRes(nil).Result.(map[string]interface{})["echo"]
// 	if resfin != "echo" {
// 		t.Fatal("Last echo did return an invalid response:", resfin)
// 	}
//
// 	// todo: as client_helper is implicitly logging errors with t.Fatal(), we can't currently add useful information like below:
// 	// t.Fatal("Failed to receive queued messages after coming online")
// 	// t.Fatal("Failed to send ACK for received message queue")
// }
//
// func TestSendAsync(t *testing.T) {
// 	// test case to do all of the following simultaneously to test the async nature of titan server
// 	// - cert.auth
// 	// - msg.recv
// 	// - msg.send (bath to multiple people where some of whom are online)
// }
<commit_msg>improve todo item<commit_after>package test

import (
	"sync"
	"testing"

	"github.com/titan-x/titan/client"
)

func TestSendEcho(t *testing.T) {
	sh := NewServerHelper(t).SeedDB()
	defer sh.ListenAndServe().CloseWait()

	ch := sh.GetClientHelper().AsUser(&sh.SeedData.User1)
	defer ch.Connect().CloseWait()

	var wg sync.WaitGroup
	wg.Add(1)
	m := "Ola!"
	ch.Client.Echo(map[string]string{"message": m, "token": sh.SeedData.User1.JWTToken}, func(msg *client.Message) error {
		defer wg.Done()
		if msg.Message != m {
			t.Fatalf("expected: %v, got: %v", m, msg.Message)
		}
		return nil
	})

	wg.Wait()

	// t.Fatal("Failed to send a message to the echo user")
	// t.Fatal("Failed to send batch message to the echo user")
	// t.Fatal("Failed to send large message to the echo user")
	// t.Fatal("Did not receive ACK for a message sent")
	// t.Fatal("Failed to receive a response from echo user")
	// t.Fatal("Could not send an ACK for an incoming message")
}

func TestSendMsgOnline(t *testing.T) {
	sh := NewServerHelper(t).SeedDB()
	defer sh.ListenAndServe().CloseWait()

	ch1 := sh.GetClientHelper().AsUser(&sh.SeedData.User1)
	defer ch1.Connect().CloseWait()

	ch2 := sh.GetClientHelper().AsUser(&sh.SeedData.User2)
	defer ch2.Connect().CloseWait()

	var wg sync.WaitGroup

	// send client.info request from user 1 & 2 to server, to announce availability and get authenticated
	wg.Add(2)
	ch1.Client.GetClientInfo(sh.SeedData.User1.JWTToken, func(m string) error {
		defer wg.Done()
		if m != "ACK" {
			t.Fatal("failed to send client.info request from client 1 to server:", m)
		}
		return nil
	})
	ch2.Client.GetClientInfo(sh.SeedData.User2.JWTToken, func(m string) error {
		defer wg.Done()
		if m != "ACK" {
			t.Fatal("failed to send client.info request from client 2 to server:", m)
		}
		return nil
	})

	wg.Wait() // todo: authomate authentication with Client.UseJWT & Client.AuthHandler & Client.Authenticated = true ? also GetClientInfo -> auth.jwt

	// send a hello message from user 1 to user 2
	wg.Add(1)
	ch1.Client.SendMessages([]client.Message{client.Message{To: "2", Message: "Hello, how are you?"}}, func(ack string) error {
		defer wg.Done()
		if ack != "ACK" {
			t.Fatal("failed to send hello message to user 2:", ack)
		}
		return nil
	})

	//
	// // receive the hello message from user 1 (online) as user 2 (online)
	// var c2r recvMsgReq
	// c2req := c2.ReadReq(&c2r)
	// if c2r.From != "1" {
	// 	t.Fatal("Received message from wrong sender instead of 1:", c2r.From)
	// } else if c2r.Message != "Hello, how are you?" {
	// 	t.Fatal("Received wrong message content:", c2r.Message)
	// }
	//
	// c2.WriteResponse(c2req.ID, "ACK", nil)
	//
	// // send back a hello response to user 1 (online) as user 2 (online)
	// c2.WriteRequest("msg.send", sendMsgReq{To: "1", Message: "I'm fine, thank you."})
	// res = c2.ReadRes(nil)
	// if res.Result != "ACK" {
	// 	t.Fatal("Failed to send message to user 1:", res)
	// }
	//
	// // receive hello response from user 1 (online) as user 2 (online)
	// var c1r recvMsgReq
	// c1req := c1.ReadReq(&c1r)
	// if c1r.From != "2" {
	// 	t.Fatal("Received message from wrong sender instead of 2:", c1r.From)
	// } else if c1r.Message != "I'm fine, thank you." {
	// 	t.Fatal("Received wrong message content:", c1r.Message)
	// }
	//
	// c1.WriteResponse(c1req.ID, "ACK", nil)
	//
	// // todo: verify that there are no pending requests for either user 1 or 2
	// // todo: below is a placeholder since writing last ACK response will never finish as we never wait for it
	// c1.WriteRequest("msg.echo", map[string]string{"echo": "echo"})
	// resfin := c1.ReadRes(nil).Result.(map[string]interface{})["echo"]
	// if resfin != "echo" {
	// 	t.Fatal("Last echo did return an invalid response:", resfin)
	// }

	wg.Wait()
}

//
// func TestSendMsgOffline(t *testing.T) {
// 	s := NewServerHelper(t).SeedDB()
// 	defer s.Stop()
// 	c1 := NewConnHelper(t, s).AsUser(&s.SeedData.User1).Dial()
// 	defer c1.Close()
//
// 	// send message to user 2 with a basic hello message
// 	c1.WriteRequest("msg.send", sendMsgReq{To: "2", Message: "Hello, how are you?"})
// 	res := c1.ReadRes(nil)
// 	if res.Result != "ACK" {
// 		t.Fatal("Failed to send message to user 2:", res)
// 	}
//
// 	// connect as user 2 and send msg.recv request to announce availability and complete client-cert auth
// 	c2 := NewConnHelper(t, s).AsUser(&s.SeedData.User2).Dial()
// 	defer c2.Close()
//
// 	c2.WriteRequest("msg.recv", nil)
// 	res = c2.ReadRes(nil)
// 	if res.Result != "ACK" {
// 		t.Fatal("Failed to send msg.recv request from client 2 to server:", res)
// 	}
//
// 	// receive the hello message from user 1 (online) as user 2 (was offline at the time message was sent)
// 	var c2r recvMsgReq
// 	c2req := c2.ReadReq(&c2r)
// 	if c2r.From != "1" {
// 		t.Fatal("Received message from wrong sender instead of 1:", c2r.From)
// 	} else if c2r.Message != "Hello, how are you?" {
// 		t.Fatal("Received wrong message content:", c2r.Message)
// 	}
//
// 	c2.WriteResponse(c2req.ID, "ACK", nil)
//
// 	// todo: verify that there are no pending requests for either user 1 or 2
// 	// todo: below is a placeholder since writing last ACK response will never finish as we never wait for it
// 	c1.WriteRequest("msg.echo", map[string]string{"echo": "echo"})
// 	resfin := c1.ReadRes(nil).Result.(map[string]interface{})["echo"]
// 	if resfin != "echo" {
// 		t.Fatal("Last echo did return an invalid response:", resfin)
// 	}
//
// 	// todo: as client_helper is implicitly logging errors with t.Fatal(), we can't currently add useful information like below:
// 	// t.Fatal("Failed to receive queued messages after coming online")
// 	// t.Fatal("Failed to send ACK for received message queue")
// }
//
// func TestSendAsync(t *testing.T) {
// 	// test case to do all of the following simultaneously to test the async nature of titan server
// 	// - cert.auth
// 	// - msg.recv
// 	// - msg.send (bath to multiple people where some of whom are online)
// }
<|endoftext|>


<commit_before>package node

import (
	"bytes"
	"fmt"
	"sync"
	"time"

	"github.com/jsimonetti/go-artnet/packet"
	"github.com/jsimonetti/go-artnet/packet/code"
)

type controlNodes struct {
	lastSeen time.Time
	node     Config
}

// Controller holds the information for a controller
type Controller struct {
	// Node is the controller itself
	Node

	// Nodes is a slice of nodes that are seen by this controller
	Nodes    []controlNodes
	nodeLock sync.Mutex

	shutdownCh chan struct{}
}

// Start will start this controller
func (c *Controller) Start() error {
	go c.pollLoop()
	return c.Node.Start()
}

// Stop will stop this controller
func (c *Controller) Stop() {
	c.Node.Stop()
	close(c.shutdownCh)
}

func (c *Controller) pollLoop() {
	timer := time.NewTicker(3 * time.Second)
	artPoll := &packet.ArtPollPacket{
		TalkToMe: new(code.TalkToMe).WithReplyOnChange(true),
		Priority: code.DpAll,
	}
	b, err := artPoll.MarshalBinary()
	if err != nil {
		return
	}
	for {
		select {
		case <-timer.C:
			// send ArtPollPacket
			c.Node.sendCh <- &netPayload{data: b}

		case p := <-c.Node.pollReplyCh:
			cfg := ConfigFromArtPollReply(p)
			c.updateNode(cfg)

		case <-c.shutdownCh:
			return
		}
	}
}

// updateNode will add a Node to the list of known nodes
func (c *Controller) updateNode(cfg Config) error {
	c.nodeLock.Lock()
	defer c.nodeLock.Unlock()

	for i, n := range c.Nodes {
		if bytes.Equal(cfg.IP, n.node.IP) {
			fmt.Printf("updated node: %s, %s\n", cfg.Name, cfg.IP.String())
			c.Nodes[i].node = cfg
			c.Nodes[i].lastSeen = time.Now()
			return nil
		}
	}
	fmt.Printf("added node: %s, %s\n", cfg.Name, cfg.IP.String())
	c.Nodes = append(c.Nodes, controlNodes{node: cfg, lastSeen: time.Now()})

	return nil
}

// deleteNode will delete a Node from the list of known nodes
func (c *Controller) deleteNode(node Config) error {
	c.nodeLock.Lock()
	defer c.nodeLock.Unlock()

	for i, n := range c.Nodes {
		if bytes.Equal(node.IP, n.node.IP) {
			c.Nodes = append(c.Nodes[:i], c.Nodes[i+1:]...)
		}
	}

	return fmt.Errorf("no known node with this ip known, ip: %s", node.IP)
}
<commit_msg>change name of struct<commit_after>package node

import (
	"bytes"
	"fmt"
	"sync"
	"time"

	"github.com/jsimonetti/go-artnet/packet"
	"github.com/jsimonetti/go-artnet/packet/code"
)

// controlNode hols a node configuration
type controlNode struct {
	lastSeen time.Time
	node     Config
}

// Controller holds the information for a controller
type Controller struct {
	// Node is the controller itself
	Node

	// Nodes is a slice of nodes that are seen by this controller
	Nodes    []controlNode
	nodeLock sync.Mutex

	shutdownCh chan struct{}
}

// Start will start this controller
func (c *Controller) Start() error {
	go c.pollLoop()
	return c.Node.Start()
}

// Stop will stop this controller
func (c *Controller) Stop() {
	c.Node.Stop()
	close(c.shutdownCh)
}

func (c *Controller) pollLoop() {
	timer := time.NewTicker(3 * time.Second)
	artPoll := &packet.ArtPollPacket{
		TalkToMe: new(code.TalkToMe).WithReplyOnChange(true),
		Priority: code.DpAll,
	}
	b, err := artPoll.MarshalBinary()
	if err != nil {
		return
	}
	for {
		select {
		case <-timer.C:
			// send ArtPollPacket
			c.Node.sendCh <- &netPayload{data: b}

		case p := <-c.Node.pollReplyCh:
			cfg := ConfigFromArtPollReply(p)
			c.updateNode(cfg)

		case <-c.shutdownCh:
			return
		}
	}
}

// updateNode will add a Node to the list of known nodes
func (c *Controller) updateNode(cfg Config) error {
	c.nodeLock.Lock()
	defer c.nodeLock.Unlock()

	for i, n := range c.Nodes {
		if bytes.Equal(cfg.IP, n.node.IP) {
			fmt.Printf("updated node: %s, %s\n", cfg.Name, cfg.IP.String())
			c.Nodes[i].node = cfg
			c.Nodes[i].lastSeen = time.Now()
			return nil
		}
	}
	fmt.Printf("added node: %s, %s\n", cfg.Name, cfg.IP.String())
	c.Nodes = append(c.Nodes, controlNode{node: cfg, lastSeen: time.Now()})

	return nil
}

// deleteNode will delete a Node from the list of known nodes
func (c *Controller) deleteNode(node Config) error {
	c.nodeLock.Lock()
	defer c.nodeLock.Unlock()

	for i, n := range c.Nodes {
		if bytes.Equal(node.IP, n.node.IP) {
			c.Nodes = append(c.Nodes[:i], c.Nodes[i+1:]...)
		}
	}

	return fmt.Errorf("no known node with this ip known, ip: %s", node.IP)
}
<|endoftext|>


<commit_before>/*Package noise provides functions to generate various types of image noise.*/
package noise

import (
	"image"
	"math/rand"
)

// Fn is a noise function that generates values between 0 and 255.
type Fn func() uint8

var (
	// Uniform distribution noise function.
	Uniform Fn
	// Binary distribution noise function.
	Binary Fn
	// Gaussian distribution noise function.
	Gaussian Fn
)

func init() {
	Uniform = func() uint8 {
		return uint8(rand.Intn(256))
	}
	Binary = func() uint8 {
		return 0xFF * uint8(rand.Intn(2))
	}
	Gaussian = func() uint8 {
		return uint8(rand.NormFloat64()*32.0 + 128.0)
	}
}

// Options to configure the noise generation.
type Options struct {
	// NoiseFn is a noise function that will be called for each pixel
	// on the image being generated.
	NoiseFn Fn
	// Monochrome sets if the resulting image is grayscale or colored,
	// the latter meaning that each RGB channel was filled with different values.
	Monochrome bool
}

// Generate returns an image of the parameter width and height filled
// with the values from a noise function.
// If no options are provided, defaults will be used.
func Generate(width, height int, o *Options) *image.RGBA {
	dst := image.NewRGBA(image.Rect(0, 0, width, height))

	// Get options or defaults
	noiseFn := Uniform
	monochrome := false
	if o != nil {
		if o.NoiseFn != nil {
			noiseFn = o.NoiseFn
		}
		monochrome = o.Monochrome
	}

	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			pos := y*dst.Stride + x*4
			if monochrome {
				v := noiseFn()
				dst.Pix[pos+0] = v
				dst.Pix[pos+1] = v
				dst.Pix[pos+2] = v
				dst.Pix[pos+3] = 0xFF

			} else {
				dst.Pix[pos+0] = noiseFn()
				dst.Pix[pos+1] = noiseFn()
				dst.Pix[pos+2] = noiseFn()
				dst.Pix[pos+3] = 0xFF
			}
		}
	}

	return dst
}
<commit_msg>Add parallel support for generate noise<commit_after>/*Package noise provides functions to generate various types of image noise.*/
package noise

import (
	"image"
	"math/rand"
	"time"

	"github.com/anthonynsimon/bild/parallel"
)

// Fn is a noise function that generates values between 0 and 255.
type Fn func() uint8

var (
	// Uniform distribution noise function.
	Uniform Fn
	// Binary distribution noise function.
	Binary Fn
	// Gaussian distribution noise function.
	Gaussian Fn
)

func init() {
	Uniform = func() uint8 {
		return uint8(rand.Intn(256))
	}
	Binary = func() uint8 {
		return 0xFF * uint8(rand.Intn(2))
	}
	Gaussian = func() uint8 {
		return uint8(rand.NormFloat64()*32.0 + 128.0)
	}
}

// Options to configure the noise generation.
type Options struct {
	// NoiseFn is a noise function that will be called for each pixel
	// on the image being generated.
	NoiseFn Fn
	// Monochrome sets if the resulting image is grayscale or colored,
	// the latter meaning that each RGB channel was filled with different values.
	Monochrome bool
}

// Generate returns an image of the parameter width and height filled
// with the values from a noise function.
// If no options are provided, defaults will be used.
func Generate(width, height int, o *Options) *image.RGBA {
	dst := image.NewRGBA(image.Rect(0, 0, width, height))

	// Get options or defaults
	noiseFn := Uniform
	monochrome := false
	if o != nil {
		if o.NoiseFn != nil {
			noiseFn = o.NoiseFn
		}
		monochrome = o.Monochrome
	}

	rand.Seed(time.Now().UTC().UnixNano())

	parallel.Line(height, func(start, end int) {
		for y := start; y < end; y++ {
			for x := 0; x < width; x++ {
				pos := y*dst.Stride + x*4
				if monochrome {
					v := noiseFn()
					dst.Pix[pos+0] = v
					dst.Pix[pos+1] = v
					dst.Pix[pos+2] = v
					dst.Pix[pos+3] = 0xFF

				} else {
					dst.Pix[pos+0] = noiseFn()
					dst.Pix[pos+1] = noiseFn()
					dst.Pix[pos+2] = noiseFn()
					dst.Pix[pos+3] = 0xFF
				}
			}
		}
	})

	return dst
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/astaxie/beego"
	"net/http"

	"github.com/dockercn/wharf/models"
	"github.com/dockercn/wharf/utils"
)

type UserAPIV1Controller struct {
	beego.Controller
}

func (this *UserAPIV1Controller) URLMapping() {
	this.Mapping("PostUsers", this.PostUsers)
	this.Mapping("GetUsers", this.GetUsers)
}

func (this *UserAPIV1Controller) Prepare() {
	beego.Debug("[Headers]")
	beego.Debug(this.Ctx.Input.Request.Header)

	this.EnableXSRF = false

	this.Ctx.Output.Context.ResponseWriter.Header().Set("Content-Type", "application/json;charset=UTF-8")
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Registry-Standalone", beego.AppConfig.String("docker::Standalone"))
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Registry-Version", beego.AppConfig.String("docker::Version"))
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Registry-Config", beego.AppConfig.String("docker::Config"))
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Encrypt", beego.AppConfig.String("docker::Encrypt"))
}

func (this *UserAPIV1Controller) PostUsers() {
	result := map[string]string{"error": "Don't support create user from docker command."}
	this.Data["json"] = &result

	this.Ctx.Output.Context.Output.SetStatus(http.StatusUnauthorized)
	this.ServeJson()
}

func (this *UserAPIV1Controller) GetUsers() {
	if username, passwd, err := utils.DecodeBasicAuth(this.Ctx.Input.Header("Authorization")); err != nil {

		beego.Error("[USER API] Decode Basic Auth Error:", err.Error())

		result := map[string]string{"error": "Decode authorization failure."}
		this.Data["json"] = &result

		this.Ctx.Output.Context.Output.SetStatus(http.StatusUnauthorized)
		this.ServeJson()
		this.StopRun()

	} else {
		user := new(models.User)

		if err := user.Get(username, passwd); err != nil {
			beego.Error("[USER API] Search user error: ", err.Error())

			result := map[string]string{"error": "User authorization failure."}
			this.Data["json"] = &result

			this.Ctx.Output.Context.Output.SetStatus(http.StatusUnauthorized)
			this.ServeJson()
			this.StopRun()
		}

		beego.Info("[User API]", username, "authorization successfully")

		result := map[string]string{"status": "User authorization successfully."}
		this.Data["json"] = &result

		this.Ctx.Output.Context.Output.SetStatus(http.StatusOK)
		this.ServeJson()
		this.StopRun()
	}
}
<commit_msg>增加 Docker Client Login 的日志记录<commit_after>package controllers

import (
	"github.com/astaxie/beego"
	"net/http"

	"github.com/dockercn/wharf/models"
	"github.com/dockercn/wharf/utils"
)

type UserAPIV1Controller struct {
	beego.Controller
}

func (this *UserAPIV1Controller) URLMapping() {
	this.Mapping("PostUsers", this.PostUsers)
	this.Mapping("GetUsers", this.GetUsers)
}

func (this *UserAPIV1Controller) Prepare() {
	beego.Debug("[Headers]")
	beego.Debug(this.Ctx.Input.Request.Header)

	this.EnableXSRF = false

	this.Ctx.Output.Context.ResponseWriter.Header().Set("Content-Type", "application/json;charset=UTF-8")
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Registry-Standalone", beego.AppConfig.String("docker::Standalone"))
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Registry-Version", beego.AppConfig.String("docker::Version"))
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Registry-Config", beego.AppConfig.String("docker::Config"))
	this.Ctx.Output.Context.ResponseWriter.Header().Set("X-Docker-Encrypt", beego.AppConfig.String("docker::Encrypt"))
}

func (this *UserAPIV1Controller) PostUsers() {
	result := map[string]string{"error": "Don't support create user from docker command."}
	this.Data["json"] = &result

	this.Ctx.Output.Context.Output.SetStatus(http.StatusUnauthorized)
	this.ServeJson()
}

func (this *UserAPIV1Controller) GetUsers() {
	if username, passwd, err := utils.DecodeBasicAuth(this.Ctx.Input.Header("Authorization")); err != nil {

		beego.Error("[USER API] Decode Basic Auth Error:", err.Error())

		result := map[string]string{"error": "Decode authorization failure."}
		this.Data["json"] = &result

		this.Ctx.Output.Context.Output.SetStatus(http.StatusUnauthorized)
		this.ServeJson()
		this.StopRun()

	} else {
		user := new(models.User)

		if err := user.Get(username, passwd); err != nil {
			beego.Error("[USER API] Search user error: ", err.Error())

			result := map[string]string{"error": "User authorization failure."}
			this.Data["json"] = &result

			this.Ctx.Output.Context.Output.SetStatus(http.StatusUnauthorized)
			this.ServeJson()
			this.StopRun()
		}

		beego.Info("[User API]", username, "authorization successfully")

		memo, _ := json.Marshal(this.Ctx.Input.Header)
		if err := user.Log(models.ACTION_SIGNUP, models.LEVELINFORMATIONAL, models.TYPE_API, user.UUID, memo); err != nil {
			beego.Error("[WEB API] Log Erro:", err.Error())
		}

		result := map[string]string{"status": "User authorization successfully."}
		this.Data["json"] = &result

		this.Ctx.Output.Context.Output.SetStatus(http.StatusOK)
		this.ServeJson()
		this.StopRun()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"runtime"
	"sync"

	"github.com/ikawaha/kagome/tokenizer"
)

// NewMorphizer provides new Morphizer.
func NewMorphizer() (<-chan Morphs, chan<- string, func()) {
	n := runtime.GOMAXPROCS(0)
	wg := new(sync.WaitGroup)

	out := make(chan Morphs)
	in := make(chan string)

	sign := make(chan struct{})
	stop := func() {
		close(sign)
		for range out {
		}
	}

	// kagome is NOT goroutine safe
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func() {
			kagome := tokenizer.New()
			for {
				select {
				// interrupt
				case <-sign:
					wg.Done()
					return

				// parse
				case str, ok := <-in:
					if !ok {
						wg.Done()
						return
					}
					tokens := kagome.Tokenize(str)
					out <- NewMorphs(tokens)
				}
			}
		}()
	}

	// tell finishing
	go func() {
		wg.Wait()
		close(out)
	}()

	return out, in, stop
}
<commit_msg>deffering wg.Done() in a func.<commit_after>package main

import (
	"runtime"
	"sync"

	"github.com/ikawaha/kagome/tokenizer"
)

// NewMorphizer provides new Morphizer.
func NewMorphizer() (<-chan Morphs, chan<- string, func()) {
	n := runtime.GOMAXPROCS(0)
	wg := new(sync.WaitGroup)

	out := make(chan Morphs)
	in := make(chan string)

	sign := make(chan struct{})
	stop := func() {
		close(sign)
		for range out {
		}
	}

	// kagome is NOT goroutine safe
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()

			kagome := tokenizer.New()
			for {
				select {
				// interrupt
				case <-sign:
					return

				// parse
				case str, ok := <-in:
					if !ok {
						return
					}
					tokens := kagome.Tokenize(str)
					out <- NewMorphs(tokens)
				}
			}
		}()
	}

	// tell finishing
	go func() {
		wg.Wait()
		close(out)
	}()

	return out, in, stop
}
<|endoftext|>


<commit_before>package cmd

import (
	"io/ioutil"
	"os"

	"fmt"

	"github.com/asaskevich/govalidator"
	"github.com/ellcrys/util"
	"github.com/goware/urlx"
	"github.com/hashicorp/hcl"
	c_util "github.com/ncodes/cocoon-util"
	"github.com/ncodes/cocoon/core/api/api"
	"github.com/ncodes/cocoon/core/api/api/proto_api"
	"github.com/ncodes/cocoon/core/client/client"
	"github.com/ncodes/cocoon/core/common"
	"github.com/ncodes/cocoon/core/config"
	"github.com/ncodes/cocoon/core/connector/server/acl"
	"github.com/ncodes/cocoon/core/types"
	logging "github.com/op/go-logging"
	"github.com/spf13/cobra"
)

// parseContract passes a contract files
func parseContract(path, repoVersion string) ([]*proto_api.CocoonReleasePayloadRequest, []error) {
	var id string
	var url string
	var lang string
	var version string
	var buildParams string
	var link string
	var resourceSet = "s1"
	var selectedResourceSet map[string]int
	var numSig = 1
	var sigThreshold = 1
	var firewallRules string
	var configFileData map[string]interface{}
	var aclMap map[string]interface{}
	var cocoons []*proto_api.CocoonReleasePayloadRequest
	var env map[string]interface{}
	var errs []error

	// path is a local file path
	if ok, _ := govalidator.IsFilePath(path); ok {
		fileData, err := ioutil.ReadFile(path)
		if err != nil {
			errs = append(errs, err)
			return nil, errs
		}
		if err = hcl.Decode(&configFileData, string(fileData)); err != nil {
			errs = append(errs, fmt.Errorf("failed to parse contract file: %s", err.Error()))
			return nil, errs
		}
	}

	// path is a github url, download contract from the root of the master branch
	if govalidator.IsURL(path) && c_util.IsGithubRepoURL(path) {
		url, _ := urlx.Parse(path)
		urls := []string{
			fmt.Sprintf("https://raw.githubusercontent.com%s/%s/contract.hcl", url.Path, repoVersion),
			fmt.Sprintf("https://raw.githubusercontent.com%s/%s/contract.json", url.Path, repoVersion),
		}
		for _, url := range urls {
			var fileData []byte
			err := util.DownloadURLToFunc(url, func(b []byte, code int) error {
				if code == 404 {
					return fmt.Errorf("contract file not found")
				}
				fileData = append(fileData, b...)
				if len(fileData) > 5000000 {
					return fmt.Errorf("Maximum contract file size reached. aborting download")
				}
				return nil
			})
			if err != nil {
				errs = append(errs, fmt.Errorf("failed to download contract file: %s", err))
				return nil, errs
			}
			if err = hcl.Decode(&configFileData, string(fileData)); err != nil {
				errs = append(errs, fmt.Errorf("failed to parse contract file: %s", err.Error()))
				return nil, errs
			}
			path = ""
			break
		}
	}

	// path is a url, download it
	if govalidator.IsURL(path) {
		var fileData []byte
		err := util.DownloadURLToFunc(path, func(b []byte, code int) error {
			if code == 404 {
				return fmt.Errorf("contract file not found")
			}
			fileData = append(fileData, b...)
			if len(fileData) > 5000000 {
				return fmt.Errorf("Maximum contract file size reached. aborting download")
			}
			return nil
		})
		if err != nil {
			errs = append(errs, fmt.Errorf("failed to download contract file: %s", err))
			return nil, errs
		}
		if err = hcl.Decode(&configFileData, string(fileData)); err != nil {
			errs = append(errs, fmt.Errorf("failed to parse contract file: %s", err.Error()))
			return nil, errs
		}
	}

	if len(configFileData) > 0 && configFileData["contracts"] != nil {
		if contracts, ok := configFileData["contracts"].([]map[string]interface{}); ok && len(contracts) > 0 {
			for i, contract := range contracts {

				id = util.UUID4()
				if _id, ok := contract["id"].(string); ok && len(_id) > 0 {
					id = _id
				}

				if repos, ok := contract["repo"].([]map[string]interface{}); ok && len(repos) > 0 {
					url = toStringOr(repos[0]["url"], "")
					version = toStringOr(repos[0]["version"], "")
					lang = toStringOr(repos[0]["language"], "")
					link = toStringOr(repos[0]["link"], "")
				} else {
					errs = append(errs, fmt.Errorf("contract %d: missing repo stanza", i))
					return nil, errs
				}

				if builds, ok := contract["build"].([]map[string]interface{}); ok && len(builds) > 0 {
					buildJSON, _ := util.ToJSON(builds[0])
					buildParams = string(buildJSON)
				}

				if resources, ok := contract["resources"].([]map[string]interface{}); ok && len(resources) > 0 {
					resourceSet = toStringOr(resources[0]["resource_set"], resourceSet)
					valid := false
					for k, v := range common.SupportedResourceSets {
						if k == resourceSet {
							valid = true
							selectedResourceSet = v
						}
					}
					if !valid {
						errs = append(errs, fmt.Errorf("resources: unknown resource_set value: %s", resourceSet))
					}
				}

				if signatories, ok := contract["signatories"].([]map[string]interface{}); ok && len(signatories) > 0 {
					numSig = toIntOr(signatories[0]["max"], numSig)
					sigThreshold = toIntOr(signatories[0]["threshold"], sigThreshold)
				}

				if acls, ok := contract["acl"].([]map[string]interface{}); ok && len(acls) > 0 {
					aclMap = acls[0]
				}

				if firewall, ok := contract["firewall"].([]map[string]interface{}); ok && len(firewall) > 0 {
					if len(firewall[0]["rule"].([]map[string]interface{})) > 0 {
						bs, _ := util.ToJSON(firewall[0]["rule"])
						firewallRules = string(bs)
					}
				}

				if envs, ok := contract["env"].([]map[string]interface{}); ok && len(envs) > 0 {
					env = envs[0]
				}

				// validate ACLMap
				if len(aclMap) > 0 {
					var _errs = acl.NewInterpreter(aclMap, false).Validate()
					if len(errs) > 0 {
						for _, err := range _errs {
							errs = append(errs, fmt.Errorf("acl: %s", err))
						}
						return nil, errs
					}
				}

				// parse and validate firewall
				var payloadFirewallRules []*proto_api.FirewallRule
				if len(firewallRules) > 0 {
					var _errs []error
					validFirewallRules, _errs := api.ValidateFirewallRules(firewallRules)
					if len(_errs) > 0 {
						for _, err := range errs {
							errs = append(errs, fmt.Errorf("firewall: %s", err))
						}
						return nil, errs
					}
					for _, rule := range validFirewallRules {
						payloadFirewallRules = append(payloadFirewallRules, &proto_api.FirewallRule{
							Destination:     rule.Destination,
							DestinationPort: rule.DestinationPort,
							Protocol:        rule.Protocol,
						})
					}
				}

				cocoons = append(cocoons, &proto_api.CocoonReleasePayloadRequest{
					CocoonID:       id,
					URL:            url,
					Language:       lang,
					Version:        version,
					BuildParam:     buildParams,
					Firewall:       payloadFirewallRules,
					ACL:            types.NewACLMap(aclMap).ToJSON(),
					Env:            types.NewEnv(env),
					Memory:         int32(selectedResourceSet["memory"]),
					CPUShare:       int32(selectedResourceSet["cpuShare"]),
					Link:           link,
					NumSignatories: int32(numSig),
					SigThreshold:   int32(sigThreshold),
				})
			}
		}
		return cocoons, nil
	}

	return nil, []error{fmt.Errorf("Unrecognised path: %s", path)}
}

// createCmd represents the create command
var createCmd = &cobra.Command{
	Use:   "create [OPTIONS] CONTRACT_FILE_PATH",
	Short: "Create a new cocoon",
	Long:  `Create a new cocoon`,
	Run: func(cmd *cobra.Command, args []string) {

		log := logging.MustGetLogger("api.client")
		log.SetBackend(config.MessageOnlyBackend)

		v, _ := cmd.Flags().GetString("version")

		if len(args) == 0 {
			UsageError(log, cmd, `"ellcrys create" requires at least 1 argument(s)`, `ellcrys create --help`)
		}

		stopSpinner := util.Spinner("Please wait...")

		cocoons, errs := parseContract(args[0], v)
		if errs != nil && len(errs) > 0 {
			stopSpinner()
			for _, err := range errs {
				log.Errorf("Err: %s", err.Error())
			}
			os.Exit(1)
		}

		stopSpinner()
		for i, cocoon := range cocoons {
			err := client.CreateCocoon(cocoon)
			if err != nil {
				log.Fatalf("Err (Contract %d): %s", i, (common.GetRPCErrDesc(err)))
			}
		}
	},
}

func init() {
	RootCmd.AddCommand(createCmd)
	createCmd.PersistentFlags().StringP("version", "v", "master", "Set the branch name or commit hash for a github hosted contract file")
}
<commit_msg>Use copier<commit_after>package cmd

import (
	"io/ioutil"
	"os"

	"fmt"

	"github.com/asaskevich/govalidator"
	"github.com/ellcrys/util"
	"github.com/goware/urlx"
	"github.com/hashicorp/hcl"
	"github.com/jinzhu/copier"
	c_util "github.com/ncodes/cocoon-util"
	"github.com/ncodes/cocoon/core/api/api"
	"github.com/ncodes/cocoon/core/api/api/proto_api"
	"github.com/ncodes/cocoon/core/client/client"
	"github.com/ncodes/cocoon/core/common"
	"github.com/ncodes/cocoon/core/config"
	"github.com/ncodes/cocoon/core/connector/server/acl"
	"github.com/ncodes/cocoon/core/types"
	logging "github.com/op/go-logging"
	"github.com/spf13/cobra"
)

// parseContract passes a contract files
func parseContract(path, repoVersion string) ([]*proto_api.CocoonReleasePayloadRequest, []error) {
	var id string
	var url string
	var lang string
	var version string
	var buildParams string
	var link string
	var resourceSet = "s1"
	var selectedResourceSet map[string]int
	var numSig = 1
	var sigThreshold = 1
	var firewallRules string
	var configFileData map[string]interface{}
	var aclMap map[string]interface{}
	var cocoons []*proto_api.CocoonReleasePayloadRequest
	var env map[string]interface{}
	var errs []error

	// path is a local file path
	if ok, _ := govalidator.IsFilePath(path); ok {
		fileData, err := ioutil.ReadFile(path)
		if err != nil {
			errs = append(errs, err)
			return nil, errs
		}
		if err = hcl.Decode(&configFileData, string(fileData)); err != nil {
			errs = append(errs, fmt.Errorf("failed to parse contract file: %s", err.Error()))
			return nil, errs
		}
	}

	// path is a github url, download contract from the root of the master branch
	if govalidator.IsURL(path) && c_util.IsGithubRepoURL(path) {
		url, _ := urlx.Parse(path)
		urls := []string{
			fmt.Sprintf("https://raw.githubusercontent.com%s/%s/contract.hcl", url.Path, repoVersion),
			fmt.Sprintf("https://raw.githubusercontent.com%s/%s/contract.json", url.Path, repoVersion),
		}
		for _, url := range urls {
			var fileData []byte
			err := util.DownloadURLToFunc(url, func(b []byte, code int) error {
				if code == 404 {
					return fmt.Errorf("contract file not found")
				}
				fileData = append(fileData, b...)
				if len(fileData) > 5000000 {
					return fmt.Errorf("Maximum contract file size reached. aborting download")
				}
				return nil
			})
			if err != nil {
				errs = append(errs, fmt.Errorf("failed to download contract file: %s", err))
				return nil, errs
			}
			if err = hcl.Decode(&configFileData, string(fileData)); err != nil {
				errs = append(errs, fmt.Errorf("failed to parse contract file: %s", err.Error()))
				return nil, errs
			}
			path = ""
			break
		}
	}

	// path is a url, download it
	if govalidator.IsURL(path) {
		var fileData []byte
		err := util.DownloadURLToFunc(path, func(b []byte, code int) error {
			if code == 404 {
				return fmt.Errorf("contract file not found")
			}
			fileData = append(fileData, b...)
			if len(fileData) > 5000000 {
				return fmt.Errorf("Maximum contract file size reached. aborting download")
			}
			return nil
		})
		if err != nil {
			errs = append(errs, fmt.Errorf("failed to download contract file: %s", err))
			return nil, errs
		}
		if err = hcl.Decode(&configFileData, string(fileData)); err != nil {
			errs = append(errs, fmt.Errorf("failed to parse contract file: %s", err.Error()))
			return nil, errs
		}
	}

	if len(configFileData) > 0 && configFileData["contracts"] != nil {
		if contracts, ok := configFileData["contracts"].([]map[string]interface{}); ok && len(contracts) > 0 {
			for i, contract := range contracts {

				id = util.UUID4()
				if _id, ok := contract["id"].(string); ok && len(_id) > 0 {
					id = _id
				}

				if repos, ok := contract["repo"].([]map[string]interface{}); ok && len(repos) > 0 {
					url = toStringOr(repos[0]["url"], "")
					version = toStringOr(repos[0]["version"], "")
					lang = toStringOr(repos[0]["language"], "")
					link = toStringOr(repos[0]["link"], "")
				} else {
					errs = append(errs, fmt.Errorf("contract %d: missing repo stanza", i))
					return nil, errs
				}

				if builds, ok := contract["build"].([]map[string]interface{}); ok && len(builds) > 0 {
					buildJSON, _ := util.ToJSON(builds[0])
					buildParams = string(buildJSON)
				}

				if resources, ok := contract["resources"].([]map[string]interface{}); ok && len(resources) > 0 {
					resourceSet = toStringOr(resources[0]["resource_set"], resourceSet)
					valid := false
					for k, v := range common.SupportedResourceSets {
						if k == resourceSet {
							valid = true
							selectedResourceSet = v
						}
					}
					if !valid {
						errs = append(errs, fmt.Errorf("resources: unknown resource_set value: %s", resourceSet))
					}
				}

				if signatories, ok := contract["signatories"].([]map[string]interface{}); ok && len(signatories) > 0 {
					numSig = toIntOr(signatories[0]["max"], numSig)
					sigThreshold = toIntOr(signatories[0]["threshold"], sigThreshold)
				}

				if acls, ok := contract["acl"].([]map[string]interface{}); ok && len(acls) > 0 {
					aclMap = acls[0]
				}

				if firewall, ok := contract["firewall"].([]map[string]interface{}); ok && len(firewall) > 0 {
					if len(firewall[0]["rule"].([]map[string]interface{})) > 0 {
						bs, _ := util.ToJSON(firewall[0]["rule"])
						firewallRules = string(bs)
					}
				}

				if envs, ok := contract["env"].([]map[string]interface{}); ok && len(envs) > 0 {
					env = envs[0]
				}

				// validate ACLMap
				if len(aclMap) > 0 {
					var _errs = acl.NewInterpreter(aclMap, false).Validate()
					if len(errs) > 0 {
						for _, err := range _errs {
							errs = append(errs, fmt.Errorf("acl: %s", err))
						}
						return nil, errs
					}
				}

				// parse and validate firewall
				var payloadFirewallRules []*proto_api.FirewallRule
				if len(firewallRules) > 0 {
					var _errs []error
					validFirewallRules, _errs := api.ValidateFirewallRules(firewallRules)
					if len(_errs) > 0 {
						for _, err := range errs {
							errs = append(errs, fmt.Errorf("firewall: %s", err))
						}
						return nil, errs
					}
					copier.Copy(&payloadFirewallRules, validFirewallRules)
				}

				cocoons = append(cocoons, &proto_api.CocoonReleasePayloadRequest{
					CocoonID:       id,
					URL:            url,
					Language:       lang,
					Version:        version,
					BuildParam:     buildParams,
					Firewall:       payloadFirewallRules,
					ACL:            types.NewACLMap(aclMap).ToJSON(),
					Env:            types.NewEnv(env),
					Memory:         int32(selectedResourceSet["memory"]),
					CPUShare:       int32(selectedResourceSet["cpuShare"]),
					Link:           link,
					NumSignatories: int32(numSig),
					SigThreshold:   int32(sigThreshold),
				})
			}
		}
		return cocoons, nil
	}

	return nil, []error{fmt.Errorf("Unrecognised path: %s", path)}
}

// createCmd represents the create command
var createCmd = &cobra.Command{
	Use:   "create [OPTIONS] CONTRACT_FILE_PATH",
	Short: "Create a new cocoon",
	Long:  `Create a new cocoon`,
	Run: func(cmd *cobra.Command, args []string) {

		log := logging.MustGetLogger("api.client")
		log.SetBackend(config.MessageOnlyBackend)

		v, _ := cmd.Flags().GetString("version")

		if len(args) == 0 {
			UsageError(log, cmd, `"ellcrys create" requires at least 1 argument(s)`, `ellcrys create --help`)
		}

		stopSpinner := util.Spinner("Please wait...")

		cocoons, errs := parseContract(args[0], v)
		if errs != nil && len(errs) > 0 {
			stopSpinner()
			for _, err := range errs {
				log.Errorf("Err: %s", err.Error())
			}
			os.Exit(1)
		}

		stopSpinner()
		for i, cocoon := range cocoons {
			err := client.CreateCocoon(cocoon)
			if err != nil {
				log.Fatalf("Err (Contract %d): %s", i, (common.GetRPCErrDesc(err)))
			}
		}
	},
}

func init() {
	RootCmd.AddCommand(createCmd)
	createCmd.PersistentFlags().StringP("version", "v", "master", "Set the branch name or commit hash for a github hosted contract file")
}
<|endoftext|>


<commit_before>package msgp

import (
	"math"
)

// Locate returns a []byte pointing to the field
// in a messagepack map with the provided key. (The returned []byte
// points to a sub-slice of 'raw'; Locate does no allocations.) If the
// key doesn't exist in the map, a zero-length []byte will be returned.
func Locate(key string, raw []byte) []byte {
	s, n := locate(raw, key)
	return raw[s:n]
}

// Replace takes a key ("key") in a messagepack map ("raw")
// and replaces its value with the one provided and returns
// the new []byte. The returned []byte may point to the same
// memory as "raw". Replace makes no effort to evaluate the validity
// of the contents of 'val'. It may use up to the full capacity of 'raw.'
// Replace returns 'nil' if the field doesn't exist or if the object in 'raw'
// is not a map.
func Replace(key string, raw []byte, val []byte) []byte {
	start, end := locate(raw, key)
	if start == end {
		return nil
	}
	return replace(raw, start, end, val, true)
}

// CopyReplace works similarly to Replace except that the returned
// byte slice does not point to the same memory as 'raw'. CopyReplace
// returns 'nil' if the field doesn't exist or 'raw' isn't a map.
func CopyReplace(key string, raw []byte, val []byte) []byte {
	start, end := locate(raw, key)
	if start == end {
		return nil
	}
	return replace(raw, start, end, val, false)
}

// Remove removes a key-value pair from 'raw'. It returns
// 'raw' unchanged if the key didn't exist.
func Remove(key string, raw []byte) []byte {
	start, end := locateKV(raw, key)
	if start == end {
		return raw
	}
	raw = raw[:start+copy(raw[start:], raw[end:])]
	return resizeMap(raw, -1)
}

// HasKey returns whether the map in 'raw' has
// a field with key 'key'
func HasKey(key string, raw []byte) bool {
	sz, bts, err := ReadMapHeaderBytes(raw)
	if err != nil {
		return false
	}
	var field []byte
	for i := uint32(0); i < sz; i++ {
		field, bts, err = ReadStringZC(bts)
		if err != nil {
			return false
		}
		if UnsafeString(field) == key {
			return true
		}
	}
	return false
}

func replace(raw []byte, start int, end int, val []byte, inplace bool) []byte {
	ll := end - start // length of segment to replace
	lv := len(val)

	if inplace {
		extra := lv - ll

		// fastest case: we're doing
		// a 1:1 replacement
		if extra == 0 {
			copy(raw[start:], val)
			return raw

		} else if extra < 0 {
			// 'val' smaller than replaced value
			// copy in place and shift back

			x := copy(raw[start:], val)
			y := copy(raw[start+x:], raw[end:])
			return raw[:start+x+y]

		} else if extra < cap(raw)-len(raw) {
			// 'val' less than (cap-len) extra bytes
			// copy in place and shift forward
			raw = raw[0 : len(raw)+extra]
			// shift end forward
			copy(raw[end+extra:], raw[end:])
			copy(raw[start:], val)
			return raw
		}
	}

	// we have to allocate new space
	out := make([]byte, len(raw)+len(val)-ll)
	x := copy(out, raw[:start])
	y := copy(out[x:], val)
	copy(out[x+y:], raw[end:])
	return out
}

// locate does a naive O(n) search for the map key; returns start, end
// (returns 0,0 on error)
func locate(raw []byte, key string) (start int, end int) {
	var (
		sz    uint32
		bts   []byte
		field []byte
		err   error
	)
	sz, bts, err = ReadMapHeaderBytes(raw)
	if err != nil {
		return
	}

	// loop and locate field
	for i := uint32(0); i < sz; i++ {
		field, bts, err = ReadStringZC(bts)
		if err != nil {
			return 0, 0
		}
		if UnsafeString(field) == key {
			// start location
			l := len(raw)
			start = l - len(bts)
			bts, err = Skip(bts)
			if err != nil {
				return 0, 0
			}
			end = l - len(bts)
			return
		}
		bts, err = Skip(bts)
		if err != nil {
			return 0, 0
		}
	}
	return 0, 0
}

// locate key AND value
func locateKV(raw []byte, key string) (start int, end int) {
	var (
		sz    uint32
		bts   []byte
		field []byte
		err   error
	)
	sz, bts, err = ReadMapHeaderBytes(raw)
	if err != nil {
		return 0, 0
	}

	for i := uint32(0); i < sz; i++ {
		tmp := len(bts)
		field, bts, err = ReadStringZC(bts)
		if err != nil {
			return 0, 0
		}
		if UnsafeString(field) == key {
			start = len(raw) - tmp
			bts, err = Skip(bts)
			if err != nil {
				return 0, 0
			}
			end = len(raw) - len(bts)
			return
		}
		bts, err = Skip(bts)
		if err != nil {
			return 0, 0
		}
	}
	return 0, 0
}

// delta is delta on map size
func resizeMap(raw []byte, delta int64) []byte {
	var sz int64
	switch raw[0] {
	case mmap16:
		sz = int64(big.Uint16(raw[1:]))
		if sz+delta <= math.MaxUint16 {
			big.PutUint16(raw[1:], uint16(sz+delta))
			return raw
		}
		if cap(raw)-len(raw) >= 2 {
			raw = raw[0 : len(raw)+2]
			copy(raw[5:], raw[3:])
			big.PutUint32(raw[1:], uint32(sz+delta))
			return raw
		}
		n := make([]byte, 0, len(raw)+5)
		n = AppendMapHeader(n, uint32(sz+delta))
		return append(n, raw[3:]...)

	case mmap32:
		sz = int64(big.Uint32(raw[1:]))
		big.PutUint32(raw[1:], uint32(sz+delta))
		return raw

	default:
		sz = int64(rfixmap(raw[0]))
		if sz+delta < 16 {
			raw[0] = wfixmap(uint8(sz + delta))
			return raw
		} else if sz+delta <= math.MaxUint16 {
			if cap(raw)-len(raw) >= 2 {
				raw = raw[0 : len(raw)+2]
				copy(raw[3:], raw[1:])
				raw[0] = mmap16
				big.PutUint16(raw[1:], uint16(sz+delta))
				return raw
			}
			n := make([]byte, 0, len(raw)+5)
			n = AppendMapHeader(n, uint32(sz+delta))
			return append(n, raw[1:]...)
		}
		if cap(raw)-len(raw) >= 4 {
			raw = raw[0 : len(raw)+4]
			copy(raw[5:], raw[1:])
			raw[0] = mmap32
			big.PutUint32(raw[1:], uint32(sz+delta))
			return raw
		}
		n := make([]byte, 0, len(raw)+5)
		n = AppendMapHeader(n, uint32(sz+delta))
		return append(n, raw[1:]...)
	}
}
<commit_msg>add missing magic number when map is sized from mm16 -> mm32 (#216)<commit_after>package msgp

import (
	"math"
)

// Locate returns a []byte pointing to the field
// in a messagepack map with the provided key. (The returned []byte
// points to a sub-slice of 'raw'; Locate does no allocations.) If the
// key doesn't exist in the map, a zero-length []byte will be returned.
func Locate(key string, raw []byte) []byte {
	s, n := locate(raw, key)
	return raw[s:n]
}

// Replace takes a key ("key") in a messagepack map ("raw")
// and replaces its value with the one provided and returns
// the new []byte. The returned []byte may point to the same
// memory as "raw". Replace makes no effort to evaluate the validity
// of the contents of 'val'. It may use up to the full capacity of 'raw.'
// Replace returns 'nil' if the field doesn't exist or if the object in 'raw'
// is not a map.
func Replace(key string, raw []byte, val []byte) []byte {
	start, end := locate(raw, key)
	if start == end {
		return nil
	}
	return replace(raw, start, end, val, true)
}

// CopyReplace works similarly to Replace except that the returned
// byte slice does not point to the same memory as 'raw'. CopyReplace
// returns 'nil' if the field doesn't exist or 'raw' isn't a map.
func CopyReplace(key string, raw []byte, val []byte) []byte {
	start, end := locate(raw, key)
	if start == end {
		return nil
	}
	return replace(raw, start, end, val, false)
}

// Remove removes a key-value pair from 'raw'. It returns
// 'raw' unchanged if the key didn't exist.
func Remove(key string, raw []byte) []byte {
	start, end := locateKV(raw, key)
	if start == end {
		return raw
	}
	raw = raw[:start+copy(raw[start:], raw[end:])]
	return resizeMap(raw, -1)
}

// HasKey returns whether the map in 'raw' has
// a field with key 'key'
func HasKey(key string, raw []byte) bool {
	sz, bts, err := ReadMapHeaderBytes(raw)
	if err != nil {
		return false
	}
	var field []byte
	for i := uint32(0); i < sz; i++ {
		field, bts, err = ReadStringZC(bts)
		if err != nil {
			return false
		}
		if UnsafeString(field) == key {
			return true
		}
	}
	return false
}

func replace(raw []byte, start int, end int, val []byte, inplace bool) []byte {
	ll := end - start // length of segment to replace
	lv := len(val)

	if inplace {
		extra := lv - ll

		// fastest case: we're doing
		// a 1:1 replacement
		if extra == 0 {
			copy(raw[start:], val)
			return raw

		} else if extra < 0 {
			// 'val' smaller than replaced value
			// copy in place and shift back

			x := copy(raw[start:], val)
			y := copy(raw[start+x:], raw[end:])
			return raw[:start+x+y]

		} else if extra < cap(raw)-len(raw) {
			// 'val' less than (cap-len) extra bytes
			// copy in place and shift forward
			raw = raw[0 : len(raw)+extra]
			// shift end forward
			copy(raw[end+extra:], raw[end:])
			copy(raw[start:], val)
			return raw
		}
	}

	// we have to allocate new space
	out := make([]byte, len(raw)+len(val)-ll)
	x := copy(out, raw[:start])
	y := copy(out[x:], val)
	copy(out[x+y:], raw[end:])
	return out
}

// locate does a naive O(n) search for the map key; returns start, end
// (returns 0,0 on error)
func locate(raw []byte, key string) (start int, end int) {
	var (
		sz    uint32
		bts   []byte
		field []byte
		err   error
	)
	sz, bts, err = ReadMapHeaderBytes(raw)
	if err != nil {
		return
	}

	// loop and locate field
	for i := uint32(0); i < sz; i++ {
		field, bts, err = ReadStringZC(bts)
		if err != nil {
			return 0, 0
		}
		if UnsafeString(field) == key {
			// start location
			l := len(raw)
			start = l - len(bts)
			bts, err = Skip(bts)
			if err != nil {
				return 0, 0
			}
			end = l - len(bts)
			return
		}
		bts, err = Skip(bts)
		if err != nil {
			return 0, 0
		}
	}
	return 0, 0
}

// locate key AND value
func locateKV(raw []byte, key string) (start int, end int) {
	var (
		sz    uint32
		bts   []byte
		field []byte
		err   error
	)
	sz, bts, err = ReadMapHeaderBytes(raw)
	if err != nil {
		return 0, 0
	}

	for i := uint32(0); i < sz; i++ {
		tmp := len(bts)
		field, bts, err = ReadStringZC(bts)
		if err != nil {
			return 0, 0
		}
		if UnsafeString(field) == key {
			start = len(raw) - tmp
			bts, err = Skip(bts)
			if err != nil {
				return 0, 0
			}
			end = len(raw) - len(bts)
			return
		}
		bts, err = Skip(bts)
		if err != nil {
			return 0, 0
		}
	}
	return 0, 0
}

// delta is delta on map size
func resizeMap(raw []byte, delta int64) []byte {
	var sz int64
	switch raw[0] {
	case mmap16:
		sz = int64(big.Uint16(raw[1:]))
		if sz+delta <= math.MaxUint16 {
			big.PutUint16(raw[1:], uint16(sz+delta))
			return raw
		}
		if cap(raw)-len(raw) >= 2 {
			raw = raw[0 : len(raw)+2]
			copy(raw[5:], raw[3:])
			raw[0] = mmap32
			big.PutUint32(raw[1:], uint32(sz+delta))
			return raw
		}
		n := make([]byte, 0, len(raw)+5)
		n = AppendMapHeader(n, uint32(sz+delta))
		return append(n, raw[3:]...)

	case mmap32:
		sz = int64(big.Uint32(raw[1:]))
		big.PutUint32(raw[1:], uint32(sz+delta))
		return raw

	default:
		sz = int64(rfixmap(raw[0]))
		if sz+delta < 16 {
			raw[0] = wfixmap(uint8(sz + delta))
			return raw
		} else if sz+delta <= math.MaxUint16 {
			if cap(raw)-len(raw) >= 2 {
				raw = raw[0 : len(raw)+2]
				copy(raw[3:], raw[1:])
				raw[0] = mmap16
				big.PutUint16(raw[1:], uint16(sz+delta))
				return raw
			}
			n := make([]byte, 0, len(raw)+5)
			n = AppendMapHeader(n, uint32(sz+delta))
			return append(n, raw[1:]...)
		}
		if cap(raw)-len(raw) >= 4 {
			raw = raw[0 : len(raw)+4]
			copy(raw[5:], raw[1:])
			raw[0] = mmap32
			big.PutUint32(raw[1:], uint32(sz+delta))
			return raw
		}
		n := make([]byte, 0, len(raw)+5)
		n = AppendMapHeader(n, uint32(sz+delta))
		return append(n, raw[1:]...)
	}
}
<|endoftext|>