<commit_before>package main

import "io/ioutil"
import "log"
import "math/big"
import "runtime"
import "testing"

// The number of rounds to use for big.Int.ProbablyPrime().
const _NUM_PROBABLY_PRIME_ROUNDS = 10

// Returns the first prime with the given number of decimal digits.
func getFirstPrimeWithDigits(numDigits int64) *big.Int {
	one := big.NewInt(1)
	n := big.NewInt(10)
	n.Exp(n, big.NewInt(numDigits), nil)
	for !n.ProbablyPrime(_NUM_PROBABLY_PRIME_ROUNDS) {
		n.Add(n, one)
	}
	return n
}

// Benchmark isAKSWitness for the first prime number of the given
// number of decimal digits.
func runIsAKSWitnessBenchmark(b *testing.B, numDigits int64) {
	b.StopTimer()
	n := getFirstPrimeWithDigits(numDigits)
	r := calculateAKSModulus(n)
	// Any a > 1 suffices.
	a := big.NewInt(2)

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		isAKSWitness(n, r, a)
	}
}

// Benchmark isAKSWitness for values of n of varying digit sizes.

func BenchmarkIsAKSWitness3Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 3)
}

func BenchmarkIsAKSWitness4Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 4)
}

func BenchmarkIsAKSWitness5Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 5)
}

func BenchmarkIsAKSWitness6Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 6)
}

func BenchmarkIsAKSWitness7Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 7)
}

func BenchmarkIsAKSWitness8Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 8)
}

// Benchmark isAKSWitnessWord for the first prime number of the given
// number of decimal digits.
func runIsAKSWitnessWordBenchmark(b *testing.B, numDigits int) {
	b.StopTimer()
	var n Word = 10
	for i := 0; i < numDigits; i++ {
		n *= 10
	}
	rounds := 10
	for ; !big.NewInt(int64(n)).ProbablyPrime(rounds); n++ {
	}
	r := Word(calculateAKSModulus(big.NewInt(int64(n))).Int64())
	// Any a > 1 suffices.
	var a Word = 2

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		isAKSWitnessWord(n, r, a)
	}
}

// Benchmark isAKSWitnessWord for values of n of varying digit sizes.

func BenchmarkIsAKSWitnessWord3Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 3)
}

func BenchmarkIsAKSWitnessWord4Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 4)
}

func BenchmarkIsAKSWitnessWord5Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 5)
}

func BenchmarkIsAKSWitnessWord6Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 6)
}

func BenchmarkIsAKSWitnessWord7Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 7)
}

func BenchmarkIsAKSWitnessWord8Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 8)
}

func BenchmarkIsAKSWitnessWord9Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 9)
}

func BenchmarkIsAKSWitnessWord10Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 10)
}

var nullLogger *log.Logger = log.New(ioutil.Discard, "", 0)

// Benchmark getFirstAKSWitness for the first prime number of the
// given number of decimal digits.
func runGetFirstAKSWitnessBenchmark(b *testing.B, numDigits int64) {
	b.StopTimer()
	n := getFirstPrimeWithDigits(numDigits)
	r := calculateAKSModulus(n)
	M := big.NewInt(10)

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		getFirstAKSWitness(n, r, M, nullLogger)
	}
}

// Benchmark getFirstAKSWitness for values of n of varying digit sizes.

func BenchmarkGetFirstAKSWitness3Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 3)
}

func BenchmarkGetFirstAKSWitness4Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 4)
}

func BenchmarkGetFirstAKSWitness5Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 5)
}

func BenchmarkGetFirstAKSWitness6Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 6)
}

func BenchmarkGetFirstAKSWitness7Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 7)
}

func BenchmarkGetFirstAKSWitness8Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 8)
}

func BenchmarkGetFirstAKSWitness11Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 11)
}

func BenchmarkGetFirstAKSWitness12Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 12)
}

// Benchmark getAKSWitness for the first prime number of the given
// number of decimal digits.
func runGetAKSWitnessBenchmark(b *testing.B, numDigits int64) {
	b.StopTimer()
	n := getFirstPrimeWithDigits(numDigits)
	r := calculateAKSModulus(n)
	M := big.NewInt(10)

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		getAKSWitness(n, r, M, runtime.GOMAXPROCS(0), nullLogger)
	}
}

// Benchmark getFirstAKSWitness for values of n of varying digit sizes.

func BenchmarkGetAKSWitness3Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 3)
}

func BenchmarkGetAKSWitness4Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 4)
}

func BenchmarkGetAKSWitness5Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 5)
}

func BenchmarkGetAKSWitness6Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 6)
}

func BenchmarkGetAKSWitness7Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 7)
}

func BenchmarkGetAKSWitness8Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 8)
}

func BenchmarkGetAKSWitness11Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 11)
}

func BenchmarkGetAKSWitness12Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 12)
}
<commit_msg>Add benchmarks for largest 32-bit prime number<commit_after>package main

import "io/ioutil"
import "log"
import "math/big"
import "runtime"
import "testing"

// The number of rounds to use for big.Int.ProbablyPrime().
const _NUM_PROBABLY_PRIME_ROUNDS = 10

// Returns the first prime with the given number of decimal digits.
func getFirstPrimeWithDigits(numDigits int64) *big.Int {
	one := big.NewInt(1)
	n := big.NewInt(10)
	n.Exp(n, big.NewInt(numDigits), nil)
	for !n.ProbablyPrime(_NUM_PROBABLY_PRIME_ROUNDS) {
		n.Add(n, one)
	}
	return n
}

// Benchmark isAKSWitness for the first prime number of the given
// number of decimal digits.
func runIsAKSWitnessBenchmark(b *testing.B, numDigits int64) {
	b.StopTimer()
	n := getFirstPrimeWithDigits(numDigits)
	r := calculateAKSModulus(n)
	// Any a > 1 suffices.
	a := big.NewInt(2)

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		isAKSWitness(n, r, a)
	}
}

// Benchmark isAKSWitness for values of n of varying digit sizes.

func BenchmarkIsAKSWitness3Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 3)
}

func BenchmarkIsAKSWitness4Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 4)
}

func BenchmarkIsAKSWitness5Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 5)
}

func BenchmarkIsAKSWitness6Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 6)
}

func BenchmarkIsAKSWitness7Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 7)
}

func BenchmarkIsAKSWitness8Digits(b *testing.B) {
	runIsAKSWitnessBenchmark(b, 8)
}

// Benchmark isAKSWitnessWord for the first prime number of the given
// number of decimal digits.
func runIsAKSWitnessWordBenchmark(b *testing.B, numDigits int) {
	b.StopTimer()
	var n Word = 10
	for i := 0; i < numDigits; i++ {
		n *= 10
	}
	rounds := 10
	for ; !big.NewInt(int64(n)).ProbablyPrime(rounds); n++ {
	}
	r := Word(calculateAKSModulus(big.NewInt(int64(n))).Int64())
	// Any a > 1 suffices.
	var a Word = 2

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		isAKSWitnessWord(n, r, a)
	}
}

// Benchmark isAKSWitnessWord for values of n of varying digit sizes.

func BenchmarkIsAKSWitnessWord3Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 3)
}

func BenchmarkIsAKSWitnessWord4Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 4)
}

func BenchmarkIsAKSWitnessWord5Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 5)
}

func BenchmarkIsAKSWitnessWord6Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 6)
}

func BenchmarkIsAKSWitnessWord7Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 7)
}

func BenchmarkIsAKSWitnessWord8Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 8)
}

func BenchmarkIsAKSWitnessWord9Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 9)
}

func BenchmarkIsAKSWitnessWord10Digits(b *testing.B) {
	runIsAKSWitnessWordBenchmark(b, 10)
}

func BenchmarkIsAKSWitnessMax32(b *testing.B) {
	b.StopTimer()
	n := big.NewInt(4294967291)
	r := calculateAKSModulus(n)
	// Any a > 1 suffices.
	a := big.NewInt(2)

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		isAKSWitness(n, r, a)
	}
}

func BenchmarkIsAKSWitnessWordMax32(b *testing.B) {
	b.StopTimer()
	var n Word = 4294967291
	r := Word(calculateAKSModulus(big.NewInt(int64(n))).Int64())
	// Any a > 1 suffices.
	var a Word = 2

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		isAKSWitnessWord(n, r, a)
	}
}

var nullLogger *log.Logger = log.New(ioutil.Discard, "", 0)

// Benchmark getFirstAKSWitness for the first prime number of the
// given number of decimal digits.
func runGetFirstAKSWitnessBenchmark(b *testing.B, numDigits int64) {
	b.StopTimer()
	n := getFirstPrimeWithDigits(numDigits)
	r := calculateAKSModulus(n)
	M := big.NewInt(10)

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		getFirstAKSWitness(n, r, M, nullLogger)
	}
}

// Benchmark getFirstAKSWitness for values of n of varying digit sizes.

func BenchmarkGetFirstAKSWitness3Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 3)
}

func BenchmarkGetFirstAKSWitness4Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 4)
}

func BenchmarkGetFirstAKSWitness5Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 5)
}

func BenchmarkGetFirstAKSWitness6Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 6)
}

func BenchmarkGetFirstAKSWitness7Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 7)
}

func BenchmarkGetFirstAKSWitness8Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 8)
}

func BenchmarkGetFirstAKSWitness11Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 11)
}

func BenchmarkGetFirstAKSWitness12Digits(b *testing.B) {
	runGetFirstAKSWitnessBenchmark(b, 12)
}

// Benchmark getAKSWitness for the first prime number of the given
// number of decimal digits.
func runGetAKSWitnessBenchmark(b *testing.B, numDigits int64) {
	b.StopTimer()
	n := getFirstPrimeWithDigits(numDigits)
	r := calculateAKSModulus(n)
	M := big.NewInt(10)

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		getAKSWitness(n, r, M, runtime.GOMAXPROCS(0), nullLogger)
	}
}

// Benchmark getFirstAKSWitness for values of n of varying digit sizes.

func BenchmarkGetAKSWitness3Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 3)
}

func BenchmarkGetAKSWitness4Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 4)
}

func BenchmarkGetAKSWitness5Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 5)
}

func BenchmarkGetAKSWitness6Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 6)
}

func BenchmarkGetAKSWitness7Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 7)
}

func BenchmarkGetAKSWitness8Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 8)
}

func BenchmarkGetAKSWitness11Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 11)
}

func BenchmarkGetAKSWitness12Digits(b *testing.B) {
	runGetAKSWitnessBenchmark(b, 12)
}
<|endoftext|>


<commit_before>package f

import "fmt"
import "github.com/qlova/ilang/src"
import "github.com/qlova/ilang/src/types/list"

var ForLoop = ilang.NewFlag()
var Delete = ilang.NewFlag()

func init() {
	ilang.RegisterToken([]string{"for"}, ScanFor)
	ilang.RegisterListener(ForLoop, EndForLoop)
	ilang.RegisterFunction("delete", ilang.Function{
		Inline: true,
		Method: true,
		Assemble: func(ic *ilang.Compiler) string {
			if !ic.GetFlag(ForLoop) {
				ic.RaiseError("delete with zero arguments must be called from within a for loop!")
			}

			//Delete things in a for loop.
			return fmt.Sprint(	"PLACE ", ic.GetVariable("i_for_delete").Name, "\n",
								"PUT ", ic.GetVariable("i_for_id").Name)
		},
	})
}

func EndForLoop(ic *ilang.Compiler) {
	if ic.LastToken != "end" {
		ic.RaiseError("For Loops must end with a 'end' token, found '", ic.LastToken, "'")
	}
	ic.Assembly("REPEAT")

	if ic.GetScopedFlag(TypeLoop) {
		EndTypeLoop(ic)
	}

	if ic.GetScopedFlag(Delete) {
		var array = ic.GetVariable("i_for_array").Name
		var del = ic.GetVariable("i_for_delete").Name

		var collect = ""
		if ic.GetVariable(array).SubType != nil {
			collect = ic.GetVariable(array).SubType.Free("i_pointer")
		}

		ic.Assembly(`
	VAR i_i
	VAR i_test
	LOOP
		SGE i_test i_i #`+del+`
		IF i_test
			BREAK
		END

		IF #`+array+`
		ELSE
			BREAK
		END

		PLACE `+del+`
		PUSH i_i
		GET i_index

		PLACE `+array+`
		PUSH i_index
		GET i_pointer
		`+collect+`

		PLACE `+array+`
		PUSH -1
		GET i_swapdex

		PUSH i_index
		SET i_swapdex

		POP end
		ADD end 0 0

		ADD i_i i_i 1
	REPEAT
				`)
		ic.LoseScope()
	}
	ic.Assembly("END")
}

func ScanFor(ic *ilang.Compiler) {

	var name = ic.Scan(ilang.Name)

	var name2 string

	if ic.Peek() == "," {
		ic.Scan(',')
		name2 = ic.Scan(ilang.Name)
	}

	var OverList = false

	switch ic.Scan(0) {
		case "=":
			ic.AssembleVar(name, ic.ScanExpression())
			ic.Scan(',')
			ic.Assembly("IF 1")
			ic.Assembly("LOOP")
			ic.GainScope()
			condition := ic.ScanExpression()
			ic.Assembly("IF ", condition)
			ic.Assembly("	ADD ",name," ",name," 0")
			ic.Assembly("ELSE")
			ic.Assembly("	BREAK")
			ic.Assembly("END")
			ic.SetFlag(ForLoop)

		case "over":
			var token = ic.Scan(0)
			if token == "[" {
				a := ic.ScanExpression()
				ic.Scan(',')
				b := ic.ScanExpression()
				ic.Scan(']')

				condition := ic.Tmp("over")
				backup := ic.Tmp("backup")

				ic.Assembly("IF 1\n",
					"VAR ",name,"\n",
					"VAR ",backup,"\n",
					"ADD ",backup," 0 ",a,"\n",
					"ADD ",name," 0 ",a,"\n",
					"LOOP\n",
					"	VAR ",condition,"\n",
					"	SNE ",condition," ",name," ",b,"\n",
					"	ADD ",name," 0 ",backup,"\n",
					"	IF ",condition,"\n",
					"		SLT ",condition," ",name," ",b,"\n",
					"		IF ",condition,"\n",
					"			ADD ",backup," ",name," 1\n",
					"		ELSE\n",
					"			SUB ",backup," ",name," 1\n",
					"		END\n",
					"		SEQ ",condition," ",a," ",b,"\n",
					"		IF ",condition,"\n",
					"			BREAK\n",
					"		END\n",
					"	ELSE\n",
					"		SEQ ",condition," ",a," ",b,"\n",
					"		IF ",condition,"\n",
					"			ADD ",name," ",name," 1\n",
					"       ELSE\n",
					"			BREAK\n",
					"		END\n",
					"	END\n",
				)
				ic.GainScope()
				if name != "each" {
					ic.SetVariable(name, ilang.Number)
				}
				ic.SetFlag(ForLoop)
				return
			}
			ic.NextToken = token
			OverList = true
			fallthrough
		case "in":
			var peek = ic.Scan(0)
			if t, ok := ic.DefinedTypes[peek]; ok {
				ScanTypeLoop(ic, t, name, name2)
				return
			} else {
				ic.NextToken = peek
			}
			var array = ic.ScanExpression()

			if ic.ExpressionType == list.Type {
				//We can ignore this loop.
				for {
					var token = ic.Scan(0)
					if token == "end" {
						return
					}
				}
			}

			if ic.ExpressionType.Push != "SHARE" {
				ic.RaiseError("Cannot iterate over "+array+" (", ic.ExpressionType.Name, ")")
			}

			var condition = ic.Tmp("in")

			var i, v, vo string
			if name2 != "" {
				i = name
				v = name2
			} else {
				i = ic.Tmp("i")
				v = name
			}

			if OverList {
				i = name
			}

			vo = v
			if ic.ExpressionType.Name == list.Type.Name && ic.ExpressionType.SubType.Push == "SHARE" {
				v += "_address"
			}

			backup := ic.Tmp("backup")
			del := ic.Tmp("delete")

			if OverList {
			ic.Assembly(`
IF 1
ARRAY %v
VAR %v
VAR %v
LOOP
	VAR %v
	ADD %v 0 %v
	SGE %v %v #%v
	IF %v
		BREAK
	END
	ADD %v %v 1
`, del, i,backup, condition, i, backup,  condition, i, array, condition, backup, i)
			} else {
			ic.Assembly(`
IF 1
ARRAY %v
VAR %v
VAR %v
LOOP
	VAR %v
	ADD %v 0 %v
	SGE %v %v #%v
	IF %v
		BREAK
	END
	PLACE %v
	PUSH %v
	GET %v
	ADD %v %v 1
`, del, i,backup, condition, i, backup,  condition, i, array, condition, array, i, v, backup, i)
		if ic.ExpressionType == ilang.Array || ic.ExpressionType == ilang.Text {
			//ic.Assembly("ADD %v %v %v", name, 0, i)
		}
	}

			if ic.ExpressionType.Name == list.Type.Name && ic.ExpressionType.SubType.Push == "SHARE" {
				ic.Assembly("PUSH ", v)
				ic.Assembly("HEAP")
				ic.Assembly("GRAB ", vo)
			}

			ic.GainScope()
			ic.SetFlag(Delete)
			ic.SetVariable("i_for_delete", ilang.Type{Name:del})
			ic.SetVariable("i_for_id", ilang.Type{Name:i})
			ic.SetVariable("i_for_array", ilang.Type{Name:array})

			ic.GainScope()
			ic.SetVariable(i, ilang.Number)

			if !OverList {

			if ic.ExpressionType.Name == list.Type.Name  {
				ic.SetVariable(vo, *ic.ExpressionType.SubType)
				ic.SetVariable(vo+".", ilang.Protected)

			} else if ic.ExpressionType == ilang.Text {
				ic.SetVariable(vo, ilang.GetType("letter"))
			} else {
				ic.RaiseError("Cannot find values inside ", ic.ExpressionType)
			}
			}

			ic.SetFlag(ForLoop)
			return
	}
}
<commit_msg>Fix unused variable bug in Go.<commit_after>package f

import "fmt"
import "github.com/qlova/ilang/src"
import "github.com/qlova/ilang/src/types/list"

var ForLoop = ilang.NewFlag()
var Delete = ilang.NewFlag()

func init() {
	ilang.RegisterToken([]string{"for"}, ScanFor)
	ilang.RegisterListener(ForLoop, EndForLoop)
	ilang.RegisterFunction("delete", ilang.Function{
		Inline: true,
		Method: true,
		Assemble: func(ic *ilang.Compiler) string {
			if !ic.GetFlag(ForLoop) {
				ic.RaiseError("delete with zero arguments must be called from within a for loop!")
			}

			//Delete things in a for loop.
			return fmt.Sprint(	"PLACE ", ic.GetVariable("i_for_delete").Name, "\n",
								"PUT ", ic.GetVariable("i_for_id").Name)
		},
	})
}

func EndForLoop(ic *ilang.Compiler) {
	if ic.LastToken != "end" {
		ic.RaiseError("For Loops must end with a 'end' token, found '", ic.LastToken, "'")
	}
	ic.Assembly("REPEAT")

	if ic.GetScopedFlag(TypeLoop) {
		EndTypeLoop(ic)
	}

	if ic.GetScopedFlag(Delete) {
		var array = ic.GetVariable("i_for_array").Name
		var del = ic.GetVariable("i_for_delete").Name

		var collect = ""
		if ic.GetVariable(array).SubType != nil {
			collect = ic.GetVariable(array).SubType.Free("i_pointer")
		}

		ic.Assembly(`
	VAR i_i
	VAR i_test
	LOOP
		SGE i_test i_i #`+del+`
		IF i_test
			BREAK
		END

		IF #`+array+`
		ELSE
			BREAK
		END

		PLACE `+del+`
		PUSH i_i
		GET i_index

		PLACE `+array+`
		PUSH i_index
		GET i_pointer
		ADD i_pointer i_pointer 0
		`+collect+`

		PLACE `+array+`
		PUSH -1
		GET i_swapdex

		PUSH i_index
		SET i_swapdex

		POP end
		ADD end 0 0

		ADD i_i i_i 1
	REPEAT
				`)
		ic.LoseScope()
	}
	ic.Assembly("END")
}

func ScanFor(ic *ilang.Compiler) {

	var name = ic.Scan(ilang.Name)

	var name2 string

	if ic.Peek() == "," {
		ic.Scan(',')
		name2 = ic.Scan(ilang.Name)
	}

	var OverList = false

	switch ic.Scan(0) {
		case "=":
			ic.AssembleVar(name, ic.ScanExpression())
			ic.Scan(',')
			ic.Assembly("IF 1")
			ic.Assembly("LOOP")
			ic.GainScope()
			condition := ic.ScanExpression()
			ic.Assembly("IF ", condition)
			ic.Assembly("	ADD ",name," ",name," 0")
			ic.Assembly("ELSE")
			ic.Assembly("	BREAK")
			ic.Assembly("END")
			ic.SetFlag(ForLoop)

		case "over":
			var token = ic.Scan(0)
			if token == "[" {
				a := ic.ScanExpression()
				ic.Scan(',')
				b := ic.ScanExpression()
				ic.Scan(']')

				condition := ic.Tmp("over")
				backup := ic.Tmp("backup")

				ic.Assembly("IF 1\n",
					"VAR ",name,"\n",
					"VAR ",backup,"\n",
					"ADD ",backup," 0 ",a,"\n",
					"ADD ",name," 0 ",a,"\n",
					"LOOP\n",
					"	VAR ",condition,"\n",
					"	SNE ",condition," ",name," ",b,"\n",
					"	ADD ",name," 0 ",backup,"\n",
					"	IF ",condition,"\n",
					"		SLT ",condition," ",name," ",b,"\n",
					"		IF ",condition,"\n",
					"			ADD ",backup," ",name," 1\n",
					"		ELSE\n",
					"			SUB ",backup," ",name," 1\n",
					"		END\n",
					"		SEQ ",condition," ",a," ",b,"\n",
					"		IF ",condition,"\n",
					"			BREAK\n",
					"		END\n",
					"	ELSE\n",
					"		SEQ ",condition," ",a," ",b,"\n",
					"		IF ",condition,"\n",
					"			ADD ",name," ",name," 1\n",
					"       ELSE\n",
					"			BREAK\n",
					"		END\n",
					"	END\n",
				)
				ic.GainScope()
				if name != "each" {
					ic.SetVariable(name, ilang.Number)
				}
				ic.SetFlag(ForLoop)
				return
			}
			ic.NextToken = token
			OverList = true
			fallthrough
		case "in":
			var peek = ic.Scan(0)
			if t, ok := ic.DefinedTypes[peek]; ok {
				ScanTypeLoop(ic, t, name, name2)
				return
			} else {
				ic.NextToken = peek
			}
			var array = ic.ScanExpression()

			if ic.ExpressionType == list.Type {
				//We can ignore this loop.
				for {
					var token = ic.Scan(0)
					if token == "end" {
						return
					}
				}
			}

			if ic.ExpressionType.Push != "SHARE" {
				ic.RaiseError("Cannot iterate over "+array+" (", ic.ExpressionType.Name, ")")
			}

			var condition = ic.Tmp("in")

			var i, v, vo string
			if name2 != "" {
				i = name
				v = name2
			} else {
				i = ic.Tmp("i")
				v = name
			}

			if OverList {
				i = name
			}

			vo = v
			if ic.ExpressionType.Name == list.Type.Name && ic.ExpressionType.SubType.Push == "SHARE" {
				v += "_address"
			}

			backup := ic.Tmp("backup")
			del := ic.Tmp("delete")

			if OverList {
			ic.Assembly(`
IF 1
ARRAY %v
VAR %v
VAR %v
LOOP
	VAR %v
	ADD %v 0 %v
	SGE %v %v #%v
	IF %v
		BREAK
	END
	ADD %v %v 1
`, del, i,backup, condition, i, backup,  condition, i, array, condition, backup, i)
			} else {
			ic.Assembly(`
IF 1
ARRAY %v
VAR %v
VAR %v
LOOP
	VAR %v
	ADD %v 0 %v
	SGE %v %v #%v
	IF %v
		BREAK
	END
	PLACE %v
	PUSH %v
	GET %v
	ADD %v %v 1
`, del, i,backup, condition, i, backup,  condition, i, array, condition, array, i, v, backup, i)
		if ic.ExpressionType == ilang.Array || ic.ExpressionType == ilang.Text {
			//ic.Assembly("ADD %v %v %v", name, 0, i)
		}
	}

			if ic.ExpressionType.Name == list.Type.Name && ic.ExpressionType.SubType.Push == "SHARE" {
				ic.Assembly("PUSH ", v)
				ic.Assembly("HEAP")
				ic.Assembly("GRAB ", vo)
			}

			ic.GainScope()
			ic.SetFlag(Delete)
			ic.SetVariable("i_for_delete", ilang.Type{Name:del})
			ic.SetVariable("i_for_id", ilang.Type{Name:i})
			ic.SetVariable("i_for_array", ilang.Type{Name:array})

			ic.GainScope()
			ic.SetVariable(i, ilang.Number)

			if !OverList {

			if ic.ExpressionType.Name == list.Type.Name  {
				ic.SetVariable(vo, *ic.ExpressionType.SubType)
				ic.SetVariable(vo+".", ilang.Protected)

			} else if ic.ExpressionType == ilang.Text {
				ic.SetVariable(vo, ilang.GetType("letter"))
			} else {
				ic.RaiseError("Cannot find values inside ", ic.ExpressionType)
			}
			}

			ic.SetFlag(ForLoop)
			return
	}
}
<|endoftext|>


<commit_before>package task

import (
	"fmt"
	"neon/build"
	"neon/util"
)

func init() {
	build.TaskMap["throw"] = build.TaskDescriptor{
		Constructor: Throw,
		Help: `Throws an error.

Arguments:

- throw: the message of the error.

Examples:

    # stop the build because tests don't run
    - throw: "ERROR: tests don't run"

Notes:

- The error message will be printed on the console as the source of the build
  failure.`,
	}
}

func Throw(target *build.Target, args util.Object) (build.Task, error) {
	fields := []string{"throw"}
	if err := CheckFields(args, fields, fields); err != nil {
		return nil, err
	}
	message, ok := args["throw"].(string)
	if !ok {
		return nil, fmt.Errorf("argument of throw print must be a string")
	}
	return func() error {
		return fmt.Errorf(message)
	}, nil
}
<commit_msg>Fixed throw task<commit_after>package task

import (
	"fmt"
	"neon/build"
	"neon/util"
)

func init() {
	build.TaskMap["throw"] = build.TaskDescriptor{
		Constructor: Throw,
		Help: `Throws an error.

Arguments:

- throw: the message of the error.

Examples:

    # stop the build because tests don't run
    - throw: "ERROR: tests don't run"

Notes:

- The error message will be printed on the console as the source of the build
  failure.`,
	}
}

func Throw(target *build.Target, args util.Object) (build.Task, error) {
	fields := []string{"throw"}
	if err := CheckFields(args, fields, fields); err != nil {
		return nil, err
	}
	message, ok := args["throw"].(string)
	if !ok {
		return nil, fmt.Errorf("argument of throw print must be a string")
	}
	return func() error {
		eval, err := target.Build.Context.ReplaceProperties(message)
		if err != nil {
			return fmt.Errorf("processing thow argument: %v", err)
		}
		return fmt.Errorf(eval)
	}, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The Vanadium 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 test

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

	"v.io/x/devtools/internal/collect"
	"v.io/x/devtools/internal/runutil"
	"v.io/x/devtools/internal/test"
	"v.io/x/devtools/internal/tool"
	"v.io/x/devtools/internal/util"
)

const (
	stagingBlessingsRoot    = "dev.staging.v.io" // TODO(jingjin): use a better name and update prod.go.
	localMountTable         = "/ns.dev.staging.v.io:8151"
	globalMountTable        = "/ns.dev.staging.v.io:8101"
	numRetries              = 30
	objNameForDeviceManager = "devices/vanadium-cell-master/devmgr/device"
	retryPeriod             = 10 * time.Second
)

var (
	defaultReleaseTestTimeout = time.Minute * 5

	serviceBinaries = []string{
		"binaryd",
		"applicationd",
		"proxyd",
		"identityd",
		"mounttabled",
		"roled",
		"deviced",
	}
)

// vanadiumReleaseTest updates binaries of staging cloud services and run tests for them.
func vanadiumReleaseTest(ctx *tool.Context, testName string, opts ...Opt) (_ *test.Result, e error) {
	root, err := util.V23Root()
	if err != nil {
		return nil, err
	}

	cleanup, err := initTest(ctx, testName, []string{})
	if err != nil {
		return nil, internalTestError{err, "Init"}
	}
	defer collect.Error(func() error { return cleanup() }, &e)

	type step struct {
		msg string
		fn  func() error
	}
	adminCredDir, publisherCredDir := getCredDirOptValues(opts)
	steps := []step{
		step{
			msg: fmt.Sprintf("Fetching credentials from %v (admin) and %v (publisher)\n", adminCredDir, publisherCredDir),
			fn: func() error {
				if _, err := os.Stat(adminCredDir); err != nil {
					return err
				}
				if _, err := os.Stat(publisherCredDir); err != nil {
					return err
				}
				return nil
			},
		},
		step{
			msg: "Build binaries\n",
			fn:  func() error { return buildBinaries(ctx, root) },
		},
		step{
			msg: "Update services\n",
			fn:  func() error { return updateServices(ctx, root, adminCredDir, publisherCredDir) },
		},
		step{
			msg: "Check services\n",
			fn:  func() error { return checkServices(ctx) },
		},
		step{
			msg: "Create snapshot\n",
			fn:  func() error { return createSnapshot(ctx) },
		},
	}
	for _, step := range steps {
		if result, err := invoker(ctx, step.msg, step.fn); result != nil || err != nil {
			return result, err
		}
	}
	return &test.Result{Status: test.Passed}, nil
}

// invoker invokes the given function and returns test.Result and/or
// errors based on function's results.
func invoker(ctx *tool.Context, msg string, fn func() error) (*test.Result, error) {
	if err := fn(); err != nil {
		test.Fail(ctx, msg)
		if err == runutil.CommandTimedOutErr {
			return &test.Result{
				Status:       test.TimedOut,
				TimeoutValue: defaultReleaseTestTimeout,
			}, nil
		}
		fmt.Fprintf(ctx.Stderr(), "%s\n", err.Error())
		return nil, internalTestError{err, msg}
	}
	test.Pass(ctx, msg)
	return nil, nil
}

// getCredDirOptValues returns the values of credentials dirs (admin, publisher)
// from the given Opt slice.
func getCredDirOptValues(opts []Opt) (string, string) {
	adminCredDir, publisherCredDir := "", ""
	for _, opt := range opts {
		switch v := opt.(type) {
		case AdminCredDirOpt:
			adminCredDir = string(v)
		case PublisherCredDirOpt:
			publisherCredDir = string(v)
		}
	}
	return adminCredDir, publisherCredDir
}

// buildBinaries builds all vanadium binaries.
func buildBinaries(ctx *tool.Context, root string) error {
	args := []string{"go", "install", "v.io/..."}
	if err := ctx.Run().Command("v23", args...); err != nil {
		return err
	}
	return nil
}

// updateServices pushes services' binaries to the applications and binaries
// services and tells the device manager to update all its app.
func updateServices(ctx *tool.Context, root, adminCredDir, publisherCredDir string) (e error) {
	deviceBin := filepath.Join(root, "release", "go", "bin", "device")
	adminCredentialsArg := fmt.Sprintf("--v23.credentials=%s", adminCredDir)
	publisherCredentialsArg := fmt.Sprintf("--v23.credentials=%s", publisherCredDir)
	nsArg := fmt.Sprintf("--v23.namespace.root=%s", globalMountTable)

	// Push all binaries.
	{
		fmt.Fprintln(ctx.Stdout(), "Pushing binaries...")
		args := []string{
			publisherCredentialsArg,
			nsArg,
			"publish",
			"--goos=linux",
			"--goarch=amd64",
		}
		args = append(args, serviceBinaries...)
		if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, deviceBin, args...); err != nil {
			return err
		}
	}

	// A helper function to update a single app.
	updateAppFn := func(appName string) error {
		args := []string{
			adminCredentialsArg,
			fmt.Sprintf("--v23.namespace.root=%s", localMountTable),
			"update",
			"-parallelism=BYKIND",
			appName + "/...",
		}
		if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, deviceBin, args...); err != nil {
			return err
		}
		return nil
	}

	// Update services except for device manager and mounttable.
	{
		fmt.Fprintln(ctx.Stdout(), "Updating services other than device manager and mounttable...")
		apps := []string{
			"devmgr/apps/applicationd",
			"devmgr/apps/binaryd",
			"devmgr/apps/identityd",
			"devmgr/apps/proxyd",
			"devmgr/apps/roled",
		}
		for _, app := range apps {
			if err := updateAppFn(app); err != nil {
				return err
			}
		}
	}

	// Update Device Manager.
	{
		fmt.Fprintln(ctx.Stdout(), "Updating device manager...")
		if err := updateDeviceManagerEnvelope(ctx, root, publisherCredentialsArg, nsArg); err != nil {
			return err
		}
		args := []string{
			adminCredentialsArg,
			fmt.Sprintf("--v23.namespace.root=%s", globalMountTable),
			"update",
			objNameForDeviceManager,
		}
		if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, deviceBin, args...); err != nil {
			return err
		}
		if err := waitForMounttable(ctx, root, adminCredentialsArg, localMountTable); err != nil {
			return err
		}
	}

	// Update mounttable last.
	{
		fmt.Fprintln(ctx.Stdout(), "Updating mounttable...")
		if err := updateAppFn("devmgr/apps/mounttabled"); err != nil {
			return err
		}
		if err := waitForMounttable(ctx, root, adminCredentialsArg, globalMountTable); err != nil {
			return err
		}
	}
	return nil
}

// updateDeviceManagerEnvelope updates the envelope's title from "deviced" to
// "device manager".
func updateDeviceManagerEnvelope(ctx *tool.Context, root, credentialsArg, nsArg string) (e error) {
	applicationBin := filepath.Join(root, "release", "go", "bin", "application")
	appName := "applications/deviced/0"
	appProfile := "linux-amd64"
	// Get current envelope.
	args := []string{
		credentialsArg,
		nsArg,
		"match",
		appName,
		appProfile,
	}
	var out bytes.Buffer
	opts := ctx.Run().Opts()
	opts.Stdout = io.MultiWriter(opts.Stdout, &out)
	opts.Stderr = io.MultiWriter(opts.Stderr, &out)
	if err := ctx.Run().CommandWithOpts(opts, applicationBin, args...); err != nil {
		return err
	}

	// Replace title.
	strEnvelope := strings.Replace(out.String(), `"Title": "deviced"`, `"Title": "device manager"`, -1)
	tmpDir, err := ctx.Run().TempDir("", "")
	if err != nil {
		return err
	}
	defer collect.Error(func() error { return ctx.Run().RemoveAll(tmpDir) }, &e)
	filename := filepath.Join(tmpDir, "envelope")
	if err := ctx.Run().WriteFile(filename, []byte(strEnvelope), os.FileMode(0600)); err != nil {
		return err
	}

	// Update envelope.
	args = []string{
		credentialsArg,
		nsArg,
		"put",
		appName,
		appProfile,
		filename,
	}
	if err := ctx.Run().Command(applicationBin, args...); err != nil {
		return err
	}
	return nil
}

// waitForMounttable waits for the given mounttable to be up
// (timeout: 5 minutes).
func waitForMounttable(ctx *tool.Context, root, credentialsArg, mounttableRoot string) error {
	debugBin := filepath.Join(root, "release", "go", "bin", "debug")
	args := []string{
		credentialsArg,
		"glob",
		mounttableRoot + "/*",
	}
	up := false
	for i := 0; i < numRetries; i++ {
		if err := ctx.Run().Command(debugBin, args...); err != nil {
			time.Sleep(retryPeriod)
			continue
		} else {
			up = true
			break
		}
	}
	if !up {
		return fmt.Errorf("mounttable %q not up after 5 minute", mounttableRoot)
	}
	return nil
}

// checkServices runs "v23 test run vanadium-prod-services-test" against
// staging.
func checkServices(ctx *tool.Context) error {
	// Wait 5 minutes.
	fmt.Fprintf(ctx.Stdout(), "Wait for 5 minutes before checking")
	time.Sleep(time.Minute * 5)

	args := []string{
		"test",
		"run",
		fmt.Sprintf("--v23.namespace.root=%s", globalMountTable),
		fmt.Sprintf("--blessings-root=%s", stagingBlessingsRoot),
		"vanadium-prod-services-test",
	}
	if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, "v23", args...); err != nil {
		return err
	}
	return nil
}

// createSnapshot creates a snapshot with "release" label.
func createSnapshot(ctx *tool.Context) (e error) {
	args := []string{
		"snapshot",
		"--remote",
		"create",
		"--time-format=2006-01-02", // Only include date in label names
		"release",
	}
	if err := ctx.Run().Command("v23", args...); err != nil {
		return err
	}
	return nil
}
<commit_msg>devtools/v23/internal/test/release: check app build time<commit_after>// Copyright 2015 The Vanadium 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 test

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"v.io/x/devtools/internal/collect"
	"v.io/x/devtools/internal/runutil"
	"v.io/x/devtools/internal/test"
	"v.io/x/devtools/internal/tool"
	"v.io/x/devtools/internal/util"
)

const (
	stagingBlessingsRoot    = "dev.staging.v.io" // TODO(jingjin): use a better name and update prod.go.
	localMountTable         = "/ns.dev.staging.v.io:8151"
	globalMountTable        = "/ns.dev.staging.v.io:8101"
	numRetries              = 30
	objNameForDeviceManager = "devices/vanadium-cell-master/devmgr/device"
	retryPeriod             = 10 * time.Second
)

var (
	defaultReleaseTestTimeout = time.Minute * 5

	serviceBinaries = []string{
		"binaryd",
		"applicationd",
		"proxyd",
		"identityd",
		"mounttabled",
		"roled",
		"deviced",
	}
)

// vanadiumReleaseTest updates binaries of staging cloud services and run tests for them.
func vanadiumReleaseTest(ctx *tool.Context, testName string, opts ...Opt) (_ *test.Result, e error) {
	root, err := util.V23Root()
	if err != nil {
		return nil, err
	}

	cleanup, err := initTest(ctx, testName, []string{})
	if err != nil {
		return nil, internalTestError{err, "Init"}
	}
	defer collect.Error(func() error { return cleanup() }, &e)

	type step struct {
		msg string
		fn  func() error
	}
	adminCredDir, publisherCredDir := getCredDirOptValues(opts)
	steps := []step{
		step{
			msg: fmt.Sprintf("Fetching credentials from %v (admin) and %v (publisher)\n", adminCredDir, publisherCredDir),
			fn: func() error {
				if _, err := os.Stat(adminCredDir); err != nil {
					return err
				}
				if _, err := os.Stat(publisherCredDir); err != nil {
					return err
				}
				return nil
			},
		},
		step{
			msg: "Build binaries\n",
			fn:  func() error { return buildBinaries(ctx, root) },
		},
		step{
			msg: "Update services\n",
			fn:  func() error { return updateServices(ctx, root, adminCredDir, publisherCredDir) },
		},
		step{
			msg: "Check services\n",
			fn:  func() error { return checkServices(ctx) },
		},
		step{
			msg: "Create snapshot\n",
			fn:  func() error { return createSnapshot(ctx) },
		},
	}
	for _, step := range steps {
		if result, err := invoker(ctx, step.msg, step.fn); result != nil || err != nil {
			return result, err
		}
	}
	return &test.Result{Status: test.Passed}, nil
}

// invoker invokes the given function and returns test.Result and/or
// errors based on function's results.
func invoker(ctx *tool.Context, msg string, fn func() error) (*test.Result, error) {
	if err := fn(); err != nil {
		test.Fail(ctx, msg)
		if err == runutil.CommandTimedOutErr {
			return &test.Result{
				Status:       test.TimedOut,
				TimeoutValue: defaultReleaseTestTimeout,
			}, nil
		}
		fmt.Fprintf(ctx.Stderr(), "%s\n", err.Error())
		return nil, internalTestError{err, msg}
	}
	test.Pass(ctx, msg)
	return nil, nil
}

// getCredDirOptValues returns the values of credentials dirs (admin, publisher)
// from the given Opt slice.
func getCredDirOptValues(opts []Opt) (string, string) {
	adminCredDir, publisherCredDir := "", ""
	for _, opt := range opts {
		switch v := opt.(type) {
		case AdminCredDirOpt:
			adminCredDir = string(v)
		case PublisherCredDirOpt:
			publisherCredDir = string(v)
		}
	}
	return adminCredDir, publisherCredDir
}

// buildBinaries builds all vanadium binaries.
func buildBinaries(ctx *tool.Context, root string) error {
	args := []string{"go", "install", "v.io/..."}
	if err := ctx.Run().Command("v23", args...); err != nil {
		return err
	}
	return nil
}

// updateServices pushes services' binaries to the applications and binaries
// services and tells the device manager to update all its app.
func updateServices(ctx *tool.Context, root, adminCredDir, publisherCredDir string) (e error) {
	debugBin := filepath.Join(root, "release", "go", "bin", "debug")
	deviceBin := filepath.Join(root, "release", "go", "bin", "device")
	adminCredentialsArg := fmt.Sprintf("--v23.credentials=%s", adminCredDir)
	publisherCredentialsArg := fmt.Sprintf("--v23.credentials=%s", publisherCredDir)
	nsArg := fmt.Sprintf("--v23.namespace.root=%s", globalMountTable)

	// Push all binaries.
	{
		fmt.Fprintln(ctx.Stdout(), "Pushing binaries...")
		args := []string{
			publisherCredentialsArg,
			nsArg,
			"publish",
			"--goos=linux",
			"--goarch=amd64",
		}
		args = append(args, serviceBinaries...)
		if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, deviceBin, args...); err != nil {
			return err
		}
	}

	// A helper function to update a single app.
	updateAppFn := func(appName string) error {
		args := []string{
			adminCredentialsArg,
			fmt.Sprintf("--v23.namespace.root=%s", localMountTable),
			"update",
			"-parallelism=BYKIND",
			appName + "/...",
		}
		if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, deviceBin, args...); err != nil {
			return err
		}
		return nil
	}

	// A helper function to check a single app's build time.
	checkBuildTimeFn := func(appName string) error {
		now := time.Now()
		adminCredentialsArg := fmt.Sprintf("--v23.credentials=%s", adminCredDir)
		args := []string{
			adminCredentialsArg,
			fmt.Sprintf("--v23.namespace.root=%s", localMountTable),
			"stats",
			"read",
			fmt.Sprintf("%s/*/*/stats/system/metadata/build.Time", appName),
		}
		var out bytes.Buffer
		opts := ctx.Run().Opts()
		opts.Stdout = io.MultiWriter(opts.Stdout, &out)
		if err := ctx.Run().TimedCommandWithOpts(defaultReleaseTestTimeout, opts, debugBin, args...); err != nil {
			return err
		}
		// TODO(jingjin): check the build manifest label after changing the
		// pre-release process to first cut the snapshot and then get the binaries
		// for staging from the snapshot where we should be able to exactly match
		// the build label.
		buildTimeRE := regexp.MustCompile(fmt.Sprintf(`.*build\.Time:\s%sT.*`, now.Format("2006-01-02")))
		statsOutput := out.String()
		if !buildTimeRE.MatchString(statsOutput) {
			return fmt.Errorf("Update failed.\nBuild time: %s", statsOutput)
		}
		return nil
	}

	// Update services except for device manager and mounttable.
	{
		fmt.Fprintln(ctx.Stdout(), "Updating services other than device manager and mounttable...")
		apps := []string{
			"devmgr/apps/applicationd",
			"devmgr/apps/binaryd",
			"devmgr/apps/identityd",
			"devmgr/apps/proxyd",
			"devmgr/apps/roled",
		}
		for _, app := range apps {
			if err := updateAppFn(app); err != nil {
				return err
			}
			if err := checkBuildTimeFn(app); err != nil {
				return err
			}
		}
	}

	// Update Device Manager.
	{
		fmt.Fprintln(ctx.Stdout(), "Updating device manager...")
		if err := updateDeviceManagerEnvelope(ctx, root, publisherCredentialsArg, nsArg); err != nil {
			return err
		}
		args := []string{
			adminCredentialsArg,
			fmt.Sprintf("--v23.namespace.root=%s", globalMountTable),
			"update",
			objNameForDeviceManager,
		}
		if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, deviceBin, args...); err != nil {
			return err
		}
		if err := waitForMounttable(ctx, root, adminCredentialsArg, localMountTable); err != nil {
			return err
		}
		// TODO(jingjin): check build time for device manager.
	}

	// Update mounttable last.
	{
		fmt.Fprintln(ctx.Stdout(), "Updating mounttable...")
		mounttableName := "devmgr/apps/mounttabled"
		if err := updateAppFn(mounttableName); err != nil {
			return err
		}
		if err := waitForMounttable(ctx, root, adminCredentialsArg, globalMountTable); err != nil {
			return err
		}
		if err := checkBuildTimeFn(mounttableName); err != nil {
			return err
		}
	}
	return nil
}

// updateDeviceManagerEnvelope updates the envelope's title from "deviced" to
// "device manager".
func updateDeviceManagerEnvelope(ctx *tool.Context, root, credentialsArg, nsArg string) (e error) {
	applicationBin := filepath.Join(root, "release", "go", "bin", "application")
	appName := "applications/deviced/0"
	appProfile := "linux-amd64"
	// Get current envelope.
	args := []string{
		credentialsArg,
		nsArg,
		"match",
		appName,
		appProfile,
	}
	var out bytes.Buffer
	opts := ctx.Run().Opts()
	opts.Stdout = io.MultiWriter(opts.Stdout, &out)
	opts.Stderr = io.MultiWriter(opts.Stderr, &out)
	if err := ctx.Run().CommandWithOpts(opts, applicationBin, args...); err != nil {
		return err
	}

	// Replace title.
	strEnvelope := strings.Replace(out.String(), `"Title": "deviced"`, `"Title": "device manager"`, -1)
	tmpDir, err := ctx.Run().TempDir("", "")
	if err != nil {
		return err
	}
	defer collect.Error(func() error { return ctx.Run().RemoveAll(tmpDir) }, &e)
	filename := filepath.Join(tmpDir, "envelope")
	if err := ctx.Run().WriteFile(filename, []byte(strEnvelope), os.FileMode(0600)); err != nil {
		return err
	}

	// Update envelope.
	args = []string{
		credentialsArg,
		nsArg,
		"put",
		appName,
		appProfile,
		filename,
	}
	if err := ctx.Run().Command(applicationBin, args...); err != nil {
		return err
	}
	return nil
}

// waitForMounttable waits for the given mounttable to be up
// (timeout: 5 minutes).
func waitForMounttable(ctx *tool.Context, root, credentialsArg, mounttableRoot string) error {
	debugBin := filepath.Join(root, "release", "go", "bin", "debug")
	args := []string{
		credentialsArg,
		"glob",
		mounttableRoot + "/*",
	}
	up := false
	for i := 0; i < numRetries; i++ {
		if err := ctx.Run().Command(debugBin, args...); err != nil {
			time.Sleep(retryPeriod)
			continue
		} else {
			up = true
			break
		}
	}
	if !up {
		return fmt.Errorf("mounttable %q not up after 5 minute", mounttableRoot)
	}
	return nil
}

// checkServices runs "v23 test run vanadium-prod-services-test" against
// staging.
func checkServices(ctx *tool.Context) error {
	// Wait 5 minutes.
	fmt.Fprintf(ctx.Stdout(), "Wait for 5 minutes before checking")
	time.Sleep(time.Minute * 5)

	args := []string{
		"test",
		"run",
		fmt.Sprintf("--v23.namespace.root=%s", globalMountTable),
		fmt.Sprintf("--blessings-root=%s", stagingBlessingsRoot),
		"vanadium-prod-services-test",
	}
	if err := ctx.Run().TimedCommand(defaultReleaseTestTimeout, "v23", args...); err != nil {
		return err
	}
	return nil
}

// createSnapshot creates a snapshot with "release" label.
func createSnapshot(ctx *tool.Context) (e error) {
	args := []string{
		"snapshot",
		"--remote",
		"create",
		"--time-format=2006-01-02", // Only include date in label names
		"release",
	}
	if err := ctx.Run().Command("v23", args...); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 The go-vm 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 vdiskmanager

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"

	"github.com/go-vm/vmware/internal/vmwareutil"
)

// VMware Virtual Disk Manager - build 5192483.
// Usage: vmware-vdiskmanager OPTIONS <disk-name> | <mount-point>
// Offline disk manipulation utility
//   Operations, only one may be specified at a time:
//      -c                   : create disk.  Additional creation options must
//                             be specified.  Only local virtual disks can be
//                             created.
//      -d                   : defragment the specified virtual disk. Only
//                             local virtual disks may be defragmented.
//      -k                   : shrink the specified virtual disk. Only local
//                             virtual disks may be shrunk.
//      -n <source-disk>     : rename the specified virtual disk; need to
//                             specify destination disk-name. Only local virtual
//                             disks may be renamed.
//      -p                   : prepare the mounted virtual disk specified by
//                             the volume path for shrinking.
//      -r <source-disk>     : convert the specified disk; need to specify
//                             destination disk-type.  For local destination disks
//                             the disk type must be specified.
//      -x <new-capacity>    : expand the disk to the specified capacity. Only
//                             local virtual disks may be expanded.
//      -R                   : check a sparse virtual disk for consistency and attempt
//                             to repair any errors.
//      -e                   : check for disk chain consistency.
//      -D                   : make disk deletable.  This should only be used on disks
//                             that have been copied from another product.
//
//   Other Options:
//      -q                   : do not log messages
//
//   Additional options for create and convert:
//      -a <adapter>         : (for use with -c only) adapter type
//                             (ide, buslogic, lsilogic). Pass lsilogic for other adapter types.
//      -s <size>            : capacity of the virtual disk
//      -t <disk-type>       : disk type id
//
//   Disk types:
//       0                   : single growable virtual disk
//       1                   : growable virtual disk split in 2GB files
//       2                   : preallocated virtual disk
//       3                   : preallocated virtual disk split in 2GB files
//       4                   : preallocated ESX-type virtual disk
//       5                   : compressed disk optimized for streaming
//       6                   : thin provisioned virtual disk - ESX 3.x and above
//
//      The capacity can be specified in sectors, KB, MB or GB.
//      The acceptable ranges:
//                            ide/scsi adapter : [1MB, 8192.0GB]
//                            buslogic adapter : [1MB, 2040.0GB]
//         ex 1: vmware-vdiskmanager -c -s 850MB -a ide -t 0 myIdeDisk.vmdk
//         ex 2: vmware-vdiskmanager -d myDisk.vmdk
//         ex 3: vmware-vdiskmanager -r sourceDisk.vmdk -t 0 destinationDisk.vmdk
//         ex 4: vmware-vdiskmanager -x 36GB myDisk.vmdk
//         ex 5: vmware-vdiskmanager -n sourceName.vmdk destinationName.vmdk
//         ex 6: vmware-vdiskmanager -r sourceDisk.vmdk -t 4 -h esx-name.mycompany.com \
//               -u username -f passwordfile "[storage1]/path/to/targetDisk.vmdk"
//         ex 7: vmware-vdiskmanager -k myDisk.vmdk
//         ex 8: vmware-vdiskmanager -p <mount-point>
//               (A virtual disk first needs to be mounted at <mount-point>)
//

var vdiskmanagerPath = vmwareutil.LookPath("vmware-vdiskmanager")

// vdiskmanager wrapper of vmware-vdiskmanager command.
func vdiskmanager(args ...string) error {
	cmd := exec.Command(vdiskmanagerPath, args...)

	if err := cmd.Run(); err != nil {
		if runErr := err.(*exec.ExitError); runErr != nil {
			return runErr
		}
		return err
	}

	return nil
}

// AdapterType represents a adapter type.
type AdapterType int

const (
	// LsiLogic is a lsilogic type.
	LsiLogic AdapterType = iota
	// Ide is a ide type.
	Ide
	// BusLogic is a buslogic type.
	BusLogic
)

// String implements a fmt.Stringer interface.
func (a AdapterType) String() string {
	switch a {
	case LsiLogic:
		return "lsilogic"
	case Ide:
		return "ide"
	case BusLogic:
		return "buslogic"
	default:
		return ""
	}
}

// Config represents a vdiskmanager create config.
type Config struct {
	Size     int
	DiskType int
	Adapter  AdapterType
}

// Create create disk.
func Create(dst string, config *Config) error {
	size := 20000       // default is 20GB
	var diskType int    // default is 0
	adapter := LsiLogic // default is lsilogic

	if config != nil {
		if config.Size > 0 {
			size = config.Size
		}
		if config.DiskType > 0 {
			diskType = config.DiskType
		}
		if config.Adapter > 0 {
			adapter = config.Adapter
		}
	}

	if !strings.HasSuffix(dst, ".vmdk") {
		dst = dst + ".vmdk"
	}

	return vdiskmanager("-c", "-s", fmt.Sprintf("%dMB", size), "-t", strconv.Itoa(diskType), "-a", adapter.String(), dst)
}

// Defrag defragment the specified virtual disk.
func Defrag(src string) error {
	return vdiskmanager("-d", src)
}

// Shrink shrink the specified virtual disk.
func Shrink(src string) error {
	return vdiskmanager("-k", src)
}

// Rename rename the specified virtual disk.
func Rename(src, dst string) error {
	return vdiskmanager("-n", src, dst)
}

// Prepare the mounted virtual disk specified by the volume path for shrinking.
func Prepare(src string) error {
	return vdiskmanager("-p", src)
}

// Convert convert the specified disk.
func Convert(src, dst string, diskType int) error {
	return vdiskmanager("-r", src, "-t", strconv.Itoa(diskType), dst)
}

// Expand expand the disk to the specified capacity.
func Expand(capacity int, src string) error {
	return vdiskmanager("-x", fmt.Sprintf("%dMB", capacity), src)
}

// Repair check a sparse virtual disk for consistency and attempt to repair any errors.
func Repair(src string) error {
	return vdiskmanager("-R", src)
}

// Check check for disk chain consistency.
func Check(src string) error {
	return vdiskmanager("-e", src)
}

// Delete make disk deletable.
func Delete(src string) error {
	return vdiskmanager("-D", src)
}
<commit_msg>vdiskmanager: explicitly declare diskType to 0<commit_after>// Copyright 2017 The go-vm 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 vdiskmanager

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"

	"github.com/go-vm/vmware/internal/vmwareutil"
)

// VMware Virtual Disk Manager - build 5192483.
// Usage: vmware-vdiskmanager OPTIONS <disk-name> | <mount-point>
// Offline disk manipulation utility
//   Operations, only one may be specified at a time:
//      -c                   : create disk.  Additional creation options must
//                             be specified.  Only local virtual disks can be
//                             created.
//      -d                   : defragment the specified virtual disk. Only
//                             local virtual disks may be defragmented.
//      -k                   : shrink the specified virtual disk. Only local
//                             virtual disks may be shrunk.
//      -n <source-disk>     : rename the specified virtual disk; need to
//                             specify destination disk-name. Only local virtual
//                             disks may be renamed.
//      -p                   : prepare the mounted virtual disk specified by
//                             the volume path for shrinking.
//      -r <source-disk>     : convert the specified disk; need to specify
//                             destination disk-type.  For local destination disks
//                             the disk type must be specified.
//      -x <new-capacity>    : expand the disk to the specified capacity. Only
//                             local virtual disks may be expanded.
//      -R                   : check a sparse virtual disk for consistency and attempt
//                             to repair any errors.
//      -e                   : check for disk chain consistency.
//      -D                   : make disk deletable.  This should only be used on disks
//                             that have been copied from another product.
//
//   Other Options:
//      -q                   : do not log messages
//
//   Additional options for create and convert:
//      -a <adapter>         : (for use with -c only) adapter type
//                             (ide, buslogic, lsilogic). Pass lsilogic for other adapter types.
//      -s <size>            : capacity of the virtual disk
//      -t <disk-type>       : disk type id
//
//   Disk types:
//       0                   : single growable virtual disk
//       1                   : growable virtual disk split in 2GB files
//       2                   : preallocated virtual disk
//       3                   : preallocated virtual disk split in 2GB files
//       4                   : preallocated ESX-type virtual disk
//       5                   : compressed disk optimized for streaming
//       6                   : thin provisioned virtual disk - ESX 3.x and above
//
//      The capacity can be specified in sectors, KB, MB or GB.
//      The acceptable ranges:
//                            ide/scsi adapter : [1MB, 8192.0GB]
//                            buslogic adapter : [1MB, 2040.0GB]
//         ex 1: vmware-vdiskmanager -c -s 850MB -a ide -t 0 myIdeDisk.vmdk
//         ex 2: vmware-vdiskmanager -d myDisk.vmdk
//         ex 3: vmware-vdiskmanager -r sourceDisk.vmdk -t 0 destinationDisk.vmdk
//         ex 4: vmware-vdiskmanager -x 36GB myDisk.vmdk
//         ex 5: vmware-vdiskmanager -n sourceName.vmdk destinationName.vmdk
//         ex 6: vmware-vdiskmanager -r sourceDisk.vmdk -t 4 -h esx-name.mycompany.com \
//               -u username -f passwordfile "[storage1]/path/to/targetDisk.vmdk"
//         ex 7: vmware-vdiskmanager -k myDisk.vmdk
//         ex 8: vmware-vdiskmanager -p <mount-point>
//               (A virtual disk first needs to be mounted at <mount-point>)
//

var vdiskmanagerPath = vmwareutil.LookPath("vmware-vdiskmanager")

// vdiskmanager wrapper of vmware-vdiskmanager command.
func vdiskmanager(args ...string) error {
	cmd := exec.Command(vdiskmanagerPath, args...)

	if err := cmd.Run(); err != nil {
		if runErr := err.(*exec.ExitError); runErr != nil {
			return runErr
		}
		return err
	}

	return nil
}

// AdapterType represents a adapter type.
type AdapterType int

const (
	// LsiLogic is a lsilogic type.
	LsiLogic AdapterType = iota
	// Ide is a ide type.
	Ide
	// BusLogic is a buslogic type.
	BusLogic
)

// String implements a fmt.Stringer interface.
func (a AdapterType) String() string {
	switch a {
	case LsiLogic:
		return "lsilogic"
	case Ide:
		return "ide"
	case BusLogic:
		return "buslogic"
	default:
		return ""
	}
}

// Config represents a vdiskmanager create config.
type Config struct {
	Size     int
	DiskType int
	Adapter  AdapterType
}

// Create create disk.
func Create(dst string, config *Config) error {
	size := 20000       // default is 20GB
	diskType := 0       // default is 0
	adapter := LsiLogic // default is lsilogic

	if config != nil {
		if config.Size > 0 {
			size = config.Size
		}
		if config.DiskType > 0 {
			diskType = config.DiskType
		}
		if config.Adapter > 0 {
			adapter = config.Adapter
		}
	}

	if !strings.HasSuffix(dst, ".vmdk") {
		dst = dst + ".vmdk"
	}

	return vdiskmanager("-c", "-s", fmt.Sprintf("%dMB", size), "-t", strconv.Itoa(diskType), "-a", adapter.String(), dst)
}

// Defrag defragment the specified virtual disk.
func Defrag(src string) error {
	return vdiskmanager("-d", src)
}

// Shrink shrink the specified virtual disk.
func Shrink(src string) error {
	return vdiskmanager("-k", src)
}

// Rename rename the specified virtual disk.
func Rename(src, dst string) error {
	return vdiskmanager("-n", src, dst)
}

// Prepare the mounted virtual disk specified by the volume path for shrinking.
func Prepare(src string) error {
	return vdiskmanager("-p", src)
}

// Convert convert the specified disk.
func Convert(src, dst string, diskType int) error {
	return vdiskmanager("-r", src, "-t", strconv.Itoa(diskType), dst)
}

// Expand expand the disk to the specified capacity.
func Expand(capacity int, src string) error {
	return vdiskmanager("-x", fmt.Sprintf("%dMB", capacity), src)
}

// Repair check a sparse virtual disk for consistency and attempt to repair any errors.
func Repair(src string) error {
	return vdiskmanager("-R", src)
}

// Check check for disk chain consistency.
func Check(src string) error {
	return vdiskmanager("-e", src)
}

// Delete make disk deletable.
func Delete(src string) error {
	return vdiskmanager("-D", src)
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

// Primitive HTTP client. See RFC 2616.

package http

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"encoding/base64"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
	"strings"
)

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// Used in Send to implement io.ReadCloser by bundling together the
// bufio.Reader through which we read the response, and the underlying
// network connection.
type readClose struct {
	io.Reader
	io.Closer
}

// Send issues an HTTP request.  Caller should close resp.Body when done reading it.
//
// TODO: support persistent connections (multiple requests on a single connection).
// send() method is nonpublic because, when we refactor the code for persistent
// connections, it may no longer make sense to have a method with this signature.
func send(req *Request) (resp *Response, err os.Error) {
	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
		return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
	}

	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":" + req.URL.Scheme
	}
	info := req.URL.RawUserinfo
	if len(info) > 0 {
		enc := base64.URLEncoding
		encoded := make([]byte, enc.EncodedLen(len(info)))
		enc.Encode(encoded, []byte(info))
		if req.Header == nil {
			req.Header = make(map[string]string)
		}
		req.Header["Authorization"] = "Basic " + string(encoded)
	}

	var conn io.ReadWriteCloser
	if req.URL.Scheme == "http" {
		conn, err = net.Dial("tcp", "", addr)
		if err != nil {
			return nil, err
		}
	} else { // https
		conn, err = tls.Dial("tcp", "", addr, nil)
		if err != nil {
			return nil, err
		}
		h := req.URL.Host
		if hasPort(h) {
			h = h[0:strings.LastIndex(h, ":")]
		}
		if err := conn.(*tls.Conn).VerifyHostname(h); err != nil {
			return nil, err
		}
	}

	err = req.Write(conn)
	if err != nil {
		conn.Close()
		return nil, err
	}

	reader := bufio.NewReader(conn)
	resp, err = ReadResponse(reader, req.Method)
	if err != nil {
		conn.Close()
		return nil, err
	}

	resp.Body = readClose{resp.Body, conn}

	return
}

// True if the specified HTTP status code is one for which the Get utility should
// automatically redirect.
func shouldRedirect(statusCode int) bool {
	switch statusCode {
	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
		return true
	}
	return false
}

// Get issues a GET to the specified URL.  If the response is one of the following
// redirect codes, it follows the redirect, up to a maximum of 10 redirects:
//
//    301 (Moved Permanently)
//    302 (Found)
//    303 (See Other)
//    307 (Temporary Redirect)
//
// finalURL is the URL from which the response was fetched -- identical to the
// input URL unless redirects were followed.
//
// Caller should close r.Body when done reading it.
func Get(url string) (r *Response, finalURL string, err os.Error) {
	// TODO: if/when we add cookie support, the redirected request shouldn't
	// necessarily supply the same cookies as the original.
	// TODO: set referrer header on redirects.
	for redirect := 0; ; redirect++ {
		if redirect >= 10 {
			err = os.ErrorString("stopped after 10 redirects")
			break
		}

		var req Request
		if req.URL, err = ParseURL(url); err != nil {
			break
		}
		url = req.URL.String()
		if r, err = send(&req); err != nil {
			break
		}
		if shouldRedirect(r.StatusCode) {
			r.Body.Close()
			if url = r.GetHeader("Location"); url == "" {
				err = os.ErrorString(fmt.Sprintf("%d response missing Location header", r.StatusCode))
				break
			}
			continue
		}
		finalURL = url
		return
	}

	err = &URLError{"Get", url, err}
	return
}

// Post issues a POST to the specified URL.
//
// Caller should close r.Body when done reading it.
func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) {
	var req Request
	req.Method = "POST"
	req.ProtoMajor = 1
	req.ProtoMinor = 1
	req.Close = true
	req.Body = nopCloser{body}
	req.Header = map[string]string{
		"Content-Type": bodyType,
	}
	req.TransferEncoding = []string{"chunked"}

	req.URL, err = ParseURL(url)
	if err != nil {
		return nil, err
	}

	return send(&req)
}

// PostForm issues a POST to the specified URL,
// with data's keys and values urlencoded as the request body.
//
// Caller should close r.Body when done reading it.
func PostForm(url string, data map[string]string) (r *Response, err os.Error) {
	var req Request
	req.Method = "POST"
	req.ProtoMajor = 1
	req.ProtoMinor = 1
	req.Close = true
	body := urlencode(data)
	req.Body = nopCloser{body}
	req.Header = map[string]string{
		"Content-Type":   "application/x-www-form-urlencoded",
		"Content-Length": strconv.Itoa(body.Len()),
	}
	req.ContentLength = int64(body.Len())

	req.URL, err = ParseURL(url)
	if err != nil {
		return nil, err
	}

	return send(&req)
}

// TODO: remove this function when PostForm takes a multimap.
func urlencode(data map[string]string) (b *bytes.Buffer) {
	m := make(map[string][]string, len(data))
	for k, v := range data {
		m[k] = []string{v}
	}
	return bytes.NewBuffer([]byte(EncodeQuery(m)))
}

// Head issues a HEAD to the specified URL.
func Head(url string) (r *Response, err os.Error) {
	var req Request
	req.Method = "HEAD"
	if req.URL, err = ParseURL(url); err != nil {
		return
	}
	url = req.URL.String()
	if r, err = send(&req); err != nil {
		return
	}
	return
}

type nopCloser struct {
	io.Reader
}

func (nopCloser) Close() os.Error { return nil }
<commit_msg>http: follow relative redirect in Get<commit_after>// Copyright 2009 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.

// Primitive HTTP client. See RFC 2616.

package http

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"encoding/base64"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
	"strings"
)

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// Used in Send to implement io.ReadCloser by bundling together the
// bufio.Reader through which we read the response, and the underlying
// network connection.
type readClose struct {
	io.Reader
	io.Closer
}

// Send issues an HTTP request.  Caller should close resp.Body when done reading it.
//
// TODO: support persistent connections (multiple requests on a single connection).
// send() method is nonpublic because, when we refactor the code for persistent
// connections, it may no longer make sense to have a method with this signature.
func send(req *Request) (resp *Response, err os.Error) {
	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
		return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
	}

	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":" + req.URL.Scheme
	}
	info := req.URL.RawUserinfo
	if len(info) > 0 {
		enc := base64.URLEncoding
		encoded := make([]byte, enc.EncodedLen(len(info)))
		enc.Encode(encoded, []byte(info))
		if req.Header == nil {
			req.Header = make(map[string]string)
		}
		req.Header["Authorization"] = "Basic " + string(encoded)
	}

	var conn io.ReadWriteCloser
	if req.URL.Scheme == "http" {
		conn, err = net.Dial("tcp", "", addr)
		if err != nil {
			return nil, err
		}
	} else { // https
		conn, err = tls.Dial("tcp", "", addr, nil)
		if err != nil {
			return nil, err
		}
		h := req.URL.Host
		if hasPort(h) {
			h = h[0:strings.LastIndex(h, ":")]
		}
		if err := conn.(*tls.Conn).VerifyHostname(h); err != nil {
			return nil, err
		}
	}

	err = req.Write(conn)
	if err != nil {
		conn.Close()
		return nil, err
	}

	reader := bufio.NewReader(conn)
	resp, err = ReadResponse(reader, req.Method)
	if err != nil {
		conn.Close()
		return nil, err
	}

	resp.Body = readClose{resp.Body, conn}

	return
}

// True if the specified HTTP status code is one for which the Get utility should
// automatically redirect.
func shouldRedirect(statusCode int) bool {
	switch statusCode {
	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
		return true
	}
	return false
}

// Get issues a GET to the specified URL.  If the response is one of the following
// redirect codes, it follows the redirect, up to a maximum of 10 redirects:
//
//    301 (Moved Permanently)
//    302 (Found)
//    303 (See Other)
//    307 (Temporary Redirect)
//
// finalURL is the URL from which the response was fetched -- identical to the
// input URL unless redirects were followed.
//
// Caller should close r.Body when done reading it.
func Get(url string) (r *Response, finalURL string, err os.Error) {
	// TODO: if/when we add cookie support, the redirected request shouldn't
	// necessarily supply the same cookies as the original.
	// TODO: set referrer header on redirects.
	var base *URL
	for redirect := 0; ; redirect++ {
		if redirect >= 10 {
			err = os.ErrorString("stopped after 10 redirects")
			break
		}

		var req Request
		if base == nil {
			req.URL, err = ParseURL(url)
		} else {
			req.URL, err = base.ParseURL(url)
		}
		if err != nil {
			break
		}
		url = req.URL.String()
		if r, err = send(&req); err != nil {
			break
		}
		if shouldRedirect(r.StatusCode) {
			r.Body.Close()
			if url = r.GetHeader("Location"); url == "" {
				err = os.ErrorString(fmt.Sprintf("%d response missing Location header", r.StatusCode))
				break
			}
			base = req.URL
			continue
		}
		finalURL = url
		return
	}

	err = &URLError{"Get", url, err}
	return
}

// Post issues a POST to the specified URL.
//
// Caller should close r.Body when done reading it.
func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) {
	var req Request
	req.Method = "POST"
	req.ProtoMajor = 1
	req.ProtoMinor = 1
	req.Close = true
	req.Body = nopCloser{body}
	req.Header = map[string]string{
		"Content-Type": bodyType,
	}
	req.TransferEncoding = []string{"chunked"}

	req.URL, err = ParseURL(url)
	if err != nil {
		return nil, err
	}

	return send(&req)
}

// PostForm issues a POST to the specified URL,
// with data's keys and values urlencoded as the request body.
//
// Caller should close r.Body when done reading it.
func PostForm(url string, data map[string]string) (r *Response, err os.Error) {
	var req Request
	req.Method = "POST"
	req.ProtoMajor = 1
	req.ProtoMinor = 1
	req.Close = true
	body := urlencode(data)
	req.Body = nopCloser{body}
	req.Header = map[string]string{
		"Content-Type":   "application/x-www-form-urlencoded",
		"Content-Length": strconv.Itoa(body.Len()),
	}
	req.ContentLength = int64(body.Len())

	req.URL, err = ParseURL(url)
	if err != nil {
		return nil, err
	}

	return send(&req)
}

// TODO: remove this function when PostForm takes a multimap.
func urlencode(data map[string]string) (b *bytes.Buffer) {
	m := make(map[string][]string, len(data))
	for k, v := range data {
		m[k] = []string{v}
	}
	return bytes.NewBuffer([]byte(EncodeQuery(m)))
}

// Head issues a HEAD to the specified URL.
func Head(url string) (r *Response, err os.Error) {
	var req Request
	req.Method = "HEAD"
	if req.URL, err = ParseURL(url); err != nil {
		return
	}
	url = req.URL.String()
	if r, err = send(&req); err != nil {
		return
	}
	return
}

type nopCloser struct {
	io.Reader
}

func (nopCloser) Close() os.Error { return nil }
<|endoftext|>


<commit_before>// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package requests

// CreateFunctionRequest create a function in the swarm.
type CreateFunctionRequest struct {

	// Service corresponds to a Docker Service
	Service string `json:"service"`

	// Image corresponds to a Docker image
	Image string `json:"image"`

	// Network is specific to Docker Swarm - default overlay network is: func_functions
	Network string `json:"network"`

	// EnvProcess corresponds to the fprocess variable for your container watchdog.
	EnvProcess string `json:"envProcess"`

	// EnvVars provides overrides for functions.
	EnvVars map[string]string `json:"envVars"`

	// RegistryAuth is the registry authentication (optional)
	// in the same encoded format as Docker native credentials
	// (see ~/.docker/config.json)
	RegistryAuth string `json:"registryAuth,omitempty"`

	// Constraints are specific to back-end orchestration platform
	Constraints []string `json:"constraints"`

	// Secrets list of secrets to be made available to function
	Secrets []string `json:"secrets"`

	// Labels are metadata for functions which may be used by the
	// back-end for making scheduling or routing decisions
	Labels *map[string]string `json:"labels"`

	// Limits for function
	Limits *FunctionResources `json:"limits"`

	// Requests of resources requested by function
	Requests *FunctionResources `json:"requests"`
}

// FunctionResources Memory and CPU
type FunctionResources struct {
	Memory string `json:"memory"`
	CPU    string `json:"cpu"`
}

// Function exported for system/functions endpoint
type Function struct {
	Name            string  `json:"name"`
	Image           string  `json:"image"`
	InvocationCount float64 `json:"invocationCount"` // TODO: shouldn't this be int64?
	Replicas        uint64  `json:"replicas"`
	EnvProcess      string  `json:"envProcess"`

	// AvailableReplicas is the count of replicas ready to receive invocations as reported by the back-end
	AvailableReplicas uint64 `json:"availableReplicas"`

	// Labels are metadata for functions which may be used by the
	// back-end for making scheduling or routing decisions
	Labels *map[string]string `json:"labels"`
}

// AsyncReport is the report from a function executed on a queue worker.
type AsyncReport struct {
	FunctionName string  `json:"name"`
	StatusCode   int     `json:"statusCode"`
	TimeTaken    float64 `json:"timeTaken"`
}

// DeleteFunctionRequest delete a deployed function
type DeleteFunctionRequest struct {
	FunctionName string `json:"functionName"`
}
<commit_msg>Add ReadOnlyRootFilesystem flag<commit_after>// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package requests

// CreateFunctionRequest create a function in the swarm.
type CreateFunctionRequest struct {

	// Service corresponds to a Docker Service
	Service string `json:"service"`

	// Image corresponds to a Docker image
	Image string `json:"image"`

	// Network is specific to Docker Swarm - default overlay network is: func_functions
	Network string `json:"network"`

	// EnvProcess corresponds to the fprocess variable for your container watchdog.
	EnvProcess string `json:"envProcess"`

	// EnvVars provides overrides for functions.
	EnvVars map[string]string `json:"envVars"`

	// RegistryAuth is the registry authentication (optional)
	// in the same encoded format as Docker native credentials
	// (see ~/.docker/config.json)
	RegistryAuth string `json:"registryAuth,omitempty"`

	// Constraints are specific to back-end orchestration platform
	Constraints []string `json:"constraints"`

	// Secrets list of secrets to be made available to function
	Secrets []string `json:"secrets"`

	// Labels are metadata for functions which may be used by the
	// back-end for making scheduling or routing decisions
	Labels *map[string]string `json:"labels"`

	// Limits for function
	Limits *FunctionResources `json:"limits"`

	// Requests of resources requested by function
	Requests *FunctionResources `json:"requests"`

	// ReadOnlyRootFilesystem removes write-access from the root filesystem
	// mount-point.
	ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem"`
}

// FunctionResources Memory and CPU
type FunctionResources struct {
	Memory string `json:"memory"`
	CPU    string `json:"cpu"`
}

// Function exported for system/functions endpoint
type Function struct {
	Name            string  `json:"name"`
	Image           string  `json:"image"`
	InvocationCount float64 `json:"invocationCount"` // TODO: shouldn't this be int64?
	Replicas        uint64  `json:"replicas"`
	EnvProcess      string  `json:"envProcess"`

	// AvailableReplicas is the count of replicas ready to receive invocations as reported by the back-end
	AvailableReplicas uint64 `json:"availableReplicas"`

	// Labels are metadata for functions which may be used by the
	// back-end for making scheduling or routing decisions
	Labels *map[string]string `json:"labels"`
}

// AsyncReport is the report from a function executed on a queue worker.
type AsyncReport struct {
	FunctionName string  `json:"name"`
	StatusCode   int     `json:"statusCode"`
	TimeTaken    float64 `json:"timeTaken"`
}

// DeleteFunctionRequest delete a deployed function
type DeleteFunctionRequest struct {
	FunctionName string `json:"functionName"`
}
<|endoftext|>


<commit_before>// +build !windows

package service

import (
	"os/exec"
	"syscall"
)

func stopProc(cmd *exec.Cmd) error {
	return cmd.Process.Signal(syscall.SIGINT)
}
<commit_msg>Stop process properly<commit_after>// +build !windows

package service

import (
	"os/exec"
	"syscall"
)

func stopProc(cmd *exec.Cmd) error {
		exitCode := cmd.Process.Signal(syscall.SIGINT)
		cmd.Wait()
		return exitCode
}
<|endoftext|>


<commit_before>package main

import (
    "flag"
    "net/http"
)

func main() {

        flag.Parse()

	http.HandleFunc("/v1/authorize", Authorize)
	http.HandleFunc("/v1/sign", Sign)
	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}

}

func Authorize(w http.ResponseWriter, req *http.Request) {

}

func Sign(w http.ResponseWriter, req *http.Request) {

}
<commit_msg>Basic service implementation w/o authentication for requests. Formatted.<commit_after>package main

import (
	"crypto/x509"
	"flag"
	"io/ioutil"
	"net/http"
	"os/exec"
	"time"
)

var db = map[string]int{}

func main() {

	flag.Parse()

	http.HandleFunc("/v1/authorize", Authorize)
	http.HandleFunc("/v1/sign", Sign)

	// Placeholder for authentication / authorization middleware on authorize call.

	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}

}

func Authorize(w http.ResponseWriter, req *http.Request) {
	log.Println("Received authorize call.")
	// Parse input
	sn := req.FormValue("cn")
	ttl := req.FormValue("ttl")

	// Construct ttl
	d := time.ParseDuration(ttl)
	expires := time.Now().Add(d)

	// queue for write to map
	// ...

	w.Write("")
	req.Body.Close()
}

func Sign(w http.ResponseWriter, req *http.Request) {
	log.Println("Received sign call.")

	// Upload the CSR and copy it to some known location
	r.ParseMultipartForm(32 << 20)
	file, handler, err := r.FormFile("uploadfile")
	if err != nil {
		log.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	rawFilename := "./test/" + handler.Filename

	defer file.Close()
	fmt.Fprintf(w, "%v", handler.Header)
	f, err := os.OpenFile(rawFilename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		log.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	io.Copy(f, file)
	f.Close()

	// Parse the CSR
	rawCSR, _ := ioutil.ReadFile(rawFilename)
	csr, err := x509.ParseCertificateRequest(rawCSR)
	if err != nil {
		log.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	log.Println("Received CSR for: " + csr.Subject.CommonName)
	// check authorization for the provided commonname
	// TODO ...

	// Build the command for exec
	// openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr
	app := "openssl"
	command := "ca"
	c_flag := "-config"
	c_value := "openssl-ca.cnf"
	p_flag := "-policy"
	p_value := "signing_policy"
	e_flag := "-extensions"
	e_value := "signing_req"
	o_flag := "-out"
	outputFile := "./test/" + handler.Filename + ".crt"
	i_flag := "-infiles"

	// Sign the CSR with OpenSSL
	cmd := exec.Command(app, command, c_flag, c_value, p_flag, p_value, e_flag, e_value, o_flag, outputFile, i_flag, rawFilename)
	stdout, err := cmd.Output()
	if err != nil {
		log.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Open the output file for reading and stream it back on the response
	w.Write(string(ioutil.ReadFile(outputFile)))
}
<|endoftext|>


<commit_before>package neoutils

import (
	"fmt"
	"net/http"
	"time"

	"github.com/jmcvetta/neoism"
)

type ConnectionConfig struct {
	// BatchSize controls how and whether to batch multiple requests to
	// CypherQuery into a single batch. BatchSize 0 disables this behaviour.
	// Values >0 indicate the largest preferred batch size.  Actual sizes
	// may be larger because values from a single call will never be split.
	BatchSize int
	// Transactional indicates that the connection should use the
	// transactional endpoints in the neo4j REST API.
	Transactional bool
	// Optionally a custom http.Client can be supplied
	HTTPClient *http.Client
}

func DefaultConnectionConfig() *ConnectionConfig {
	return &ConnectionConfig{
		BatchSize:     1024,
		Transactional: true,
		HTTPClient: &http.Client{
			Transport: &http.Transport{
				MaxIdleConnsPerHost: 100,
			},
			Timeout: 1 * time.Minute,
		},
	}
}

func Connect(neoURL string, conf *ConnectionConfig) (NeoConnection, error) {
	if conf == nil {
		conf = DefaultConnectionConfig()
	}

	db, err := neoism.Connect(neoURL)
	if err != nil {
		return nil, err
	}

	if conf.HTTPClient != nil {
		db.Session.Client = conf.HTTPClient
	}

	var cr CypherRunner = db
	if conf.Transactional {
		cr = TransactionalCypherRunner{db}
	} else {
		cr = db
	}

	if conf.BatchSize > 0 {
		cr = NewBatchCypherRunner(cr, conf.BatchSize)
	}

	ie := &defaultIndexEnsurer{db}

	return &DefaultNeoConnection{neoURL, cr, ie, db}, nil
}

type DefaultNeoConnection struct {
	dbURL string
	cr    CypherRunner
	ie    IndexEnsurer

	db *neoism.Database
}

func (c *DefaultNeoConnection) CypherBatch(cypher []*neoism.CypherQuery) error {
	return c.cr.CypherBatch(cypher)

}

func (c *DefaultNeoConnection) EnsureConstraints(constraints map[string]string) error {
	return c.ie.EnsureConstraints(constraints)
}

func (c *DefaultNeoConnection) EnsureIndexes(indexes map[string]string) error {
	return c.ie.EnsureIndexes(indexes)
}

func (c *DefaultNeoConnection) String() string {
	return fmt.Sprintf("DefaultNeoConnection(%s)", c.dbURL)
}

var _ NeoConnection = (*DefaultNeoConnection)(nil) //{}

type defaultIndexEnsurer struct {
	db *neoism.Database
}

func (ie *defaultIndexEnsurer) EnsureIndexes(indexes map[string]string) error {
	return EnsureIndexes(ie.db, indexes)
}

func (ie *defaultIndexEnsurer) EnsureConstraints(constraints map[string]string) error {
	return EnsureConstraints(ie.db, constraints)
}
<commit_msg>Add application identifier<commit_after>package neoutils

import (
	"fmt"
	"net/http"
	"time"

	"github.com/jmcvetta/neoism"
)

type ConnectionConfig struct {
	// BatchSize controls how and whether to batch multiple requests to
	// CypherQuery into a single batch. BatchSize 0 disables this behaviour.
	// Values >0 indicate the largest preferred batch size.  Actual sizes
	// may be larger because values from a single call will never be split.
	BatchSize int
	// Transactional indicates that the connection should use the
	// transactional endpoints in the neo4j REST API.
	Transactional bool
	// Optionally a custom http.Client can be supplied
	HTTPClient *http.Client
	// Optional application id, used for logging and as part of the user agent
	// in outgoing HTTP requests.
	ApplicationId string
}

func DefaultConnectionConfig() *ConnectionConfig {
	return &ConnectionConfig{
		BatchSize:     1024,
		Transactional: true,
		HTTPClient: &http.Client{
			Transport: &http.Transport{
				MaxIdleConnsPerHost: 100,
			},
			Timeout: 1 * time.Minute,
		},
	}
}

func Connect(neoURL string, conf *ConnectionConfig) (NeoConnection, error) {
	if conf == nil {
		conf = DefaultConnectionConfig()
	}

	db, err := neoism.Connect(neoURL)
	if err != nil {
		return nil, err
	}

	if conf.HTTPClient != nil {
		db.Session.Client = conf.HTTPClient
	}

	if conf.ApplicationId != "" {
		db.Session.Header.Set("User-Agent", conf.ApplicationId+" (via neoutils)")
	}

	var cr CypherRunner = db
	if conf.Transactional {
		cr = TransactionalCypherRunner{db}
	} else {
		cr = db
	}

	if conf.BatchSize > 0 {
		cr = NewBatchCypherRunner(cr, conf.BatchSize)
	}

	ie := &defaultIndexEnsurer{db}

	return &DefaultNeoConnection{neoURL, cr, ie, db}, nil
}

type DefaultNeoConnection struct {
	dbURL string
	cr    CypherRunner
	ie    IndexEnsurer

	db *neoism.Database
}

func (c *DefaultNeoConnection) CypherBatch(cypher []*neoism.CypherQuery) error {
	return c.cr.CypherBatch(cypher)

}

func (c *DefaultNeoConnection) EnsureConstraints(constraints map[string]string) error {
	return c.ie.EnsureConstraints(constraints)
}

func (c *DefaultNeoConnection) EnsureIndexes(indexes map[string]string) error {
	return c.ie.EnsureIndexes(indexes)
}

func (c *DefaultNeoConnection) String() string {
	return fmt.Sprintf("DefaultNeoConnection(%s)", c.dbURL)
}

var _ NeoConnection = (*DefaultNeoConnection)(nil) //{}

type defaultIndexEnsurer struct {
	db *neoism.Database
}

func (ie *defaultIndexEnsurer) EnsureIndexes(indexes map[string]string) error {
	return EnsureIndexes(ie.db, indexes)
}

func (ie *defaultIndexEnsurer) EnsureConstraints(constraints map[string]string) error {
	return EnsureConstraints(ie.db, constraints)
}
<|endoftext|>


<commit_before>// Copyright 2015 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package orm_test

import (
	"testing"

	"github.com/issue9/assert"

	"github.com/issue9/orm/v2/internal/test"
)

func TestDB_LastInsertID(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		t.NotError(t.DB.Create(&User{}))
		defer func() {
			t.NotError(t.DB.Drop(&User{}))
		}()

		id, err := t.DB.LastInsertID(&User{Username: "1"})
		t.NotError(err).
			Equal(id, 1)

		id, err = t.DB.LastInsertID(&User{Username: "2"})
		t.NotError(err).
			Equal(id, 2)
	})
}

func TestDB_Update(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// update
		r, err := t.DB.Update(&UserInfo{
			UID:       1,
			FirstName: "firstName1",
			LastName:  "lastName1",
			Sex:       "sex1",
		})
		a.NotError(err)
		cnt, err := r.RowsAffected()
		t.NotError(err).
			Equal(1, cnt)

		r, err = t.DB.Update(&UserInfo{
			UID:       2,
			FirstName: "firstName2",
			LastName:  "lastName2",
			Sex:       "sex2",
		})
		t.NotError(err)
		cnt, err = r.RowsAffected()
		a.NotError(err).
			Equal(1, cnt)

		u1 := &UserInfo{UID: 1}
		t.NotError(t.DB.Select(u1))
		t.Equal(u1, &UserInfo{UID: 1, FirstName: "firstName1", LastName: "lastName1", Sex: "sex1"})

		u2 := &UserInfo{LastName: "lastName2", FirstName: "firstName2"}
		t.NotError(t.DB.Select(u2))
		t.Equal(u2, &UserInfo{UID: 2, FirstName: "firstName2", LastName: "lastName2", Sex: "sex2"})
	})
}

func TestDB_Update_occ(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		r, err := t.DB.Insert(&Account{
			UID:     1,
			Account: 1,
		})
		t.NotError(err).NotNil(r)

		// 正常更新
		r, err = t.DB.Update(&Account{
			UID:     1,
			Account: 2,
			Version: 0, // 如果线上数据为 0，则能正常更新
		})
		t.NotError(err).NotNil(r)
		cnt, err := r.RowsAffected()
		t.NotError(err).Equal(1, cnt)

		r, err = t.DB.Update(&Account{
			UID:     1,
			Account: 2,
			Version: 1, // 更新一次之后，应该变为 1，则值为 1 时能正常更新。
		})
		t.NotError(err).NotNil(r)
		cnt, err = r.RowsAffected()
		t.NotError(err).Equal(1, cnt)

		r, err = t.DB.Update(&Account{
			UID:     1,
			Account: 2,
			Version: 1, // 多次更新之后，肯定不为 1，则此次更新失败
		})
		t.NotError(err).NotNil(r)
		cnt, err = r.RowsAffected()
		t.NotError(err).Equal(0, cnt)

		obj := &Account{UID: 1}
		obj.Account = 100
		t.NotError(t.DB.Select(obj))
		r, err = t.DB.Update(obj)
		t.NotError(err).NotNil(r)
		cnt, err = r.RowsAffected()
		t.NotError(err).Equal(1, cnt)
	})
}

func TestDB_Update_error(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// 非结构体传入
		r, err := t.DB.Update(123)
		t.Error(err, "%s@%s", err, t.DriverName).Nil(r)
	})
}

func TestDB_Delete(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// delete
		r, err := t.DB.Delete(&UserInfo{UID: 1})
		t.NotError(err)
		cnt, err := r.RowsAffected()
		t.NotError(err).
			Equal(cnt, 1)

		r, err = t.DB.Delete(
			&UserInfo{
				LastName:  "l2",
				FirstName: "f2",
			})
		t.NotError(err)
		cnt, err = r.RowsAffected()
		t.NotError(err).
			Equal(cnt, 1)

		r, err = t.DB.Delete(&Admin{Email: "email1"})
		t.NotError(err)
		cnt, err = r.RowsAffected()
		t.NotError(err).
			Equal(cnt, 1)

		hasCount(t.DB, t.Assertion, "user_info", 0)
		hasCount(t.DB, t.Assertion, "administrators", 0)

		// delete 并不会重置 ai 计数
		_, err = t.DB.Insert(&Admin{Group: 1, Email: "email1"})
		t.NotError(err)
		a1 := &Admin{Email: "email1"}
		t.NotError(t.DB.Select(a1))
		t.Equal(a1.ID, 2) // a1.ID为一个自增列,不会在delete中被重置
	})
}

func TestDB_Count(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// 单条件
		count, err := t.DB.Count(
			&UserInfo{
				UID: 1,
			},
		)
		t.NotError(err).
			Equal(1, count)

		// 无条件
		count, err = t.DB.Count(&UserInfo{})
		t.NotError(err).
			Equal(2, count)

		// 条件不存在
		count, err = t.DB.Count(
			&Admin{Email: "email1-1000"}, // 该条件不存在
		)
		t.NotError(err).
			Equal(0, count)
	})
}

func TestDB_Truncate(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		hasCount(t.DB, t.Assertion, "administrators", 1)

		// truncate 之后，会重置 AI
		t.NotError(t.DB.Truncate(&Admin{}))
		hasCount(t.DB, t.Assertion, "administrators", 0)

		_, err := t.DB.Insert(&Admin{Group: 1, Email: "email1", User: User{Username: "u1"}})
		t.NotError(err)
		_, err = t.DB.Insert(&Admin{Group: 1, Email: "email2", User: User{Username: "u2"}})
		t.NotError(err)

		a1 := &Admin{Email: "email1"}
		t.NotError(t.DB.Select(a1))
		t.Equal(1, a1.ID)

		a2 := &Admin{Email: "email2"}
		t.NotError(t.DB.Select(a2))
		t.Equal(2, a2.ID)
	})
}

func TestDB_Drop(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		t.NotError(t.DB.Drop(&UserInfo{}))
		t.NotError(t.DB.Drop(&Admin{}))
		r, err := t.DB.Insert(&Admin{})
		t.Error(err).Nil(r)
	})
}

func TestDB_Version(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		v, err := t.DB.Version()
		t.NotError(err).
			NotEmpty(v)
	})
}
<commit_msg>添加插入空对象的测试<commit_after>// Copyright 2015 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package orm_test

import (
	"testing"

	"github.com/issue9/assert"

	"github.com/issue9/orm/v2/internal/test"
)

func TestDB_LastInsertID(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		t.NotError(t.DB.Create(&User{}))
		defer func() {
			t.NotError(t.DB.Drop(&User{}))
		}()

		id, err := t.DB.LastInsertID(&User{Username: "1"})
		t.NotError(err).
			Equal(id, 1)

		id, err = t.DB.LastInsertID(&User{Username: "2"})
		t.NotError(err).
			Equal(id, 2)
	})
}

func TestDB_InsertDefaultValues(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	type user struct {
		Name string `orm:"name(name);nullable"`
		Age  int    `orm:"name(age);default(-1)"`
	}

	suite.ForEach(func(d *test.Driver) {
		d.NotError(d.DB.Create(&user{}))
		defer func() {
			d.NotError(d.DB.Drop(&user{}))
		}()

		a.NotError(d.DB.Insert(&user{}))
		hasCount(d.DB, a, "user", 1)

		a.NotError(d.DB.Insert(&user{}))
		hasCount(d.DB, a, "user", 2)
	})
}

func TestDB_Update(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// update
		r, err := t.DB.Update(&UserInfo{
			UID:       1,
			FirstName: "firstName1",
			LastName:  "lastName1",
			Sex:       "sex1",
		})
		a.NotError(err)
		cnt, err := r.RowsAffected()
		t.NotError(err).
			Equal(1, cnt)

		r, err = t.DB.Update(&UserInfo{
			UID:       2,
			FirstName: "firstName2",
			LastName:  "lastName2",
			Sex:       "sex2",
		})
		t.NotError(err)
		cnt, err = r.RowsAffected()
		a.NotError(err).
			Equal(1, cnt)

		u1 := &UserInfo{UID: 1}
		t.NotError(t.DB.Select(u1))
		t.Equal(u1, &UserInfo{UID: 1, FirstName: "firstName1", LastName: "lastName1", Sex: "sex1"})

		u2 := &UserInfo{LastName: "lastName2", FirstName: "firstName2"}
		t.NotError(t.DB.Select(u2))
		t.Equal(u2, &UserInfo{UID: 2, FirstName: "firstName2", LastName: "lastName2", Sex: "sex2"})
	})
}

func TestDB_Update_occ(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		r, err := t.DB.Insert(&Account{
			UID:     1,
			Account: 1,
		})
		t.NotError(err).NotNil(r)

		// 正常更新
		r, err = t.DB.Update(&Account{
			UID:     1,
			Account: 2,
			Version: 0, // 如果线上数据为 0，则能正常更新
		})
		t.NotError(err).NotNil(r)
		cnt, err := r.RowsAffected()
		t.NotError(err).Equal(1, cnt)

		r, err = t.DB.Update(&Account{
			UID:     1,
			Account: 2,
			Version: 1, // 更新一次之后，应该变为 1，则值为 1 时能正常更新。
		})
		t.NotError(err).NotNil(r)
		cnt, err = r.RowsAffected()
		t.NotError(err).Equal(1, cnt)

		r, err = t.DB.Update(&Account{
			UID:     1,
			Account: 2,
			Version: 1, // 多次更新之后，肯定不为 1，则此次更新失败
		})
		t.NotError(err).NotNil(r)
		cnt, err = r.RowsAffected()
		t.NotError(err).Equal(0, cnt)

		obj := &Account{UID: 1}
		obj.Account = 100
		t.NotError(t.DB.Select(obj))
		r, err = t.DB.Update(obj)
		t.NotError(err).NotNil(r)
		cnt, err = r.RowsAffected()
		t.NotError(err).Equal(1, cnt)
	})
}

func TestDB_Update_error(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// 非结构体传入
		r, err := t.DB.Update(123)
		t.Error(err, "%s@%s", err, t.DriverName).Nil(r)
	})
}

func TestDB_Delete(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// delete
		r, err := t.DB.Delete(&UserInfo{UID: 1})
		t.NotError(err)
		cnt, err := r.RowsAffected()
		t.NotError(err).
			Equal(cnt, 1)

		r, err = t.DB.Delete(
			&UserInfo{
				LastName:  "l2",
				FirstName: "f2",
			})
		t.NotError(err)
		cnt, err = r.RowsAffected()
		t.NotError(err).
			Equal(cnt, 1)

		r, err = t.DB.Delete(&Admin{Email: "email1"})
		t.NotError(err)
		cnt, err = r.RowsAffected()
		t.NotError(err).
			Equal(cnt, 1)

		hasCount(t.DB, t.Assertion, "user_info", 0)
		hasCount(t.DB, t.Assertion, "administrators", 0)

		// delete 并不会重置 ai 计数
		_, err = t.DB.Insert(&Admin{Group: 1, Email: "email1"})
		t.NotError(err)
		a1 := &Admin{Email: "email1"}
		t.NotError(t.DB.Select(a1))
		t.Equal(a1.ID, 2) // a1.ID为一个自增列,不会在delete中被重置
	})
}

func TestDB_Count(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		// 单条件
		count, err := t.DB.Count(
			&UserInfo{
				UID: 1,
			},
		)
		t.NotError(err).
			Equal(1, count)

		// 无条件
		count, err = t.DB.Count(&UserInfo{})
		t.NotError(err).
			Equal(2, count)

		// 条件不存在
		count, err = t.DB.Count(
			&Admin{Email: "email1-1000"}, // 该条件不存在
		)
		t.NotError(err).
			Equal(0, count)
	})
}

func TestDB_Truncate(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		hasCount(t.DB, t.Assertion, "administrators", 1)

		// truncate 之后，会重置 AI
		t.NotError(t.DB.Truncate(&Admin{}))
		hasCount(t.DB, t.Assertion, "administrators", 0)

		_, err := t.DB.Insert(&Admin{Group: 1, Email: "email1", User: User{Username: "u1"}})
		t.NotError(err)
		_, err = t.DB.Insert(&Admin{Group: 1, Email: "email2", User: User{Username: "u2"}})
		t.NotError(err)

		a1 := &Admin{Email: "email1"}
		t.NotError(t.DB.Select(a1))
		t.Equal(1, a1.ID)

		a2 := &Admin{Email: "email2"}
		t.NotError(t.DB.Select(a2))
		t.Equal(2, a2.ID)
	})
}

func TestDB_Drop(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		initData(t)
		defer clearData(t)

		t.NotError(t.DB.Drop(&UserInfo{}))
		t.NotError(t.DB.Drop(&Admin{}))
		r, err := t.DB.Insert(&Admin{})
		t.Error(err).Nil(r)
	})
}

func TestDB_Version(t *testing.T) {
	a := assert.New(t)
	suite := test.NewSuite(a)
	defer suite.Close()

	suite.ForEach(func(t *test.Driver) {
		v, err := t.DB.Version()
		t.NotError(err).
			NotEmpty(v)
	})
}
<|endoftext|>