<commit_before>// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tabletserver

import (
	"net/http"
	"os/exec"
	"strconv"
	"sync"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/memcache"
	"github.com/youtube/vitess/go/pools"
	"github.com/youtube/vitess/go/stats"
	"github.com/youtube/vitess/go/sync2"
)

const statsURL = "/debug/memcache/"

type CreateCacheFunc func() (*memcache.Connection, error)

// CachePool re-exposes ResourcePool as a pool of Memcache connection objects.
type CachePool struct {
	name          string
	pool          *pools.ResourcePool
	maxPrefix     sync2.AtomicInt64
	cmd           *exec.Cmd
	commandLine   []string
	capacity      int
	port          string
	idleTimeout   time.Duration
	DeleteExpiry  uint64
	memcacheStats *MemcacheStats
	mu            sync.Mutex
}

// Cache re-exposes memcache.Connection
// that can be recycled.
type Cache struct {
	*memcache.Connection
	pool *CachePool
}

func (cache *Cache) Recycle() {
	if cache.IsClosed() {
		cache.pool.Put(nil)
	} else {
		cache.pool.Put(cache)
	}
}

func NewCachePool(name string, commandLine []string, queryTimeout time.Duration, idleTimeout time.Duration) *CachePool {
	cp := &CachePool{name: name, idleTimeout: idleTimeout}
	if name != "" {
		cp.memcacheStats = NewMemcacheStats(cp)
		stats.Publish(name+"Capacity", stats.IntFunc(cp.Capacity))
		stats.Publish(name+"Available", stats.IntFunc(cp.Available))
		stats.Publish(name+"MaxCap", stats.IntFunc(cp.MaxCap))
		stats.Publish(name+"WaitCount", stats.IntFunc(cp.WaitCount))
		stats.Publish(name+"WaitTime", stats.DurationFunc(cp.WaitTime))
		stats.Publish(name+"IdleTimeout", stats.DurationFunc(cp.IdleTimeout))
	}
	http.Handle(statsURL, cp)

	if len(commandLine) == 0 {
		return cp
	}
	cp.commandLine = commandLine

	// Start with memcached defaults
	cp.capacity = 1024 - 50
	cp.port = "11211"
	for i := 0; i < len(commandLine); i++ {
		switch commandLine[i] {
		case "-p", "-s":
			i++
			if i == len(commandLine) {
				log.Fatalf("expecting value after -p")
			}
			cp.port = commandLine[i]
		case "-c":
			i++
			if i == len(commandLine) {
				log.Fatalf("expecting value after -c")
			}
			capacity, err := strconv.Atoi(commandLine[i])
			if err != nil {
				log.Fatalf("%V", err)
			}
			if capacity <= 50 {
				log.Fatalf("insufficient capacity: %d", capacity)
			}
			cp.capacity = capacity - 50
		}
	}

	seconds := uint64(queryTimeout / time.Second)
	// Add an additional grace period for
	// memcache expiry of deleted items
	if seconds != 0 {
		cp.DeleteExpiry = 2*seconds + 15
	}
	return cp
}

func (cp *CachePool) Open() {
	if len(cp.commandLine) == 0 {
		log.Infof("rowcache not enabled")
		return
	}
	cp.startMemcache()
	log.Infof("rowcache is enabled")
	f := func() (pools.Resource, error) {
		c, err := memcache.Connect(cp.port)
		if err != nil {
			return nil, err
		}
		return &Cache{c, cp}, nil
	}
	cp.mu.Lock()
	defer cp.mu.Unlock()
	cp.pool = pools.NewResourcePool(f, cp.capacity, cp.capacity, cp.idleTimeout)
	cp.memcacheStats.Open()
}

func (cp *CachePool) startMemcache() {
	cp.cmd = exec.Command(cp.commandLine[0], cp.commandLine[1:]...)
	if err := cp.cmd.Start(); err != nil {
		panic(NewTabletError(FATAL, "can't start memcache: %v", err))
	}
	attempts := 0
	for {
		time.Sleep(50 * time.Millisecond)
		c, err := memcache.Connect(cp.port)
		if err != nil {
			attempts++
			if attempts >= 30 {
				cp.cmd.Process.Kill()
				// FIXME(sougou): Throw proper error if we can recover
				log.Fatal("Can't connect to memcache")
			}
			continue
		}
		if _, err = c.Set("health", 0, 0, []byte("ok")); err != nil {
			panic(NewTabletError(FATAL, "can't communicate with memcache: %v", err))
		}
		c.Close()
		break
	}
}

func (cp *CachePool) Close() {
	cp.mu.Lock()
	defer cp.mu.Unlock()
	if cp.pool == nil {
		return
	}
	cp.memcacheStats.Close()
	cp.pool.Close()
	cp.cmd.Process.Kill()
	cp.pool = nil
}

func (cp *CachePool) IsClosed() bool {
	cp.mu.Lock()
	defer cp.mu.Unlock()
	return cp.pool == nil
}

func (cp *CachePool) getPool() *pools.ResourcePool {
	cp.mu.Lock()
	defer cp.mu.Unlock()
	return cp.pool
}

// You must call Recycle on the *Cache once done.
func (cp *CachePool) Get() *Cache {
	pool := cp.getPool()
	if pool == nil {
		return nil
	}
	r, err := pool.Get()
	if err != nil {
		panic(NewTabletErrorSql(FATAL, err))
	}
	return r.(*Cache)
}

func (cp *CachePool) Put(conn *Cache) {
	pool := cp.getPool()
	if pool == nil {
		return
	}
	pool.Put(conn)
}

func (cp *CachePool) StatsJSON() string {
	pool := cp.getPool()
	if pool == nil {
		return "{}"
	}
	return pool.StatsJSON()
}

func (cp *CachePool) Capacity() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.Capacity()
}

func (cp *CachePool) Available() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.Available()
}

func (cp *CachePool) MaxCap() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.MaxCap()
}

func (cp *CachePool) WaitCount() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.WaitCount()
}

func (cp *CachePool) WaitTime() time.Duration {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.WaitTime()
}

func (cp *CachePool) IdleTimeout() time.Duration {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.IdleTimeout()
}

func (cp *CachePool) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	defer func() {
		if x := recover(); x != nil {
			response.Write(([]byte)(x.(error).Error()))
		}
	}()
	response.Header().Set("Content-Type", "text/plain")
	pool := cp.getPool()
	if pool == nil {
		response.Write(([]byte)("closed"))
		return
	}
	command := request.URL.Path[len(statsURL):]
	if command == "stats" {
		command = ""
	}
	conn := cp.Get()
	defer conn.Recycle()
	r, err := conn.Stats(command)
	if err != nil {
		response.Write(([]byte)(err.Error()))
	} else {
		response.Write(r)
	}
}
<commit_msg>Fix memcache stats variable reference<commit_after>// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tabletserver

import (
	"net/http"
	"os/exec"
	"strconv"
	"sync"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/memcache"
	"github.com/youtube/vitess/go/pools"
	"github.com/youtube/vitess/go/stats"
	"github.com/youtube/vitess/go/sync2"
)

const statsURL = "/debug/memcache/"

type CreateCacheFunc func() (*memcache.Connection, error)

// CachePool re-exposes ResourcePool as a pool of Memcache connection objects.
type CachePool struct {
	name          string
	pool          *pools.ResourcePool
	maxPrefix     sync2.AtomicInt64
	cmd           *exec.Cmd
	commandLine   []string
	capacity      int
	port          string
	idleTimeout   time.Duration
	DeleteExpiry  uint64
	memcacheStats *MemcacheStats
	mu            sync.Mutex
}

// Cache re-exposes memcache.Connection
// that can be recycled.
type Cache struct {
	*memcache.Connection
	pool *CachePool
}

func (cache *Cache) Recycle() {
	if cache.IsClosed() {
		cache.pool.Put(nil)
	} else {
		cache.pool.Put(cache)
	}
}

func NewCachePool(name string, commandLine []string, queryTimeout time.Duration, idleTimeout time.Duration) *CachePool {
	cp := &CachePool{name: name, idleTimeout: idleTimeout}
	if name != "" {
		cp.memcacheStats = NewMemcacheStats(cp)
		stats.Publish(name+"Capacity", stats.IntFunc(cp.Capacity))
		stats.Publish(name+"Available", stats.IntFunc(cp.Available))
		stats.Publish(name+"MaxCap", stats.IntFunc(cp.MaxCap))
		stats.Publish(name+"WaitCount", stats.IntFunc(cp.WaitCount))
		stats.Publish(name+"WaitTime", stats.DurationFunc(cp.WaitTime))
		stats.Publish(name+"IdleTimeout", stats.DurationFunc(cp.IdleTimeout))
	}
	http.Handle(statsURL, cp)

	if len(commandLine) == 0 {
		return cp
	}
	cp.commandLine = commandLine

	// Start with memcached defaults
	cp.capacity = 1024 - 50
	cp.port = "11211"
	for i := 0; i < len(commandLine); i++ {
		switch commandLine[i] {
		case "-p", "-s":
			i++
			if i == len(commandLine) {
				log.Fatalf("expecting value after -p")
			}
			cp.port = commandLine[i]
		case "-c":
			i++
			if i == len(commandLine) {
				log.Fatalf("expecting value after -c")
			}
			capacity, err := strconv.Atoi(commandLine[i])
			if err != nil {
				log.Fatalf("%V", err)
			}
			if capacity <= 50 {
				log.Fatalf("insufficient capacity: %d", capacity)
			}
			cp.capacity = capacity - 50
		}
	}

	seconds := uint64(queryTimeout / time.Second)
	// Add an additional grace period for
	// memcache expiry of deleted items
	if seconds != 0 {
		cp.DeleteExpiry = 2*seconds + 15
	}
	return cp
}

func (cp *CachePool) Open() {
	if len(cp.commandLine) == 0 {
		log.Infof("rowcache not enabled")
		return
	}
	cp.startMemcache()
	log.Infof("rowcache is enabled")
	f := func() (pools.Resource, error) {
		c, err := memcache.Connect(cp.port)
		if err != nil {
			return nil, err
		}
		return &Cache{c, cp}, nil
	}
	cp.mu.Lock()
	defer cp.mu.Unlock()
	cp.pool = pools.NewResourcePool(f, cp.capacity, cp.capacity, cp.idleTimeout)
	if cp.memcacheStats != nil {
		cp.memcacheStats.Open()
	}
}

func (cp *CachePool) startMemcache() {
	cp.cmd = exec.Command(cp.commandLine[0], cp.commandLine[1:]...)
	if err := cp.cmd.Start(); err != nil {
		panic(NewTabletError(FATAL, "can't start memcache: %v", err))
	}
	attempts := 0
	for {
		time.Sleep(50 * time.Millisecond)
		c, err := memcache.Connect(cp.port)
		if err != nil {
			attempts++
			if attempts >= 30 {
				cp.cmd.Process.Kill()
				// FIXME(sougou): Throw proper error if we can recover
				log.Fatal("Can't connect to memcache")
			}
			continue
		}
		if _, err = c.Set("health", 0, 0, []byte("ok")); err != nil {
			panic(NewTabletError(FATAL, "can't communicate with memcache: %v", err))
		}
		c.Close()
		break
	}
}

func (cp *CachePool) Close() {
	cp.mu.Lock()
	defer cp.mu.Unlock()
	if cp.pool == nil {
		return
	}
	if cp.memcacheStats != nil {
		cp.memcacheStats.Close()
	}
	cp.pool.Close()
	cp.cmd.Process.Kill()
	cp.pool = nil
}

func (cp *CachePool) IsClosed() bool {
	cp.mu.Lock()
	defer cp.mu.Unlock()
	return cp.pool == nil
}

func (cp *CachePool) getPool() *pools.ResourcePool {
	cp.mu.Lock()
	defer cp.mu.Unlock()
	return cp.pool
}

// You must call Recycle on the *Cache once done.
func (cp *CachePool) Get() *Cache {
	pool := cp.getPool()
	if pool == nil {
		return nil
	}
	r, err := pool.Get()
	if err != nil {
		panic(NewTabletErrorSql(FATAL, err))
	}
	return r.(*Cache)
}

func (cp *CachePool) Put(conn *Cache) {
	pool := cp.getPool()
	if pool == nil {
		return
	}
	pool.Put(conn)
}

func (cp *CachePool) StatsJSON() string {
	pool := cp.getPool()
	if pool == nil {
		return "{}"
	}
	return pool.StatsJSON()
}

func (cp *CachePool) Capacity() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.Capacity()
}

func (cp *CachePool) Available() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.Available()
}

func (cp *CachePool) MaxCap() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.MaxCap()
}

func (cp *CachePool) WaitCount() int64 {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.WaitCount()
}

func (cp *CachePool) WaitTime() time.Duration {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.WaitTime()
}

func (cp *CachePool) IdleTimeout() time.Duration {
	pool := cp.getPool()
	if pool == nil {
		return 0
	}
	return pool.IdleTimeout()
}

func (cp *CachePool) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	defer func() {
		if x := recover(); x != nil {
			response.Write(([]byte)(x.(error).Error()))
		}
	}()
	response.Header().Set("Content-Type", "text/plain")
	pool := cp.getPool()
	if pool == nil {
		response.Write(([]byte)("closed"))
		return
	}
	command := request.URL.Path[len(statsURL):]
	if command == "stats" {
		command = ""
	}
	conn := cp.Get()
	defer conn.Recycle()
	r, err := conn.Stats(command)
	if err != nil {
		response.Write(([]byte)(err.Error()))
	} else {
		response.Write(r)
	}
}
<|endoftext|>


<commit_before>package consensus

import (
	"testing"

	"github.com/NebulousLabs/Sia/types"
)

// TestEarliestChildTimestamp probes the earliestChildTimestamp method of the
// block node type.
func TestEarliestChildTimestamp(t *testing.T) {
	// Check the earliest timestamp generated when the block node has no
	// parent.
	bn1 := &blockNode{block: types.Block{Timestamp: 1}}
	if bn1.earliestChildTimestamp() != 1 {
		t.Error("earliest child timestamp has been calculated incorrectly.")
	}

	// Set up a series of targets, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
	bn2 := &blockNode{block: types.Block{Timestamp: 2}, parent: bn1}
	bn3 := &blockNode{block: types.Block{Timestamp: 3}, parent: bn2}
	bn4 := &blockNode{block: types.Block{Timestamp: 4}, parent: bn3}
	bn5 := &blockNode{block: types.Block{Timestamp: 5}, parent: bn4}
	bn6 := &blockNode{block: types.Block{Timestamp: 6}, parent: bn5}
	bn7 := &blockNode{block: types.Block{Timestamp: 7}, parent: bn6}
	bn8 := &blockNode{block: types.Block{Timestamp: 8}, parent: bn7}
	bn9 := &blockNode{block: types.Block{Timestamp: 9}, parent: bn8}
	bn10 := &blockNode{block: types.Block{Timestamp: 10}, parent: bn9}
	bn11 := &blockNode{block: types.Block{Timestamp: 11}, parent: bn10}

	// Median should be '1' for bn6.
	if bn6.earliestChildTimestamp() != 1 {
		t.Error("incorrect child timestamp")
	}
	// Median should be '2' for bn7.
	if bn7.earliestChildTimestamp() != 2 {
		t.Error("incorrect child timestamp")
	}
	// Median should be '6' for bn11.
	if bn11.earliestChildTimestamp() != 6 {
		t.Error("incorrect child timestamp")
	}

	// Mix up the sorting:
	//           7, 5, 5, 2, 3, 9, 12, 1, 8, 6, 14
	// sorted11: 1, 2, 3, 5, 5, 6, 7, 8, 9, 12, 14
	// sorted10: 1, 2, 3, 5, 5, 6, 7, 7, 8, 9, 12
	// sorted9:  1, 2, 3, 5, 5, 7, 7, 7, 8, 9, 12
	bn1.block.Timestamp = 7
	bn2.block.Timestamp = 5
	bn3.block.Timestamp = 5
	bn4.block.Timestamp = 2
	bn5.block.Timestamp = 3
	bn6.block.Timestamp = 9
	bn7.block.Timestamp = 12
	bn8.block.Timestamp = 1
	bn9.block.Timestamp = 8
	bn10.block.Timestamp = 6
	bn11.block.Timestamp = 14

	// Median of bn11 should be '6'.
	if bn11.earliestChildTimestamp() != 6 {
		t.Error("incorrect child timestamp")
	}
	// Median of bn10 should be '6'.
	if bn10.earliestChildTimestamp() != 6 {
		t.Error("incorrect child timestamp")
	}
	// Median of bn9 should be '7'.
	if bn9.earliestChildTimestamp() != 7 {
		t.Error("incorrect child timestamp")
	}
}

// TestHeavierThan probes the heavierThan method of the blockNode type.
func TestHeavierThan(t *testing.T) {
	// Create a light node.
	bnLight := new(blockNode)
	bnLight.depth[0] = 64
	bnLight.childTarget[0] = 200

	// Create a node that's heavier, but not enough to beat the surpass
	// threshold.
	bnMiddle := new(blockNode)
	bnMiddle.depth[0] = 60
	bnMiddle.childTarget[0] = 200

	// Create a node that's heavy enough to break the surpass threshold.
	bnHeavy := new(blockNode)
	bnHeavy.depth[0] = 16
	bnHeavy.childTarget[0] = 200

	// bnLight should not be heavier than bnHeavy.
	if bnLight.heavierThan(bnHeavy) {
		t.Error("light heavier than heavy")
	}
	// bnLight should not be heavier than middle.
	if bnLight.heavierThan(bnMiddle) {
		t.Error("light heavier than middle")
	}
	// bnLight should not be heavier than itself.
	if bnLight.heavierThan(bnLight) {
		t.Error("light heavier than itself")
	}

	// bnMiddle should not be heavier than bnLight.
	if bnMiddle.heavierThan(bnLight) {
		t.Error("middle heaver than light - surpass threshold should not have been broken")
	}
	// bnHeavy should be heaver than bnLight.
	if !bnHeavy.heavierThan(bnLight) {
		t.Error("heavy is not heavier than light")
	}
	// bnHeavy should be heavier than bnMiddle.
	if !bnHeavy.heavierThan(bnMiddle) {
		t.Error("heavy is not heavier than middle")
	}
}

// TestChildDepth probes the childDeath method of the blockNode type.
func TestChildDept(t *testing.T) {
	bn := new(blockNode)
	bn.depth[0] = 64
	bn.childTarget[0] = 64
	childDepth := bn.childDepth()
	if childDepth[0] != 32 {
		t.Error("unexpected child depth")
	}

	bn.depth[0] = 24
	bn.childTarget[0] = 48
	childDepth = bn.childDepth()
	if childDepth[0] != 16 {
		t.Error("unexpected child depth")
	}
}

// TestTargetAdjustmentBase probes the targetAdjustmentBase method of the block
// node type.
func TestTargetAdjustmentBase(t *testing.T) {
	// Create a genesis node at timestamp 10,000
	genesisNode := &blockNode{
		block: types.Block{Timestamp: 10000},
	}
	exactTimeNode := &blockNode{
		block: types.Block{Timestamp: types.Timestamp(10000 + types.BlockFrequency)},
	}
	exactTimeNode.parent = genesisNode

	// Base adjustment for the exactTimeNode should be 1.
	adjustment, exact := exactTimeNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Fatal("did not get an exact target adjustment")
	}
	if adjustment != 1 {
		t.Error("block did not adjust itself to the same target")
	}

	// Create a double-speed node and get the base adjustment.
	doubleSpeedNode := &blockNode{
		block: types.Block{Timestamp: types.Timestamp(10000 + types.BlockFrequency)},
	}
	doubleSpeedNode.parent = exactTimeNode
	adjustment, exact = doubleSpeedNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Fatal("did not get an exact adjustment")
	}
	if adjustment != 0.5 {
		t.Error("double speed node did not get a base to halve the target")
	}

	// Create a half-speed node and get the base adjustment.
	halfSpeedNode := &blockNode{
		block: types.Block{Timestamp: types.Timestamp(10000 + types.BlockFrequency*6)},
	}
	halfSpeedNode.parent = doubleSpeedNode
	adjustment, exact = halfSpeedNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Fatal("did not get an exact adjustment")
	}
	if adjustment != 2 {
		t.Error("double speed node did not get a base to halve the target")
	}

	if testing.Short() {
		t.SkipNow()
	}
	// Create a chain of nodes so that the genesis node is no longer the point
	// of comparison.
	comparisonNode := &blockNode{
		block: types.Block{Timestamp: 125000},
	}
	comparisonNode.parent = halfSpeedNode
	startingNode := comparisonNode
	for i := types.BlockHeight(0); i < types.TargetWindow; i++ {
		newNode := new(blockNode)
		newNode.parent = startingNode
		startingNode = newNode
	}
	startingNode.block.Timestamp = types.Timestamp(125000 + types.BlockFrequency*types.TargetWindow)
	adjustment, exact = startingNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Error("failed to get exact result")
	}
	if adjustment != 1 {
		t.Error("got wrong long-range adjustment")
	}
	startingNode.block.Timestamp = types.Timestamp(125000 + 2*types.BlockFrequency*types.TargetWindow)
	adjustment, exact = startingNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Error("failed to get exact result")
	}
	if adjustment != 2 {
		t.Error("got wrong long-range adjustment")
	}
}
<commit_msg>add test for setChildTarget<commit_after>package consensus

import (
	"math/big"
	"testing"

	"github.com/NebulousLabs/Sia/types"
)

// TestEarliestChildTimestamp probes the earliestChildTimestamp method of the
// block node type.
func TestEarliestChildTimestamp(t *testing.T) {
	// Check the earliest timestamp generated when the block node has no
	// parent.
	bn1 := &blockNode{block: types.Block{Timestamp: 1}}
	if bn1.earliestChildTimestamp() != 1 {
		t.Error("earliest child timestamp has been calculated incorrectly.")
	}

	// Set up a series of targets, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
	bn2 := &blockNode{block: types.Block{Timestamp: 2}, parent: bn1}
	bn3 := &blockNode{block: types.Block{Timestamp: 3}, parent: bn2}
	bn4 := &blockNode{block: types.Block{Timestamp: 4}, parent: bn3}
	bn5 := &blockNode{block: types.Block{Timestamp: 5}, parent: bn4}
	bn6 := &blockNode{block: types.Block{Timestamp: 6}, parent: bn5}
	bn7 := &blockNode{block: types.Block{Timestamp: 7}, parent: bn6}
	bn8 := &blockNode{block: types.Block{Timestamp: 8}, parent: bn7}
	bn9 := &blockNode{block: types.Block{Timestamp: 9}, parent: bn8}
	bn10 := &blockNode{block: types.Block{Timestamp: 10}, parent: bn9}
	bn11 := &blockNode{block: types.Block{Timestamp: 11}, parent: bn10}

	// Median should be '1' for bn6.
	if bn6.earliestChildTimestamp() != 1 {
		t.Error("incorrect child timestamp")
	}
	// Median should be '2' for bn7.
	if bn7.earliestChildTimestamp() != 2 {
		t.Error("incorrect child timestamp")
	}
	// Median should be '6' for bn11.
	if bn11.earliestChildTimestamp() != 6 {
		t.Error("incorrect child timestamp")
	}

	// Mix up the sorting:
	//           7, 5, 5, 2, 3, 9, 12, 1, 8, 6, 14
	// sorted11: 1, 2, 3, 5, 5, 6, 7, 8, 9, 12, 14
	// sorted10: 1, 2, 3, 5, 5, 6, 7, 7, 8, 9, 12
	// sorted9:  1, 2, 3, 5, 5, 7, 7, 7, 8, 9, 12
	bn1.block.Timestamp = 7
	bn2.block.Timestamp = 5
	bn3.block.Timestamp = 5
	bn4.block.Timestamp = 2
	bn5.block.Timestamp = 3
	bn6.block.Timestamp = 9
	bn7.block.Timestamp = 12
	bn8.block.Timestamp = 1
	bn9.block.Timestamp = 8
	bn10.block.Timestamp = 6
	bn11.block.Timestamp = 14

	// Median of bn11 should be '6'.
	if bn11.earliestChildTimestamp() != 6 {
		t.Error("incorrect child timestamp")
	}
	// Median of bn10 should be '6'.
	if bn10.earliestChildTimestamp() != 6 {
		t.Error("incorrect child timestamp")
	}
	// Median of bn9 should be '7'.
	if bn9.earliestChildTimestamp() != 7 {
		t.Error("incorrect child timestamp")
	}
}

// TestHeavierThan probes the heavierThan method of the blockNode type.
func TestHeavierThan(t *testing.T) {
	// Create a light node.
	bnLight := new(blockNode)
	bnLight.depth[0] = 64
	bnLight.childTarget[0] = 200

	// Create a node that's heavier, but not enough to beat the surpass
	// threshold.
	bnMiddle := new(blockNode)
	bnMiddle.depth[0] = 60
	bnMiddle.childTarget[0] = 200

	// Create a node that's heavy enough to break the surpass threshold.
	bnHeavy := new(blockNode)
	bnHeavy.depth[0] = 16
	bnHeavy.childTarget[0] = 200

	// bnLight should not be heavier than bnHeavy.
	if bnLight.heavierThan(bnHeavy) {
		t.Error("light heavier than heavy")
	}
	// bnLight should not be heavier than middle.
	if bnLight.heavierThan(bnMiddle) {
		t.Error("light heavier than middle")
	}
	// bnLight should not be heavier than itself.
	if bnLight.heavierThan(bnLight) {
		t.Error("light heavier than itself")
	}

	// bnMiddle should not be heavier than bnLight.
	if bnMiddle.heavierThan(bnLight) {
		t.Error("middle heaver than light - surpass threshold should not have been broken")
	}
	// bnHeavy should be heaver than bnLight.
	if !bnHeavy.heavierThan(bnLight) {
		t.Error("heavy is not heavier than light")
	}
	// bnHeavy should be heavier than bnMiddle.
	if !bnHeavy.heavierThan(bnMiddle) {
		t.Error("heavy is not heavier than middle")
	}
}

// TestChildDepth probes the childDeath method of the blockNode type.
func TestChildDept(t *testing.T) {
	bn := new(blockNode)
	bn.depth[0] = 64
	bn.childTarget[0] = 64
	childDepth := bn.childDepth()
	if childDepth[0] != 32 {
		t.Error("unexpected child depth")
	}

	bn.depth[0] = 24
	bn.childTarget[0] = 48
	childDepth = bn.childDepth()
	if childDepth[0] != 16 {
		t.Error("unexpected child depth")
	}
}

// TestTargetAdjustmentBase probes the targetAdjustmentBase method of the block
// node type.
func TestTargetAdjustmentBase(t *testing.T) {
	// Create a genesis node at timestamp 10,000
	genesisNode := &blockNode{
		block: types.Block{Timestamp: 10000},
	}
	exactTimeNode := &blockNode{
		block: types.Block{Timestamp: types.Timestamp(10000 + types.BlockFrequency)},
	}
	exactTimeNode.parent = genesisNode

	// Base adjustment for the exactTimeNode should be 1.
	adjustment, exact := exactTimeNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Fatal("did not get an exact target adjustment")
	}
	if adjustment != 1 {
		t.Error("block did not adjust itself to the same target")
	}

	// Create a double-speed node and get the base adjustment.
	doubleSpeedNode := &blockNode{
		block: types.Block{Timestamp: types.Timestamp(10000 + types.BlockFrequency)},
	}
	doubleSpeedNode.parent = exactTimeNode
	adjustment, exact = doubleSpeedNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Fatal("did not get an exact adjustment")
	}
	if adjustment != 0.5 {
		t.Error("double speed node did not get a base to halve the target")
	}

	// Create a half-speed node and get the base adjustment.
	halfSpeedNode := &blockNode{
		block: types.Block{Timestamp: types.Timestamp(10000 + types.BlockFrequency*6)},
	}
	halfSpeedNode.parent = doubleSpeedNode
	adjustment, exact = halfSpeedNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Fatal("did not get an exact adjustment")
	}
	if adjustment != 2 {
		t.Error("double speed node did not get a base to halve the target")
	}

	if testing.Short() {
		t.SkipNow()
	}
	// Create a chain of nodes so that the genesis node is no longer the point
	// of comparison.
	comparisonNode := &blockNode{
		block: types.Block{Timestamp: 125000},
	}
	comparisonNode.parent = halfSpeedNode
	startingNode := comparisonNode
	for i := types.BlockHeight(0); i < types.TargetWindow; i++ {
		newNode := new(blockNode)
		newNode.parent = startingNode
		startingNode = newNode
	}
	startingNode.block.Timestamp = types.Timestamp(125000 + types.BlockFrequency*types.TargetWindow)
	adjustment, exact = startingNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Error("failed to get exact result")
	}
	if adjustment != 1 {
		t.Error("got wrong long-range adjustment")
	}
	startingNode.block.Timestamp = types.Timestamp(125000 + 2*types.BlockFrequency*types.TargetWindow)
	adjustment, exact = startingNode.targetAdjustmentBase().Float64()
	if !exact {
		t.Error("failed to get exact result")
	}
	if adjustment != 2 {
		t.Error("got wrong long-range adjustment")
	}
}

// TestClampTargetAdjustment probes the clampTargetAdjustment function.
func TestClampTargetAdjustment(t *testing.T) {
	// Check that the MaxAdjustmentUp and MaxAdjustmentDown constants match the
	// test's expectations.
	if types.MaxAdjustmentUp.Cmp(big.NewRat(10001, 10000)) != 0 {
		t.Fatal("MaxAdjustmentUp changed - test now invalid")
	}
	if types.MaxAdjustmentDown.Cmp(big.NewRat(9999, 10000)) != 0 {
		t.Fatal("MaxAdjustmentDown changed - test now invalid")
	}

	// Check high and low clamping.
	initial := big.NewRat(2, 1)
	clamped := clampTargetAdjustment(initial)
	if clamped.Cmp(big.NewRat(10001, 10000)) != 0 {
		t.Error("clamp not applied to large target adjustment")
	}
	initial = big.NewRat(1, 2)
	clamped = clampTargetAdjustment(initial)
	if clamped.Cmp(big.NewRat(9999, 10000)) != 0 {
		t.Error("clamp not applied to small target adjustment")
	}

	// Check middle clamping (or lack thereof).
	initial = big.NewRat(10002, 10001)
	clamped = clampTargetAdjustment(initial)
	if clamped.Cmp(initial) != 0 {
		t.Error("clamp applied to safe target adjustment")
	}
	initial = big.NewRat(99999, 100000)
	clamped = clampTargetAdjustment(initial)
	if clamped.Cmp(initial) != 0 {
		t.Error("clamp applied to safe target adjustment")
	}
}

// TestSetChildTarget probes the setChildTarget method of the block node type.
func TestSetChildTarget(t *testing.T) {
	// Create a genesis node and a child that took 2x as long as expected.
	genesisNode := &blockNode{
		block: types.Block{Timestamp: 10000},
	}
	genesisNode.childTarget[0] = 64
	doubleTimeNode := &blockNode{
		block: types.Block{Timestamp: types.Timestamp(10000 + types.BlockFrequency*2)},
	}
	doubleTimeNode.parent = genesisNode

	// Check the resulting childTarget of the new node and see that the clamp
	// was applied.
	doubleTimeNode.setChildTarget()
	if doubleTimeNode.childTarget.Cmp(genesisNode.childTarget) <= 0 {
		t.Error("double time node target did not increase")
	}
	fullAdjustment := genesisNode.childTarget.MulDifficulty(big.NewRat(1, 2))
	if doubleTimeNode.childTarget.Cmp(fullAdjustment) >= 0 {
		t.Error("clamp was not applied when adjusting target")
	}
}
<|endoftext|>


<commit_before>package endpoint

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/infiniteloopsco/guartz/models"
	"github.com/jinzhu/gorm"
)

//TaskList serves the route GET /tasks
func TaskList(c *gin.Context) {
	var tasks []models.Task
	models.Gdb.Find(&tasks)
	c.JSON(http.StatusOK, tasks)
}

//TaskShow serves the route GET /tasks/:task_id
func TaskShow(c *gin.Context) {
	var task models.Task
	models.Gdb.Where("id like ?", c.Param("task_id")).First(&task)
	if task.ID != "" {
		c.JSON(http.StatusOK, task)
	} else {
		c.JSON(http.StatusNotFound, "")
	}
}

//TaskCreate serves the route POST /tasks
func TaskCreate(c *gin.Context) {
	models.InTx(func(txn *gorm.DB) bool {
		var task models.Task
		if err := c.BindJSON(&task); err == nil {
			if valid, errMap := models.ValidStruct(&task); valid {
				var taskExistent models.Task
				models.Gdb.Where("id like ?", task.ID).First(&taskExistent)
				var err error
				if task.ID != "" && taskExistent.ID != "" {
					err = txn.Save(&task).Error
				} else {
					err = txn.Create(&task).Error
				}
				if err == nil {
					c.JSON(http.StatusOK, task)
					return true
				} else {
					c.JSON(http.StatusBadRequest, "Couldn't create the task")
				}
			} else {
				c.JSON(http.StatusConflict, errMap)
			}
		}
		return false
	})
}

//TaskDelete serves the route DELETE /tasks/:task_id
func TaskDelete(c *gin.Context) {
	models.InTx(func(txn *gorm.DB) bool {
		var task models.Task
		models.Gdb.Where("id like ?", c.Param("task_id")).First(&task)
		if task.ID != "" {
			if err := txn.Delete(&task).Error; err == nil {
				c.JSON(http.StatusOK, task)
				return true
			} else {
				c.JSON(http.StatusBadRequest, "Could not delete the task")
			}
		} else {
			c.JSON(http.StatusNotFound, "")
		}
		return false
	})
}
<commit_msg>deploy<commit_after>package endpoint

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/infiniteloopsco/guartz/models"
	"github.com/jinzhu/gorm"
)

//TaskList serves the route GET /tasks
func TaskList(c *gin.Context) {
	var tasks []models.Task
	models.Gdb.Find(&tasks)
	c.JSON(http.StatusOK, tasks)
}

//TaskShow serves the route GET /tasks/:task_id
func TaskShow(c *gin.Context) {
	var task models.Task
	models.Gdb.Where("id like ?", c.Param("task_id")).First(&task)
	if task.ID != "" {
		c.JSON(http.StatusOK, task)
	} else {
		c.JSON(http.StatusNotFound, "")
	}
}

//TaskCreate serves the route POST /tasks
func TaskCreate(c *gin.Context) {
	models.InTx(func(txn *gorm.DB) bool {
		var task models.Task
		if err := c.BindJSON(&task); err == nil {
			if valid, errMap := models.ValidStruct(&task); valid {
				var taskExistent models.Task
				models.Gdb.Where("id like ?", task.ID).First(&taskExistent)
				var err error
				if task.ID != "" && taskExistent.ID != "" {
					taskExistent.Periodicity = task.Periodicity
					taskExistent.Command = task.Command
					err = txn.Save(&taskExistent).Error
				} else {
					err = txn.Create(&task).Error
				}
				if err == nil {
					c.JSON(http.StatusOK, task)
					return true
				} else {
					c.JSON(http.StatusBadRequest, "Couldn't create the task")
				}
			} else {
				c.JSON(http.StatusConflict, errMap)
			}
		}
		return false
	})
}

//TaskDelete serves the route DELETE /tasks/:task_id
func TaskDelete(c *gin.Context) {
	models.InTx(func(txn *gorm.DB) bool {
		var task models.Task
		models.Gdb.Where("id like ?", c.Param("task_id")).First(&task)
		if task.ID != "" {
			if err := txn.Delete(&task).Error; err == nil {
				c.JSON(http.StatusOK, task)
				return true
			} else {
				c.JSON(http.StatusBadRequest, "Could not delete the task")
			}
		} else {
			c.JSON(http.StatusNotFound, "")
		}
		return false
	})
}
<|endoftext|>


<commit_before>// Copyright 2019 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package policy

import (
	"net/http"
	"testing"

	"istio.io/istio/pkg/test/framework"
	"istio.io/istio/pkg/test/framework/components/bookinfo"
	util "istio.io/istio/tests/integration/mixer"
)

func TestWhiteListing(t *testing.T) {
	framework.Run(t, func(ctx framework.TestContext) {
		t.Skipf("https://github.com/istio/istio/issues/13845")
		if galInst == nil {
			t.Fatalf("galley not setup")
		}
		g := *galInst
		if bookinfoNamespace == nil {
			t.Fatalf("bookinfo namespace not allocated in setup")
		}
		bookinfoNs := *bookinfoNamespace
		g.ApplyConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.NetworkingBookinfoGateway.LoadGatewayFileWithNamespaceOrFail(t, bookinfoNs.Name()))
		g.ApplyConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.GetDestinationRuleConfigFile(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
			bookinfo.NetworkingVirtualServiceAllV1.LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
		)
		defer g.DeleteConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.NetworkingBookinfoGateway.LoadGatewayFileWithNamespaceOrFail(t, bookinfoNs.Name()),
		)
		defer g.DeleteConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.GetDestinationRuleConfigFile(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
			bookinfo.NetworkingVirtualServiceAllV1.LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
		)

		if ingInst == nil {
			t.Fatalf("ingress not setup")
		}
		ing := *ingInst
		// Verify you can access productpage right now.
		util.SendTrafficAndWaitForExpectedStatus(ing, t, "Sending traffic...", "", 2, http.StatusOK)

		g.ApplyConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.PolicyDenyIPRule.LoadWithNamespaceOrFail(t, bookinfoNs.Name()))
		defer g.DeleteConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.PolicyDenyIPRule.LoadWithNamespaceOrFail(t, bookinfoNs.Name()))
		// Verify you can't access productpage now.
		util.SendTrafficAndWaitForExpectedStatus(ing, t, "Sending traffic...", "", 30, http.StatusForbidden)
	})
}
<commit_msg>Enable IP Whitelist test (#14481)<commit_after>// Copyright 2019 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package policy

import (
	"net/http"
	"testing"

	"istio.io/istio/pkg/test/framework"
	"istio.io/istio/pkg/test/framework/components/bookinfo"
	util "istio.io/istio/tests/integration/mixer"
)

func TestWhiteListing(t *testing.T) {
	framework.Run(t, func(ctx framework.TestContext) {
		if galInst == nil {
			t.Fatalf("galley not setup")
		}
		g := *galInst
		if bookinfoNamespace == nil {
			t.Fatalf("bookinfo namespace not allocated in setup")
		}
		bookinfoNs := *bookinfoNamespace
		g.ApplyConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.NetworkingBookinfoGateway.LoadGatewayFileWithNamespaceOrFail(t, bookinfoNs.Name()))
		g.ApplyConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.GetDestinationRuleConfigFile(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
			bookinfo.NetworkingVirtualServiceAllV1.LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
		)
		defer g.DeleteConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.NetworkingBookinfoGateway.LoadGatewayFileWithNamespaceOrFail(t, bookinfoNs.Name()),
		)
		defer g.DeleteConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.GetDestinationRuleConfigFile(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
			bookinfo.NetworkingVirtualServiceAllV1.LoadWithNamespaceOrFail(t, bookinfoNs.Name()),
		)

		if ingInst == nil {
			t.Fatalf("ingress not setup")
		}
		ing := *ingInst
		// Verify you can access productpage right now.
		util.SendTrafficAndWaitForExpectedStatus(ing, t, "Sending traffic...", "", 2, http.StatusOK)

		g.ApplyConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.PolicyDenyIPRule.LoadWithNamespaceOrFail(t, bookinfoNs.Name()))
		defer g.DeleteConfigOrFail(
			t,
			bookinfoNs,
			bookinfo.PolicyDenyIPRule.LoadWithNamespaceOrFail(t, bookinfoNs.Name()))
		util.AllowRuleSync(t)
		// Verify you can't access productpage now.
		util.SendTrafficAndWaitForExpectedStatus(ing, t, "Sending traffic...", "", 30, http.StatusForbidden)
	})
}
<|endoftext|>


<commit_before>// Copyright (c) 2011.  Jake Brukhman <jbrukh@gmail.com>
// All rights reserved.
// This software is governed by BSD-style license, see LICENSE.

package bitvector

import (
    "bytes"
    "fmt"
)

// CONSTANTS
const WORDSIZE = 8

// BitVector represents a bit vector.
type BitVector struct {
    // internal representation (does NOT scale with WORDSIZE)
    bits []byte
}

// New creates a new BitVector that will accomodate at least
// the specified minimum length.  When necessary, the vector
// will automatically grow to accomodate the extra data.
func New(length uint) *BitVector {
    v := &BitVector{}
    v.accomodate(length - 1)
    return v
}

// Length returns the current length of the BitVector in bits.
func (v *BitVector) Length() int {
    return WORDSIZE * len(v.bits)
}

// Clear will reset all bits to 0, but the size of the vector
// remains unaffected.
func (v *BitVector) Clear() {
    for inx, _ := range v.bits {
        v.bits[inx] = 0
    }
}

// Copy returns a copy of this BitVector.
func (v *BitVector) Copy() *BitVector {
    w := &BitVector{}
    w.accomodateBytes(len(v.bits))
    copy(w.bits, v.bits)
    return w
}

// String will create a string representation of the vector.
func (v *BitVector) String() string {
    buf := bytes.NewBufferString("")
    for _, word := range v.bits {
        for inx := 0; inx < WORDSIZE; inx++ {
            // if the inx-th bit is 1, result
            // is 1; otherwise 0; following does NOT
            // scale with the value of WORDSIZE
            fmt.Fprint(buf, (0x80&word)>>7)
            word <<= 1
        }
    }
    return string(buf.Bytes())
}

// Equal returns true if and only if the BitVector
// provided is equal to this BitVector in the sense
// that all bit settings coincide in both structures.
func (v *BitVector) Equal(w *BitVector) bool {
	if w == nil {
		return false
	}
	minx := max(len(v.bits),len(w.bits))
	for i := 0; i < minx; i++ {
		if v.getByte(i) != w.getByte(i) {
			return false
		}
	}
	return true
}

// Set will set the bit at the specified index to
// the specified boolean value.
func (v *BitVector) Set(index uint, value bool) {
    v.accomodate(index)
    word, bit := locate(index)
    if value {
        v.bits[word] |= basisByte(bit)
    } else {
        v.bits[word] &= ^basisByte(bit)
    }
}

// IsSet returns true if and only if the bit at the
// specified index is set.
func (v *BitVector) Get(index uint) bool {
    return v.GetInt(index) == 1
}

// Get will retrieve the value of the bit at the
// specified index as an signed integer.
func (v *BitVector) GetInt(index uint) int {
    word, bit := locate(index)
    if int(word) >= len(v.bits) {
        return 0
    }
    return int((v.bits[word] & basisByte(bit)) >> (7 - bit))
}

// Not negates this BitVector.
func (v *BitVector) Not() {
    for inx, _ := range v.bits {
        v.bits[inx] = ^v.bits[inx]
    }
}

// Not returns the negation of this BitVector.
func Not(v *BitVector) *BitVector {
    w := v.Copy()
    w.Not()
    return w
}

// Or will OR this BitVector with another one.
func (v *BitVector) Or(w *BitVector) {
    length := len(w.bits)
    v.accomodateBytes(length)
    for inx, _ := range v.bits {
        if inx < length {
            v.bits[inx] |= w.bits[inx]
        }
    }
}

// Or returns the OR of two BitVectors.
func Or(v, w *BitVector) *BitVector {
    z := v.Copy()
    z.Or(w)
    return z
}

// And will AND this BitVector with another one.
func (v *BitVector) And(w *BitVector) {
    length := len(w.bits)
    v.accomodateBytes(length)
    for inx, _ := range v.bits {
        if inx < length {
            v.bits[inx] &= w.bits[inx]
        } else {
            v.bits[inx] = 0 //
        }
    }
}

// And returns the AND of two BitVectors.
func And(v, w *BitVector) *BitVector {
    z := v.Copy()
    z.And(w)
    return z
}

// Locate will produce the location -- word and bit index --
// of the specified absolute index of the vector.
func locate(index uint) (word, bit uint) {
    return index / WORDSIZE, index % WORDSIZE
}

// accomodate will grow the BitVector to accomodate new entries.
func (v *BitVector) accomodate(index uint) {
    if index < 0 {
        panic("must specify nonnegative index")
    }
    words := int(index/WORDSIZE) + 1
    length := len(v.bits)
    if words > length { // reallocate
        newSlice := make([]byte, max(2*length, words))
        copy(newSlice, v.bits)
        v.bits = newSlice
    }
}

func (v *BitVector) accomodateBytes(length int) {
    v.accomodate(uint(length*WORDSIZE) - 1)
}

// basisByte returns a byte with a single non-zero bit
// set at the specified index.
func basisByte(index uint) byte {
    // does NOT scale with WORDSIZE
    return 0x80 >> index
}

// getByte returns the value of the inx-th byte, if
// it is allocated, or 0.  That is, the vector is
// assumed to have an infinite 0-sequence extending
// to the right.
func (v *BitVector) getByte(inx int) byte {
    if inx < len(v.bits) {
        return v.bits[inx]
    }
    return 0
}

// max returns the maximum of two integers.
func max(a, b int) int {
    if a < b {
        return b
    }
    return a
}

// min returns the maximum of two integers.
func min(a, b int) int {
    if a > b {
        return b
    }
    return a
}
<commit_msg>Fixed handling of different-sized byte arrays.<commit_after>// Copyright (c) 2011.  Jake Brukhman <jbrukh@gmail.com>
// All rights reserved.
// This software is governed by BSD-style license, see LICENSE.

package bitvector

import (
    "bytes"
    "fmt"
)

// CONSTANTS
const WORDSIZE = 8

// BitVector represents a bit vector.
type BitVector struct {
    // internal representation (does NOT scale with WORDSIZE)
    bits []byte
}

// New creates a new BitVector that will accomodate at least
// the specified minimum length.  When necessary, the vector
// will automatically grow to accomodate the extra data.
func New(length int) *BitVector {
    v := &BitVector{}
    v.accomodate(length)
    return v
}

// Length returns the current length of the BitVector in bits.
func (v *BitVector) Length() int {
    return WORDSIZE * len(v.bits)
}

// Clear will reset all bits to 0, but the size of the vector
// remains unaffected.
func (v *BitVector) Clear() {
    for inx, _ := range v.bits {
        v.bits[inx] = 0
    }
}

// Copy returns a copy of this BitVector.
func (v *BitVector) Copy() *BitVector {
    w := &BitVector{}
    w.accomodateBytes(len(v.bits))
    copy(w.bits, v.bits)
    return w
}

// String will create a string representation of the vector.
func (v *BitVector) String() string {
    buf := bytes.NewBufferString("")
    for _, word := range v.bits {
        for inx := 0; inx < WORDSIZE; inx++ {
            // if the inx-th bit is 1, result
            // is 1; otherwise 0; following does NOT
            // scale with the value of WORDSIZE
            fmt.Fprint(buf, (0x80&word)>>7)
            word <<= 1
        }
    }
    return string(buf.Bytes())
}

// Equal returns true if and only if the BitVector
// provided is equal to this BitVector in the sense
// that all bit settings coincide in both structures.
func (v *BitVector) Equal(w *BitVector) bool {
	if w == nil {
		return false
	}
	minx := max(len(v.bits),len(w.bits))
	for i := 0; i < minx; i++ {
		if v.getByte(i) != w.getByte(i) {
			return false
		}
	}
	return true
}

// Set will set the bit at the specified index to
// the specified boolean value.
func (v *BitVector) Set(index int, value bool) {
    v.accomodate(index+1)
    word, bit := locate(index)
    if value {
        v.bits[word] |= basisByte(bit)
    } else {
        v.bits[word] &= ^basisByte(bit)
    }
}

// IsSet returns true if and only if the bit at the
// specified index is set.
func (v *BitVector) Get(index int) bool {
    return v.GetInt(index) == 1
}

// Get will retrieve the value of the bit at the
// specified index as an signed integer.
func (v *BitVector) GetInt(index int) int {
    word, bit := locate(index)
    if word >= len(v.bits) {
        return 0
    }
    return int(v.bits[word] & basisByte(bit) >> uint(7 - bit))
}

// Not negates this BitVector.
func (v *BitVector) Not() {
    for inx, _ := range v.bits {
        v.bits[inx] = ^v.bits[inx]
    }
}

// Not returns the negation of this BitVector.
func Not(v *BitVector) *BitVector {
    w := v.Copy()
    w.Not()
    return w
}

// Or will OR this BitVector with another one.
func (v *BitVector) Or(w *BitVector) {
	if w == nil {
		return
	}
    length := max(len(v.bits), len(w.bits))
    for inx := 0; inx < length; inx++ {
		v.setByte(inx, v.getByte(inx) | w.getByte(inx))
	}
}

// Or returns the OR of two BitVectors.
func Or(v, w *BitVector) *BitVector {
    z := v.Copy()
    z.Or(w)
    return z
}

// And will AND this BitVector with another one.
func (v *BitVector) And(w *BitVector) {
    if w == nil {
		return
	}
	length := max(len(v.bits), len(w.bits))
    for inx := 0; inx < length; inx++ {
		v.setByte(inx, v.getByte(inx) & w.getByte(inx))
	}
}

// And returns the AND of two BitVectors.
func And(v, w *BitVector) *BitVector {
    z := v.Copy()
    z.And(w)
    return z
}

// Locate will produce the location -- word and bit index --
// of the specified absolute index of the vector.
func locate(index int) (word, bit int) {
    return index / WORDSIZE, index % WORDSIZE
}

// accomodate will grow the BitVector to accomodate new entries.
// The parameter must be positive.
func (v *BitVector) accomodate(elements int) {
    wordsNeeded := (elements - 1) / WORDSIZE + 1
    words := len(v.bits)
    if wordsNeeded > words { // reallocate
        newSlice := make([]byte, max(2*words, wordsNeeded))
        copy(newSlice, v.bits)
        v.bits = newSlice
    }
}

// accomodate will grow the BitVector to accomodate the provided
// number of bytes.  The parameter must be positive.
func (v *BitVector) accomodateBytes(length int) {
    v.accomodate(length * WORDSIZE)
}

// basisByte returns a byte with a single non-zero bit
// set at the specified index.
func basisByte(index int) byte {
    // does NOT scale with WORDSIZE
    return 0x80 >> uint(index)
}

// getByte returns the value of the inx-th byte, if
// it is allocated, or 0.  That is, the vector is
// assumed to have an infinite 0-sequence extending
// to the right.
func (v *BitVector) getByte(inx int) byte {
    if inx < len(v.bits) {
        return v.bits[inx]
    }
    return byte(0)
}

// setByte will set the valie of the inx-th byte. If
// the interior byte array is not big enough, it may
// be reallocated if the data is non-trivial.
func (v *BitVector) setByte(inx int, data byte) {
    if inx >= len(v.bits) && data != 0 {
	    v.accomodateBytes(inx+1)	// will only resize for nontrivial data
	}
	v.bits[inx] = data
}

// max returns the maximum of two integers.
func max(a, b int) int {
    if a < b {
        return b
    }
    return a
}

// min returns the maximum of two integers.
func min(a, b int) int {
    if a > b {
        return b
    }
    return a
}
<|endoftext|>


<commit_before>package ingestor

import (
	"fmt"
	"time"

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

type PushScan struct {
	Owner      string
	Repository string
	Ref        string
	Diffs      []PushScanDiff
}

func (p PushScan) FullRepoName() string {
	return fmt.Sprintf("%s/%s", p.Owner, p.Repository)
}

func (p PushScan) FirstCommit() string {
	return p.Diffs[0].From
}

func (p PushScan) LastCommit() string {
	return p.Diffs[len(p.Diffs)-1].To
}

type PushScanDiff struct {
	From          string
	FromTimestamp time.Time
	To            string
	ToTimestamp   time.Time
}

const initialCommitParentHash = "0000000000000000000000000000000000000000"

func Extract(event github.PushEvent) (PushScan, bool) {
	if event.Before == nil {
		return PushScan{}, false
	}

	if len(event.Commits) == 0 {
		return PushScan{}, false
	}

	diffs := []PushScanDiff{
		{
			From:          *event.Before,
			To:            *event.Commits[0].ID,
			ToTimestamp:   (*event.Commits[0].Timestamp).Time,
			FromTimestamp: time.Unix(0, 0),
		},
	}

	for i, _ := range event.Commits {
		if i == len(event.Commits)-1 {
			break
		}

		from := *event.Commits[i].ID
		fromTimestamp := (*event.Commits[i].Timestamp).Time
		to := *event.Commits[i+1].ID
		toTimestamp := (*event.Commits[i+1].Timestamp).Time

		diffs = append(diffs, PushScanDiff{
			From:          from,
			FromTimestamp: fromTimestamp,
			To:            to,
			ToTimestamp:   toTimestamp,
		})
	}

	return PushScan{
		Owner:      *event.Repo.Owner.Name,
		Repository: *event.Repo.Name,
		Ref:        *event.Ref,
		Diffs:      diffs,
	}, true
}
<commit_msg>refactor and reorganize to expose symmetry<commit_after>package ingestor

import (
	"fmt"
	"time"

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

type PushScan struct {
	Owner      string
	Repository string
	Ref        string
	Diffs      []PushScanDiff
}

func (p PushScan) FullRepoName() string {
	return fmt.Sprintf("%s/%s", p.Owner, p.Repository)
}

func (p PushScan) FirstCommit() string {
	return p.Diffs[0].From
}

func (p PushScan) LastCommit() string {
	return p.Diffs[len(p.Diffs)-1].To
}

type PushScanDiff struct {
	From          string
	FromTimestamp time.Time
	To            string
	ToTimestamp   time.Time
}

const initialCommitParentHash = "0000000000000000000000000000000000000000"

func Extract(event github.PushEvent) (PushScan, bool) {
	if event.Before == nil {
		return PushScan{}, false
	}

	if len(event.Commits) == 0 {
		return PushScan{}, false
	}

	diffs := []PushScanDiff{
		{
			From:          *event.Before,
			FromTimestamp: time.Unix(0, 0),
			To:            *event.Commits[0].ID,
			ToTimestamp:   (*event.Commits[0].Timestamp).Time,
		},
	}

	for i, _ := range event.Commits {
		if i == len(event.Commits)-1 {
			break
		}

		diffs = append(diffs, PushScanDiff{
			From:          *event.Commits[i].ID,
			FromTimestamp: (*event.Commits[i].Timestamp).Time,
			To:            *event.Commits[i+1].ID,
			ToTimestamp:   (*event.Commits[i+1].Timestamp).Time,
		})
	}

	return PushScan{
		Owner:      *event.Repo.Owner.Name,
		Repository: *event.Repo.Name,
		Ref:        *event.Ref,
		Diffs:      diffs,
	}, true
}
<|endoftext|>


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

package main

import (
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const MaxCommentLength = 500 // App Engine won't store more in a StringProperty.

func (b *Builder) buildPackages(workpath string, hash string) os.Error {
	pkgs, err := packages()
	if err != nil {
		return err
	}
	for _, p := range pkgs {
		goroot := filepath.Join(workpath, "go")
		gobin := filepath.Join(goroot, "bin")
		goinstall := filepath.Join(gobin, "goinstall")
		envv := append(b.envv(), "GOROOT="+goroot)

		// add GOBIN to path
		for i, v := range envv {
			if strings.HasPrefix(v, "PATH=") {
				p := filepath.SplitList(v[5:])
				p = append([]string{gobin}, p...)
				s := strings.Join(p, string(filepath.ListSeparator))
				envv[i] = "PATH=" + s
			}
		}

		// goinstall
		buildLog, code, err := runLog(envv, "", goroot, goinstall, "-dashboard=false", p)
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
		}

		// get doc comment from package source
		info, err := packageComment(p, filepath.Join(goroot, "src", "pkg", p))
		if err != nil {
			log.Printf("packageComment %v: %v", p, err)
		}

		// update dashboard with build state + info
		err = b.updatePackage(p, code == 0, buildLog, info)
		if err != nil {
			log.Printf("updatePackage %v: %v", p, err)
		}
	}
	return nil
}

func isGoFile(fi *os.FileInfo) bool {
	return fi.IsRegular() && // exclude directories
		!strings.HasPrefix(fi.Name, ".") && // ignore .files
		filepath.Ext(fi.Name) == ".go"
}

func packageComment(pkg, pkgpath string) (info string, err os.Error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return
	}
	for name := range pkgs {
		if name == "main" {
			continue
		}
		if info != "" {
			return "", os.NewError("multiple non-main package docs")
		}
		pdoc := doc.NewPackageDoc(pkgs[name], pkg)
		info = pdoc.Doc
	}
	// grab only first paragraph
	if parts := strings.SplitN(info, "\n\n", 2); len(parts) > 1 {
		info = parts[0]
	}
	// replace newlines with spaces
	info = strings.Replace(info, "\n", " ", -1)
	// truncate
	if len(info) > MaxCommentLength {
		info = info[:MaxCommentLength]
	}
	return
}
<commit_msg>gobuilder: ignore _test.go files when looking for docs, more logging<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const MaxCommentLength = 500 // App Engine won't store more in a StringProperty.

func (b *Builder) buildPackages(workpath string, hash string) os.Error {
	logdir := filepath.Join(*buildroot, "log")
	if err := os.Mkdir(logdir, 0755); err != nil {
		return err
	}
	pkgs, err := packages()
	if err != nil {
		return err
	}
	for _, p := range pkgs {
		goroot := filepath.Join(workpath, "go")
		gobin := filepath.Join(goroot, "bin")
		goinstall := filepath.Join(gobin, "goinstall")
		envv := append(b.envv(), "GOROOT="+goroot)

		// add GOBIN to path
		for i, v := range envv {
			if strings.HasPrefix(v, "PATH=") {
				p := filepath.SplitList(v[5:])
				p = append([]string{gobin}, p...)
				s := strings.Join(p, string(filepath.ListSeparator))
				envv[i] = "PATH=" + s
			}
		}

		// goinstall
		buildLog, code, err := runLog(envv, "", goroot, goinstall, "-dashboard=false", p)
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
		}

		// get doc comment from package source
		var info string
		pkgPath := filepath.Join(goroot, "src", "pkg", p)
		if _, err := os.Stat(pkgPath); err == nil {
			info, err = packageComment(p, pkgPath)
			if err != nil {
				log.Printf("packageComment %v: %v", p, err)
			}
		}

		// update dashboard with build state + info
		err = b.updatePackage(p, code == 0, buildLog, info)
		if err != nil {
			log.Printf("updatePackage %v: %v", p, err)
		}

		if code == 0 {
			log.Println("Build succeeded:", p)
		} else {
			log.Println("Build failed:", p)
			fn := filepath.Join(logdir, strings.Replace(p, "/", "_", -1))
			if f, err := os.Create(fn); err != nil {
				log.Printf("creating %s: %v", fn, err)
			} else {
				fmt.Fprint(f, buildLog)
				f.Close()
			}
		}
	}
	return nil
}

func isGoFile(fi *os.FileInfo) bool {
	return fi.IsRegular() && // exclude directories
		!strings.HasPrefix(fi.Name, ".") && // ignore .files
		!strings.HasSuffix(fi.Name, "_test.go") && // ignore tests
		filepath.Ext(fi.Name) == ".go"
}

func packageComment(pkg, pkgpath string) (info string, err os.Error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return
	}
	for name := range pkgs {
		if name == "main" {
			continue
		}
		pdoc := doc.NewPackageDoc(pkgs[name], pkg)
		if pdoc.Doc == "" {
			continue
		}
		if info != "" {
			return "", os.NewError("multiple packages with docs")
		}
		info = pdoc.Doc
	}
	// grab only first paragraph
	if parts := strings.SplitN(info, "\n\n", 2); len(parts) > 1 {
		info = parts[0]
	}
	// replace newlines with spaces
	info = strings.Replace(info, "\n", " ", -1)
	// truncate
	if len(info) > MaxCommentLength {
		info = info[:MaxCommentLength]
	}
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package audit

import (
	"bufio"
	"bytes"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"reflect"
	"regexp"
	"strings"
	"testing"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/apiserver"
	"k8s.io/kubernetes/pkg/auth/user"
	"k8s.io/kubernetes/pkg/util/sets"
)

type simpleResponseWriter struct {
	http.ResponseWriter
}

func (*simpleResponseWriter) WriteHeader(code int) {}

type fancyResponseWriter struct {
	simpleResponseWriter
}

func (*fancyResponseWriter) CloseNotify() <-chan bool { return nil }

func (*fancyResponseWriter) Flush() {}

func (*fancyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return nil, nil, nil }

func TestConstructResponseWriter(t *testing.T) {
	actual := decorateResponseWriter(&simpleResponseWriter{}, ioutil.Discard, "")
	switch v := actual.(type) {
	case *auditResponseWriter:
	default:
		t.Errorf("Expected auditResponseWriter, got %v", reflect.TypeOf(v))
	}

	actual = decorateResponseWriter(&fancyResponseWriter{}, ioutil.Discard, "")
	switch v := actual.(type) {
	case *fancyResponseWriterDelegator:
	default:
		t.Errorf("Expected fancyResponseWriterDelegator, got %v", reflect.TypeOf(v))
	}
}

type fakeHTTPHandler struct{}

func (*fakeHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(200)
}

type fakeRequestContextMapper struct{}

func (*fakeRequestContextMapper) Get(req *http.Request) (api.Context, bool) {
	return api.WithUser(api.NewContext(), &user.DefaultInfo{Name: "admin"}), true

}

func (*fakeRequestContextMapper) Update(req *http.Request, context api.Context) error {
	return nil
}

func TestAudit(t *testing.T) {
	var buf bytes.Buffer
	attributeGetter := apiserver.NewRequestAttributeGetter(&fakeRequestContextMapper{},
		&apiserver.RequestInfoResolver{APIPrefixes: sets.NewString("api", "apis"), GrouplessAPIPrefixes: sets.NewString("api")})
	handler := WithAudit(&fakeHTTPHandler{}, attributeGetter, &buf)
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
	req.RemoteAddr = "127.0.0.1"
	handler.ServeHTTP(httptest.NewRecorder(), req)
	line := strings.Split(strings.TrimSpace(buf.String()), "\n")
	if len(line) != 2 {
		t.Fatalf("Unexpected amount of lines in audit log: %d", len(line))
	}
	match, err := regexp.MatchString(`[\d\:\-\.\+]+ AUDIT: id="[\w-]+" ip="127.0.0.1" method="GET" user="admin" as="<self>" asgroups="<lookup>" namespace="default" uri="/api/v1/namespaces/default/pods"`, line[0])
	if err != nil {
		t.Errorf("Unexpected error matching first line: %v", err)
	}
	if !match {
		t.Errorf("Unexpected first line of audit: %s", line[0])
	}
	match, err = regexp.MatchString(`[\d\:\-\.\+]+ AUDIT: id="[\w-]+" response="200"`, line[1])
	if err != nil {
		t.Errorf("Unexpected error matching second line: %v", err)
	}
	if !match {
		t.Errorf("Unexpected second line of audit: %s", line[1])
	}
}
<commit_msg>UPSTREAM: 32593: Audit test fails to take into account timezone<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package audit

import (
	"bufio"
	"bytes"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"reflect"
	"regexp"
	"strings"
	"testing"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/apiserver"
	"k8s.io/kubernetes/pkg/auth/user"
	"k8s.io/kubernetes/pkg/util/sets"
)

type simpleResponseWriter struct {
	http.ResponseWriter
}

func (*simpleResponseWriter) WriteHeader(code int) {}

type fancyResponseWriter struct {
	simpleResponseWriter
}

func (*fancyResponseWriter) CloseNotify() <-chan bool { return nil }

func (*fancyResponseWriter) Flush() {}

func (*fancyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return nil, nil, nil }

func TestConstructResponseWriter(t *testing.T) {
	actual := decorateResponseWriter(&simpleResponseWriter{}, ioutil.Discard, "")
	switch v := actual.(type) {
	case *auditResponseWriter:
	default:
		t.Errorf("Expected auditResponseWriter, got %v", reflect.TypeOf(v))
	}

	actual = decorateResponseWriter(&fancyResponseWriter{}, ioutil.Discard, "")
	switch v := actual.(type) {
	case *fancyResponseWriterDelegator:
	default:
		t.Errorf("Expected fancyResponseWriterDelegator, got %v", reflect.TypeOf(v))
	}
}

type fakeHTTPHandler struct{}

func (*fakeHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(200)
}

type fakeRequestContextMapper struct{}

func (*fakeRequestContextMapper) Get(req *http.Request) (api.Context, bool) {
	return api.WithUser(api.NewContext(), &user.DefaultInfo{Name: "admin"}), true

}

func (*fakeRequestContextMapper) Update(req *http.Request, context api.Context) error {
	return nil
}

func TestAudit(t *testing.T) {
	var buf bytes.Buffer
	attributeGetter := apiserver.NewRequestAttributeGetter(&fakeRequestContextMapper{},
		&apiserver.RequestInfoResolver{APIPrefixes: sets.NewString("api", "apis"), GrouplessAPIPrefixes: sets.NewString("api")})
	handler := WithAudit(&fakeHTTPHandler{}, attributeGetter, &buf)
	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
	req.RemoteAddr = "127.0.0.1"
	handler.ServeHTTP(httptest.NewRecorder(), req)
	line := strings.Split(strings.TrimSpace(buf.String()), "\n")
	if len(line) != 2 {
		t.Fatalf("Unexpected amount of lines in audit log: %d", len(line))
	}
	match, err := regexp.MatchString(`[\d\:\-\.\+TZ]+ AUDIT: id="[\w-]+" ip="127.0.0.1" method="GET" user="admin" as="<self>" asgroups="<lookup>" namespace="default" uri="/api/v1/namespaces/default/pods"`, line[0])
	if err != nil {
		t.Errorf("Unexpected error matching first line: %v", err)
	}
	if !match {
		t.Errorf("Unexpected first line of audit: %s", line[0])
	}
	match, err = regexp.MatchString(`[\d\:\-\.\+TZ]+ AUDIT: id="[\w-]+" response="200"`, line[1])
	if err != nil {
		t.Errorf("Unexpected error matching second line: %v", err)
	}
	if !match {
		t.Errorf("Unexpected second line of audit: %s", line[1])
	}
}
<|endoftext|>


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

package prog

import (
	"bytes"
	"testing"

	"github.com/google/syzkaller/sys"
)

func TestChecksumIP(t *testing.T) {
	tests := []struct {
		data string
		csum uint16
	}{
		{
			"",
			0xffff,
		},
		{
			"\x00",
			0xffff,
		},
		{
			"\x00\x00",
			0xffff,
		},
		{
			"\x00\x00\xff\xff",
			0x0000,
		},
		{
			"\xfc",
			0x03ff,
		},
		{
			"\xfc\x12",
			0x03ed,
		},
		{
			"\xfc\x12\x3e",
			0xc5ec,
		},
		{
			"\xfc\x12\x3e\x00\xc5\xec",
			0x0000,
		},
		{
			"\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd",
			0xe143,
		},
		{
			"\x00\x00\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd",
			0xe143,
		},
		{
			"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\xab\xcd",
			0x3250,
		},
		{
			"\x00\x00\x12\x34\x56\x78",
			0x9753,
		},
		{
			"\x00\x00\x12\x34\x00\x00\x56\x78\x00\x06\x00\x04\xab\xcd",
			0xeb7b,
		},
		{
			"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\xab\xcd",
			0x5428,
		},
		{
			"\x00\x00\x12\x34\x00\x00\x56\x78\x00\x11\x00\x04\xab\xcd",
			0xeb70,
		},
		{
			"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x11\x00\x00\xab\xcd",
			0x541d,
		},
	}

	for _, test := range tests {
		csum := ipChecksum([]byte(test.data))
		if csum != test.csum {
			t.Fatalf("incorrect ip checksum, got: %x, want: %x, data: %+v", csum, test.csum, []byte(test.data))
		}
	}
}

func TestChecksumIPAcc(t *testing.T) {
	rs, iters := initTest(t)
	r := newRand(rs)

	for i := 0; i < iters; i++ {
		bytes := make([]byte, r.Intn(256))
		for i := 0; i < len(bytes); i++ {
			bytes[i] = byte(r.Intn(256))
		}
		step := int(r.randRange(1, 8)) * 2
		var csumAcc IPChecksum
		for i := 0; i < len(bytes)/step; i++ {
			csumAcc.Update(bytes[i*step : (i+1)*step])
		}
		if len(bytes)%step != 0 {
			csumAcc.Update(bytes[len(bytes)-(len(bytes)%step) : len(bytes)])
		}
		csum := ipChecksum(bytes)
		if csum != csumAcc.Digest() {
			t.Fatalf("inconsistent ip checksum: %x vs %x, step: %v, data: %+v", csum, csumAcc.Digest(), step, bytes)
		}
	}
}

func TestChecksumEncode(t *testing.T) {
	tests := []struct {
		prog    string
		encoded string
	}{
		{
			"syz_test$csum_encode(&(0x7f0000000000)={0x42, 0x43, [0x44, 0x45], 0xa, 0xb, \"aabbccdd\"})",
			"\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd",
		},
	}
	for i, test := range tests {
		p, err := Deserialize([]byte(test.prog))
		if err != nil {
			t.Fatalf("failed to deserialize prog %v: %v", test.prog, err)
		}
		encoded := encodeArg(p.Calls[0].Args[0].Res, 0)
		if !bytes.Equal(encoded, []byte(test.encoded)) {
			t.Fatalf("incorrect encoding for prog #%v, got: %+v, want: %+v", i, encoded, []byte(test.encoded))
		}
	}
}

func TestChecksumCalc(t *testing.T) {
	tests := []struct {
		prog string
		kind sys.CsumKind
		csum uint16
	}{
		{
			"syz_test$csum_ipv4(&(0x7f0000000000)={0x0, 0x1234, 0x5678})",
			sys.CsumIPv4,
			0x9753,
		},
		{
			"syz_test$csum_ipv4_tcp(&(0x7f0000000000)={{0x0, 0x1234, 0x5678}, {{0x0}, \"abcd\"}})",
			sys.CsumTCP,
			0xeb7b,
		},
		{
			"syz_test$csum_ipv6_tcp(&(0x7f0000000000)={{\"00112233445566778899aabbccddeeff\", \"ffeeddccbbaa99887766554433221100\"}, {{0x0}, \"abcd\"}})",
			sys.CsumTCP,
			0x5428,
		},
		{
			"syz_test$csum_ipv4_udp(&(0x7f0000000000)={{0x0, 0x1234, 0x5678}, {0x0, \"abcd\"}})",
			sys.CsumUDP,
			0xeb70,
		},
		{
			"syz_test$csum_ipv6_udp(&(0x7f0000000000)={{\"00112233445566778899aabbccddeeff\", \"ffeeddccbbaa99887766554433221100\"}, {0x0, \"abcd\"}})",
			sys.CsumUDP,
			0x541d,
		},
	}
	for i, test := range tests {
		p, err := Deserialize([]byte(test.prog))
		if err != nil {
			t.Fatalf("failed to deserialize prog %v: %v", test.prog, err)
		}
		csumMap := calcChecksumsCall(p.Calls[0], i%32)
		found := false
		for oldField, newField := range csumMap {
			if typ, ok := newField.Type.(*sys.CsumType); ok {
				if typ.Kind == test.kind {
					found = true
					csum := newField.Value(i % 32)
					if csum != uintptr(test.csum) {
						t.Fatalf("failed to calc checksum, got %x, want %x, kind %v, prog '%v'", csum, test.csum, test.kind, test.prog)
					}
				}
			} else {
				t.Fatalf("non csum key %+v in csum map %+v", oldField, csumMap)
			}
		}
		if !found {
			t.Fatalf("csum field not found, kind %v, prog '%v'", test.kind, test.prog);
		}
	}
}

func TestChecksumCalcRandom(t *testing.T) {
	rs, iters := initTest(t)
	for i := 0; i < iters; i++ {
		p := Generate(rs, 10, nil)
		for _, call := range p.Calls {
			calcChecksumsCall(call, i%32)
		}
		for try := 0; try <= 10; try++ {
			p.Mutate(rs, 10, nil, nil)
			for _, call := range p.Calls {
				calcChecksumsCall(call, i%32)
			}
		}
	}
}
<commit_msg>prog: reformat code<commit_after>// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package prog

import (
	"bytes"
	"testing"

	"github.com/google/syzkaller/sys"
)

func TestChecksumIP(t *testing.T) {
	tests := []struct {
		data string
		csum uint16
	}{
		{
			"",
			0xffff,
		},
		{
			"\x00",
			0xffff,
		},
		{
			"\x00\x00",
			0xffff,
		},
		{
			"\x00\x00\xff\xff",
			0x0000,
		},
		{
			"\xfc",
			0x03ff,
		},
		{
			"\xfc\x12",
			0x03ed,
		},
		{
			"\xfc\x12\x3e",
			0xc5ec,
		},
		{
			"\xfc\x12\x3e\x00\xc5\xec",
			0x0000,
		},
		{
			"\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd",
			0xe143,
		},
		{
			"\x00\x00\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd",
			0xe143,
		},
		{
			"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\xab\xcd",
			0x3250,
		},
		{
			"\x00\x00\x12\x34\x56\x78",
			0x9753,
		},
		{
			"\x00\x00\x12\x34\x00\x00\x56\x78\x00\x06\x00\x04\xab\xcd",
			0xeb7b,
		},
		{
			"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\xab\xcd",
			0x5428,
		},
		{
			"\x00\x00\x12\x34\x00\x00\x56\x78\x00\x11\x00\x04\xab\xcd",
			0xeb70,
		},
		{
			"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x11\x00\x00\xab\xcd",
			0x541d,
		},
	}

	for _, test := range tests {
		csum := ipChecksum([]byte(test.data))
		if csum != test.csum {
			t.Fatalf("incorrect ip checksum, got: %x, want: %x, data: %+v", csum, test.csum, []byte(test.data))
		}
	}
}

func TestChecksumIPAcc(t *testing.T) {
	rs, iters := initTest(t)
	r := newRand(rs)

	for i := 0; i < iters; i++ {
		bytes := make([]byte, r.Intn(256))
		for i := 0; i < len(bytes); i++ {
			bytes[i] = byte(r.Intn(256))
		}
		step := int(r.randRange(1, 8)) * 2
		var csumAcc IPChecksum
		for i := 0; i < len(bytes)/step; i++ {
			csumAcc.Update(bytes[i*step : (i+1)*step])
		}
		if len(bytes)%step != 0 {
			csumAcc.Update(bytes[len(bytes)-(len(bytes)%step) : len(bytes)])
		}
		csum := ipChecksum(bytes)
		if csum != csumAcc.Digest() {
			t.Fatalf("inconsistent ip checksum: %x vs %x, step: %v, data: %+v", csum, csumAcc.Digest(), step, bytes)
		}
	}
}

func TestChecksumEncode(t *testing.T) {
	tests := []struct {
		prog    string
		encoded string
	}{
		{
			"syz_test$csum_encode(&(0x7f0000000000)={0x42, 0x43, [0x44, 0x45], 0xa, 0xb, \"aabbccdd\"})",
			"\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd",
		},
	}
	for i, test := range tests {
		p, err := Deserialize([]byte(test.prog))
		if err != nil {
			t.Fatalf("failed to deserialize prog %v: %v", test.prog, err)
		}
		encoded := encodeArg(p.Calls[0].Args[0].Res, 0)
		if !bytes.Equal(encoded, []byte(test.encoded)) {
			t.Fatalf("incorrect encoding for prog #%v, got: %+v, want: %+v", i, encoded, []byte(test.encoded))
		}
	}
}

func TestChecksumCalc(t *testing.T) {
	tests := []struct {
		prog string
		kind sys.CsumKind
		csum uint16
	}{
		{
			"syz_test$csum_ipv4(&(0x7f0000000000)={0x0, 0x1234, 0x5678})",
			sys.CsumIPv4,
			0x9753,
		},
		{
			"syz_test$csum_ipv4_tcp(&(0x7f0000000000)={{0x0, 0x1234, 0x5678}, {{0x0}, \"abcd\"}})",
			sys.CsumTCP,
			0xeb7b,
		},
		{
			"syz_test$csum_ipv6_tcp(&(0x7f0000000000)={{\"00112233445566778899aabbccddeeff\", \"ffeeddccbbaa99887766554433221100\"}, {{0x0}, \"abcd\"}})",
			sys.CsumTCP,
			0x5428,
		},
		{
			"syz_test$csum_ipv4_udp(&(0x7f0000000000)={{0x0, 0x1234, 0x5678}, {0x0, \"abcd\"}})",
			sys.CsumUDP,
			0xeb70,
		},
		{
			"syz_test$csum_ipv6_udp(&(0x7f0000000000)={{\"00112233445566778899aabbccddeeff\", \"ffeeddccbbaa99887766554433221100\"}, {0x0, \"abcd\"}})",
			sys.CsumUDP,
			0x541d,
		},
	}
	for i, test := range tests {
		p, err := Deserialize([]byte(test.prog))
		if err != nil {
			t.Fatalf("failed to deserialize prog %v: %v", test.prog, err)
		}
		csumMap := calcChecksumsCall(p.Calls[0], i%32)
		found := false
		for oldField, newField := range csumMap {
			if typ, ok := newField.Type.(*sys.CsumType); ok {
				if typ.Kind == test.kind {
					found = true
					csum := newField.Value(i % 32)
					if csum != uintptr(test.csum) {
						t.Fatalf("failed to calc checksum, got %x, want %x, kind %v, prog '%v'", csum, test.csum, test.kind, test.prog)
					}
				}
			} else {
				t.Fatalf("non csum key %+v in csum map %+v", oldField, csumMap)
			}
		}
		if !found {
			t.Fatalf("csum field not found, kind %v, prog '%v'", test.kind, test.prog)
		}
	}
}

func TestChecksumCalcRandom(t *testing.T) {
	rs, iters := initTest(t)
	for i := 0; i < iters; i++ {
		p := Generate(rs, 10, nil)
		for _, call := range p.Calls {
			calcChecksumsCall(call, i%32)
		}
		for try := 0; try <= 10; try++ {
			p.Mutate(rs, 10, nil, nil)
			for _, call := range p.Calls {
				calcChecksumsCall(call, i%32)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"image/color"
	"log"
	"strconv"

	"github.com/200sc/go-dist/floatrange"
	"github.com/200sc/go-dist/intrange"
	"github.com/oakmound/oak"
	"github.com/oakmound/oak/event"
	"github.com/oakmound/oak/mouse"
	"github.com/oakmound/oak/physics"
	"github.com/oakmound/oak/render"
	pt "github.com/oakmound/oak/render/particle"
	"github.com/oakmound/oak/scene"
	"github.com/oakmound/oak/shape"
)

var (
	startColor     color.Color
	startColorRand color.Color
	endColor       color.Color
	endColorRand   color.Color
	src            *pt.Source
)

func parseShape(args []string) shape.Shape {
	if len(args) > 0 {
		switch args[0] {
		case "heart":
			return shape.Heart
		case "square":
			return shape.Square
		case "circle":
			return shape.Circle
		case "diamond":
			return shape.Diamond
		case "checkered":
			return shape.Checkered
		case "or":
			return shape.JustIn(shape.OrIn(parseShape(args[1:2]).In, parseShape(args[2:]).In))
		case "and":
			return shape.JustIn(shape.AndIn(parseShape(args[1:2]).In, parseShape(args[2:]).In))
		case "not":
			return shape.JustIn(shape.NotIn(parseShape(args[1:]).In))
		}
	}
	return nil
}

func main() {

	err := oak.LoadConf("oak.config")
	if err != nil {
		log.Fatal(err)
	}

	oak.AddCommand("followMouse", func(args []string) {
		event.GlobalBind(func(int, interface{}) int {
			// It'd be interesting to attach to the mouse position
			src.SetPos(float64(mouse.LastEvent.X()), float64(mouse.LastEvent.Y()))
			return 0
		}, "EnterFrame")
	})

	oak.AddCommand("shape", func(args []string) {
		if len(args) > 1 {
			sh := parseShape(args[1:])
			if sh != nil {
				src.Generator.(pt.Shapeable).SetShape(sh)
			}
		}
	})

	oak.AddCommand("size", func(args []string) {
		f1, f2, two, err := parseInts(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.(pt.Sizeable).SetSize(intrange.NewConstant(f1))
		} else {
			src.Generator.(pt.Sizeable).SetSize(intrange.NewLinear(f1, f2))
		}
	})

	oak.AddCommand("endsize", func(args []string) {
		f1, f2, two, err := parseInts(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.(pt.Sizeable).SetEndSize(intrange.NewConstant(f1))
		} else {
			src.Generator.(pt.Sizeable).SetEndSize(intrange.NewLinear(f1, f2))
		}
	})

	oak.AddCommand("count", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().NewPerFrame = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().NewPerFrame = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("life", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().LifeSpan = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().LifeSpan = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("rotation", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().Rotation = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().Rotation = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("angle", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().Angle = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().Angle = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("speed", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().Speed = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().Speed = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("spread", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.GetBaseGenerator().Spread.SetPos(npf, npf2)
	})

	oak.AddCommand("gravity", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.GetBaseGenerator().Gravity.SetPos(npf, npf2)
	})

	oak.AddCommand("speeddecay", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.GetBaseGenerator().SpeedDecay.SetPos(npf, npf2)
	})

	oak.AddCommand("pos", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.SetPos(npf, npf2)
	})

	oak.AddCommand("startcolor", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			startColor = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetStartColor(startColor, startColorRand)
		}
	})

	oak.AddCommand("startrand", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			startColorRand = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetStartColor(startColor, startColorRand)
		}
	})

	oak.AddCommand("endcolor", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			endColor = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetEndColor(endColor, endColorRand)
		}
	})

	oak.AddCommand("endrand", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			endColorRand = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetEndColor(endColor, endColorRand)
		}
	})

	oak.Add("demo", func(string, interface{}) {
		fmt.Println("Demo start")
		x := 320.0
		y := 240.0
		newPf := floatrange.NewLinear(1, 2)
		life := floatrange.NewLinear(100, 120)
		angle := floatrange.NewLinear(0, 360)
		speed := floatrange.NewLinear(1, 5)
		size := intrange.Constant(1)
		layerFn := func(v physics.Vector) int {
			return 1
		}
		startColor = color.RGBA{255, 255, 255, 255}
		startColorRand = color.RGBA{0, 0, 0, 0}
		endColor = color.RGBA{255, 255, 255, 255}
		endColorRand = color.RGBA{0, 0, 0, 0}
		shape := shape.Square
		src = pt.NewColorGenerator(
			pt.Pos(x, y),
			pt.Duration(pt.Inf),
			pt.LifeSpan(life),
			pt.Angle(angle),
			pt.Speed(speed),
			pt.Layer(layerFn),
			pt.Shape(shape),
			pt.Size(size),
			pt.Color(startColor, startColorRand, endColor, endColorRand),
			pt.NewPerFrame(newPf)).Generate(0)
	}, func() bool {
		return true
	}, func() (string, *scene.Result) {
		return "demo", nil
	})

	render.SetDrawStack(
		render.NewCompositeR(),
	)

	oak.Init("demo")
}

func parseRGBA(args []string) (r, g, b, a int, err error) {
	if len(args) < 5 {
		return
	}
	r, err = strconv.Atoi(args[1])
	if err != nil {
		return
	}
	g, err = strconv.Atoi(args[2])
	if err != nil {
		return
	}
	b, err = strconv.Atoi(args[3])
	if err != nil {
		return
	}
	a, err = strconv.Atoi(args[4])
	return
}

func parseFloats(args []string) (f1, f2 float64, two bool, err error) {
	if len(args) < 2 {
		err = errors.New("No args")
		return
	}
	f1, err = strconv.ParseFloat(args[1], 64)
	if err != nil {
		return
	}
	if len(args) < 3 {
		return
	}
	f2, err = strconv.ParseFloat(args[2], 64)
	if err != nil {
		return
	}
	two = true
	return
}

func parseInts(args []string) (i1, i2 int, two bool, err error) {
	if len(args) < 2 {
		err = errors.New("No args")
		return
	}
	i1, err = strconv.Atoi(args[1])
	if err != nil {
		return
	}
	if len(args) < 3 {
		return
	}
	i2, err = strconv.Atoi(args[2])
	if err != nil {
		return
	}
	two = true
	return
}
<commit_msg>Fix some bugs in particle demo since we removed 'c' from commands<commit_after>package main

import (
	"errors"
	"fmt"
	"image/color"
	"log"
	"strconv"

	"github.com/200sc/go-dist/floatrange"
	"github.com/200sc/go-dist/intrange"
	"github.com/oakmound/oak"
	"github.com/oakmound/oak/event"
	"github.com/oakmound/oak/mouse"
	"github.com/oakmound/oak/physics"
	"github.com/oakmound/oak/render"
	pt "github.com/oakmound/oak/render/particle"
	"github.com/oakmound/oak/scene"
	"github.com/oakmound/oak/shape"
)

var (
	startColor     color.Color
	startColorRand color.Color
	endColor       color.Color
	endColorRand   color.Color
	src            *pt.Source
)

func parseShape(args []string) shape.Shape {
	if len(args) > 1 {
		switch args[1] {
		case "heart":
			return shape.Heart
		case "square":
			return shape.Square
		case "circle":
			return shape.Circle
		case "diamond":
			return shape.Diamond
		case "checkered":
			return shape.Checkered
		case "or":
			return shape.JustIn(shape.OrIn(parseShape(args[1:2]).In, parseShape(args[2:]).In))
		case "and":
			return shape.JustIn(shape.AndIn(parseShape(args[1:2]).In, parseShape(args[2:]).In))
		case "not":
			return shape.JustIn(shape.NotIn(parseShape(args[1:]).In))
		}
	}
	return nil
}

func main() {

	err := oak.LoadConf("oak.config")
	if err != nil {
		log.Fatal(err)
	}

	oak.AddCommand("followMouse", func(args []string) {
		event.GlobalBind(func(int, interface{}) int {
			// It'd be interesting to attach to the mouse position
			src.SetPos(float64(mouse.LastEvent.X()), float64(mouse.LastEvent.Y()))
			return 0
		}, "EnterFrame")
	})

	oak.AddCommand("shape", func(args []string) {
		if len(args) > 1 {
			sh := parseShape(args[1:])
			if sh != nil {
				src.Generator.(pt.Shapeable).SetShape(sh)
			}
		}
	})

	oak.AddCommand("size", func(args []string) {
		f1, f2, two, err := parseInts(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.(pt.Sizeable).SetSize(intrange.NewConstant(f1))
		} else {
			src.Generator.(pt.Sizeable).SetSize(intrange.NewLinear(f1, f2))
		}
	})

	oak.AddCommand("endsize", func(args []string) {
		f1, f2, two, err := parseInts(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.(pt.Sizeable).SetEndSize(intrange.NewConstant(f1))
		} else {
			src.Generator.(pt.Sizeable).SetEndSize(intrange.NewLinear(f1, f2))
		}
	})

	oak.AddCommand("count", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().NewPerFrame = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().NewPerFrame = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("life", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().LifeSpan = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().LifeSpan = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("rotation", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().Rotation = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().Rotation = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("angle", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().Angle = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().Angle = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("speed", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			src.Generator.GetBaseGenerator().Speed = floatrange.NewConstant(npf)
		} else {
			src.Generator.GetBaseGenerator().Speed = floatrange.NewLinear(npf, npf2)
		}
	})

	oak.AddCommand("spread", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.GetBaseGenerator().Spread.SetPos(npf, npf2)
	})

	oak.AddCommand("gravity", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.GetBaseGenerator().Gravity.SetPos(npf, npf2)
	})

	oak.AddCommand("speeddecay", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.GetBaseGenerator().SpeedDecay.SetPos(npf, npf2)
	})

	oak.AddCommand("pos", func(args []string) {
		npf, npf2, two, err := parseFloats(args)
		if err != nil {
			return
		}
		if !two {
			return
		}
		src.Generator.SetPos(npf, npf2)
	})

	oak.AddCommand("startcolor", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			startColor = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetStartColor(startColor, startColorRand)
		}
	})

	oak.AddCommand("startrand", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			startColorRand = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetStartColor(startColor, startColorRand)
		}
	})

	oak.AddCommand("endcolor", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			endColor = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetEndColor(endColor, endColorRand)
		}
	})

	oak.AddCommand("endrand", func(args []string) {
		if len(args) > 4 {
			r, g, b, a, err := parseRGBA(args)
			if err != nil {
				return
			}
			endColorRand = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			src.Generator.(pt.Colorable).SetEndColor(endColor, endColorRand)
		}
	})

	oak.Add("demo", func(string, interface{}) {
		fmt.Println("Demo start")
		x := 320.0
		y := 240.0
		newPf := floatrange.NewLinear(1, 2)
		life := floatrange.NewLinear(100, 120)
		angle := floatrange.NewLinear(0, 360)
		speed := floatrange.NewLinear(1, 5)
		size := intrange.Constant(1)
		layerFn := func(v physics.Vector) int {
			return 1
		}
		startColor = color.RGBA{255, 255, 255, 255}
		startColorRand = color.RGBA{0, 0, 0, 0}
		endColor = color.RGBA{255, 255, 255, 255}
		endColorRand = color.RGBA{0, 0, 0, 0}
		shape := shape.Square
		src = pt.NewColorGenerator(
			pt.Pos(x, y),
			pt.Duration(pt.Inf),
			pt.LifeSpan(life),
			pt.Angle(angle),
			pt.Speed(speed),
			pt.Layer(layerFn),
			pt.Shape(shape),
			pt.Size(size),
			pt.Color(startColor, startColorRand, endColor, endColorRand),
			pt.NewPerFrame(newPf)).Generate(0)
	}, func() bool {
		return true
	}, func() (string, *scene.Result) {
		return "demo", nil
	})

	render.SetDrawStack(
		render.NewCompositeR(),
	)

	oak.Init("demo")
}

func parseRGBA(args []string) (r, g, b, a int, err error) {
	if len(args) < 4 {
		return
	}
	r, err = strconv.Atoi(args[0])
	if err != nil {
		return
	}
	g, err = strconv.Atoi(args[1])
	if err != nil {
		return
	}
	b, err = strconv.Atoi(args[2])
	if err != nil {
		return
	}
	a, err = strconv.Atoi(args[3])
	return
}

func parseFloats(args []string) (f1, f2 float64, two bool, err error) {
	if len(args) < 1 {
		err = errors.New("No args")
		return
	}
	f1, err = strconv.ParseFloat(args[0], 64)
	if err != nil {
		return
	}
	if len(args) < 2 {
		return
	}
	f2, err = strconv.ParseFloat(args[1], 64)
	if err != nil {
		return
	}
	two = true
	return
}

func parseInts(args []string) (i1, i2 int, two bool, err error) {
	if len(args) < 1 {
		err = errors.New("No args")
		return
	}
	i1, err = strconv.Atoi(args[0])
	if err != nil {
		return
	}
	if len(args) < 2 {
		return
	}
	i2, err = strconv.Atoi(args[1])
	if err != nil {
		return
	}
	two = true
	return
}
<|endoftext|>


<commit_before>package replicant

// #cgo pkg-config: replicant
// #include <stdlib.h>
// #include <string.h>
// #include <poll.h>
// #include <replicant.h>
import "C"
import "unsafe"
import "fmt"
import "runtime"
import "sync"

const (
	SUCCESS        = C.REPLICANT_SUCCESS
	MAYBE          = C.REPLICANT_MAYBE
	SEE_ERRNO      = C.REPLICANT_SEE_ERRNO
	CLUSTER_JUMP   = C.REPLICANT_CLUSTER_JUMP
	COMM_FAILED    = C.REPLICANT_COMM_FAILED
	OBJ_NOT_FOUND  = C.REPLICANT_OBJ_NOT_FOUND
	OBJ_EXIST      = C.REPLICANT_OBJ_EXIST
	FUNC_NOT_FOUND = C.REPLICANT_FUNC_NOT_FOUND
	COND_NOT_FOUND = C.REPLICANT_COND_NOT_FOUND
	COND_DESTROYED = C.REPLICANT_COND_DESTROYED
	SERVER_ERROR   = C.REPLICANT_SERVER_ERROR
	TIMEOUT        = C.REPLICANT_TIMEOUT
	INTERRUPTED    = C.REPLICANT_INTERRUPTED
	NONE_PENDING   = C.REPLICANT_NONE_PENDING
	INTERNAL       = C.REPLICANT_INTERNAL
	EXCEPTION      = C.REPLICANT_EXCEPTION
	GARBAGE        = C.REPLICANT_GARBAGE
)

type Status int

type Error struct {
	Status   Status
	Message  string
	Location string
}

func (s Status) String() string {
	return C.GoString(C.replicant_returncode_to_string(C.enum_replicant_returncode(s)))
}

func (e Error) Error() string {
	return C.GoString(C.replicant_returncode_to_string(C.enum_replicant_returncode(e.Status))) + ": " + e.Message
}

func (e Error) String() string {
	return e.Error()
}

type Client struct {
	mutex     sync.Mutex
	ptr       *C.struct_replicant_client
	errChan   chan Error
	closeChan chan bool
	ops       map[int64]chan Error
}

func NewClient(connection string) (*Client, error, chan Error) {
    conn := C.CString(connection)
    defer C.free(unsafe.Pointer(conn))
	ptr := C.replicant_client_create_conn_str(conn)
    if ptr == nil {
        return nil, fmt.Errorf("could not create replicant client"), nil
    }
	errChan := make(chan Error, 16)
	closeChan := make(chan bool, 1)
    client := &Client{sync.Mutex{}, ptr, errChan, closeChan, map[int64]chan Error{}}
    runtime.SetFinalizer(client, clientFinalizer)
    go client.runForever()
    return client, nil, errChan
}

func (client *Client) Destroy() {
    close(client.closeChan)
	close(client.errChan)
}

func clientFinalizer(c *Client) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	C.replicant_client_destroy(c.ptr)
	for _, val := range c.ops {
		close(val)
	}
}

func (client *Client) runForever() {
	for {
		select {
		case <-client.closeChan:
			return
		default:
			C.replicant_client_block(client.ptr, 250)
			var loop_status C.enum_replicant_returncode
			client.mutex.Lock()
			reqid := int64(C.replicant_client_loop(client.ptr, 0, &loop_status))
			if reqid < 0 && loop_status == TIMEOUT {
				// pass
			} else if reqid < 0 && loop_status == NONE_PENDING {
				// pass
			} else if reqid < 0 && loop_status == INTERRUPTED {
				// pass
			} else if reqid < 0 {
				e := Error{Status(loop_status),
					C.GoString(C.replicant_client_error_message(client.ptr)),
					C.GoString(C.replicant_client_error_location(client.ptr))}
				client.errChan <- e
			} else if c, ok := (client.ops)[reqid]; ok {
				e := Error{Status(loop_status),
					C.GoString(C.replicant_client_error_message(client.ptr)),
					C.GoString(C.replicant_client_error_location(client.ptr))}
				c <- e
				delete(client.ops, reqid)
			}
			client.mutex.Unlock()
		}
	}
}

func (client *Client) Poke() (err *Error) {
    err = nil
	var c_status C.enum_replicant_returncode
	done := make(chan Error)
	client.mutex.Lock()
    reqid := C.replicant_client_poke(client.ptr, &c_status)
    if reqid >= 0 {
        client.ops[int64(reqid)] = done
    } else {
	    err = &Error{Status(c_status),
	             C.GoString(C.replicant_client_error_message(client.ptr)),
	             C.GoString(C.replicant_client_error_location(client.ptr))}
    }
    client.mutex.Unlock()
    if reqid >= 0 {
        rc := <-done
        if c_status != SUCCESS {
            err = &rc
            err.Status = Status(c_status)
        }
    }
    return
}

func (client *Client) GenerateUniqueNumber() (num uint64, err *Error) {
    err = nil
	var c_status C.enum_replicant_returncode
    var c_num C.uint64_t
	done := make(chan Error)
	client.mutex.Lock()
    reqid := C.replicant_client_generate_unique_number(client.ptr, &c_status, &c_num)
    if reqid >= 0 {
        client.ops[int64(reqid)] = done
    } else {
	    err = &Error{Status(c_status),
	             C.GoString(C.replicant_client_error_message(client.ptr)),
	             C.GoString(C.replicant_client_error_location(client.ptr))}
    }
    client.mutex.Unlock()
    if reqid >= 0 {
        rc := <-done
        num = uint64(c_num)
        if c_status != SUCCESS {
            err = &rc
            err.Status = Status(c_status)
        }
    }
    return
}

const (
    CALL_IDEMPOTENT = C.REPLICANT_CALL_IDEMPOTENT
    CALL_ROBUST     = C.REPLICANT_CALL_ROBUST
)

func (client *Client) Call(obj string, fun string, input []byte, flags uint) (output []byte, err *Error) {
    output = nil
    err = &Error{SUCCESS, "success", ""}
    c_obj := C.CString(obj)
    defer C.free(unsafe.Pointer(c_obj))
    c_func := C.CString(fun)
    defer C.free(unsafe.Pointer(c_func))
    c_flags := C.unsigned(flags)
	var c_status C.enum_replicant_returncode
    var c_output *C.char = nil
    var c_output_sz C.size_t = 0
	done := make(chan Error)
	client.mutex.Lock()
    reqid := C.replicant_client_call(client.ptr, c_obj, c_func,
                                     (*C.char)(unsafe.Pointer(&input[0])), C.size_t(len(input)),
                                     c_flags, &c_status, &c_output, &c_output_sz)
    if reqid >= 0 {
        client.ops[int64(reqid)] = done
    } else {
	    err = &Error{Status(c_status),
	             C.GoString(C.replicant_client_error_message(client.ptr)),
	             C.GoString(C.replicant_client_error_location(client.ptr))}
    }
    client.mutex.Unlock()
    if reqid >= 0 {
        rc := <-done
        if c_status == SUCCESS {
            if c_output_sz > 0 {
                output = C.GoBytes(unsafe.Pointer(c_output), C.int(c_output_sz))
            } else {
                output = make([]byte, 0)
            }
        } else {
            err = &rc
            err.Status = Status(c_status)
        }
    }
    return
}

// XXX
//int64_t
//replicant_client_cond_wait(struct replicant_client* client,
//                           const char* object,
//                           const char* cond,
//                           uint64_t state,
//                           enum replicant_returncode* status,
//                           char** data, size_t* data_sz);
//
//int64_t
//replicant_client_cond_follow(struct replicant_client* client,
//                             const char* object,
//                             const char* cond,
//                             enum replicant_returncode* status,
//                             uint64_t* state,
//                             char** data, size_t* data_sz);
//
//int64_t
//replicant_client_defended_call(struct replicant_client* client,
//                               const char* object,
//                               const char* enter_func,
//                               const char* enter_input, size_t enter_input_sz,
//                               const char* exit_func,
//                               const char* exit_input, size_t exit_input_sz,
//                               enum replicant_returncode* status);
<commit_msg>Remove go bindings until they can be maintained well.<commit_after><|endoftext|>


<commit_before>package main

import (
	"io"
	"text/template"
)

type ClientVars struct {
	DefaultPostURL string
}

const (
	shellClient = `
#!/bin/bash

POSTURL="${GJFY_POSTURL:-{{.DefaultPostURL}}}"

which jq >/dev/null 2>&1 || {
    echo "jq utility not found" >&2
    exit 1
}

if [[ $# -lt 2 ]]
then
    echo "usage: $0 <authtoken> <secret>" >&2
    exit 2
fi

if [[ -z "$3" ]]
then
    postdata="{\"auth_token\":\"$1\",\"secret\":\"$2\"}"
else
    postdata="{\"auth_token\":\"$1\",\"secret\":\"$2\",\"max_clicks\":$3}"
fi
curl -s -X POST -d "$postdata" "$POSTURL" | jq -r '.url,.api_url,.error | select (.!=null)'
`
)

func ClientShellScript(out io.Writer, url string) error {
	cv := ClientVars{url}
	tmpl, err := template.New("shellClient").Parse(shellClient)
	if err != nil {
		return err
	}
	err = tmpl.Execute(out, cv)
	if err != nil {
		return err
	}
	return err
}
<commit_msg>fix empty first line in shell script download<commit_after>package main

import (
	"io"
	"text/template"
)

type ClientVars struct {
	DefaultPostURL string
}

const (
	shellClient = `#!/bin/bash

POSTURL="${GJFY_POSTURL:-{{.DefaultPostURL}}}"

which jq >/dev/null 2>&1 || {
    echo "jq utility not found" >&2
    exit 1
}

if [[ $# -lt 2 ]]
then
    echo "usage: $0 <authtoken> <secret>" >&2
    exit 2
fi

if [[ -z "$3" ]]
then
    postdata="{\"auth_token\":\"$1\",\"secret\":\"$2\"}"
else
    postdata="{\"auth_token\":\"$1\",\"secret\":\"$2\",\"max_clicks\":$3}"
fi
curl -s -X POST -d "$postdata" "$POSTURL" | jq -r '.url,.api_url,.error | select (.!=null)'
`
)

func ClientShellScript(out io.Writer, url string) error {
	cv := ClientVars{url}
	tmpl, err := template.New("shellClient").Parse(shellClient)
	if err != nil {
		return err
	}
	err = tmpl.Execute(out, cv)
	if err != nil {
		return err
	}
	return err
}
<|endoftext|>