<commit_before>package main

import (
	"errors"
	"os"
	"fmt"
	"flag"
	"path"
	"strings"
	"io/ioutil"
	"go/token"
	"go/scanner"
	stringslice "./slice"
)

func dieWith(e string) {
	fmt.Fprintln(os.Stderr, e)
	os.Exit(1)
}

var pname = flag.String("package-name", "NAME", "name of output package")
var prefix = flag.String("prefix", "NAME", "prefix for top-level functions")
var outname = flag.String("o", "GONAME", "name of output file")

func main() {
	flag.Parse()
	if len(flag.Args()) < 1 {
		fmt.Println(flag.Args())
		dieWith("gotgo requires at least one argument: the .got file")
	}
	if flag.Args()[0][len(flag.Args()[0])-4:] != ".got" {
		dieWith("the argument should end with .got")
	}
	var e error
	outf := os.Stdout
	if *outname != "GONAME" {
		dir,_ := path.Split(*outname)
		os.MkdirAll(dir, 0777)
		outf, e = os.OpenFile(*outname, os.O_WRONLY+os.O_CREATE+os.O_TRUNC,0666)
		if e != nil { dieWith(e.Error()) }
	}
	e = writeGotGotgo(flag.Args()[0], outf, flag.Args()[1:])
	if e != nil { dieWith(e.Error()) }
}

func writeGotGotgo(filename string, out *os.File, actualtypes []string) (e error) {
	fileset := token.NewFileSet()
	fileInfo, err := os.Stat(filename)
	file := fileset.AddFile(filename, 0, int(fileInfo.Size()))
	x, e := ioutil.ReadFile(filename)
	if e != nil { return }
	var scan scanner.Scanner
	scan.Init(file, x, nil, 0)
	tok := token.COMMA // anything but EOF or PACKAGE
	for tok != token.EOF && tok != token.PACKAGE {
		_, tok, _ = scan.Scan()
	}
	if tok == token.EOF { return errors.New("Unexpected EOF...") }
	_, tok, gotpname := scan.Scan()
	if tok != token.IDENT {
		return errors.New("Expected package ident, not "+string(gotpname))
	}
	if *pname == "NAME" {
		*pname = string(gotpname)
	}
	if *prefix == "NAME" {
		*prefix = ""
	}
	_, tok, lit := scan.Scan()
	if tok != token.LPAREN {
		return errors.New("Expected (, not "+string(lit))
	}
	params, types, restpos, e := getTypes(&scan)
	if e != nil { return }
	vartypes := make(map[string]string)
	imports := []string{}
	for i,t := range types {
		if i < len(actualtypes) {
			if dot := strings.LastIndex(actualtypes[i], "."); dot != -1 {
				// We've got to add an import!
				imports = stringslice.Append(imports,
					"import " + params[i] + ` "` + actualtypes[i][0:dot]+`"`)
				vartypes[params[i]] = params[i]+actualtypes[i][dot:]
			} else {
				vartypes[params[i]] = actualtypes[i]
			}
		} else {
			if t == params[0] {
				vartypes[params[i]] = vartypes[params[0]]
			} else {
				vartypes[params[i]] = t
			}
		}
	}
	lastpos := restpos.Offset+1
	// Now let's write the package file...
	fmt.Fprintf(out, "package %s\n\n", *pname)
	for _,imp := range imports {
		// These are extra imports for data types...
		fmt.Fprintf(out, "%s\n", imp)
	}
	pos,tok,lit := scan.Scan();
	for tok != token.EOF {
		if t,ok := vartypes[string(lit)]; ok {
			fmt.Fprint(out, string(x[lastpos:pos.Offset]))
			fmt.Fprint(out, t)
			lastpos = pos.Offset + len(lit)
		}
		newpos,newtok,newlit := scan.Scan()
		if string(lit) == string(gotpname) && newtok == token.PERIOD {
			fmt.Fprint(out, string(x[lastpos:pos.Offset]))
			fmt.Fprint(out, *prefix)
			lastpos = newpos.Offset + len(newlit)
			pos,tok,lit = scan.Scan()
		} else {
			pos, tok, lit = newpos, newtok, newlit
		}
	}
	fmt.Fprintf(out, string(x[lastpos:]))

	fmt.Fprintf(out,`
// Here we will test that the types parameters are ok...
func %stestTypes(arg0 %s`, *prefix, vartypes[params[0]])
	for i,p := range params[1:] {
		t := vartypes[p]
		if t == params[0] { t = vartypes[params[0]] }
		fmt.Fprintf(out, `, arg%d %s`, i+1, t)
	}
	fmt.Fprintf(out, `) {
    f := func(%s`, types[0])
	for _,t := range types[1:] {
		if t == params[0] { t = types[0] }
		fmt.Fprintf(out, `, %s`, t)
	}
  fmt.Fprint(out, ") { } // this func does nothing...")
	convert := func(t string, argnum int) string {
		arg := "arg" + fmt.Sprint(argnum)
		if strings.Index(t, "{") == -1 {
			return t+"("+arg+")"
		}
		return arg  // it's an interface, so we needn't convert
	}
	fmt.Fprintf(out, `
    f(%s`, convert(types[0], 0))
	for i,t := range types[1:] {
		if t == params[0] { t = types[0] }
		fmt.Fprintf(out, `, %s`, convert(t, i+1))
	}
	fmt.Fprint(out, `)
}
`)
	return
}

func getTypes(s *scanner.Scanner) (params []string, types []string, pos token.Position, error error) {
	tok := token.COMMA
	var lit []byte
	for tok == token.COMMA {
		pos, tok,lit = s.Scan()
		if tok != token.TYPE {
			error = errors.New("Expected 'type', not "+string(lit))
			return
		}
		var tname string
		var par []byte
		pos, tok,par = s.Scan()
		if tok != token.IDENT {
			error = errors.New("Identifier expected, not "+string(par))
			return
		}
		tname,pos,tok,lit = getType(s)
		params = stringslice.Append(params, string(par))
		types = stringslice.Append(types, string(tname))
	}
	if tok != token.RPAREN {
		error = errors.New(fmt.Sprintf("inappropriate token %v with lit: %s",
			tok, lit))
	}
	return
}

func getType(s *scanner.Scanner) (t string, pos token.Position, tok token.Token, lit []byte)  {
	pos, tok, lit = s.Scan()
	for tok != token.RPAREN && tok != token.COMMA {
		t += string(lit)
		pos, tok, lit = s.Scan()
	}
	if t == "" { t = "interface{}" }
	return
}
<commit_msg>go fmt<commit_after>package main

import (
	stringslice "./slice"
	"errors"
	"flag"
	"fmt"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path"
	"strings"
)

func dieWith(e string) {
	fmt.Fprintln(os.Stderr, e)
	os.Exit(1)
}

var pname = flag.String("package-name", "NAME", "name of output package")
var prefix = flag.String("prefix", "NAME", "prefix for top-level functions")
var outname = flag.String("o", "GONAME", "name of output file")

func main() {
	flag.Parse()
	if len(flag.Args()) < 1 {
		fmt.Println(flag.Args())
		dieWith("gotgo requires at least one argument: the .got file")
	}
	if flag.Args()[0][len(flag.Args()[0])-4:] != ".got" {
		dieWith("the argument should end with .got")
	}
	var e error
	outf := os.Stdout
	if *outname != "GONAME" {
		dir, _ := path.Split(*outname)
		os.MkdirAll(dir, 0777)
		outf, e = os.OpenFile(*outname, os.O_WRONLY+os.O_CREATE+os.O_TRUNC, 0666)
		if e != nil {
			dieWith(e.Error())
		}
	}
	e = writeGotGotgo(flag.Args()[0], outf, flag.Args()[1:])
	if e != nil {
		dieWith(e.Error())
	}
}

func writeGotGotgo(filename string, out *os.File, actualtypes []string) (e error) {
	fileset := token.NewFileSet()
	fileInfo, err := os.Stat(filename)
	file := fileset.AddFile(filename, 0, int(fileInfo.Size()))
	x, e := ioutil.ReadFile(filename)
	if e != nil {
		return
	}
	var scan scanner.Scanner
	scan.Init(file, x, nil, 0)
	tok := token.COMMA // anything but EOF or PACKAGE
	for tok != token.EOF && tok != token.PACKAGE {
		_, tok, _ = scan.Scan()
	}
	if tok == token.EOF {
		return errors.New("Unexpected EOF...")
	}
	_, tok, gotpname := scan.Scan()
	if tok != token.IDENT {
		return errors.New("Expected package ident, not " + string(gotpname))
	}
	if *pname == "NAME" {
		*pname = string(gotpname)
	}
	if *prefix == "NAME" {
		*prefix = ""
	}
	_, tok, lit := scan.Scan()
	if tok != token.LPAREN {
		return errors.New("Expected (, not " + string(lit))
	}
	params, types, restpos, e := getTypes(&scan)
	if e != nil {
		return
	}
	vartypes := make(map[string]string)
	imports := []string{}
	for i, t := range types {
		if i < len(actualtypes) {
			if dot := strings.LastIndex(actualtypes[i], "."); dot != -1 {
				// We've got to add an import!
				imports = stringslice.Append(imports,
					"import "+params[i]+` "`+actualtypes[i][0:dot]+`"`)
				vartypes[params[i]] = params[i] + actualtypes[i][dot:]
			} else {
				vartypes[params[i]] = actualtypes[i]
			}
		} else {
			if t == params[0] {
				vartypes[params[i]] = vartypes[params[0]]
			} else {
				vartypes[params[i]] = t
			}
		}
	}
	lastpos := restpos.Offset + 1
	// Now let's write the package file...
	fmt.Fprintf(out, "package %s\n\n", *pname)
	for _, imp := range imports {
		// These are extra imports for data types...
		fmt.Fprintf(out, "%s\n", imp)
	}
	pos, tok, lit := scan.Scan()
	for tok != token.EOF {
		if t, ok := vartypes[string(lit)]; ok {
			fmt.Fprint(out, string(x[lastpos:pos.Offset]))
			fmt.Fprint(out, t)
			lastpos = pos.Offset + len(lit)
		}
		newpos, newtok, newlit := scan.Scan()
		if string(lit) == string(gotpname) && newtok == token.PERIOD {
			fmt.Fprint(out, string(x[lastpos:pos.Offset]))
			fmt.Fprint(out, *prefix)
			lastpos = newpos.Offset + len(newlit)
			pos, tok, lit = scan.Scan()
		} else {
			pos, tok, lit = newpos, newtok, newlit
		}
	}
	fmt.Fprintf(out, string(x[lastpos:]))

	fmt.Fprintf(out, `
// Here we will test that the types parameters are ok...
func %stestTypes(arg0 %s`, *prefix, vartypes[params[0]])
	for i, p := range params[1:] {
		t := vartypes[p]
		if t == params[0] {
			t = vartypes[params[0]]
		}
		fmt.Fprintf(out, `, arg%d %s`, i+1, t)
	}
	fmt.Fprintf(out, `) {
    f := func(%s`, types[0])
	for _, t := range types[1:] {
		if t == params[0] {
			t = types[0]
		}
		fmt.Fprintf(out, `, %s`, t)
	}
	fmt.Fprint(out, ") { } // this func does nothing...")
	convert := func(t string, argnum int) string {
		arg := "arg" + fmt.Sprint(argnum)
		if strings.Index(t, "{") == -1 {
			return t + "(" + arg + ")"
		}
		return arg // it's an interface, so we needn't convert
	}
	fmt.Fprintf(out, `
    f(%s`, convert(types[0], 0))
	for i, t := range types[1:] {
		if t == params[0] {
			t = types[0]
		}
		fmt.Fprintf(out, `, %s`, convert(t, i+1))
	}
	fmt.Fprint(out, `)
}
`)
	return
}

func getTypes(s *scanner.Scanner) (params []string, types []string, pos token.Position, error error) {
	tok := token.COMMA
	var lit []byte
	for tok == token.COMMA {
		pos, tok, lit = s.Scan()
		if tok != token.TYPE {
			error = errors.New("Expected 'type', not " + string(lit))
			return
		}
		var tname string
		var par []byte
		pos, tok, par = s.Scan()
		if tok != token.IDENT {
			error = errors.New("Identifier expected, not " + string(par))
			return
		}
		tname, pos, tok, lit = getType(s)
		params = stringslice.Append(params, string(par))
		types = stringslice.Append(types, string(tname))
	}
	if tok != token.RPAREN {
		error = errors.New(fmt.Sprintf("inappropriate token %v with lit: %s",
			tok, lit))
	}
	return
}

func getType(s *scanner.Scanner) (t string, pos token.Position, tok token.Token, lit []byte) {
	pos, tok, lit = s.Scan()
	for tok != token.RPAREN && tok != token.COMMA {
		t += string(lit)
		pos, tok, lit = s.Scan()
	}
	if t == "" {
		t = "interface{}"
	}
	return
}
<|endoftext|>


<commit_before>package shikaku

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

type ShikakuMap struct {
	Width       int
	Height      int
	XPos        int
	YPos        int
	SubMaps     []*ShikakuMap
	BusyGrid    [][]int
	NumbersGrid [][]int
	RandXPos    int
	RandYPos    int
}

func NewShikakuMap(width, height, xpos, ypos int) *ShikakuMap {
	sMap := ShikakuMap{
		Width:    width,
		Height:   height,
		XPos:     xpos,
		YPos:     ypos,
		RandXPos: rand.Intn(width),
		RandYPos: rand.Intn(height),
	}
	sMap.Reset()
	return &sMap
}

func (m *ShikakuMap) Reset() {
	m.SubMaps = make([]*ShikakuMap, 0)
	m.BusyGrid = make([][]int, m.Height)
	m.NumbersGrid = make([][]int, m.Height)
	for i := 0; i < m.Height; i++ {
		m.BusyGrid[i] = make([]int, m.Width)
		m.NumbersGrid[i] = make([]int, m.Width)
	}
}

func (m *ShikakuMap) GenerateBlocks(amount int) error {
	// first try to place N blocks
	for generateAttempt := 0; generateAttempt < 1000; generateAttempt++ {
		hasError := false
		for i := 0; i < amount; i++ {
			addSucceed := false
			for addAttempt := 0; addAttempt < 10; addAttempt++ {
				width := 1
				height := 1
				xPos := rand.Intn(m.Width)
				yPos := rand.Intn(m.Height)

				block := NewShikakuMap(width, height, xPos, yPos)
				block = block.Grow()
				if m.BlockFits(block) {
					if err := m.AddBlock(block); err != nil {
						panic(err)
					}
					addSucceed = true
					break
				}
			}
			if !addSucceed {
				hasError = true
				break
			}
		}
		if !hasError {
			// grow the existing blocks
			for i := 0; i < 1000; i++ {
				idx := rand.Intn(amount)
				if err := m.TryToGrowBlock(idx); err == nil {
					if m.AvailableSlots() == 0 {
						return nil
					}
				}
			}
		}

		m.Reset()
	}

	return fmt.Errorf("Failed to generate a map within 1000 attempts")
}

func (m *ShikakuMap) RemoveBlock(blockIdx int) error {
	block := m.SubMaps[blockIdx]
	m.SubMaps = append(m.SubMaps[:blockIdx], m.SubMaps[blockIdx+1:]...)
	for y := 0; y < block.Height; y++ {
		for x := 0; x < block.Width; x++ {
			m.BusyGrid[y+block.YPos][x+block.XPos]--
		}
	}
	m.NumbersGrid[block.YPos+block.RandYPos][block.XPos+block.RandXPos] = 0
	return nil
}

func (m *ShikakuMap) TryToGrowBlock(blockIdx int) error {
	block := m.SubMaps[blockIdx]
	newBlock := block.Grow()
	if err := m.RemoveBlock(blockIdx); err != nil {
		return err
	}

	if m.BlockFits(newBlock) {
		m.AddBlock(newBlock)
		return nil
	}

	// add back the old block
	m.AddBlock(block)
	return fmt.Errorf("nothing changed")
}

func (m *ShikakuMap) AvailableSlots() int {
	available := 0
	for y := 0; y < m.Height; y++ {
		for x := 0; x < m.Width; x++ {
			if m.BusyGrid[y][x] == 0 {
				available++
			}
		}
	}
	return available
}

func (m *ShikakuMap) BlockFits(block *ShikakuMap) bool {
	if block.Size() < 2 {
		return false
	}

	if block.XPos < 0 || block.YPos < 0 {
		return false
	}
	if block.XPos+block.Width > m.Width || block.YPos+block.Height > m.Height {
		return false
	}
	for y := 0; y < block.Height; y++ {
		for x := 0; x < block.Width; x++ {
			if m.BusyGrid[block.YPos+y][block.XPos+x] > 0 {
				return false
			}
		}
	}
	return true
}

func (m *ShikakuMap) Grow() *ShikakuMap {
	biggerMap := NewShikakuMap(m.Width, m.Height, m.XPos, m.YPos)
	switch rand.Intn(4) {
	case 0:
		biggerMap.Width++
	case 1:
		biggerMap.XPos--
	case 2:
		biggerMap.Height++
	case 3:
		biggerMap.YPos--
	}
	return biggerMap
}

func (m *ShikakuMap) AddBlock(block *ShikakuMap) error {
	if !m.BlockFits(block) {
		return fmt.Errorf("The block does not fit in the current map")
	}
	m.SubMaps = append(m.SubMaps, block)
	for y := 0; y < block.Height; y++ {
		for x := 0; x < block.Width; x++ {
			m.BusyGrid[y+block.YPos][x+block.XPos]++
			m.NumbersGrid[block.YPos+block.RandYPos][block.XPos+block.RandXPos] = block.Size()
		}
	}
	return nil
}

func (m *ShikakuMap) Size() int {
	return m.Width * m.Height
}

func (m *ShikakuMap) Blocks() []*ShikakuMap {
	blocks := []*ShikakuMap{}

	if len(m.SubMaps) > 0 {
		for _, subMap := range m.SubMaps {
			blocks = append(blocks, subMap.Blocks()...)
		}
	} else {
		blocks = append(blocks, m)
	}
	return blocks
}

func (m *ShikakuMap) BlockDetailString() string {
	return fmt.Sprintf("%d %d-%d(%d) %d-%d(%d)", m.Size(), m.XPos, m.Width, m.XPos+m.RandXPos, m.YPos, m.Height, m.YPos+m.RandYPos)
}

func (m *ShikakuMap) BlockString() string {
	return fmt.Sprintf("%d %d %d", m.Size(), m.XPos+m.RandXPos, m.YPos+m.RandYPos)
}

func (m *ShikakuMap) String() string {
	lines := []string{
		fmt.Sprintf("T %d %d", m.Width, m.Height),
	}

	for _, block := range m.Blocks() {
		lines = append(lines, block.BlockString())
	}

	return strings.Join(lines, "\n")
}

func (m *ShikakuMap) DrawSolution() string {
	output := []string{}

	output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	for _, line := range m.NumbersGrid {
		lineOutput := "|"
		for _, col := range line {
			switch col {
			case 0:
				lineOutput += "    "
			default:
				lineOutput += fmt.Sprintf(" %-3d", col)
			}
		}
		output = append(output, fmt.Sprintf("%s|", lineOutput[:len(lineOutput)-1]))
		output = append(output, fmt.Sprintf("+%s", strings.Repeat("   +", m.Width)))
	}
	output[len(output)-1] = fmt.Sprintf("+%s", strings.Repeat("---+", m.Width))

	return strings.Join(output, "\n")
}

func (m *ShikakuMap) DrawEmptyAsciiMap() []string {
	output := []string{}

	output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	for i := 0; i < m.Height; i++ {
		output = append(output, fmt.Sprintf("+%s", strings.Repeat("   |", m.Width)))
		output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	}

	return output
}

func (m *ShikakuMap) GetBlockAtPos(x, y int) *ShikakuMap {
	for _, block := range m.Blocks() {
		if y >= block.YPos && y <= block.YPos+block.Height-1 {
			if x >= block.XPos && x <= block.XPos+block.Width-1 {
				return block
			}
		}
	}
	return nil
}

func (m *ShikakuMap) DrawMap() string {
	output := []string{}

	output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	for y := 0; y < m.Height; y++ {
		// a line: horizontal separators
		lineOutput := "|"
		for x := 0; x < m.Width; x++ {
			if x == m.Width-1 {
				lineOutput += "   |"
			} else {
				if m.GetBlockAtPos(x, y) == m.GetBlockAtPos(x+1, y) {
					lineOutput += "    "
				} else {
					lineOutput += "   |"
				}
			}
		}
		output = append(output, lineOutput)

		// vertical separators
		lineOutput = "+"
		for x := 0; x < m.Width; x++ {
			if y == m.Height-1 {
				lineOutput += "---+"
			} else {
				if m.GetBlockAtPos(x, y) == m.GetBlockAtPos(x, y+1) {
					lineOutput += "   +"
				} else {
					lineOutput += "---+"
				}
			}
		}
		output = append(output, lineOutput)
	}

	return strings.Join(output, "\n")
}
<commit_msg>Revert "Invert DrawMap and DrawSolution"<commit_after>package shikaku

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

type ShikakuMap struct {
	Width       int
	Height      int
	XPos        int
	YPos        int
	SubMaps     []*ShikakuMap
	BusyGrid    [][]int
	NumbersGrid [][]int
	RandXPos    int
	RandYPos    int
}

func NewShikakuMap(width, height, xpos, ypos int) *ShikakuMap {
	sMap := ShikakuMap{
		Width:    width,
		Height:   height,
		XPos:     xpos,
		YPos:     ypos,
		RandXPos: rand.Intn(width),
		RandYPos: rand.Intn(height),
	}
	sMap.Reset()
	return &sMap
}

func (m *ShikakuMap) Reset() {
	m.SubMaps = make([]*ShikakuMap, 0)
	m.BusyGrid = make([][]int, m.Height)
	m.NumbersGrid = make([][]int, m.Height)
	for i := 0; i < m.Height; i++ {
		m.BusyGrid[i] = make([]int, m.Width)
		m.NumbersGrid[i] = make([]int, m.Width)
	}
}

func (m *ShikakuMap) GenerateBlocks(amount int) error {
	// first try to place N blocks
	for generateAttempt := 0; generateAttempt < 1000; generateAttempt++ {
		hasError := false
		for i := 0; i < amount; i++ {
			addSucceed := false
			for addAttempt := 0; addAttempt < 10; addAttempt++ {
				width := 1
				height := 1
				xPos := rand.Intn(m.Width)
				yPos := rand.Intn(m.Height)

				block := NewShikakuMap(width, height, xPos, yPos)
				block = block.Grow()
				if m.BlockFits(block) {
					if err := m.AddBlock(block); err != nil {
						panic(err)
					}
					addSucceed = true
					break
				}
			}
			if !addSucceed {
				hasError = true
				break
			}
		}
		if !hasError {
			// grow the existing blocks
			for i := 0; i < 1000; i++ {
				idx := rand.Intn(amount)
				if err := m.TryToGrowBlock(idx); err == nil {
					if m.AvailableSlots() == 0 {
						return nil
					}
				}
			}
		}

		m.Reset()
	}

	return fmt.Errorf("Failed to generate a map within 1000 attempts")
}

func (m *ShikakuMap) RemoveBlock(blockIdx int) error {
	block := m.SubMaps[blockIdx]
	m.SubMaps = append(m.SubMaps[:blockIdx], m.SubMaps[blockIdx+1:]...)
	for y := 0; y < block.Height; y++ {
		for x := 0; x < block.Width; x++ {
			m.BusyGrid[y+block.YPos][x+block.XPos]--
		}
	}
	m.NumbersGrid[block.YPos+block.RandYPos][block.XPos+block.RandXPos] = 0
	return nil
}

func (m *ShikakuMap) TryToGrowBlock(blockIdx int) error {
	block := m.SubMaps[blockIdx]
	newBlock := block.Grow()
	if err := m.RemoveBlock(blockIdx); err != nil {
		return err
	}

	if m.BlockFits(newBlock) {
		m.AddBlock(newBlock)
		return nil
	}

	// add back the old block
	m.AddBlock(block)
	return fmt.Errorf("nothing changed")
}

func (m *ShikakuMap) AvailableSlots() int {
	available := 0
	for y := 0; y < m.Height; y++ {
		for x := 0; x < m.Width; x++ {
			if m.BusyGrid[y][x] == 0 {
				available++
			}
		}
	}
	return available
}

func (m *ShikakuMap) BlockFits(block *ShikakuMap) bool {
	if block.Size() < 2 {
		return false
	}

	if block.XPos < 0 || block.YPos < 0 {
		return false
	}
	if block.XPos+block.Width > m.Width || block.YPos+block.Height > m.Height {
		return false
	}
	for y := 0; y < block.Height; y++ {
		for x := 0; x < block.Width; x++ {
			if m.BusyGrid[block.YPos+y][block.XPos+x] > 0 {
				return false
			}
		}
	}
	return true
}

func (m *ShikakuMap) Grow() *ShikakuMap {
	biggerMap := NewShikakuMap(m.Width, m.Height, m.XPos, m.YPos)
	switch rand.Intn(4) {
	case 0:
		biggerMap.Width++
	case 1:
		biggerMap.XPos--
	case 2:
		biggerMap.Height++
	case 3:
		biggerMap.YPos--
	}
	return biggerMap
}

func (m *ShikakuMap) AddBlock(block *ShikakuMap) error {
	if !m.BlockFits(block) {
		return fmt.Errorf("The block does not fit in the current map")
	}
	m.SubMaps = append(m.SubMaps, block)
	for y := 0; y < block.Height; y++ {
		for x := 0; x < block.Width; x++ {
			m.BusyGrid[y+block.YPos][x+block.XPos]++
			m.NumbersGrid[block.YPos+block.RandYPos][block.XPos+block.RandXPos] = block.Size()
		}
	}
	return nil
}

func (m *ShikakuMap) Size() int {
	return m.Width * m.Height
}

func (m *ShikakuMap) Blocks() []*ShikakuMap {
	blocks := []*ShikakuMap{}

	if len(m.SubMaps) > 0 {
		for _, subMap := range m.SubMaps {
			blocks = append(blocks, subMap.Blocks()...)
		}
	} else {
		blocks = append(blocks, m)
	}
	return blocks
}

func (m *ShikakuMap) BlockDetailString() string {
	return fmt.Sprintf("%d %d-%d(%d) %d-%d(%d)", m.Size(), m.XPos, m.Width, m.XPos+m.RandXPos, m.YPos, m.Height, m.YPos+m.RandYPos)
}

func (m *ShikakuMap) BlockString() string {
	return fmt.Sprintf("%d %d %d", m.Size(), m.XPos+m.RandXPos, m.YPos+m.RandYPos)
}

func (m *ShikakuMap) String() string {
	lines := []string{
		fmt.Sprintf("T %d %d", m.Width, m.Height),
	}

	for _, block := range m.Blocks() {
		lines = append(lines, block.BlockString())
	}

	return strings.Join(lines, "\n")
}

func (m *ShikakuMap) DrawMap() string {
	output := []string{}

	output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	for _, line := range m.NumbersGrid {
		lineOutput := "|"
		for _, col := range line {
			switch col {
			case 0:
				lineOutput += "    "
			default:
				lineOutput += fmt.Sprintf(" %-3d", col)
			}
		}
		output = append(output, fmt.Sprintf("%s|", lineOutput[:len(lineOutput)-1]))
		output = append(output, fmt.Sprintf("+%s", strings.Repeat("   +", m.Width)))
	}
	output[len(output)-1] = fmt.Sprintf("+%s", strings.Repeat("---+", m.Width))

	return strings.Join(output, "\n")
}

func (m *ShikakuMap) DrawEmptyAsciiMap() []string {
	output := []string{}

	output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	for i := 0; i < m.Height; i++ {
		output = append(output, fmt.Sprintf("+%s", strings.Repeat("   |", m.Width)))
		output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	}

	return output
}

func (m *ShikakuMap) GetBlockAtPos(x, y int) *ShikakuMap {
	for _, block := range m.Blocks() {
		if y >= block.YPos && y <= block.YPos+block.Height-1 {
			if x >= block.XPos && x <= block.XPos+block.Width-1 {
				return block
			}
		}
	}
	return nil
}

func (m *ShikakuMap) DrawSolution() string {
	output := []string{}

	output = append(output, fmt.Sprintf("+%s", strings.Repeat("---+", m.Width)))
	for y := 0; y < m.Height; y++ {
		// a line: horizontal separators
		lineOutput := "|"
		for x := 0; x < m.Width; x++ {
			if x == m.Width-1 {
				lineOutput += "   |"
			} else {
				if m.GetBlockAtPos(x, y) == m.GetBlockAtPos(x+1, y) {
					lineOutput += "    "
				} else {
					lineOutput += "   |"
				}
			}
		}
		output = append(output, lineOutput)

		// vertical separators
		lineOutput = "+"
		for x := 0; x < m.Width; x++ {
			if y == m.Height-1 {
				lineOutput += "---+"
			} else {
				if m.GetBlockAtPos(x, y) == m.GetBlockAtPos(x, y+1) {
					lineOutput += "   +"
				} else {
					lineOutput += "---+"
				}
			}
		}
		output = append(output, lineOutput)
	}

	return strings.Join(output, "\n")
}
<|endoftext|>


<commit_before>package util

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net"

	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/logger"
)

// InMemoryNetwork creates a fully in-memory listener and dial function.
//
// Each time the dial function is invoked a new pair of net.Conn objects will
// be created using net.Pipe: the listener's Accept method will unblock and
// return one end of the pipe and the other end will be returned by the dial
// function.
func InMemoryNetwork() (net.Listener, func() net.Conn) {
	listener := &inMemoryListener{
		conns:  make(chan net.Conn, 16),
		closed: make(chan struct{}),
	}
	dialer := func() net.Conn {
		server, client := net.Pipe()
		listener.conns <- server
		return client
	}
	return listener, dialer
}

type inMemoryListener struct {
	conns  chan net.Conn
	closed chan struct{}
}

// Accept waits for and returns the next connection to the listener.
func (l *inMemoryListener) Accept() (net.Conn, error) {
	select {
	case conn := <-l.conns:
		return conn, nil
	case <-l.closed:
		return nil, fmt.Errorf("closed")
	}
}

// Close closes the listener.
// Any blocked Accept operations will be unblocked and return errors.
func (l *inMemoryListener) Close() error {
	close(l.closed)
	return nil
}

// Addr returns the listener's network address.
func (l *inMemoryListener) Addr() net.Addr {
	return &inMemoryAddr{}
}

type inMemoryAddr struct {
}

func (a *inMemoryAddr) Network() string {
	return "memory"
}

func (a *inMemoryAddr) String() string {
	return ""
}

// CanonicalNetworkAddress parses the given network address and returns a string of the form "host:port",
// possibly filling it with the default port if it's missing.
func CanonicalNetworkAddress(address string) string {
	_, _, err := net.SplitHostPort(address)
	if err != nil {
		ip := net.ParseIP(address)
		if ip != nil {
			// If the input address is a bare IP address, then convert it to a proper listen address
			// using the canonical IP with default port and wrap IPv6 addresses in square brackets.
			address = net.JoinHostPort(ip.String(), fmt.Sprintf("%d", shared.DefaultPort))
		} else {
			// Otherwise assume this is either a host name or a partial address (e.g `[::]`) without
			// a port number, so append the default port.
			address = fmt.Sprintf("%s:%d", address, shared.DefaultPort)
		}
	}

	return address
}

// CanonicalNetworkAddressFromAddressAndPort returns a network address from separate address and port values.
// The address accepts values such as "[::]", "::" and "localhost".
func CanonicalNetworkAddressFromAddressAndPort(address string, port int) string {
	// Because we accept just the host part of an IPv6 listen address (e.g. `[::]`) don't use net.JoinHostPort.
	// If a bare IP address is supplied then CanonicalNetworkAddress will use net.JoinHostPort if needed.
	return CanonicalNetworkAddress(fmt.Sprintf("%s:%d", address, port))
}

// ServerTLSConfig returns a new server-side tls.Config generated from the give
// certificate info.
func ServerTLSConfig(cert *shared.CertInfo) *tls.Config {
	config := shared.InitTLSConfig()
	config.ClientAuth = tls.RequestClientCert
	config.Certificates = []tls.Certificate{cert.KeyPair()}
	config.NextProtos = []string{"h2"} // Required by gRPC

	if cert.CA() != nil {
		pool := x509.NewCertPool()
		pool.AddCert(cert.CA())
		config.RootCAs = pool
		config.ClientCAs = pool

		logger.Infof("LXD is in CA mode, only CA-signed certificates will be allowed")
	}

	config.BuildNameToCertificate()
	return config
}

// NetworkInterfaceAddress returns the first global unicast address of any of the system network interfaces.
// Return the empty string if none is found.
func NetworkInterfaceAddress() string {
	ifaces, err := net.Interfaces()
	if err != nil {
		return ""
	}

	for _, iface := range ifaces {
		addrs, err := iface.Addrs()
		if err != nil {
			continue
		}

		if len(addrs) == 0 {
			continue
		}

		for _, addr := range addrs {
			ipNet, ok := addr.(*net.IPNet)
			if !ok {
				continue
			}

			if !ipNet.IP.IsGlobalUnicast() {
				continue
			}

			return ipNet.IP.String()
		}
	}

	return ""
}

// IsAddressCovered detects if network address1 is actually covered by
// address2, in the sense that they are either the same address or address2 is
// specified using a wildcard with the same port of address1.
func IsAddressCovered(address1, address2 string) bool {
	address1 = CanonicalNetworkAddress(address1)
	address2 = CanonicalNetworkAddress(address2)

	if address1 == address2 {
		return true
	}

	host1, port1, err := net.SplitHostPort(address1)
	if err != nil {
		return false
	}

	host2, port2, err := net.SplitHostPort(address2)
	if err != nil {
		return false
	}

	// If the ports are different, then address1 is clearly not covered by
	// address2.
	if port2 != port1 {
		return false
	}

	// If address1 contains a host name, let's try to resolve it, in order
	// to compare the actual IPs.
	var addresses1 []net.IP
	if host1 != "" {
		ip := net.ParseIP(host1)
		if ip != nil {
			addresses1 = append(addresses1, ip)
		} else {
			ips, err := net.LookupHost(host1)
			if err == nil && len(ips) > 0 {
				for _, ipStr := range ips {
					ip := net.ParseIP(ipStr)
					if ip != nil {
						addresses1 = append(addresses1, ip)
					}
				}
			}
		}
	}

	// If address2 contains a host name, let's try to resolve it, in order
	// to compare the actual IPs.
	var addresses2 []net.IP
	if host2 != "" {
		ip := net.ParseIP(host2)
		if ip != nil {
			addresses2 = append(addresses2, ip)
		} else {
			ips, err := net.LookupHost(host2)
			if err == nil && len(ips) > 0 {
				for _, ipStr := range ips {
					ip := net.ParseIP(ipStr)
					if ip != nil {
						addresses2 = append(addresses2, ip)
					}
				}
			}
		}
	}

	for _, a1 := range addresses1 {
		for _, a2 := range addresses2 {
			if a1.Equal(a2) {
				return true
			}
		}
	}

	// If address2 is using an IPv4 wildcard for the host, then address2 is
	// only covered if it's an IPv4 address.
	if host2 == "0.0.0.0" {
		ip1 := net.ParseIP(host1)
		if ip1 != nil && ip1.To4() != nil {
			return true
		}
		return false
	}

	// If address2 is using an IPv6 wildcard for the host, then address2 is
	// always covered.
	if host2 == "::" || host2 == "" {
		return true
	}

	return false
}

// IsWildCardAddress returns whether the given address is a wildcard.
func IsWildCardAddress(address string) bool {
	address = CanonicalNetworkAddress(address)

	host, _, err := net.SplitHostPort(address)
	if err != nil {
		return false
	}

	if host == "0.0.0.0" || host == "::" || host == "" {
		return true
	}

	return false
}

// SysctlGet retrieves the value of a sysctl file in /proc/sys.
func SysctlGet(path string) (string, error) {
	// Read the current content
	content, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/%s", path))
	if err != nil {
		return "", err
	}

	return string(content), nil
}

// SysctlSet writes a value to a sysctl file in /proc/sys.
// Requires an even number of arguments as key/value pairs. E.g. SysctlSet("path1", "value1", "path2", "value2")
func SysctlSet(parts ...string) error {
	partsLen := len(parts)
	if partsLen%2 != 0 {
		return fmt.Errorf("Requires even number of arguments")
	}

	for i := 0; i < partsLen; i = i + 2 {
		path := parts[i]
		newValue := parts[i+1]

		// Get current value.
		currentValue, err := SysctlGet(path)
		if err == nil && currentValue == newValue {
			// Nothing to update.
			return nil
		}

		err = ioutil.WriteFile(fmt.Sprintf("/proc/sys/%s", path), []byte(newValue), 0)
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>lxd/util/net: Improve comment in CanonicalNetworkAddress<commit_after>package util

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net"

	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/logger"
)

// InMemoryNetwork creates a fully in-memory listener and dial function.
//
// Each time the dial function is invoked a new pair of net.Conn objects will
// be created using net.Pipe: the listener's Accept method will unblock and
// return one end of the pipe and the other end will be returned by the dial
// function.
func InMemoryNetwork() (net.Listener, func() net.Conn) {
	listener := &inMemoryListener{
		conns:  make(chan net.Conn, 16),
		closed: make(chan struct{}),
	}
	dialer := func() net.Conn {
		server, client := net.Pipe()
		listener.conns <- server
		return client
	}
	return listener, dialer
}

type inMemoryListener struct {
	conns  chan net.Conn
	closed chan struct{}
}

// Accept waits for and returns the next connection to the listener.
func (l *inMemoryListener) Accept() (net.Conn, error) {
	select {
	case conn := <-l.conns:
		return conn, nil
	case <-l.closed:
		return nil, fmt.Errorf("closed")
	}
}

// Close closes the listener.
// Any blocked Accept operations will be unblocked and return errors.
func (l *inMemoryListener) Close() error {
	close(l.closed)
	return nil
}

// Addr returns the listener's network address.
func (l *inMemoryListener) Addr() net.Addr {
	return &inMemoryAddr{}
}

type inMemoryAddr struct {
}

func (a *inMemoryAddr) Network() string {
	return "memory"
}

func (a *inMemoryAddr) String() string {
	return ""
}

// CanonicalNetworkAddress parses the given network address and returns a string of the form "host:port",
// possibly filling it with the default port if it's missing. It will also wrap a bare IPv6 address with square
// brackets if needed.
func CanonicalNetworkAddress(address string) string {
	_, _, err := net.SplitHostPort(address)
	if err != nil {
		ip := net.ParseIP(address)
		if ip != nil {
			// If the input address is a bare IP address, then convert it to a proper listen address
			// using the canonical IP with default port and wrap IPv6 addresses in square brackets.
			address = net.JoinHostPort(ip.String(), fmt.Sprintf("%d", shared.DefaultPort))
		} else {
			// Otherwise assume this is either a host name or a partial address (e.g `[::]`) without
			// a port number, so append the default port.
			address = fmt.Sprintf("%s:%d", address, shared.DefaultPort)
		}
	}

	return address
}

// CanonicalNetworkAddressFromAddressAndPort returns a network address from separate address and port values.
// The address accepts values such as "[::]", "::" and "localhost".
func CanonicalNetworkAddressFromAddressAndPort(address string, port int) string {
	// Because we accept just the host part of an IPv6 listen address (e.g. `[::]`) don't use net.JoinHostPort.
	// If a bare IP address is supplied then CanonicalNetworkAddress will use net.JoinHostPort if needed.
	return CanonicalNetworkAddress(fmt.Sprintf("%s:%d", address, port))
}

// ServerTLSConfig returns a new server-side tls.Config generated from the give
// certificate info.
func ServerTLSConfig(cert *shared.CertInfo) *tls.Config {
	config := shared.InitTLSConfig()
	config.ClientAuth = tls.RequestClientCert
	config.Certificates = []tls.Certificate{cert.KeyPair()}
	config.NextProtos = []string{"h2"} // Required by gRPC

	if cert.CA() != nil {
		pool := x509.NewCertPool()
		pool.AddCert(cert.CA())
		config.RootCAs = pool
		config.ClientCAs = pool

		logger.Infof("LXD is in CA mode, only CA-signed certificates will be allowed")
	}

	config.BuildNameToCertificate()
	return config
}

// NetworkInterfaceAddress returns the first global unicast address of any of the system network interfaces.
// Return the empty string if none is found.
func NetworkInterfaceAddress() string {
	ifaces, err := net.Interfaces()
	if err != nil {
		return ""
	}

	for _, iface := range ifaces {
		addrs, err := iface.Addrs()
		if err != nil {
			continue
		}

		if len(addrs) == 0 {
			continue
		}

		for _, addr := range addrs {
			ipNet, ok := addr.(*net.IPNet)
			if !ok {
				continue
			}

			if !ipNet.IP.IsGlobalUnicast() {
				continue
			}

			return ipNet.IP.String()
		}
	}

	return ""
}

// IsAddressCovered detects if network address1 is actually covered by
// address2, in the sense that they are either the same address or address2 is
// specified using a wildcard with the same port of address1.
func IsAddressCovered(address1, address2 string) bool {
	address1 = CanonicalNetworkAddress(address1)
	address2 = CanonicalNetworkAddress(address2)

	if address1 == address2 {
		return true
	}

	host1, port1, err := net.SplitHostPort(address1)
	if err != nil {
		return false
	}

	host2, port2, err := net.SplitHostPort(address2)
	if err != nil {
		return false
	}

	// If the ports are different, then address1 is clearly not covered by
	// address2.
	if port2 != port1 {
		return false
	}

	// If address1 contains a host name, let's try to resolve it, in order
	// to compare the actual IPs.
	var addresses1 []net.IP
	if host1 != "" {
		ip := net.ParseIP(host1)
		if ip != nil {
			addresses1 = append(addresses1, ip)
		} else {
			ips, err := net.LookupHost(host1)
			if err == nil && len(ips) > 0 {
				for _, ipStr := range ips {
					ip := net.ParseIP(ipStr)
					if ip != nil {
						addresses1 = append(addresses1, ip)
					}
				}
			}
		}
	}

	// If address2 contains a host name, let's try to resolve it, in order
	// to compare the actual IPs.
	var addresses2 []net.IP
	if host2 != "" {
		ip := net.ParseIP(host2)
		if ip != nil {
			addresses2 = append(addresses2, ip)
		} else {
			ips, err := net.LookupHost(host2)
			if err == nil && len(ips) > 0 {
				for _, ipStr := range ips {
					ip := net.ParseIP(ipStr)
					if ip != nil {
						addresses2 = append(addresses2, ip)
					}
				}
			}
		}
	}

	for _, a1 := range addresses1 {
		for _, a2 := range addresses2 {
			if a1.Equal(a2) {
				return true
			}
		}
	}

	// If address2 is using an IPv4 wildcard for the host, then address2 is
	// only covered if it's an IPv4 address.
	if host2 == "0.0.0.0" {
		ip1 := net.ParseIP(host1)
		if ip1 != nil && ip1.To4() != nil {
			return true
		}
		return false
	}

	// If address2 is using an IPv6 wildcard for the host, then address2 is
	// always covered.
	if host2 == "::" || host2 == "" {
		return true
	}

	return false
}

// IsWildCardAddress returns whether the given address is a wildcard.
func IsWildCardAddress(address string) bool {
	address = CanonicalNetworkAddress(address)

	host, _, err := net.SplitHostPort(address)
	if err != nil {
		return false
	}

	if host == "0.0.0.0" || host == "::" || host == "" {
		return true
	}

	return false
}

// SysctlGet retrieves the value of a sysctl file in /proc/sys.
func SysctlGet(path string) (string, error) {
	// Read the current content
	content, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/%s", path))
	if err != nil {
		return "", err
	}

	return string(content), nil
}

// SysctlSet writes a value to a sysctl file in /proc/sys.
// Requires an even number of arguments as key/value pairs. E.g. SysctlSet("path1", "value1", "path2", "value2")
func SysctlSet(parts ...string) error {
	partsLen := len(parts)
	if partsLen%2 != 0 {
		return fmt.Errorf("Requires even number of arguments")
	}

	for i := 0; i < partsLen; i = i + 2 {
		path := parts[i]
		newValue := parts[i+1]

		// Get current value.
		currentValue, err := SysctlGet(path)
		if err == nil && currentValue == newValue {
			// Nothing to update.
			return nil
		}

		err = ioutil.WriteFile(fmt.Sprintf("/proc/sys/%s", path), []byte(newValue), 0)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>//go:build linux && cgo && !agent
// +build linux,cgo,!agent

package util

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	log "github.com/lxc/lxd/shared/log15"
	liblxc "gopkg.in/lxc/go-lxc.v2"

	"github.com/lxc/lxd/shared/idmap"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/osarch"
)

// GetArchitectures returns the list of supported architectures.
func GetArchitectures() ([]int, error) {
	architectures := []int{}

	architectureName, err := osarch.ArchitectureGetLocal()
	if err != nil {
		return nil, err
	}

	architecture, err := osarch.ArchitectureId(architectureName)
	if err != nil {
		return nil, err
	}
	architectures = append(architectures, architecture)

	personalities, err := osarch.ArchitecturePersonalities(architecture)
	if err != nil {
		return nil, err
	}
	for _, personality := range personalities {
		architectures = append(architectures, personality)
	}
	return architectures, nil
}

// GetIdmapSet reads the uid/gid allocation.
func GetIdmapSet() *idmap.IdmapSet {
	idmapSet, err := idmap.DefaultIdmapSet("", "")
	if err != nil {
		logger.Warn("Error reading default uid/gid map", log.Ctx{"err": err.Error()})
		logger.Warnf("Only privileged containers will be able to run")
		idmapSet = nil
	} else {
		kernelIdmapSet, err := idmap.CurrentIdmapSet()
		if err == nil {
			logger.Infof("Kernel uid/gid map:")
			for _, lxcmap := range kernelIdmapSet.ToLxcString() {
				logger.Infof(fmt.Sprintf(" - %s", lxcmap))
			}
		}

		if len(idmapSet.Idmap) == 0 {
			logger.Warnf("No available uid/gid map could be found")
			logger.Warnf("Only privileged containers will be able to run")
			idmapSet = nil
		} else {
			logger.Infof("Configured LXD uid/gid map:")
			for _, lxcmap := range idmapSet.Idmap {
				suffix := ""

				if lxcmap.Usable() != nil {
					suffix = " (unusable)"
				}

				for _, lxcEntry := range lxcmap.ToLxcString() {
					logger.Infof(" - %s%s", lxcEntry, suffix)
				}
			}

			err = idmapSet.Usable()
			if err != nil {
				logger.Warnf("One or more uid/gid map entry isn't usable (typically due to nesting)")
				logger.Warnf("Only privileged containers will be able to run")
				idmapSet = nil
			}
		}
	}
	return idmapSet
}

// RuntimeLiblxcVersionAtLeast checks if the system's liblxc matches the
// provided version requirement
func RuntimeLiblxcVersionAtLeast(major int, minor int, micro int) bool {
	version := liblxc.Version()
	version = strings.Replace(version, " (devel)", "-devel", 1)
	parts := strings.Split(version, ".")
	partsLen := len(parts)
	if partsLen == 0 {
		return false
	}

	develParts := strings.Split(parts[partsLen-1], "-")
	if len(develParts) == 2 && develParts[1] == "devel" {
		return true
	}

	maj := -1
	min := -1
	mic := -1

	for i, v := range parts {
		if i > 2 {
			break
		}

		num, err := strconv.Atoi(v)
		if err != nil {
			return false
		}

		switch i {
		case 0:
			maj = num
		case 1:
			min = num
		case 2:
			mic = num
		}
	}

	/* Major version is greater. */
	if maj > major {
		return true
	}

	if maj < major {
		return false
	}

	/* Minor number is greater.*/
	if min > minor {
		return true
	}

	if min < minor {
		return false
	}

	/* Patch number is greater. */
	if mic > micro {
		return true
	}

	if mic < micro {
		return false
	}

	return true
}

// GetExecPath returns the path to the current binary
func GetExecPath() string {
	execPath := os.Getenv("LXD_EXEC_PATH")
	if execPath != "" {
		return execPath
	}

	execPath, err := os.Readlink("/proc/self/exe")
	if err != nil {
		execPath = "bad-exec-path"
	}

	// The execPath from /proc/self/exe can end with " (deleted)" if the lxd binary has been removed/changed
	// since the lxd process was started, strip this so that we only return a valid path.
	return strings.TrimSuffix(execPath, " (deleted)")
}
<commit_msg>lxd/util/sys: add ReplaceDaemon<commit_after>//go:build linux && cgo && !agent
// +build linux,cgo,!agent

package util

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	log "github.com/lxc/lxd/shared/log15"
	"golang.org/x/sys/unix"
	liblxc "gopkg.in/lxc/go-lxc.v2"

	"github.com/lxc/lxd/shared/idmap"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/osarch"
)

// GetArchitectures returns the list of supported architectures.
func GetArchitectures() ([]int, error) {
	architectures := []int{}

	architectureName, err := osarch.ArchitectureGetLocal()
	if err != nil {
		return nil, err
	}

	architecture, err := osarch.ArchitectureId(architectureName)
	if err != nil {
		return nil, err
	}
	architectures = append(architectures, architecture)

	personalities, err := osarch.ArchitecturePersonalities(architecture)
	if err != nil {
		return nil, err
	}
	for _, personality := range personalities {
		architectures = append(architectures, personality)
	}
	return architectures, nil
}

// GetIdmapSet reads the uid/gid allocation.
func GetIdmapSet() *idmap.IdmapSet {
	idmapSet, err := idmap.DefaultIdmapSet("", "")
	if err != nil {
		logger.Warn("Error reading default uid/gid map", log.Ctx{"err": err.Error()})
		logger.Warnf("Only privileged containers will be able to run")
		idmapSet = nil
	} else {
		kernelIdmapSet, err := idmap.CurrentIdmapSet()
		if err == nil {
			logger.Infof("Kernel uid/gid map:")
			for _, lxcmap := range kernelIdmapSet.ToLxcString() {
				logger.Infof(fmt.Sprintf(" - %s", lxcmap))
			}
		}

		if len(idmapSet.Idmap) == 0 {
			logger.Warnf("No available uid/gid map could be found")
			logger.Warnf("Only privileged containers will be able to run")
			idmapSet = nil
		} else {
			logger.Infof("Configured LXD uid/gid map:")
			for _, lxcmap := range idmapSet.Idmap {
				suffix := ""

				if lxcmap.Usable() != nil {
					suffix = " (unusable)"
				}

				for _, lxcEntry := range lxcmap.ToLxcString() {
					logger.Infof(" - %s%s", lxcEntry, suffix)
				}
			}

			err = idmapSet.Usable()
			if err != nil {
				logger.Warnf("One or more uid/gid map entry isn't usable (typically due to nesting)")
				logger.Warnf("Only privileged containers will be able to run")
				idmapSet = nil
			}
		}
	}
	return idmapSet
}

// RuntimeLiblxcVersionAtLeast checks if the system's liblxc matches the
// provided version requirement
func RuntimeLiblxcVersionAtLeast(major int, minor int, micro int) bool {
	version := liblxc.Version()
	version = strings.Replace(version, " (devel)", "-devel", 1)
	parts := strings.Split(version, ".")
	partsLen := len(parts)
	if partsLen == 0 {
		return false
	}

	develParts := strings.Split(parts[partsLen-1], "-")
	if len(develParts) == 2 && develParts[1] == "devel" {
		return true
	}

	maj := -1
	min := -1
	mic := -1

	for i, v := range parts {
		if i > 2 {
			break
		}

		num, err := strconv.Atoi(v)
		if err != nil {
			return false
		}

		switch i {
		case 0:
			maj = num
		case 1:
			min = num
		case 2:
			mic = num
		}
	}

	/* Major version is greater. */
	if maj > major {
		return true
	}

	if maj < major {
		return false
	}

	/* Minor number is greater.*/
	if min > minor {
		return true
	}

	if min < minor {
		return false
	}

	/* Patch number is greater. */
	if mic > micro {
		return true
	}

	if mic < micro {
		return false
	}

	return true
}

// GetExecPath returns the path to the current binary
func GetExecPath() string {
	execPath := os.Getenv("LXD_EXEC_PATH")
	if execPath != "" {
		return execPath
	}

	execPath, err := os.Readlink("/proc/self/exe")
	if err != nil {
		execPath = "bad-exec-path"
	}

	// The execPath from /proc/self/exe can end with " (deleted)" if the lxd binary has been removed/changed
	// since the lxd process was started, strip this so that we only return a valid path.
	return strings.TrimSuffix(execPath, " (deleted)")
}

// ReplaceDaemon replaces the LXD process.
func ReplaceDaemon() error {
	err := unix.Exec(GetExecPath(), os.Args, os.Environ())
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package lzbase

// states defines the overall state count
const states = 12

// Value of the end of stream (EOS) marker.
const eosDist = 1<<32 - 1

// Dictionary abstracts the two concrete Dictionaries away.
type Dictionary interface {
	Byte(dist int64) byte
	Offset() int64
}

// State maintains the full state of the operation encoding process.
type State struct {
	Properties  Properties
	dict        Dictionary
	state       uint32
	posBitMask  uint32
	isMatch     [states << maxPosBits]prob
	isRep       [states]prob
	isRepG0     [states]prob
	isRepG1     [states]prob
	isRepG2     [states]prob
	isRepG0Long [states << maxPosBits]prob
	rep         [4]uint32
	litCodec    literalCodec
	lenCodec    lengthCodec
	repLenCodec lengthCodec
	distCodec   distCodec
}

// initProbSlice initializes a slice of probabilities.
func initProbSlice(p []prob) {
	for i := range p {
		p[i] = probInit
	}
}

// Reset sets all state information to the original values.
func (s *State) Reset() {
	lc, lp, pb := s.Properties.LC(), s.Properties.LP(), s.Properties.PB()
	*s = State{
		Properties: s.Properties,
		dict:       s.dict,
		posBitMask: (uint32(1) << uint(pb)) - 1,
	}
	initProbSlice(s.isMatch[:])
	initProbSlice(s.isRep[:])
	initProbSlice(s.isRepG0[:])
	initProbSlice(s.isRepG1[:])
	initProbSlice(s.isRepG2[:])
	initProbSlice(s.isRepG0Long[:])
	s.litCodec.init(lc, lp)
	s.lenCodec.init()
	s.repLenCodec.init()
	s.distCodec.init()
}

// NewState creates a new State instance
func NewState(p Properties, dict Dictionary) *State {
	s := new(State)
	s.Properties = p
	s.dict = dict
	s.Reset()
	return s
}

// updateStateLiteral updates the state for a literal.
func (s *State) updateStateLiteral() {
	switch {
	case s.state < 4:
		s.state = 0
		return
	case s.state < 10:
		s.state -= 3
		return
	}
	s.state -= 6
}

// updateStateMatch updates the state for a match.
func (s *State) updateStateMatch() {
	if s.state < 7 {
		s.state = 7
	} else {
		s.state = 10
	}
}

// updateStateRep updates the state for a repetition.
func (s *State) updateStateRep() {
	if s.state < 7 {
		s.state = 8
	} else {
		s.state = 11
	}
}

// updateStateShortRep updates the state for a short repetition.
func (s *State) updateStateShortRep() {
	if s.state < 7 {
		s.state = 9
	} else {
		s.state = 11
	}
}

// states computes the states of the operation codec.
func (s *State) states() (state, state2, posState uint32) {
	state = s.state
	posState = uint32(s.dict.Offset()) & s.posBitMask
	state2 = (s.state << maxPosBits) | posState
	return
}

// litState computes the literal state.
func (s *State) litState() uint32 {
	prevByte := s.dict.Byte(1)
	lp, lc := uint(s.Properties.LP()), uint(s.Properties.LC())
	litState := ((uint32(s.dict.Offset())) & ((1 << lp) - 1) << lc) |
		(uint32(prevByte) >> (8 - lc))
	return litState
}
<commit_msg>lzbase: provided WriterState and ReaderState<commit_after>package lzbase

// states defines the overall state count
const states = 12

// Value of the end of stream (EOS) marker.
const eosDist = 1<<32 - 1

// dictionary abstracts the two concrete Dictionaries away.
type dictionary interface {
	Byte(dist int64) byte
	Offset() int64
}

// state maintains the full state of the operation encoding process.
type state struct {
	Properties  Properties
	dict        dictionary
	state       uint32
	posBitMask  uint32
	isMatch     [states << maxPosBits]prob
	isRep       [states]prob
	isRepG0     [states]prob
	isRepG1     [states]prob
	isRepG2     [states]prob
	isRepG0Long [states << maxPosBits]prob
	rep         [4]uint32
	litCodec    literalCodec
	lenCodec    lengthCodec
	repLenCodec lengthCodec
	distCodec   distCodec
}

// initProbSlice initializes a slice of probabilities.
func initProbSlice(p []prob) {
	for i := range p {
		p[i] = probInit
	}
}

// Reset sets all state information to the original values.
func (s *state) Reset() {
	lc, lp, pb := s.Properties.LC(), s.Properties.LP(), s.Properties.PB()
	*s = state{
		Properties: s.Properties,
		dict:       s.dict,
		posBitMask: (uint32(1) << uint(pb)) - 1,
	}
	initProbSlice(s.isMatch[:])
	initProbSlice(s.isRep[:])
	initProbSlice(s.isRepG0[:])
	initProbSlice(s.isRepG1[:])
	initProbSlice(s.isRepG2[:])
	initProbSlice(s.isRepG0Long[:])
	s.litCodec.init(lc, lp)
	s.lenCodec.init()
	s.repLenCodec.init()
	s.distCodec.init()
}

// initState initialized a state variable.
func initState(s *state, p Properties, dict dictionary) {
	s.Properties = p
	s.dict = dict
	s.Reset()
}

// updateStateLiteral updates the state for a literal.
func (s *state) updateStateLiteral() {
	switch {
	case s.state < 4:
		s.state = 0
		return
	case s.state < 10:
		s.state -= 3
		return
	}
	s.state -= 6
}

// updateStateMatch updates the state for a match.
func (s *state) updateStateMatch() {
	if s.state < 7 {
		s.state = 7
	} else {
		s.state = 10
	}
}

// updateStateRep updates the state for a repetition.
func (s *state) updateStateRep() {
	if s.state < 7 {
		s.state = 8
	} else {
		s.state = 11
	}
}

// updateStateShortRep updates the state for a short repetition.
func (s *state) updateStateShortRep() {
	if s.state < 7 {
		s.state = 9
	} else {
		s.state = 11
	}
}

// states computes the states of the operation codec.
func (s *state) states() (state1, state2, posState uint32) {
	state1 = s.state
	posState = uint32(s.dict.Offset()) & s.posBitMask
	state2 = (s.state << maxPosBits) | posState
	return
}

// litState computes the literal state.
func (s *state) litState() uint32 {
	prevByte := s.dict.Byte(1)
	lp, lc := uint(s.Properties.LP()), uint(s.Properties.LC())
	litState := ((uint32(s.dict.Offset())) & ((1 << lp) - 1) << lc) |
		(uint32(prevByte) >> (8 - lc))
	return litState
}

// ReaderState represents the state of the operation decoding process.
type ReaderState struct {
	state
}

// NewReaderState allocates and initializes the ReaderState.
func NewReaderState(p Properties, rd *ReaderDict) *ReaderState {
	rs := new(ReaderState)
	initState(&rs.state, p, rd)
	return rs
}

// ReaderDict returns the reader dictionary.
func (rs *ReaderState) ReaderDict() *ReaderDict {
	rd, ok := rs.dict.(*ReaderDict)
	if !ok {
		panic("ReaderState value doesn't contain a ReaderDict value")
	}
	return rd
}

// WriterState represents the state of the operation encoding process.
type WriterState struct {
	state
}

// NewWriterState allocates and initializes a WriterState value.
func NewWriterState(p Properties, wd *WriterDict) *WriterState {
	ws := new(WriterState)
	initState(&ws.state, p, wd)
	return ws
}

// WriterDict returns the writer dictionary.
func (ws *WriterState) WriterDict() *WriterDict {
	wd, ok := ws.dict.(*WriterDict)
	if !ok {
		panic("WriterState value doesn't contain a WriterDict value")
	}
	return wd
}
<|endoftext|>


<commit_before>package acceptance_test

import (
	"cf-pusher/cf_cli_adapter"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"

	"os"

	"regexp"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("external connectivity", func() {
	var (
		appA            string
		orgName         string
		spaceName       string
		appRoute        string
		destinationGuid string
		cli             *cf_cli_adapter.Adapter
		testDestination = `{
			"destinations": [
				{
					"name": %q,
					"description": "Testing description",
					"protocol": "tcp",
					"ports": [ { "start": 80, "end": 80 } ],
					"ips": [ { "start": "0.0.0.0", "end": "255.255.255.255" } ]
				}
			]
		}`
		testEgressPolicies = `{
			"egress_policies": [ {
					"source": { "id": %q, "type": %q },
					"destination": { "id": %q }
				} ]
		}`
	)

	BeforeEach(func() {
		if testConfig.Internetless || testConfig.SkipExperimentalDynamicEgressTest {
			Skip("skipping egress policy tests")
		}

		cli = &cf_cli_adapter.Adapter{CfCliPath: "cf"}
		appA = fmt.Sprintf("appA-%d", rand.Int31())

		orgName = testConfig.Prefix + "egress-policy-org"
		spaceName = testConfig.Prefix + "space"
		setupOrgAndSpace(orgName, spaceName)

		By("unbinding all running ASGs")
		for _, sg := range testConfig.DefaultSecurityGroups {
			Expect(cf.Cf("unbind-running-security-group", sg).Wait(Timeout_Short)).To(gexec.Exit(0))
		}

		By("creating a destination")
		destinationGuid = createDestination(cli, fmt.Sprintf(testDestination, fmt.Sprintf("egress-policies-%d", rand.Int31())))
	})

	AfterEach(func() {
		By("deleting destination")
		deleteDestination(cli, destinationGuid)

		By("adding back all the original running ASGs")
		for _, sg := range testConfig.DefaultSecurityGroups {
			Expect(cf.Cf("bind-running-security-group", sg).Wait(Timeout_Short)).To(gexec.Exit(0))
		}

		By("deleting the test org")
		Expect(cf.Cf("delete-org", orgName, "-f").Wait(Timeout_Push)).To(gexec.Exit(0))
	})

	checkRequest := func(route string, expectedStatusCode int, expectedResponseRegex string) error {
		regex := regexp.MustCompile(expectedResponseRegex)
		resp, err := http.Get(route)
		if err != nil {
			return err
		}
		defer resp.Body.Close()

		respBytes, err := ioutil.ReadAll(resp.Body)
		Expect(err).NotTo(HaveOccurred())
		respBody := string(respBytes)

		if resp.StatusCode != expectedStatusCode {
			return fmt.Errorf("test http get to %s: expected response code %d but got %d.  response body:\n%s", route, expectedStatusCode, resp.StatusCode, respBody)
		}
		if !regex.MatchString(respBody) {
			return fmt.Errorf("test http get to %s: expected response to contain %q but instead saw:\n%s", route, expectedResponseRegex, respBody)
		}
		return nil
	}

	canProxy := func() error {
		return checkRequest(appRoute+"proxy/example.com", 200, `Example Domain`)
	}
	cannotProxy := func() error {
		return checkRequest(appRoute+"proxy/example.com", 500, "connection refused|i/o timeout")
	}

	Describe("egress policy connectivity", func() {
		Context("when the egress policy is for the app", func() {
			var (
				egressPolicyGuid string
			)

			AfterEach(func() {
				By("deleting egress policy")
				deleteEgressPolicy(cli, egressPolicyGuid)

				By("checking that the app cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())
			})

			It("the app can reach the internet when egress policy is present", func(done Done) {
				By("pushing the test app")
				pushProxy(appA)
				appRoute = fmt.Sprintf("http://%s.%s/", appA, config.AppsDomain)

				By("checking that the app cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())

				By("creating egress policy")
				appAGuid, err := cli.AppGuid(appA)
				Expect(err).NotTo(HaveOccurred())
				egressPolicyGuid = createEgressPolicy(cli, fmt.Sprintf(testEgressPolicies, appAGuid, "app", destinationGuid))

				By("checking that the app can use dns and http to reach the internet")
				Eventually(canProxy, "10s", "1s").Should(Succeed())
				Consistently(canProxy, "2s", "0.5s").Should(Succeed())

				close(done)
			}, 180 /* <-- overall spec timeout in seconds */)
		})

		Context("when the egress policy is for the space", func() {
			var (
				egressPolicyGuid string
			)

			AfterEach(func() {
				By("deleting egress policy")
				deleteEgressPolicy(cli, egressPolicyGuid)

				By("checking that the app cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())
			})

			It("the app in the space can reach the internet when egress policy is present", func(done Done) {
				By("pushing the test app")
				pushProxy(appA)
				appRoute = fmt.Sprintf("http://%s.%s/", appA, config.AppsDomain)

				By("checking that the space cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())

				By("creating egress policy")
				spaceGuid, err := cli.SpaceGuid(spaceName)
				Expect(err).NotTo(HaveOccurred())
				egressPolicyGuid = createEgressPolicy(cli, fmt.Sprintf(testEgressPolicies, spaceGuid, "space", destinationGuid))

				By("checking that the app can use dns and http to reach the internet")
				Eventually(canProxy, "10s", "1s").Should(Succeed())
				Consistently(canProxy, "2s", "0.5s").Should(Succeed())

				close(done)
			}, 180 /* <-- overall spec timeout in seconds */)

			Context("when a policy is already applied to the space", func() {
				var (
					egressPolicyGuid string
				)

				BeforeEach(func() {
					By("creating an egress policy")
					spaceGuid, err := cli.SpaceGuid(spaceName)
					Expect(err).NotTo(HaveOccurred())
					egressPolicyGuid = createEgressPolicy(cli, fmt.Sprintf(testEgressPolicies, spaceGuid, "space", destinationGuid))
				})

				AfterEach(func() {
					By("deleting egress policy")
					deleteEgressPolicy(cli, egressPolicyGuid)
				})

				It("the app in the space can reach the internet immediately after a push", func(done Done) {
					By("pushing the test app")
					pushProxy(appA)
					appRoute = fmt.Sprintf("http://%s.%s/", appA, config.AppsDomain)

					Expect(canProxy()).To(Succeed())

					close(done)
				}, 180 /* <-- overall spec timeout in seconds */)
			})
		})
	})
})

func deleteEgressPolicy(cli *cf_cli_adapter.Adapter, guid string) {
	var egressPolicyDeleteStruct struct {
		Error string `json:"error"`
	}

	response, err := cli.Curl("DELETE", fmt.Sprintf("/networking/v1/external/egress_policies/%s", guid), "")
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &egressPolicyDeleteStruct)
	Expect(err).NotTo(HaveOccurred())
	Expect(egressPolicyDeleteStruct.Error).To(BeEmpty())
}

func createEgressPolicy(cli *cf_cli_adapter.Adapter, payload string) string {
	payloadFile, err := ioutil.TempFile("", "")
	Expect(err).NotTo(HaveOccurred())

	var egressPolicyStruct struct {
		EgressPolicies []struct {
			ID string `json:"id"`
		} `json:"egress_policies"`
		Error string `json:"error"`
	}

	_, err = payloadFile.Write([]byte(payload))
	Expect(err).NotTo(HaveOccurred())

	err = payloadFile.Close()
	Expect(err).NotTo(HaveOccurred())

	response, err := cli.Curl("POST", "/networking/v1/external/egress_policies", payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &egressPolicyStruct)
	Expect(err).NotTo(HaveOccurred())
	Expect(egressPolicyStruct.Error).To(BeEmpty())

	err = os.Remove(payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())
	return egressPolicyStruct.EgressPolicies[0].ID
}

func createDestination(cli *cf_cli_adapter.Adapter, payload string) string {
	payloadFile, err := ioutil.TempFile("", "")
	Expect(err).NotTo(HaveOccurred())

	var destStruct struct {
		Destinations []struct {
			ID string `json:"id"`
		} `json:"destinations"`
		Error string `json:"error"`
	}

	_, err = payloadFile.Write([]byte(payload))
	Expect(err).NotTo(HaveOccurred())

	err = payloadFile.Close()
	Expect(err).NotTo(HaveOccurred())

	response, err := cli.Curl("POST", "/networking/v1/external/destinations", payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &destStruct)
	Expect(err).NotTo(HaveOccurred())
	Expect(destStruct.Error).To(BeEmpty())

	err = os.Remove(payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())

	return destStruct.Destinations[0].ID
}

func deleteDestination(cli *cf_cli_adapter.Adapter, guid string) {
	var destDeleteStruct struct {
		Error string `json:"error"`
	}

	response, err := cli.Curl("DELETE", fmt.Sprintf("/networking/v1/external/destinations/%s", guid), "")
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &destDeleteStruct)
	Expect(err).NotTo(HaveOccurred())
	Expect(destDeleteStruct.Error).To(BeEmpty())
}
<commit_msg>Move out nested context in egress policy test<commit_after>package acceptance_test

import (
	"cf-pusher/cf_cli_adapter"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"

	"os"

	"regexp"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("external connectivity", func() {
	var (
		appA            string
		orgName         string
		spaceName       string
		appRoute        string
		destinationGuid string
		cli             *cf_cli_adapter.Adapter
		testDestination = `{
			"destinations": [
				{
					"name": %q,
					"description": "Testing description",
					"protocol": "tcp",
					"ports": [ { "start": 80, "end": 80 } ],
					"ips": [ { "start": "0.0.0.0", "end": "255.255.255.255" } ]
				}
			]
		}`
		testEgressPolicies = `{
			"egress_policies": [ {
					"source": { "id": %q, "type": %q },
					"destination": { "id": %q }
				} ]
		}`
	)

	BeforeEach(func() {
		if testConfig.Internetless || testConfig.SkipExperimentalDynamicEgressTest {
			Skip("skipping egress policy tests")
		}

		cli = &cf_cli_adapter.Adapter{CfCliPath: "cf"}
		appA = fmt.Sprintf("appA-%d", rand.Int31())

		orgName = testConfig.Prefix + "egress-policy-org"
		spaceName = testConfig.Prefix + "space"
		setupOrgAndSpace(orgName, spaceName)

		By("unbinding all running ASGs")
		for _, sg := range testConfig.DefaultSecurityGroups {
			Expect(cf.Cf("unbind-running-security-group", sg).Wait(Timeout_Short)).To(gexec.Exit(0))
		}

		By("creating a destination")
		destinationGuid = createDestination(cli, fmt.Sprintf(testDestination, fmt.Sprintf("egress-policies-%d", rand.Int31())))
	})

	AfterEach(func() {
		By("deleting destination")
		deleteDestination(cli, destinationGuid)

		By("adding back all the original running ASGs")
		for _, sg := range testConfig.DefaultSecurityGroups {
			Expect(cf.Cf("bind-running-security-group", sg).Wait(Timeout_Short)).To(gexec.Exit(0))
		}

		By("deleting the test org")
		Expect(cf.Cf("delete-org", orgName, "-f").Wait(Timeout_Push)).To(gexec.Exit(0))
	})

	checkRequest := func(route string, expectedStatusCode int, expectedResponseRegex string) error {
		regex := regexp.MustCompile(expectedResponseRegex)
		resp, err := http.Get(route)
		if err != nil {
			return err
		}
		defer resp.Body.Close()

		respBytes, err := ioutil.ReadAll(resp.Body)
		Expect(err).NotTo(HaveOccurred())
		respBody := string(respBytes)

		if resp.StatusCode != expectedStatusCode {
			return fmt.Errorf("test http get to %s: expected response code %d but got %d.  response body:\n%s", route, expectedStatusCode, resp.StatusCode, respBody)
		}
		if !regex.MatchString(respBody) {
			return fmt.Errorf("test http get to %s: expected response to contain %q but instead saw:\n%s", route, expectedResponseRegex, respBody)
		}
		return nil
	}

	canProxy := func() error {
		return checkRequest(appRoute+"proxy/example.com", 200, `Example Domain`)
	}
	cannotProxy := func() error {
		return checkRequest(appRoute+"proxy/example.com", 500, "connection refused|i/o timeout")
	}

	Describe("egress policy connectivity", func() {
		Context("when the egress policy is for the app", func() {
			var (
				egressPolicyGuid string
			)

			AfterEach(func() {
				By("deleting egress policy")
				deleteEgressPolicy(cli, egressPolicyGuid)

				By("checking that the app cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())
			})

			It("the app can reach the internet when egress policy is present", func(done Done) {
				By("pushing the test app")
				pushProxy(appA)
				appRoute = fmt.Sprintf("http://%s.%s/", appA, config.AppsDomain)

				By("checking that the app cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())

				By("creating egress policy")
				appAGuid, err := cli.AppGuid(appA)
				Expect(err).NotTo(HaveOccurred())
				egressPolicyGuid = createEgressPolicy(cli, fmt.Sprintf(testEgressPolicies, appAGuid, "app", destinationGuid))

				By("checking that the app can use dns and http to reach the internet")
				Eventually(canProxy, "10s", "1s").Should(Succeed())
				Consistently(canProxy, "2s", "0.5s").Should(Succeed())

				close(done)
			}, 180 /* <-- overall spec timeout in seconds */)
		})

		Context("when the egress policy is for the space", func() {
			var (
				egressPolicyGuid string
			)

			AfterEach(func() {
				By("deleting egress policy")
				deleteEgressPolicy(cli, egressPolicyGuid)

				By("checking that the app cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())
			})

			It("the app in the space can reach the internet when egress policy is present", func(done Done) {
				By("pushing the test app")
				pushProxy(appA)
				appRoute = fmt.Sprintf("http://%s.%s/", appA, config.AppsDomain)

				By("checking that the space cannot reach the internet using http and dns")
				Eventually(cannotProxy, "10s", "1s").Should(Succeed())
				Consistently(cannotProxy, "2s", "0.5s").Should(Succeed())

				By("creating egress policy")
				spaceGuid, err := cli.SpaceGuid(spaceName)
				Expect(err).NotTo(HaveOccurred())
				egressPolicyGuid = createEgressPolicy(cli, fmt.Sprintf(testEgressPolicies, spaceGuid, "space", destinationGuid))

				By("checking that the app can use dns and http to reach the internet")
				Eventually(canProxy, "10s", "1s").Should(Succeed())
				Consistently(canProxy, "2s", "0.5s").Should(Succeed())

				close(done)
			}, 180 /* <-- overall spec timeout in seconds */)
		})

		Context("when a policy is already applied to the space", func() {
			var (
				egressPolicyGuid string
			)

			BeforeEach(func() {
				By("creating an egress policy")
				spaceGuid, err := cli.SpaceGuid(spaceName)
				Expect(err).NotTo(HaveOccurred())
				egressPolicyGuid = createEgressPolicy(cli, fmt.Sprintf(testEgressPolicies, spaceGuid, "space", destinationGuid))
			})

			AfterEach(func() {
				By("deleting egress policy")
				deleteEgressPolicy(cli, egressPolicyGuid)
			})

			It("the app in the space can reach the internet immediately after a push", func(done Done) {
				By("pushing the test app")
				pushProxy(appA)
				appRoute = fmt.Sprintf("http://%s.%s/", appA, config.AppsDomain)

				Expect(canProxy()).To(Succeed())

				close(done)
			}, 180 /* <-- overall spec timeout in seconds */)
		})
	})
})

func deleteEgressPolicy(cli *cf_cli_adapter.Adapter, guid string) {
	var egressPolicyDeleteStruct struct {
		Error string `json:"error"`
	}

	response, err := cli.Curl("DELETE", fmt.Sprintf("/networking/v1/external/egress_policies/%s", guid), "")
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &egressPolicyDeleteStruct)
	Expect(err).NotTo(HaveOccurred())
	Expect(egressPolicyDeleteStruct.Error).To(BeEmpty())
}

func createEgressPolicy(cli *cf_cli_adapter.Adapter, payload string) string {
	payloadFile, err := ioutil.TempFile("", "")
	Expect(err).NotTo(HaveOccurred())

	var egressPolicyStruct struct {
		EgressPolicies []struct {
			ID string `json:"id"`
		} `json:"egress_policies"`
		Error string `json:"error"`
	}

	_, err = payloadFile.Write([]byte(payload))
	Expect(err).NotTo(HaveOccurred())

	err = payloadFile.Close()
	Expect(err).NotTo(HaveOccurred())

	response, err := cli.Curl("POST", "/networking/v1/external/egress_policies", payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &egressPolicyStruct)
	Expect(err).NotTo(HaveOccurred())
	Expect(egressPolicyStruct.Error).To(BeEmpty())

	err = os.Remove(payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())
	return egressPolicyStruct.EgressPolicies[0].ID
}

func createDestination(cli *cf_cli_adapter.Adapter, payload string) string {
	payloadFile, err := ioutil.TempFile("", "")
	Expect(err).NotTo(HaveOccurred())

	var destStruct struct {
		Destinations []struct {
			ID string `json:"id"`
		} `json:"destinations"`
		Error string `json:"error"`
	}

	_, err = payloadFile.Write([]byte(payload))
	Expect(err).NotTo(HaveOccurred())

	err = payloadFile.Close()
	Expect(err).NotTo(HaveOccurred())

	response, err := cli.Curl("POST", "/networking/v1/external/destinations", payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &destStruct)
	Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("cannot unmarshal json: %s", response))
	Expect(destStruct.Error).To(BeEmpty())

	err = os.Remove(payloadFile.Name())
	Expect(err).NotTo(HaveOccurred())

	return destStruct.Destinations[0].ID
}

func deleteDestination(cli *cf_cli_adapter.Adapter, guid string) {
	var destDeleteStruct struct {
		Error string `json:"error"`
	}

	response, err := cli.Curl("DELETE", fmt.Sprintf("/networking/v1/external/destinations/%s", guid), "")
	Expect(err).NotTo(HaveOccurred())
	err = json.Unmarshal(response, &destDeleteStruct)
	Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("cannot unmarshal json: %s", response))
	Expect(destDeleteStruct.Error).To(BeEmpty())
}
<|endoftext|>


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

package macaron

import (
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
	"time"

	. "github.com/smartystreets/goconvey/convey"
)

func Test_Version(t *testing.T) {
	Convey("Get version", t, func() {
		So(Version(), ShouldEqual, _VERSION)
	})
}

func Test_New(t *testing.T) {
	Convey("Initialize a new instance", t, func() {
		So(New(), ShouldNotBeNil)
	})

	Convey("Just test that Run doesn't bomb", t, func() {
		go New().Run()
		time.Sleep(1 * time.Second)
		os.Setenv("PORT", "4001")
		go New().Run("0.0.0.0")
		go New().Run(4002)
		go New().Run("0.0.0.0", 4003)
	})
}

func Test_Macaron_Before(t *testing.T) {
	Convey("Register before handlers", t, func() {
		m := New()
		m.Before(func(rw http.ResponseWriter, req *http.Request) bool {
			return false
		})
		m.Before(func(rw http.ResponseWriter, req *http.Request) bool {
			return true
		})
		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
	})
}

func Test_Macaron_ServeHTTP(t *testing.T) {
	Convey("Serve HTTP requests", t, func() {
		result := ""
		m := New()
		m.Use(func(c *Context) {
			result += "foo"
			c.Next()
			result += "ban"
		})
		m.Use(func(c *Context) {
			result += "bar"
			c.Next()
			result += "baz"
		})
		m.Get("/", func() {})
		m.Action(func(res http.ResponseWriter, req *http.Request) {
			result += "bat"
			res.WriteHeader(http.StatusBadRequest)
		})

		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
		So(result, ShouldEqual, "foobarbatbazban")
		So(resp.Code, ShouldEqual, http.StatusBadRequest)
	})
}

func Test_Macaron_Handlers(t *testing.T) {
	Convey("Add custom handlers", t, func() {
		result := ""
		batman := func(c *Context) {
			result += "batman!"
		}

		m := New()
		m.Use(func(c *Context) {
			result += "foo"
			c.Next()
			result += "ban"
		})
		m.Handlers(
			batman,
			batman,
			batman,
		)

		Convey("Add not callable function", func() {
			defer func() {
				So(recover(), ShouldNotBeNil)
			}()
			m.Use("shit")
		})

		m.Get("/", func() {})
		m.Action(func(res http.ResponseWriter, req *http.Request) {
			result += "bat"
			res.WriteHeader(http.StatusBadRequest)
		})

		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
		So(result, ShouldEqual, "batman!batman!batman!bat")
		So(resp.Code, ShouldEqual, http.StatusBadRequest)
	})
}

func Test_Macaron_EarlyWrite(t *testing.T) {
	Convey("Write early content to response", t, func() {
		result := ""
		m := New()
		m.Use(func(res http.ResponseWriter) {
			result += "foobar"
			res.Write([]byte("Hello world"))
		})
		m.Use(func() {
			result += "bat"
		})
		m.Get("/", func() {})
		m.Action(func(res http.ResponseWriter) {
			result += "baz"
			res.WriteHeader(http.StatusBadRequest)
		})

		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
		So(result, ShouldEqual, "foobar")
		So(resp.Code, ShouldEqual, http.StatusOK)
	})
}

func Test_Macaron_Written(t *testing.T) {
	Convey("Written sign", t, func() {
		resp := httptest.NewRecorder()
		m := New()
		m.Handlers(func(res http.ResponseWriter) {
			res.WriteHeader(http.StatusOK)
		})

		ctx := m.createContext(resp, &http.Request{Method: "GET"})
		So(ctx.Written(), ShouldBeFalse)

		ctx.run()
		So(ctx.Written(), ShouldBeTrue)
	})
}

func Test_Macaron_Basic_NoRace(t *testing.T) {
	Convey("Make sure no race between requests", t, func() {
		m := New()
		handlers := []Handler{func() {}, func() {}}
		// Ensure append will not realloc to trigger the race condition
		m.handlers = handlers[:1]
		m.Get("/", func() {})
		req, _ := http.NewRequest("GET", "/", nil)
		for i := 0; i < 2; i++ {
			go func() {
				resp := httptest.NewRecorder()
				m.ServeHTTP(resp, req)
			}()
		}
	})
}

func Test_SetENV(t *testing.T) {
	Convey("Get and save environment variable", t, func() {
		tests := []struct {
			in  string
			out string
		}{
			{"", "development"},
			{"not_development", "not_development"},
		}

		for _, test := range tests {
			setENV(test.in)
			So(Env, ShouldEqual, test.out)
		}
	})
}

func Test_Config(t *testing.T) {
	Convey("Set and get configuration object", t, func() {
		So(Config(), ShouldBeNil)
		So(SetConfig([]byte("")), ShouldBeNil)
		So(Config(), ShouldNotBeNil)
	})
}
<commit_msg>fix test case<commit_after>// Copyright 2013 Martini Authors
// Copyright 2014 Unknwon
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

package macaron

import (
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
	"time"

	. "github.com/smartystreets/goconvey/convey"
)

func Test_Version(t *testing.T) {
	Convey("Get version", t, func() {
		So(Version(), ShouldEqual, _VERSION)
	})
}

func Test_New(t *testing.T) {
	Convey("Initialize a new instance", t, func() {
		So(New(), ShouldNotBeNil)
	})

	Convey("Just test that Run doesn't bomb", t, func() {
		go New().Run()
		time.Sleep(1 * time.Second)
		os.Setenv("PORT", "4001")
		go New().Run("0.0.0.0")
		go New().Run(4002)
		go New().Run("0.0.0.0", 4003)
	})
}

func Test_Macaron_Before(t *testing.T) {
	Convey("Register before handlers", t, func() {
		m := New()
		m.Before(func(rw http.ResponseWriter, req *http.Request) bool {
			return false
		})
		m.Before(func(rw http.ResponseWriter, req *http.Request) bool {
			return true
		})
		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
	})
}

func Test_Macaron_ServeHTTP(t *testing.T) {
	Convey("Serve HTTP requests", t, func() {
		result := ""
		m := New()
		m.Use(func(c *Context) {
			result += "foo"
			c.Next()
			result += "ban"
		})
		m.Use(func(c *Context) {
			result += "bar"
			c.Next()
			result += "baz"
		})
		m.Get("/", func() {})
		m.Action(func(res http.ResponseWriter, req *http.Request) {
			result += "bat"
			res.WriteHeader(http.StatusBadRequest)
		})

		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
		So(result, ShouldEqual, "foobarbatbazban")
		So(resp.Code, ShouldEqual, http.StatusBadRequest)
	})
}

func Test_Macaron_Handlers(t *testing.T) {
	Convey("Add custom handlers", t, func() {
		result := ""
		batman := func(c *Context) {
			result += "batman!"
		}

		m := New()
		m.Use(func(c *Context) {
			result += "foo"
			c.Next()
			result += "ban"
		})
		m.Handlers(
			batman,
			batman,
			batman,
		)

		Convey("Add not callable function", func() {
			defer func() {
				So(recover(), ShouldNotBeNil)
			}()
			m.Use("shit")
		})

		m.Get("/", func() {})
		m.Action(func(res http.ResponseWriter, req *http.Request) {
			result += "bat"
			res.WriteHeader(http.StatusBadRequest)
		})

		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
		So(result, ShouldEqual, "batman!batman!batman!bat")
		So(resp.Code, ShouldEqual, http.StatusBadRequest)
	})
}

func Test_Macaron_EarlyWrite(t *testing.T) {
	Convey("Write early content to response", t, func() {
		result := ""
		m := New()
		m.Use(func(res http.ResponseWriter) {
			result += "foobar"
			res.Write([]byte("Hello world"))
		})
		m.Use(func() {
			result += "bat"
		})
		m.Get("/", func() {})
		m.Action(func(res http.ResponseWriter) {
			result += "baz"
			res.WriteHeader(http.StatusBadRequest)
		})

		resp := httptest.NewRecorder()
		req, err := http.NewRequest("GET", "/", nil)
		So(err, ShouldBeNil)
		m.ServeHTTP(resp, req)
		So(result, ShouldEqual, "foobar")
		So(resp.Code, ShouldEqual, http.StatusOK)
	})
}

func Test_Macaron_Written(t *testing.T) {
	Convey("Written sign", t, func() {
		resp := httptest.NewRecorder()
		m := New()
		m.Handlers(func(res http.ResponseWriter) {
			res.WriteHeader(http.StatusOK)
		})

		ctx := m.createContext(resp, &http.Request{Method: "GET"})
		So(ctx.Written(), ShouldBeFalse)

		ctx.run()
		So(ctx.Written(), ShouldBeTrue)
	})
}

func Test_Macaron_Basic_NoRace(t *testing.T) {
	Convey("Make sure no race between requests", t, func() {
		m := New()
		handlers := []Handler{func() {}, func() {}}
		// Ensure append will not realloc to trigger the race condition
		m.handlers = handlers[:1]
		m.Get("/", func() {})
		req, _ := http.NewRequest("GET", "/", nil)
		for i := 0; i < 2; i++ {
			go func() {
				resp := httptest.NewRecorder()
				m.ServeHTTP(resp, req)
			}()
		}
	})
}

func Test_SetENV(t *testing.T) {
	Convey("Get and save environment variable", t, func() {
		tests := []struct {
			in  string
			out string
		}{
			{"", "development"},
			{"not_development", "not_development"},
		}

		for _, test := range tests {
			setENV(test.in)
			So(Env, ShouldEqual, test.out)
		}
	})
}

func Test_Config(t *testing.T) {
	Convey("Set and get configuration object", t, func() {
		So(Config(), ShouldNotBeNil)
		So(SetConfig([]byte("")), ShouldBeNil)
		So(Config(), ShouldNotBeNil)
	})
}
<|endoftext|>