<commit_before>package ddldiff

import (
	"github.com/pagarme/teleport/action"
	"testing"
)

// Foo implements Diffable
type Foo struct {
	Name string
	Id   int
	Bars []*Bar
}

type Bar struct {
	Name string
	Id   int
}

type FooAction struct {
	Kind string
}

func (a *FooAction) Execute(c action.Context) error {
	return nil
}

func (a *FooAction) Filter(targetExpression string) bool {
	return true
}

func (a *FooAction) NeedsSeparatedBatch() bool {
	return false
}

type BarAction struct {
	Kind string
}

func (a *BarAction) Execute(c action.Context) error {
	return nil
}

func (a *BarAction) Filter(targetExpression string) bool {
	return true
}

func (a *BarAction) NeedsSeparatedBatch() bool {
	return false
}

func NewFoo(name string, id int, bars []*Bar) *Foo {
	return &Foo{name, id, bars}
}

func NewBar(name string, id int) *Bar {
	return &Bar{name, id}
}

func (post *Foo) Diff(other Diffable) []action.Action {
	if other == nil {
		return []action.Action{
			&FooAction{
				"CREATE FOO",
			},
		}
	} else {
		pre := other.(*Foo)

		if pre.Name != post.Name {
			return []action.Action{
				&FooAction{
					"RENAME FOO",
				},
			}
		}
	}

	return []action.Action{}
}

func (post *Bar) Diff(other Diffable) []action.Action {
	if other == nil {
		return []action.Action{
			&BarAction{
				"CREATE BAR",
			},
		}
	} else {
		pre := other.(*Bar)

		if pre.Name != post.Name {
			return []action.Action{
				&BarAction{
					"RENAME BAR",
				},
			}
		}
	}

	return []action.Action{}
}

func (f *Foo) Children() []Diffable {
	children := make([]Diffable, 0)

	for i, _ := range f.Bars {
		children = append(children, f.Bars[i])
	}

	return children
}

func (b *Bar) Children() []Diffable {
	return []Diffable{}
}

func (f *Foo) Drop() []action.Action {
	return []action.Action{
		&FooAction{
			"DROP FOO",
		},
	}
}

func (b *Bar) Drop() []action.Action {
	return []action.Action{
		&BarAction{
			"DROP BAR",
		},
	}
}

func (f *Foo) IsEqual(other Diffable) bool {
	if other == nil {
		return false
	}

	otherFoo := other.(*Foo)
	return (otherFoo.Id == f.Id)
}

func (b *Bar) IsEqual(other Diffable) bool {
	if other == nil {
		return false
	}

	otherBar := other.(*Bar)
	return (otherBar.Id == b.Id)
}

// // Test a diff that should create something
func TestDiffCreate(t *testing.T) {
	pre := []Diffable{}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	actions := Diff(pre, post)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	fooAction := actions[0].(*FooAction)

	if fooAction.Kind != "CREATE FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "CREATE FOO")
	}
}

// Test a diff that should rename something
func TestDiffRename(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	post := []Diffable{
		Diffable(NewFoo("testing this", 1, []*Bar{})),
	}

	actions := Diff(pre, post)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	fooAction := actions[0].(*FooAction)

	if fooAction.Kind != "RENAME FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "RENAME FOO")
	}
}

// Test a diff that should drop something
func TestDiffDrop(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	post := []Diffable{}

	actions := Diff(pre, post)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	fooAction := actions[0].(*FooAction)

	if fooAction.Kind != "DROP FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "DROP FOO")
	}
}

// Test a diff that should create something recursively
func TestDiffCreateTree(t *testing.T) {
	pre := []Diffable{}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	actions := Diff(pre, post)

	if len(actions) != 2 {
		t.Errorf("len actions => %d, want %d", len(actions), 2)
	}

	fooAction := actions[0].(*FooAction)
	barAction := actions[1].(*BarAction)

	if fooAction.Kind != "CREATE FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "CREATE FOO")
	}

	if barAction.Kind != "CREATE BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "CREATE BAR")
	}
}

// Test a diff that should create something recursively
func TestDiffCreateRecursively(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	actions := Diff(pre, post)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	barAction := actions[0].(*BarAction)

	if barAction.Kind != "CREATE BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "CREATE BAR")
	}
}

// Test a diff that should rename something recursively
func TestDiffRenameRecursively(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	post := []Diffable{
		Diffable(NewFoo("test edited", 1, []*Bar{NewBar("sub test edited", 1)})),
	}

	actions := Diff(pre, post)

	if len(actions) != 2 {
		t.Errorf("len actions => %d, want %d", len(actions), 2)
	}

	fooAction := actions[0].(*FooAction)
	barAction := actions[1].(*BarAction)

	if fooAction.Kind != "RENAME FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "RENAME FOO")
	}

	if barAction.Kind != "RENAME BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "RENAME BAR")
	}
}

// Test a diff that should drop something recursively
func TestDiffDropRecursively(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	actions := Diff(pre, post)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	barAction := actions[0].(*BarAction)

	if barAction.Kind != "DROP BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "DROP BAR")
	}
}
<commit_msg>Fix tests.<commit_after>package ddldiff

import (
	"github.com/pagarme/teleport/action"
	"testing"
	"fmt"
)

// Foo implements Diffable
type Foo struct {
	Name string
	Id   int
	Bars []*Bar
}

type Bar struct {
	Name string
	Id   int
}

type FooAction struct {
	Kind string
}

func (a *FooAction) Execute(c action.Context) error {
	return nil
}

func (a *FooAction) Filter(targetExpression string) bool {
	return true
}

func (a *FooAction) NeedsSeparatedBatch() bool {
	return false
}

type BarAction struct {
	Kind string
}

func (a *BarAction) Execute(c action.Context) error {
	return nil
}

func (a *BarAction) Filter(targetExpression string) bool {
	return true
}

func (a *BarAction) NeedsSeparatedBatch() bool {
	return false
}

func NewFoo(name string, id int, bars []*Bar) *Foo {
	return &Foo{name, id, bars}
}

func NewBar(name string, id int) *Bar {
	return &Bar{name, id}
}

var defaultContext Context

func init() {
	defaultContext = Context{
		Schema: "default_context",
	}
}

func (post *Foo) Diff(other Diffable, context Context) []action.Action {
	if other == nil {
		return []action.Action{
			&FooAction{
				fmt.Sprintf("CREATE FOO %s", context.Schema),
			},
		}
	} else {
		pre := other.(*Foo)

		if pre.Name != post.Name {
			return []action.Action{
				&FooAction{
					"RENAME FOO",
				},
			}
		}
	}

	return []action.Action{}
}

func (post *Bar) Diff(other Diffable, context Context) []action.Action {
	if other == nil {
		return []action.Action{
			&BarAction{
				"CREATE BAR",
			},
		}
	} else {
		pre := other.(*Bar)

		if pre.Name != post.Name {
			return []action.Action{
				&BarAction{
					"RENAME BAR",
				},
			}
		}
	}

	return []action.Action{}
}

func (f *Foo) Children() []Diffable {
	children := make([]Diffable, 0)

	for i, _ := range f.Bars {
		children = append(children, f.Bars[i])
	}

	return children
}

func (b *Bar) Children() []Diffable {
	return []Diffable{}
}

func (f *Foo) Drop(context Context) []action.Action {
	return []action.Action{
		&FooAction{
			"DROP FOO",
		},
	}
}

func (b *Bar) Drop(context Context) []action.Action {
	return []action.Action{
		&BarAction{
			"DROP BAR",
		},
	}
}

func (f *Foo) IsEqual(other Diffable) bool {
	if other == nil {
		return false
	}

	otherFoo := other.(*Foo)
	return (otherFoo.Id == f.Id)
}

func (b *Bar) IsEqual(other Diffable) bool {
	if other == nil {
		return false
	}

	otherBar := other.(*Bar)
	return (otherBar.Id == b.Id)
}

// // Test a diff that should create something
func TestDiffCreate(t *testing.T) {
	pre := []Diffable{}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	actions := Diff(pre, post, defaultContext)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	fooAction := actions[0].(*FooAction)

	if fooAction.Kind != "CREATE FOO default_context" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "CREATE FOO default_context")
	}
}

// Test a diff that should rename something
func TestDiffRename(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	post := []Diffable{
		Diffable(NewFoo("testing this", 1, []*Bar{})),
	}

	actions := Diff(pre, post, defaultContext)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	fooAction := actions[0].(*FooAction)

	if fooAction.Kind != "RENAME FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "RENAME FOO")
	}
}

// Test a diff that should drop something
func TestDiffDrop(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	post := []Diffable{}

	actions := Diff(pre, post, defaultContext)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	fooAction := actions[0].(*FooAction)

	if fooAction.Kind != "DROP FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "DROP FOO")
	}
}

// Test a diff that should create something recursively
func TestDiffCreateTree(t *testing.T) {
	pre := []Diffable{}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	actions := Diff(pre, post, defaultContext)

	if len(actions) != 2 {
		t.Errorf("len actions => %d, want %d", len(actions), 2)
	}

	fooAction := actions[0].(*FooAction)
	barAction := actions[1].(*BarAction)

	if fooAction.Kind != "CREATE FOO default_context" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "CREATE FOO default_context")
	}

	if barAction.Kind != "CREATE BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "CREATE BAR")
	}
}

// Test a diff that should create something recursively
func TestDiffCreateRecursively(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	actions := Diff(pre, post, defaultContext)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	barAction := actions[0].(*BarAction)

	if barAction.Kind != "CREATE BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "CREATE BAR")
	}
}

// Test a diff that should rename something recursively
func TestDiffRenameRecursively(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	post := []Diffable{
		Diffable(NewFoo("test edited", 1, []*Bar{NewBar("sub test edited", 1)})),
	}

	actions := Diff(pre, post, defaultContext)

	if len(actions) != 2 {
		t.Errorf("len actions => %d, want %d", len(actions), 2)
	}

	fooAction := actions[0].(*FooAction)
	barAction := actions[1].(*BarAction)

	if fooAction.Kind != "RENAME FOO" {
		t.Errorf("action kind => %s, want %s", fooAction.Kind, "RENAME FOO")
	}

	if barAction.Kind != "RENAME BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "RENAME BAR")
	}
}

// Test a diff that should drop something recursively
func TestDiffDropRecursively(t *testing.T) {
	pre := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{NewBar("sub test", 1)})),
	}

	post := []Diffable{
		Diffable(NewFoo("test", 1, []*Bar{})),
	}

	actions := Diff(pre, post, defaultContext)

	if len(actions) != 1 {
		t.Errorf("len actions => %d, want %d", len(actions), 1)
	}

	barAction := actions[0].(*BarAction)

	if barAction.Kind != "DROP BAR" {
		t.Errorf("action kind => %s, want %s", barAction.Kind, "DROP BAR")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"json"
	"math"
	"quag.geek.nz/nbt"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
)

var (
	out        *bufio.Writer
	yMin       int
	blockFaces bool
	hideBottom bool
	noColor    bool

	faceCount int
	faceLimit int

	chunkCount int
	chunkLimit int

	chunkMask ChunkMask

	obj3dsmax bool
)

func main() {
	var bx, bz float64
	var cx, cz int
	var square int
	var rectx, rectz int
	var maxProcs = runtime.GOMAXPROCS(0)
	var prt bool
	var solidSides bool
	var mtlNumber bool

	var defaultObjOutFilename = "a.obj"
	var defaultPrtOutFilename = "a.prt"

	var outFilename string
	flag.IntVar(&maxProcs, "cpu", maxProcs, "Number of cores to use")
	flag.StringVar(&outFilename, "o", defaultObjOutFilename, "Name for output file")
	flag.IntVar(&yMin, "y", 0, "Omit all blocks below this height. 63 is sea level")
	flag.BoolVar(&solidSides, "sides", false, "Solid sides, rather than showing underground")
	flag.BoolVar(&blockFaces, "bf", false, "Don't combine adjacent faces of the same block within a column")
	flag.BoolVar(&hideBottom, "hb", false, "Hide bottom of world")
	flag.BoolVar(&noColor, "g", false, "Omit materials")
	flag.Float64Var(&bx, "x", 0, "Center x coordinate in blocks")
	flag.Float64Var(&bz, "z", 0, "Center z coordinate in blocks")
	flag.IntVar(&cx, "cx", 0, "Center x coordinate in chunks")
	flag.IntVar(&cz, "cz", 0, "Center z coordinate in chunks")
	flag.IntVar(&square, "s", math.MaxInt32, "Chunk square size")
	flag.IntVar(&rectx, "rx", math.MaxInt32, "Width(x) of rectangle size")
	flag.IntVar(&rectz, "rz", math.MaxInt32, "Height(z) of rectangle size")
	flag.IntVar(&faceLimit, "fk", math.MaxInt32, "Face limit (thousands of faces)")
	flag.BoolVar(&prt, "prt", false, "Write out PRT file instead of Obj file")
	flag.BoolVar(&obj3dsmax, "3dsmax", true, "Create .obj file compatible with 3dsMax")
	flag.BoolVar(&mtlNumber, "mtlnum", false, "Number materials instead of using names")
	var showHelp = flag.Bool("h", false, "Show Help")
	flag.Parse()

	runtime.GOMAXPROCS(maxProcs)
	fmt.Printf("mcobj %v (cpu: %d) Copyright (c) 2011 Jonathan Wright\n", version, runtime.GOMAXPROCS(0))

	if *showHelp || flag.NArg() == 0 {
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "Usage: mcobj -cpu 4 -s 20 -o world1.obj", ExampleWorldPath())
		fmt.Fprintln(os.Stderr)
		flag.PrintDefaults()
		return
	}

	if faceLimit != math.MaxInt32 {
		faceLimit *= 1000
	}

	if mtlNumber {
		MaterialNamer = new(NumberBlockIdNamer)
	} else {
		MaterialNamer = new(NameBlockIdNamer)
	}

	switch {
	case bx == 0 && cx == 0:
		cx = 0
	case cx == 0:
		cx = int(math.Floor(bx / 16))
	}

	switch {
	case bz == 0 && cz == 0:
		cz = 0
	case cz == 0:
		cz = int(math.Floor(bz / 16))
	}

	if square != math.MaxInt32 {
		chunkLimit = square * square
		var h = square / 2
		chunkMask = &RectangeChunkMask{cx - h, cz - h, cx - h + square, cz - h + square}
	} else if rectx != math.MaxInt32 || rectz != math.MaxInt32 {
		switch {
		case rectx != math.MaxInt32 && rectz != math.MaxInt32:
			chunkLimit = rectx * rectz
			var (
				hx = rectx / 2
				hz = rectz / 2
			)
			chunkMask = &RectangeChunkMask{cx - hx, cz - hz, cx - hx + rectx, cz - hz + rectz}
		case rectx != math.MaxInt32:
			chunkLimit = math.MaxInt32
			var hx = rectx / 2
			chunkMask = &RectangeChunkMask{cx - hx, math.MinInt32, cx - hx + rectx, math.MaxInt32}
		case rectz != math.MaxInt32:
			chunkLimit = math.MaxInt32
			var hz = rectz / 2
			chunkMask = &RectangeChunkMask{math.MinInt32, cz - hz, math.MaxInt32, cz - hz + rectz}
		}
	} else {
		chunkLimit = math.MaxInt32
		chunkMask = &AllChunksMask{}
	}

	if prt && outFilename == defaultObjOutFilename {
		outFilename = defaultPrtOutFilename
	}

	if solidSides {
		defaultSide = &emptySide
	}

	{
		var dir, _ = filepath.Split(strings.Replace(os.Args[0], "\\", "/", -1))
		var jsonError = loadBlockTypesJson(filepath.Join(dir, "blocks.json"))
		if jsonError != nil {
			fmt.Fprintln(os.Stderr, jsonError)
			return
		}
	}

	for i := 0; i < flag.NArg(); i++ {
		var dirpath = flag.Arg(i)
		var fi, err = os.Stat(dirpath)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			continue
		} else if !fi.IsDirectory() {
			fmt.Fprintln(os.Stderr, dirpath, "is not a directory")
		}

		var world = OpenWorld(dirpath, chunkMask)
		var pool, poolErr = world.ChunkPool()
		if poolErr != nil {
			fmt.Fprintln(os.Stderr, poolErr)
			continue
		}

		var generator OutputGenerator
		if prt {
			generator = new(PrtGenerator)
		} else {
			generator = new(ObjGenerator)
		}
		var boundary = new(BoundaryLocator)
		boundary.Init()
		var startErr = generator.Start(outFilename, pool.Remaining(), maxProcs, boundary)
		if startErr != nil {
			fmt.Fprintln(os.Stderr, startErr)
			continue
		}

		if walkEnclosedChunks(pool, world, cx, cz, generator.GetEnclosedJobsChan()) {
			<-generator.GetCompleteChan()
		}

		var closeErr = generator.Close()
		if closeErr != nil {
			fmt.Fprintln(os.Stderr, closeErr)
			continue
		}
	}
}

type OutputGenerator interface {
	Start(outFilename string, total int, maxProcs int, boundary *BoundaryLocator) os.Error
	GetEnclosedJobsChan() chan *EnclosedChunkJob
	GetCompleteChan() chan bool
	Close() os.Error
}

type EnclosedChunkJob struct {
	last     bool
	enclosed *EnclosedChunk
}

func walkEnclosedChunks(pool ChunkPool, opener ChunkOpener, cx, cz int, enclosedsChan chan *EnclosedChunkJob) bool {
	var (
		sideCache = new(SideCache)
		started   = false
	)

	for i := 0; moreChunks(pool.Remaining()); i++ {
		for x := 0; x < i && moreChunks(pool.Remaining()); x++ {
			for z := 0; z < i && moreChunks(pool.Remaining()); z++ {
				var (
					ax = cx + unzigzag(x)
					az = cz + unzigzag(z)
				)

				if pool.Pop(ax, az) {
					loadSide(sideCache, opener, ax-1, az)
					loadSide(sideCache, opener, ax+1, az)
					loadSide(sideCache, opener, ax, az-1)
					loadSide(sideCache, opener, ax, az+1)

					var chunk, loadErr = loadChunk2(opener, ax, az)
					if loadErr != nil {
						fmt.Println(loadErr)
					} else {
						var enclosed = sideCache.EncloseChunk(chunk)
						sideCache.AddChunk(chunk)
						chunkCount++
						enclosedsChan <- &EnclosedChunkJob{!moreChunks(pool.Remaining()), enclosed}
						started = true
					}
				}
			}
		}
	}

	return started
}

type Blocks []uint16

type BlockColumn []uint16

func (b *Blocks) Get(x, y, z int) uint16 {
	return (*b)[y+(z*128+(x*128*16))]
}

func (b *Blocks) Column(x, z int) BlockColumn {
	var i = 128 * (z + x*16)
	return BlockColumn((*b)[i : i+128])
}

func zigzag(n int) int {
	return (n << 1) ^ (n >> 31)
}

func unzigzag(n int) int {
	return (n >> 1) ^ (-(n & 1))
}

func moreChunks(unprocessedCount int) bool {
	return unprocessedCount > 0 && faceCount < faceLimit && chunkCount < chunkLimit
}

func loadChunk(filename string) (*nbt.Chunk, os.Error) {
	var file, fileErr = os.Open(filename)
	defer file.Close()
	if fileErr != nil {
		return nil, fileErr
	}
	var chunk, err = nbt.ReadDat(file)
	if err == os.EOF {
		err = nil
	}
	return chunk, err
}

func loadChunk2(opener ChunkOpener, x, z int) (*nbt.Chunk, os.Error) {
	var r, openErr = opener.OpenChunk(x, z)
	if openErr != nil {
		return nil, openErr
	}
	defer r.Close()

	var chunk, nbtErr = nbt.ReadNbt(r)
	if nbtErr != nil {
		return nil, nbtErr
	}
	return chunk, nil
}

func loadSide(sideCache *SideCache, opener ChunkOpener, x, z int) {
	if !sideCache.HasSide(x, z) && !chunkMask.IsMasked(x, z) {
		var chunk, loadErr = loadChunk2(opener, x, z)
		if loadErr != nil {
			fmt.Println(loadErr)
		} else {
			sideCache.AddChunk(chunk)
		}
	}
}

func loadBlockTypesJson(filename string) os.Error {
	var jsonBytes, jsonIoError = ioutil.ReadFile(filename)

	if jsonIoError != nil {
		return jsonIoError
	}

	var f interface{}
	var unmarshalError = json.Unmarshal(jsonBytes, &f)
	if unmarshalError != nil {
		return unmarshalError
	}

	var lines, linesOk = f.([]interface{})
	if linesOk {
		for _, line := range lines {
			var fields, fieldsOk = line.(map[string]interface{})
			if fieldsOk {
				var (
					blockId      byte
					data         byte = 255
					dataArray    []byte
					name         string
					mass         SingularOrAggregate = Mass
					transparency Transparency        = Opaque
					empty        bool                = false
					color        uint32
				)
				for k, v := range fields {
					switch k {
					case "name":
						name = v.(string)
					case "color":
						switch len(v.(string)) {
						case 7:
							var n, numErr = strconv.Btoui64(v.(string)[1:], 16)
							if numErr == nil {
								color = uint32(n*0x100 + 0xff)
							}
						case 9:
							var n, numErr = strconv.Btoui64(v.(string)[1:], 16)
							if numErr == nil {
								color = uint32(n)
							}
						}
					case "blockId":
						blockId = byte(v.(float64))
					case "data":
						switch d := v.(type) {
						case float64:
							data = byte(d)
						case []interface{}:
							dataArray = make([]byte, len(d))
							for i, value := range d {
								dataArray[i] = byte(value.(float64))
							}
						}
					case "item":
						if v.(bool) {
							mass = Item
							transparency = Transparent
						} else {
							mass = Mass
							transparency = Opaque
						}
					case "transparent":
						if v.(bool) {
							transparency = Transparent
						} else {
							transparency = Opaque
						}
					case "empty":
						if v.(bool) {
							empty = true
							transparency = Transparent
							mass = Mass
						} else {
							empty = false
						}
					}
				}

				blockTypeMap[blockId] = &BlockType{blockId, mass, transparency, empty}
				if dataArray == nil {
					if data != 255 {
						extraData[blockId] = true
						colors = append(colors, MTL{blockId, data, color, name})
					} else {
						colors[blockId] = MTL{blockId, data, color, name}
					}
				} else {
					extraData[blockId] = true
					for _, data = range dataArray {
						colors = append(colors, MTL{blockId, data, color, fmt.Sprintf("%s_%d", name, data)})
					}
				}
			}
		}
	}

	return nil
}
<commit_msg>Make locating error messages easier<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"json"
	"math"
	"quag.geek.nz/nbt"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
)

var (
	out        *bufio.Writer
	yMin       int
	blockFaces bool
	hideBottom bool
	noColor    bool

	faceCount int
	faceLimit int

	chunkCount int
	chunkLimit int

	chunkMask ChunkMask

	obj3dsmax bool
)

func main() {
	var bx, bz float64
	var cx, cz int
	var square int
	var rectx, rectz int
	var maxProcs = runtime.GOMAXPROCS(0)
	var prt bool
	var solidSides bool
	var mtlNumber bool

	var defaultObjOutFilename = "a.obj"
	var defaultPrtOutFilename = "a.prt"

	var outFilename string
	flag.IntVar(&maxProcs, "cpu", maxProcs, "Number of cores to use")
	flag.StringVar(&outFilename, "o", defaultObjOutFilename, "Name for output file")
	flag.IntVar(&yMin, "y", 0, "Omit all blocks below this height. 63 is sea level")
	flag.BoolVar(&solidSides, "sides", false, "Solid sides, rather than showing underground")
	flag.BoolVar(&blockFaces, "bf", false, "Don't combine adjacent faces of the same block within a column")
	flag.BoolVar(&hideBottom, "hb", false, "Hide bottom of world")
	flag.BoolVar(&noColor, "g", false, "Omit materials")
	flag.Float64Var(&bx, "x", 0, "Center x coordinate in blocks")
	flag.Float64Var(&bz, "z", 0, "Center z coordinate in blocks")
	flag.IntVar(&cx, "cx", 0, "Center x coordinate in chunks")
	flag.IntVar(&cz, "cz", 0, "Center z coordinate in chunks")
	flag.IntVar(&square, "s", math.MaxInt32, "Chunk square size")
	flag.IntVar(&rectx, "rx", math.MaxInt32, "Width(x) of rectangle size")
	flag.IntVar(&rectz, "rz", math.MaxInt32, "Height(z) of rectangle size")
	flag.IntVar(&faceLimit, "fk", math.MaxInt32, "Face limit (thousands of faces)")
	flag.BoolVar(&prt, "prt", false, "Write out PRT file instead of Obj file")
	flag.BoolVar(&obj3dsmax, "3dsmax", true, "Create .obj file compatible with 3dsMax")
	flag.BoolVar(&mtlNumber, "mtlnum", false, "Number materials instead of using names")
	var showHelp = flag.Bool("h", false, "Show Help")
	flag.Parse()

	runtime.GOMAXPROCS(maxProcs)
	fmt.Printf("mcobj %v (cpu: %d) Copyright (c) 2011 Jonathan Wright\n", version, runtime.GOMAXPROCS(0))

	if *showHelp || flag.NArg() == 0 {
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "Usage: mcobj -cpu 4 -s 20 -o world1.obj", ExampleWorldPath())
		fmt.Fprintln(os.Stderr)
		flag.PrintDefaults()
		return
	}

	if faceLimit != math.MaxInt32 {
		faceLimit *= 1000
	}

	if mtlNumber {
		MaterialNamer = new(NumberBlockIdNamer)
	} else {
		MaterialNamer = new(NameBlockIdNamer)
	}

	switch {
	case bx == 0 && cx == 0:
		cx = 0
	case cx == 0:
		cx = int(math.Floor(bx / 16))
	}

	switch {
	case bz == 0 && cz == 0:
		cz = 0
	case cz == 0:
		cz = int(math.Floor(bz / 16))
	}

	if square != math.MaxInt32 {
		chunkLimit = square * square
		var h = square / 2
		chunkMask = &RectangeChunkMask{cx - h, cz - h, cx - h + square, cz - h + square}
	} else if rectx != math.MaxInt32 || rectz != math.MaxInt32 {
		switch {
		case rectx != math.MaxInt32 && rectz != math.MaxInt32:
			chunkLimit = rectx * rectz
			var (
				hx = rectx / 2
				hz = rectz / 2
			)
			chunkMask = &RectangeChunkMask{cx - hx, cz - hz, cx - hx + rectx, cz - hz + rectz}
		case rectx != math.MaxInt32:
			chunkLimit = math.MaxInt32
			var hx = rectx / 2
			chunkMask = &RectangeChunkMask{cx - hx, math.MinInt32, cx - hx + rectx, math.MaxInt32}
		case rectz != math.MaxInt32:
			chunkLimit = math.MaxInt32
			var hz = rectz / 2
			chunkMask = &RectangeChunkMask{math.MinInt32, cz - hz, math.MaxInt32, cz - hz + rectz}
		}
	} else {
		chunkLimit = math.MaxInt32
		chunkMask = &AllChunksMask{}
	}

	if prt && outFilename == defaultObjOutFilename {
		outFilename = defaultPrtOutFilename
	}

	if solidSides {
		defaultSide = &emptySide
	}

	{
		var dir, _ = filepath.Split(strings.Replace(os.Args[0], "\\", "/", -1))
		var jsonError = loadBlockTypesJson(filepath.Join(dir, "blocks.json"))
		if jsonError != nil {
			fmt.Fprintln(os.Stderr, "blocks.json error:", jsonError)
			return
		}
	}

	for i := 0; i < flag.NArg(); i++ {
		var dirpath = flag.Arg(i)
		var fi, err = os.Stat(dirpath)
		if err != nil {
			fmt.Fprintln(os.Stderr, "World error:", err)
			continue
		} else if !fi.IsDirectory() {
			fmt.Fprintln(os.Stderr, dirpath, "is not a directory")
		}

		var world = OpenWorld(dirpath, chunkMask)
		var pool, poolErr = world.ChunkPool()
		if poolErr != nil {
			fmt.Fprintln(os.Stderr, "Chunk pool error:", poolErr)
			continue
		}

		var generator OutputGenerator
		if prt {
			generator = new(PrtGenerator)
		} else {
			generator = new(ObjGenerator)
		}
		var boundary = new(BoundaryLocator)
		boundary.Init()
		var startErr = generator.Start(outFilename, pool.Remaining(), maxProcs, boundary)
		if startErr != nil {
			fmt.Fprintln(os.Stderr, "Generator start error:", startErr)
			continue
		}

		if walkEnclosedChunks(pool, world, cx, cz, generator.GetEnclosedJobsChan()) {
			<-generator.GetCompleteChan()
		}

		var closeErr = generator.Close()
		if closeErr != nil {
			fmt.Fprintln(os.Stderr, "Generator close error:", closeErr)
			continue
		}
	}
}

type OutputGenerator interface {
	Start(outFilename string, total int, maxProcs int, boundary *BoundaryLocator) os.Error
	GetEnclosedJobsChan() chan *EnclosedChunkJob
	GetCompleteChan() chan bool
	Close() os.Error
}

type EnclosedChunkJob struct {
	last     bool
	enclosed *EnclosedChunk
}

func walkEnclosedChunks(pool ChunkPool, opener ChunkOpener, cx, cz int, enclosedsChan chan *EnclosedChunkJob) bool {
	var (
		sideCache = new(SideCache)
		started   = false
	)

	for i := 0; moreChunks(pool.Remaining()); i++ {
		for x := 0; x < i && moreChunks(pool.Remaining()); x++ {
			for z := 0; z < i && moreChunks(pool.Remaining()); z++ {
				var (
					ax = cx + unzigzag(x)
					az = cz + unzigzag(z)
				)

				if pool.Pop(ax, az) {
					loadSide(sideCache, opener, ax-1, az)
					loadSide(sideCache, opener, ax+1, az)
					loadSide(sideCache, opener, ax, az-1)
					loadSide(sideCache, opener, ax, az+1)

					var chunk, loadErr = loadChunk2(opener, ax, az)
					if loadErr != nil {
						fmt.Println(loadErr)
					} else {
						var enclosed = sideCache.EncloseChunk(chunk)
						sideCache.AddChunk(chunk)
						chunkCount++
						enclosedsChan <- &EnclosedChunkJob{!moreChunks(pool.Remaining()), enclosed}
						started = true
					}
				}
			}
		}
	}

	return started
}

type Blocks []uint16

type BlockColumn []uint16

func (b *Blocks) Get(x, y, z int) uint16 {
	return (*b)[y+(z*128+(x*128*16))]
}

func (b *Blocks) Column(x, z int) BlockColumn {
	var i = 128 * (z + x*16)
	return BlockColumn((*b)[i : i+128])
}

func zigzag(n int) int {
	return (n << 1) ^ (n >> 31)
}

func unzigzag(n int) int {
	return (n >> 1) ^ (-(n & 1))
}

func moreChunks(unprocessedCount int) bool {
	return unprocessedCount > 0 && faceCount < faceLimit && chunkCount < chunkLimit
}

func loadChunk(filename string) (*nbt.Chunk, os.Error) {
	var file, fileErr = os.Open(filename)
	defer file.Close()
	if fileErr != nil {
		return nil, fileErr
	}
	var chunk, err = nbt.ReadDat(file)
	if err == os.EOF {
		err = nil
	}
	return chunk, err
}

func loadChunk2(opener ChunkOpener, x, z int) (*nbt.Chunk, os.Error) {
	var r, openErr = opener.OpenChunk(x, z)
	if openErr != nil {
		return nil, openErr
	}
	defer r.Close()

	var chunk, nbtErr = nbt.ReadNbt(r)
	if nbtErr != nil {
		return nil, nbtErr
	}
	return chunk, nil
}

func loadSide(sideCache *SideCache, opener ChunkOpener, x, z int) {
	if !sideCache.HasSide(x, z) && !chunkMask.IsMasked(x, z) {
		var chunk, loadErr = loadChunk2(opener, x, z)
		if loadErr != nil {
			fmt.Println(loadErr)
		} else {
			sideCache.AddChunk(chunk)
		}
	}
}

func loadBlockTypesJson(filename string) os.Error {
	var jsonBytes, jsonIoError = ioutil.ReadFile(filename)

	if jsonIoError != nil {
		return jsonIoError
	}

	var f interface{}
	var unmarshalError = json.Unmarshal(jsonBytes, &f)
	if unmarshalError != nil {
		return unmarshalError
	}

	var lines, linesOk = f.([]interface{})
	if linesOk {
		for _, line := range lines {
			var fields, fieldsOk = line.(map[string]interface{})
			if fieldsOk {
				var (
					blockId      byte
					data         byte = 255
					dataArray    []byte
					name         string
					mass         SingularOrAggregate = Mass
					transparency Transparency        = Opaque
					empty        bool                = false
					color        uint32
				)
				for k, v := range fields {
					switch k {
					case "name":
						name = v.(string)
					case "color":
						switch len(v.(string)) {
						case 7:
							var n, numErr = strconv.Btoui64(v.(string)[1:], 16)
							if numErr == nil {
								color = uint32(n*0x100 + 0xff)
							}
						case 9:
							var n, numErr = strconv.Btoui64(v.(string)[1:], 16)
							if numErr == nil {
								color = uint32(n)
							}
						}
					case "blockId":
						blockId = byte(v.(float64))
					case "data":
						switch d := v.(type) {
						case float64:
							data = byte(d)
						case []interface{}:
							dataArray = make([]byte, len(d))
							for i, value := range d {
								dataArray[i] = byte(value.(float64))
							}
						}
					case "item":
						if v.(bool) {
							mass = Item
							transparency = Transparent
						} else {
							mass = Mass
							transparency = Opaque
						}
					case "transparent":
						if v.(bool) {
							transparency = Transparent
						} else {
							transparency = Opaque
						}
					case "empty":
						if v.(bool) {
							empty = true
							transparency = Transparent
							mass = Mass
						} else {
							empty = false
						}
					}
				}

				blockTypeMap[blockId] = &BlockType{blockId, mass, transparency, empty}
				if dataArray == nil {
					if data != 255 {
						extraData[blockId] = true
						colors = append(colors, MTL{blockId, data, color, name})
					} else {
						colors[blockId] = MTL{blockId, data, color, name}
					}
				} else {
					extraData[blockId] = true
					for _, data = range dataArray {
						colors = append(colors, MTL{blockId, data, color, fmt.Sprintf("%s_%d", name, data)})
					}
				}
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package testutils

import (
	"sync"

	. "firempq/api"
	"sort"
	"strings"
)

type InMemDBService struct {
	mutex   sync.Mutex
	mapData map[string]string
	closed  bool
}

func NewInMemDBService() *InMemDBService {
	return &InMemDBService{
		mapData: make(map[string]string),
	}
}

func (d *InMemDBService) WaitFlush()     {}
func (d *InMemDBService) Close()         { d.closed = true }
func (d *InMemDBService) IsClosed() bool { return d.closed }

func (d *InMemDBService) CachedStore(data ...string) {
	if len(data)%2 != 0 {
		panic("Number of arguments should be even!")
	}
	d.mutex.Lock()
	for i := 0; i < len(data); i += 2 {
		d.mapData[data[i]] = data[i+1]
	}
	d.mutex.Unlock()
}

func (d *InMemDBService) DeleteDataWithPrefix(prefix string) int {
	d.mutex.Lock()
	keys := make([]string, 10)
	for k, _ := range d.mapData {
		if strings.HasPrefix(k, prefix) {
			keys = append(keys, k)
		}
	}
	for _, k := range keys {
		delete(d.mapData, k)
	}
	d.mutex.Unlock()
	return len(keys)
}

func (d *InMemDBService) StoreData(data ...string) error {
	d.CachedStore(data...)
	return nil
}

func (d *InMemDBService) DeleteData(id ...string) {
	d.mutex.Lock()
	for _, k := range id {
		delete(d.mapData, k)
	}
	d.mutex.Unlock()
}

func (d *InMemDBService) CachedDeleteData(id ...string) {
	d.DeleteData(id...)
}

func (d *InMemDBService) IterData(prefix string) ItemIterator {
	return NewInMemIterator(d.mapData, prefix)
}

func (d *InMemDBService) GetData(id string) string {
	d.mutex.Lock()
	defer d.mutex.Unlock()
	return d.mapData[id]
}

type InMemIterator struct {
	keyList []string
	curPos  int
	prefix  string
	data    map[string]string
}

func NewInMemIterator(data map[string]string, prefix string) *InMemIterator {
	keylist := make([]string, 0, 100)
	dataCopy := make(map[string]string)
	for k, v := range data {
		if strings.HasPrefix(k, prefix) {
			keylist = append(keylist, k)
			dataCopy[k] = v
		}
	}
	sort.Strings(keylist)

	return &InMemIterator{
		keyList: keylist,
		prefix:  prefix,
		curPos:  0,
		data:    dataCopy,
	}
}

func (iter *InMemIterator) Next() {
	iter.curPos++
}

func (iter *InMemIterator) Valid() bool {
	return iter.curPos < len(iter.keyList)
}

func (iter *InMemIterator) GetValue() []byte {
	return []byte(iter.data[iter.keyList[iter.curPos]])
}

func (iter *InMemIterator) GetKey() []byte {
	return []byte(iter.keyList[iter.curPos])
}

func (iter *InMemIterator) GetTrimKey() []byte {
	return iter.GetKey()[len(iter.prefix):]
}

func (iter *InMemIterator) Close() {}
<commit_msg>Added new GetStats method for in mem db.<commit_after>package testutils

import (
	"sync"

	. "firempq/api"
	"sort"
	"strings"
)

type InMemDBService struct {
	mutex   sync.Mutex
	mapData map[string]string
	closed  bool
}

func NewInMemDBService() *InMemDBService {
	return &InMemDBService{
		mapData: make(map[string]string),
	}
}

func (d *InMemDBService) WaitFlush()     {}
func (d *InMemDBService) Close()         { d.closed = true }
func (d *InMemDBService) IsClosed() bool { return d.closed }

func (d *InMemDBService) CachedStore(data ...string) {
	if len(data)%2 != 0 {
		panic("Number of arguments should be even!")
	}
	d.mutex.Lock()
	for i := 0; i < len(data); i += 2 {
		d.mapData[data[i]] = data[i+1]
	}
	d.mutex.Unlock()
}

func (d *InMemDBService) GetStats() map[string]interface{} {
	return map[string]interface{}{
		"Size":   len(d.mapData),
		"Closed": d.closed,
	}
}

func (d *InMemDBService) DeleteDataWithPrefix(prefix string) int {
	d.mutex.Lock()
	keys := make([]string, 10)
	for k, _ := range d.mapData {
		if strings.HasPrefix(k, prefix) {
			keys = append(keys, k)
		}
	}
	for _, k := range keys {
		delete(d.mapData, k)
	}
	d.mutex.Unlock()
	return len(keys)
}

func (d *InMemDBService) StoreData(data ...string) error {
	d.CachedStore(data...)
	return nil
}

func (d *InMemDBService) DeleteData(id ...string) {
	d.mutex.Lock()
	for _, k := range id {
		delete(d.mapData, k)
	}
	d.mutex.Unlock()
}

func (d *InMemDBService) CachedDeleteData(id ...string) {
	d.DeleteData(id...)
}

func (d *InMemDBService) IterData(prefix string) ItemIterator {
	return NewInMemIterator(d.mapData, prefix)
}

func (d *InMemDBService) GetData(id string) string {
	d.mutex.Lock()
	defer d.mutex.Unlock()
	return d.mapData[id]
}

type InMemIterator struct {
	keyList []string
	curPos  int
	prefix  string
	data    map[string]string
}

func NewInMemIterator(data map[string]string, prefix string) *InMemIterator {
	keylist := make([]string, 0, 100)
	dataCopy := make(map[string]string)
	for k, v := range data {
		if strings.HasPrefix(k, prefix) {
			keylist = append(keylist, k)
			dataCopy[k] = v
		}
	}
	sort.Strings(keylist)

	return &InMemIterator{
		keyList: keylist,
		prefix:  prefix,
		curPos:  0,
		data:    dataCopy,
	}
}

func (iter *InMemIterator) Next() {
	iter.curPos++
}

func (iter *InMemIterator) Valid() bool {
	return iter.curPos < len(iter.keyList)
}

func (iter *InMemIterator) GetValue() []byte {
	return []byte(iter.data[iter.keyList[iter.curPos]])
}

func (iter *InMemIterator) GetKey() []byte {
	return []byte(iter.keyList[iter.curPos])
}

func (iter *InMemIterator) GetTrimKey() []byte {
	return iter.GetKey()[len(iter.prefix):]
}

func (iter *InMemIterator) Close() {}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 blob

import (
	"fmt"
	"github.com/jacobsa/crypto/siv"
)

// A Crypter knows how to encrypt and decrypt arbitrary byte strings.
type Crypter interface {
	Encrypt(plaintext []byte) (ciphertext []byte, err error)
	Decrypt(ciphertext []byte) (plaintext []byte, err error)
}

// Return a crypter configured to use AES-SIV deterministic decryption (see RFC
// 5297) with the supplied key. The key must be 32, 48, or 64 bytes long.
func NewCrypter(key []byte) (Crypter, error) {
	switch len(key) {
	case 32, 48, 64:
	default:
		return nil, fmt.Errorf("NewCrypter requires a 32-, 48-, or 64-byte key.")
	}

	return &sivCrypter{key}, nil
}

type sivCrypter struct {
	key []byte
}

func (c *sivCrypter) Encrypt(plaintext []byte) ([]byte, error) {
	return siv.Encrypt(c.key, plaintext, nil)
}

func (c *sivCrypter) Decrypt(ciphertext []byte) ([]byte, error) {
	return siv.Decrypt(c.key, ciphertext, nil)
}
<commit_msg>Defined NotAuthenticError.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 blob

import (
	"fmt"
	"github.com/jacobsa/crypto/siv"
)

// A Crypter knows how to encrypt and decrypt arbitrary byte strings.
type Crypter interface {
	Encrypt(plaintext []byte) (ciphertext []byte, err error)
	Decrypt(ciphertext []byte) (plaintext []byte, err error)
}

// NotAuthenticError may be returned by Crypter.Decrypt if the input is
// otherwise well-formed but the ciphertext doesn't check out as authentic.
// This could be due to an incorrect key or corrupted ciphertext.
type NotAuthenticError string

func (e NotAuthenticError) Error() string {
	return string(e)
}

// Return a crypter configured to use AES-SIV deterministic decryption with
// authentication (see RFC 5297) with the supplied key. The key must be 32, 48,
// or 64 bytes long.
func NewCrypter(key []byte) (Crypter, error) {
	switch len(key) {
	case 32, 48, 64:
	default:
		return nil, fmt.Errorf("NewCrypter requires a 32-, 48-, or 64-byte key.")
	}

	return &sivCrypter{key}, nil
}

type sivCrypter struct {
	key []byte
}

func (c *sivCrypter) Encrypt(plaintext []byte) ([]byte, error) {
	return siv.Encrypt(c.key, plaintext, nil)
}

func (c *sivCrypter) Decrypt(ciphertext []byte) ([]byte, error) {
	return siv.Decrypt(c.key, ciphertext, nil)
}
<|endoftext|>


<commit_before>package dns_resource_record

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	softlayer "github.com/maximilien/softlayer-go/softlayer"
	testhelpers "github.com/maximilien/softlayer-go/test_helpers"
)

var _ = Describe("SoftLayer DNS Resource Records", func() {
	var (
		err								 error
		dnsDomainResourceRecordService 	 softlayer.SoftLayer_Dns_Domain_Resource_Record_Service
	)

	BeforeEach(func() {
		dnsDomainResourceRecordService, err = testhelpers.CreateDnsDomainResourceRecordService()
		Expect(err).ToNot(HaveOccurred())

		testhelpers.TIMEOUT = 30 * time.Second
		testhelpers.POLLING_INTERVAL = 10 * time.Second
	})

	Context("SoftLayer_Dns_Domain_ResourceRecord", func() {
		It("creates a DNS Domain resource record, update it, and delete it", func() {
			domainId := 123456
			createdDnsDomainResourceRecord, _ := testhelpers.CreateTestDnsDomainResourceRecord(domainId)

			testhelpers.WaitForCreatedDnsDomainResourceRecordToBePresent(createdDnsDomainResourceRecord.Id)

			result, err := dnsDomainResourceRecordService.GetObject(createdDnsDomainResourceRecord.Id)
			Expect(err).ToNot(HaveOccurred())

			Expect(result.Data).To(Equal("127.0.0.1"))
			Expect(result.Host).To(Equal("test.example.com"))
			Expect(result.ResponsiblePerson).To(Equal("testemail@sl.com"))
			Expect(result.Ttl).To(Equal(900))
			Expect(result.Type).To(Equal("a"))

			oldHost := result.Host
			oldResponsiblePerson := result.ResponsiblePerson

			result.Host = "edited.test.example.com"
			result.ResponsiblePerson = "editedtestemail@sl.com"
			dnsDomainResourceRecordService.EditObject(createdDnsDomainResourceRecord.Id, result)

			result2, err := dnsDomainResourceRecordService.GetObject(createdDnsDomainResourceRecord.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(result2.Host).To(Equal("edited.test.example.com"))
			Expect(result2.ResponsiblePerson).To(Equal("editedtestemail@sl.com"))

			deleted, err := dnsDomainResourceRecordService.DeleteObject(createdDnsDomainResourceRecord.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(deleted).To(BeTrue())

			testhelpers.WaitForDeletedDnsDomainResourceRecordToNoLongerBePresent(createdDnsDomainResourceRecord.Id)
		})
	})
})

<commit_msg>update integration test for Dns domain resource record. Test DnsDomain is added<commit_after>package dns_resource_record

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	softlayer "github.com/maximilien/softlayer-go/softlayer"
	testhelpers "github.com/maximilien/softlayer-go/test_helpers"
)

var _ = Describe("SoftLayer DNS Resource Records", func() {
	var (
		err								 error
		dnsDomainResourceRecordService 	 softlayer.SoftLayer_Dns_Domain_Resource_Record_Service
		dnsDomainService 	 			 softlayer.SoftLayer_Dns_Domain_Service
	)

	BeforeEach(func() {
		dnsDomainResourceRecordService, err = testhelpers.CreateDnsDomainResourceRecordService()
		Expect(err).ToNot(HaveOccurred())

		dnsDomainService, err = testhelpers.CreateDnsDomainService()
		Expect(err).ToNot(HaveOccurred())

		testhelpers.TIMEOUT = 30 * time.Second
		testhelpers.POLLING_INTERVAL = 10 * time.Second
	})

	Context("SoftLayer_Dns_Domain_ResourceRecord", func() {
		It("creates a DNS Domain resource record, update it, and delete it", func() {
			testDnsDomain := testhelpers.CreateTestDnsDomain()
			createdDnsDomainResourceRecord, _ := testhelpers.CreateTestDnsDomainResourceRecord(testDnsDomain.Id)

			testhelpers.WaitForCreatedDnsDomainResourceRecordToBePresent(createdDnsDomainResourceRecord.Id)

			result, err := dnsDomainResourceRecordService.GetObject(createdDnsDomainResourceRecord.Id)
			Expect(err).ToNot(HaveOccurred())

			Expect(result.Data).To(Equal("127.0.0.1"))
			Expect(result.Host).To(Equal("test.example.com"))
			Expect(result.ResponsiblePerson).To(Equal("testemail@sl.com"))
			Expect(result.Ttl).To(Equal(900))
			Expect(result.Type).To(Equal("a"))

			result.Host = "edited.test.example.com"
			result.ResponsiblePerson = "editedtestemail@sl.com"
			dnsDomainResourceRecordService.EditObject(createdDnsDomainResourceRecord.Id, result)

			result2, err := dnsDomainResourceRecordService.GetObject(createdDnsDomainResourceRecord.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(result2.Host).To(Equal("edited.test.example.com"))
			Expect(result2.ResponsiblePerson).To(Equal("editedtestemail@sl.com"))

			deleted, err := dnsDomainResourceRecordService.DeleteObject(createdDnsDomainResourceRecord.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(deleted).To(BeTrue())

			testhelpers.WaitForDeletedDnsDomainResourceRecordToNoLongerBePresent(createdDnsDomainResourceRecord.Id)

			//clean up
			deletedDns, err := dnsDomainService.DeleteObject(testDnsDomain.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(deletedDns).To(BeTrue())

			testhelpers.WaitForDeletedDnsDomainToNoLongerBePresent(testDnsDomain.Id)
		})
	})
})

<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudfront"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsCloudFrontOriginAccessIdentity() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsCloudFrontOriginAccessIdentityCreate,
		Read:   resourceAwsCloudFrontOriginAccessIdentityRead,
		Update: resourceAwsCloudFrontOriginAccessIdentityUpdate,
		Delete: resourceAwsCloudFrontOriginAccessIdentityDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"comment": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "",
			},
			"caller_reference": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"cloudfront_access_identity_path": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"etag": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"iam_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"s3_canonical_user_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsCloudFrontOriginAccessIdentityCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.CreateCloudFrontOriginAccessIdentityInput{
		CloudFrontOriginAccessIdentityConfig: expandOriginAccessIdentityConfig(d),
	}

	resp, err := conn.CreateCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}
	d.SetId(*resp.CloudFrontOriginAccessIdentity.Id)
	return resourceAwsCloudFrontOriginAccessIdentityRead(d, meta)
}

func resourceAwsCloudFrontOriginAccessIdentityRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.GetCloudFrontOriginAccessIdentityInput{
		Id: aws.String(d.Id()),
	}

	resp, err := conn.GetCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}

	// Update attributes from DistributionConfig
	flattenOriginAccessIdentityConfig(d, resp.CloudFrontOriginAccessIdentity.CloudFrontOriginAccessIdentityConfig)
	// Update other attributes outside of DistributionConfig
	d.SetId(*resp.CloudFrontOriginAccessIdentity.Id)
	d.Set("etag", resp.ETag)
	d.Set("s3_canonical_user_id", resp.CloudFrontOriginAccessIdentity.S3CanonicalUserId)
	d.Set("cloudfront_access_identity_path", fmt.Sprintf("origin-access-identity/cloudfront/%s", *resp.CloudFrontOriginAccessIdentity.Id))
	d.Set("iam_arn", fmt.Sprintf("arn:%s:iam::cloudfront:user/CloudFront Origin Access Identity %s",
		meta.(*AWSClient).partition, *resp.CloudFrontOriginAccessIdentity.Id))
	return nil
}

func resourceAwsCloudFrontOriginAccessIdentityUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.UpdateCloudFrontOriginAccessIdentityInput{
		Id: aws.String(d.Id()),
		CloudFrontOriginAccessIdentityConfig: expandOriginAccessIdentityConfig(d),
		IfMatch: aws.String(d.Get("etag").(string)),
	}
	_, err := conn.UpdateCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}

	return resourceAwsCloudFrontOriginAccessIdentityRead(d, meta)
}

func resourceAwsCloudFrontOriginAccessIdentityDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.DeleteCloudFrontOriginAccessIdentityInput{
		Id:      aws.String(d.Id()),
		IfMatch: aws.String(d.Get("etag").(string)),
	}

	_, err := conn.DeleteCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}

	// Done
	d.SetId("")
	return nil
}

func expandOriginAccessIdentityConfig(d *schema.ResourceData) *cloudfront.OriginAccessIdentityConfig {
	originAccessIdentityConfig := &cloudfront.OriginAccessIdentityConfig{
		Comment: aws.String(d.Get("comment").(string)),
	}
	// This sets CallerReference if it's still pending computation (ie: new resource)
	if v, ok := d.GetOk("caller_reference"); ok == false {
		originAccessIdentityConfig.CallerReference = aws.String(time.Now().Format(time.RFC3339Nano))
	} else {
		originAccessIdentityConfig.CallerReference = aws.String(v.(string))
	}
	return originAccessIdentityConfig
}

func flattenOriginAccessIdentityConfig(d *schema.ResourceData, originAccessIdentityConfig *cloudfront.OriginAccessIdentityConfig) {
	if originAccessIdentityConfig.Comment != nil {
		d.Set("comment", originAccessIdentityConfig.Comment)
	}
	d.Set("caller_reference", originAccessIdentityConfig.CallerReference)
}
<commit_msg>Use AWS ARN structure - aws_cloudfront_origin_access_identity resource.<commit_after>package aws

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/arn"
	"github.com/aws/aws-sdk-go/service/cloudfront"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsCloudFrontOriginAccessIdentity() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsCloudFrontOriginAccessIdentityCreate,
		Read:   resourceAwsCloudFrontOriginAccessIdentityRead,
		Update: resourceAwsCloudFrontOriginAccessIdentityUpdate,
		Delete: resourceAwsCloudFrontOriginAccessIdentityDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"comment": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "",
			},
			"caller_reference": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"cloudfront_access_identity_path": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"etag": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"iam_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"s3_canonical_user_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsCloudFrontOriginAccessIdentityCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.CreateCloudFrontOriginAccessIdentityInput{
		CloudFrontOriginAccessIdentityConfig: expandOriginAccessIdentityConfig(d),
	}

	resp, err := conn.CreateCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}
	d.SetId(*resp.CloudFrontOriginAccessIdentity.Id)
	return resourceAwsCloudFrontOriginAccessIdentityRead(d, meta)
}

func resourceAwsCloudFrontOriginAccessIdentityRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.GetCloudFrontOriginAccessIdentityInput{
		Id: aws.String(d.Id()),
	}

	resp, err := conn.GetCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}

	// Update attributes from DistributionConfig
	flattenOriginAccessIdentityConfig(d, resp.CloudFrontOriginAccessIdentity.CloudFrontOriginAccessIdentityConfig)
	// Update other attributes outside of DistributionConfig
	d.SetId(*resp.CloudFrontOriginAccessIdentity.Id)
	d.Set("etag", resp.ETag)
	d.Set("s3_canonical_user_id", resp.CloudFrontOriginAccessIdentity.S3CanonicalUserId)
	d.Set("cloudfront_access_identity_path", fmt.Sprintf("origin-access-identity/cloudfront/%s", *resp.CloudFrontOriginAccessIdentity.Id))
	iamArn := arn.ARN{
		Partition: meta.(*AWSClient).partition,
		Service:   "iam",
		AccountID: "cloudfront",
		Resource:  fmt.Sprintf("user/CloudFront Origin Access Identity %s", *resp.CloudFrontOriginAccessIdentity.Id),
	}
	d.Set("iam_arn", iamArn.String())
	return nil
}

func resourceAwsCloudFrontOriginAccessIdentityUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.UpdateCloudFrontOriginAccessIdentityInput{
		Id: aws.String(d.Id()),
		CloudFrontOriginAccessIdentityConfig: expandOriginAccessIdentityConfig(d),
		IfMatch: aws.String(d.Get("etag").(string)),
	}
	_, err := conn.UpdateCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}

	return resourceAwsCloudFrontOriginAccessIdentityRead(d, meta)
}

func resourceAwsCloudFrontOriginAccessIdentityDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).cloudfrontconn
	params := &cloudfront.DeleteCloudFrontOriginAccessIdentityInput{
		Id:      aws.String(d.Id()),
		IfMatch: aws.String(d.Get("etag").(string)),
	}

	_, err := conn.DeleteCloudFrontOriginAccessIdentity(params)
	if err != nil {
		return err
	}

	// Done
	d.SetId("")
	return nil
}

func expandOriginAccessIdentityConfig(d *schema.ResourceData) *cloudfront.OriginAccessIdentityConfig {
	originAccessIdentityConfig := &cloudfront.OriginAccessIdentityConfig{
		Comment: aws.String(d.Get("comment").(string)),
	}
	// This sets CallerReference if it's still pending computation (ie: new resource)
	if v, ok := d.GetOk("caller_reference"); ok == false {
		originAccessIdentityConfig.CallerReference = aws.String(time.Now().Format(time.RFC3339Nano))
	} else {
		originAccessIdentityConfig.CallerReference = aws.String(v.(string))
	}
	return originAccessIdentityConfig
}

func flattenOriginAccessIdentityConfig(d *schema.ResourceData, originAccessIdentityConfig *cloudfront.OriginAccessIdentityConfig) {
	if originAccessIdentityConfig.Comment != nil {
		d.Set("comment", originAccessIdentityConfig.Comment)
	}
	d.Set("caller_reference", originAccessIdentityConfig.CallerReference)
}
<|endoftext|>


<commit_before>package terraform

import (
	"encoding/json"
	"fmt"
	"sync"

	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/config/hcl2shim"
	"github.com/hashicorp/terraform/providers"
	"github.com/hashicorp/terraform/tfdiags"
)

var _ providers.Interface = (*MockProvider)(nil)

// MockProvider implements providers.Interface but mocks out all the
// calls for testing purposes.
type MockProvider struct {
	sync.Mutex

	// Anything you want, in case you need to store extra data with the mock.
	Meta interface{}

	GetSchemaCalled bool
	GetSchemaReturn *ProviderSchema // This is using ProviderSchema directly rather than providers.GetSchemaResponse for compatibility with old tests

	ValidateProviderConfigCalled   bool
	ValidateProviderConfigResponse providers.ValidateProviderConfigResponse
	ValidateProviderConfigRequest  providers.ValidateProviderConfigRequest
	ValidateProviderConfigFn       func(providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse

	ValidateResourceTypeConfigCalled   bool
	ValidateResourceTypeConfigTypeName string
	ValidateResourceTypeConfigResponse providers.ValidateResourceTypeConfigResponse
	ValidateResourceTypeConfigRequest  providers.ValidateResourceTypeConfigRequest
	ValidateResourceTypeConfigFn       func(providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse

	ValidateDataSourceConfigCalled   bool
	ValidateDataSourceConfigTypeName string
	ValidateDataSourceConfigResponse providers.ValidateDataSourceConfigResponse
	ValidateDataSourceConfigRequest  providers.ValidateDataSourceConfigRequest
	ValidateDataSourceConfigFn       func(providers.ValidateDataSourceConfigRequest) providers.ValidateDataSourceConfigResponse

	UpgradeResourceStateCalled   bool
	UpgradeResourceStateTypeName string
	UpgradeResourceStateResponse providers.UpgradeResourceStateResponse
	UpgradeResourceStateRequest  providers.UpgradeResourceStateRequest
	UpgradeResourceStateFn       func(providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse

	ConfigureCalled   bool
	ConfigureResponse providers.ConfigureResponse
	ConfigureRequest  providers.ConfigureRequest
	ConfigureNewFn    func(providers.ConfigureRequest) providers.ConfigureResponse // Named ConfigureNewFn so we can still have the legacy ConfigureFn declared below

	StopCalled   bool
	StopFn       func() error
	StopResponse error

	ReadResourceCalled   bool
	ReadResourceResponse providers.ReadResourceResponse
	ReadResourceRequest  providers.ReadResourceRequest
	ReadResourceFn       func(providers.ReadResourceRequest) providers.ReadResourceResponse

	PlanResourceChangeCalled   bool
	PlanResourceChangeResponse providers.PlanResourceChangeResponse
	PlanResourceChangeRequest  providers.PlanResourceChangeRequest
	PlanResourceChangeFn       func(providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse

	ApplyResourceChangeCalled   bool
	ApplyResourceChangeResponse providers.ApplyResourceChangeResponse
	ApplyResourceChangeRequest  providers.ApplyResourceChangeRequest
	ApplyResourceChangeFn       func(providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse

	ImportResourceStateCalled   bool
	ImportResourceStateResponse providers.ImportResourceStateResponse
	ImportResourceStateRequest  providers.ImportResourceStateRequest
	ImportResourceStateFn       func(providers.ImportResourceStateRequest) providers.ImportResourceStateResponse
	// Legacy return type for existing tests, which will be shimmed into an
	// ImportResourceStateResponse if set
	ImportStateReturn []*InstanceState

	ReadDataSourceCalled   bool
	ReadDataSourceResponse providers.ReadDataSourceResponse
	ReadDataSourceRequest  providers.ReadDataSourceRequest
	ReadDataSourceFn       func(providers.ReadDataSourceRequest) providers.ReadDataSourceResponse

	CloseCalled bool
	CloseError  error

	// Legacy callbacks: if these are set, we will shim incoming calls for
	// new-style methods to these old-fashioned terraform.ResourceProvider
	// mock callbacks, for the benefit of older tests that were written against
	// the old mock API.
	ValidateFn  func(c *ResourceConfig) (ws []string, es []error)
	ConfigureFn func(c *ResourceConfig) error
	DiffFn      func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error)
	ApplyFn     func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error)
}

func (p *MockProvider) GetSchema() providers.GetSchemaResponse {
	p.Lock()
	defer p.Unlock()
	return p.getSchema()
}

func (p *MockProvider) getSchema() providers.GetSchemaResponse {
	// This version of getSchema doesn't do any locking, so it's suitable to
	// call from other methods of this mock as long as they are already
	// holding the lock.

	p.GetSchemaCalled = true
	ret := providers.GetSchemaResponse{
		Provider: providers.Schema{
			Block: p.GetSchemaReturn.Provider,
		},
		DataSources:   map[string]providers.Schema{},
		ResourceTypes: map[string]providers.Schema{},
	}
	for n, s := range p.GetSchemaReturn.DataSources {
		ret.DataSources[n] = providers.Schema{
			Block: s,
		}
	}
	for n, s := range p.GetSchemaReturn.ResourceTypes {
		ret.ResourceTypes[n] = providers.Schema{
			Block: s,
		}
	}
	return ret
}

func (p *MockProvider) ValidateProviderConfig(r providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse {
	p.Lock()
	defer p.Unlock()

	p.ValidateProviderConfigCalled = true
	p.ValidateProviderConfigRequest = r
	if p.ValidateProviderConfigFn != nil {
		return p.ValidateProviderConfigFn(r)
	}
	return p.ValidateProviderConfigResponse
}

func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
	p.Lock()
	defer p.Unlock()

	p.ValidateResourceTypeConfigCalled = true
	p.ValidateResourceTypeConfigRequest = r

	if p.ValidateFn != nil {
		return providers.ValidateResourceTypeConfigResponse{
			Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("legacy ValidateFn handling in MockProvider not actually implemented yet")),
		}
	}
	if p.ValidateResourceTypeConfigFn != nil {
		return p.ValidateResourceTypeConfigFn(r)
	}

	return p.ValidateResourceTypeConfigResponse
}

func (p *MockProvider) ValidateDataSourceConfig(r providers.ValidateDataSourceConfigRequest) providers.ValidateDataSourceConfigResponse {
	p.Lock()
	defer p.Unlock()

	p.ValidateDataSourceConfigCalled = true
	p.ValidateDataSourceConfigRequest = r

	if p.ValidateDataSourceConfigFn != nil {
		return p.ValidateDataSourceConfigFn(r)
	}

	return p.ValidateDataSourceConfigResponse
}

func (p *MockProvider) UpgradeResourceState(r providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse {
	p.Lock()
	defer p.Unlock()

	p.UpgradeResourceStateCalled = true
	p.UpgradeResourceStateRequest = r

	if p.UpgradeResourceStateFn != nil {
		return p.UpgradeResourceStateFn(r)
	}

	return p.UpgradeResourceStateResponse
}

func (p *MockProvider) Configure(r providers.ConfigureRequest) providers.ConfigureResponse {
	p.Lock()
	defer p.Unlock()

	p.ConfigureCalled = true
	p.ConfigureRequest = r

	if p.ConfigureFn != nil {
		resp := p.getSchema()
		schema := resp.Provider.Block
		rc := NewResourceConfigShimmed(r.Config, schema)
		ret := providers.ConfigureResponse{}

		err := p.ConfigureFn(rc)
		if err != nil {
			ret.Diagnostics = ret.Diagnostics.Append(err)
		}
		return ret
	}
	if p.ConfigureNewFn != nil {
		return p.ConfigureNewFn(r)
	}

	return p.ConfigureResponse
}

func (p *MockProvider) Stop() error {
	p.Lock()
	defer p.Unlock()

	p.StopCalled = true
	if p.StopFn != nil {
		return p.StopFn()
	}

	return p.StopResponse
}

func (p *MockProvider) ReadResource(r providers.ReadResourceRequest) providers.ReadResourceResponse {
	p.Lock()
	defer p.Unlock()

	p.ReadResourceCalled = true
	p.ReadResourceRequest = r

	if p.ReadResourceFn != nil {
		return p.ReadResourceFn(r)
	}

	return p.ReadResourceResponse
}

func (p *MockProvider) PlanResourceChange(r providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
	p.PlanResourceChangeCalled = true
	p.PlanResourceChangeRequest = r

	if p.DiffFn != nil {
		ps := p.getSchema()
		if ps.ResourceTypes == nil || ps.ResourceTypes[r.TypeName].Block == nil {
			return providers.PlanResourceChangeResponse{
				Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Printf("mock provider has no schema for resource type %s", r.TypeName)),
			}
		}
		schema := ps.ResourceTypes[r.TypeName].Block
		info := &InstanceInfo{
			Type: r.TypeName,
		}
		priorState := NewInstanceStateShimmedFromValue(r.PriorState, 0)
		cfg := NewResourceConfigShimmed(r.Config, schema)
		legacyDiff, err := p.DiffFn(info, priorState, cfg)

		var res providers.PlanResourceChangeResponse
		res.PlannedState = cty.NullVal(schema.ImpliedType()) // mimic how an absent value would arrive over the GRPC channel
		if err != nil {
			res.Diagnostics = res.Diagnostics.Append(err)
		}
		if legacyDiff != nil {
			newVal, err := legacyDiff.ApplyToValue(r.PriorState, schema)
			if err != nil {
				res.Diagnostics = res.Diagnostics.Append(err)
			}
			res.PlannedState = newVal

			var requiresNew []string
			for attr, d := range legacyDiff.Attributes {
				if d.RequiresNew {
					requiresNew = append(requiresNew, attr)
				}
			}
			requiresReplace, err := hcl2shim.RequiresReplace(requiresNew, schema.ImpliedType())
			if err != nil {
				res.Diagnostics = res.Diagnostics.Append(err)
			}
			res.RequiresReplace = requiresReplace
		}
		return res

	}
	if p.PlanResourceChangeFn != nil {
		return p.PlanResourceChangeFn(r)
	}

	return p.PlanResourceChangeResponse
}

func (p *MockProvider) ApplyResourceChange(r providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
	p.Lock()
	p.ApplyResourceChangeCalled = true
	p.ApplyResourceChangeRequest = r
	p.Unlock()

	if p.ApplyFn != nil {
		// ApplyFn is a special callback fashioned after our old provider
		// interface, which expected to be given an actual diff rather than
		// separate old/new values to apply. Therefore we need to approximate
		// a diff here well enough that _most_ of our legacy ApplyFns in old
		// tests still see the behavior they are expecting. New tests should
		// not use this, and should instead use ApplyResourceChangeFn directly.
		providerSchema := p.getSchema()
		schema, ok := providerSchema.ResourceTypes[r.TypeName]
		if !ok {
			return providers.ApplyResourceChangeResponse{
				Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("no mocked schema available for resource type %s", r.TypeName)),
			}
		}

		info := &InstanceInfo{
			Type: r.TypeName,
		}

		priorVal := r.PriorState
		plannedVal := r.PlannedState
		priorMap := hcl2shim.FlatmapValueFromHCL2(priorVal)
		plannedMap := hcl2shim.FlatmapValueFromHCL2(plannedVal)
		s := NewInstanceStateShimmedFromValue(priorVal, 0)
		d := &InstanceDiff{
			Attributes: make(map[string]*ResourceAttrDiff),
		}
		if plannedMap == nil { // destroying, then
			d.Destroy = true
			// Destroy diffs don't have any attribute diffs
		} else {
			if priorMap == nil { // creating, then
				// We'll just make an empty prior map to make things easier below.
				priorMap = make(map[string]string)
			}

			for k, new := range plannedMap {
				old := priorMap[k]
				newComputed := false
				if new == config.UnknownVariableValue {
					new = ""
					newComputed = true
				}
				d.Attributes[k] = &ResourceAttrDiff{
					Old:         old,
					New:         new,
					NewComputed: newComputed,
					Type:        DiffAttrInput, // not generally used in tests, so just hard-coded
				}
			}
			// Also need any attributes that were removed in "planned"
			for k, old := range priorMap {
				if _, ok := plannedMap[k]; ok {
					continue
				}
				d.Attributes[k] = &ResourceAttrDiff{
					Old:        old,
					NewRemoved: true,
					Type:       DiffAttrInput,
				}
			}
		}
		newState, err := p.ApplyFn(info, s, d)
		resp := providers.ApplyResourceChangeResponse{}
		if err != nil {
			resp.Diagnostics = resp.Diagnostics.Append(err)
		}
		newVal, err := newState.AttrsAsObjectValue(schema.Block.ImpliedType())
		if err != nil {
			resp.Diagnostics = resp.Diagnostics.Append(err)
		}
		resp.NewState = newVal

		return resp
	}
	if p.ApplyResourceChangeFn != nil {
		return p.ApplyResourceChangeFn(r)
	}

	return p.ApplyResourceChangeResponse
}

func (p *MockProvider) ImportResourceState(r providers.ImportResourceStateRequest) providers.ImportResourceStateResponse {
	p.Lock()
	defer p.Unlock()

	if p.ImportStateReturn != nil {
		for _, is := range p.ImportStateReturn {
			if is.Attributes == nil {
				is.Attributes = make(map[string]string)
			}
			is.Attributes["id"] = is.ID
			schema := p.GetSchemaReturn.ResourceTypes[r.TypeName]
			private, err := json.Marshal(is.Meta)
			if err != nil {
				panic(err)
			}

			state, err := hcl2shim.HCL2ValueFromFlatmap(is.Attributes, schema.ImpliedType())
			if err != nil {
				panic(err)
			}
			p.ImportResourceStateResponse.ImportedResources = append(
				p.ImportResourceStateResponse.ImportedResources,
				providers.ImportedResource{
					TypeName: r.TypeName,
					State:    state,
					Private:  private,
				})
		}
	}

	p.ImportResourceStateCalled = true
	p.ImportResourceStateRequest = r
	if p.ImportResourceStateFn != nil {
		return p.ImportResourceStateFn(r)
	}

	return p.ImportResourceStateResponse
}

func (p *MockProvider) ReadDataSource(r providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
	p.Lock()
	defer p.Unlock()

	p.ReadDataSourceCalled = true
	p.ReadDataSourceRequest = r

	if p.ReadDataSourceFn != nil {
		return p.ReadDataSourceFn(r)
	}

	return p.ReadDataSourceResponse
}

func (p *MockProvider) Close() error {
	p.CloseCalled = true
	return p.CloseError
}
<commit_msg>core: Implement ValidateFn shim for MockProvider<commit_after>package terraform

import (
	"encoding/json"
	"fmt"
	"sync"

	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/config/hcl2shim"
	"github.com/hashicorp/terraform/providers"
	"github.com/hashicorp/terraform/tfdiags"
)

var _ providers.Interface = (*MockProvider)(nil)

// MockProvider implements providers.Interface but mocks out all the
// calls for testing purposes.
type MockProvider struct {
	sync.Mutex

	// Anything you want, in case you need to store extra data with the mock.
	Meta interface{}

	GetSchemaCalled bool
	GetSchemaReturn *ProviderSchema // This is using ProviderSchema directly rather than providers.GetSchemaResponse for compatibility with old tests

	ValidateProviderConfigCalled   bool
	ValidateProviderConfigResponse providers.ValidateProviderConfigResponse
	ValidateProviderConfigRequest  providers.ValidateProviderConfigRequest
	ValidateProviderConfigFn       func(providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse

	ValidateResourceTypeConfigCalled   bool
	ValidateResourceTypeConfigTypeName string
	ValidateResourceTypeConfigResponse providers.ValidateResourceTypeConfigResponse
	ValidateResourceTypeConfigRequest  providers.ValidateResourceTypeConfigRequest
	ValidateResourceTypeConfigFn       func(providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse

	ValidateDataSourceConfigCalled   bool
	ValidateDataSourceConfigTypeName string
	ValidateDataSourceConfigResponse providers.ValidateDataSourceConfigResponse
	ValidateDataSourceConfigRequest  providers.ValidateDataSourceConfigRequest
	ValidateDataSourceConfigFn       func(providers.ValidateDataSourceConfigRequest) providers.ValidateDataSourceConfigResponse

	UpgradeResourceStateCalled   bool
	UpgradeResourceStateTypeName string
	UpgradeResourceStateResponse providers.UpgradeResourceStateResponse
	UpgradeResourceStateRequest  providers.UpgradeResourceStateRequest
	UpgradeResourceStateFn       func(providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse

	ConfigureCalled   bool
	ConfigureResponse providers.ConfigureResponse
	ConfigureRequest  providers.ConfigureRequest
	ConfigureNewFn    func(providers.ConfigureRequest) providers.ConfigureResponse // Named ConfigureNewFn so we can still have the legacy ConfigureFn declared below

	StopCalled   bool
	StopFn       func() error
	StopResponse error

	ReadResourceCalled   bool
	ReadResourceResponse providers.ReadResourceResponse
	ReadResourceRequest  providers.ReadResourceRequest
	ReadResourceFn       func(providers.ReadResourceRequest) providers.ReadResourceResponse

	PlanResourceChangeCalled   bool
	PlanResourceChangeResponse providers.PlanResourceChangeResponse
	PlanResourceChangeRequest  providers.PlanResourceChangeRequest
	PlanResourceChangeFn       func(providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse

	ApplyResourceChangeCalled   bool
	ApplyResourceChangeResponse providers.ApplyResourceChangeResponse
	ApplyResourceChangeRequest  providers.ApplyResourceChangeRequest
	ApplyResourceChangeFn       func(providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse

	ImportResourceStateCalled   bool
	ImportResourceStateResponse providers.ImportResourceStateResponse
	ImportResourceStateRequest  providers.ImportResourceStateRequest
	ImportResourceStateFn       func(providers.ImportResourceStateRequest) providers.ImportResourceStateResponse
	// Legacy return type for existing tests, which will be shimmed into an
	// ImportResourceStateResponse if set
	ImportStateReturn []*InstanceState

	ReadDataSourceCalled   bool
	ReadDataSourceResponse providers.ReadDataSourceResponse
	ReadDataSourceRequest  providers.ReadDataSourceRequest
	ReadDataSourceFn       func(providers.ReadDataSourceRequest) providers.ReadDataSourceResponse

	CloseCalled bool
	CloseError  error

	// Legacy callbacks: if these are set, we will shim incoming calls for
	// new-style methods to these old-fashioned terraform.ResourceProvider
	// mock callbacks, for the benefit of older tests that were written against
	// the old mock API.
	ValidateFn  func(c *ResourceConfig) (ws []string, es []error)
	ConfigureFn func(c *ResourceConfig) error
	DiffFn      func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error)
	ApplyFn     func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error)
}

func (p *MockProvider) GetSchema() providers.GetSchemaResponse {
	p.Lock()
	defer p.Unlock()
	return p.getSchema()
}

func (p *MockProvider) getSchema() providers.GetSchemaResponse {
	// This version of getSchema doesn't do any locking, so it's suitable to
	// call from other methods of this mock as long as they are already
	// holding the lock.

	p.GetSchemaCalled = true
	ret := providers.GetSchemaResponse{
		Provider: providers.Schema{
			Block: p.GetSchemaReturn.Provider,
		},
		DataSources:   map[string]providers.Schema{},
		ResourceTypes: map[string]providers.Schema{},
	}
	for n, s := range p.GetSchemaReturn.DataSources {
		ret.DataSources[n] = providers.Schema{
			Block: s,
		}
	}
	for n, s := range p.GetSchemaReturn.ResourceTypes {
		ret.ResourceTypes[n] = providers.Schema{
			Block: s,
		}
	}
	return ret
}

func (p *MockProvider) ValidateProviderConfig(r providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse {
	p.Lock()
	defer p.Unlock()

	p.ValidateProviderConfigCalled = true
	p.ValidateProviderConfigRequest = r
	if p.ValidateProviderConfigFn != nil {
		return p.ValidateProviderConfigFn(r)
	}
	return p.ValidateProviderConfigResponse
}

func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
	p.Lock()
	defer p.Unlock()

	p.ValidateResourceTypeConfigCalled = true
	p.ValidateResourceTypeConfigRequest = r

	if p.ValidateFn != nil {
		resp := p.getSchema()
		schema := resp.Provider.Block
		rc := NewResourceConfigShimmed(r.Config, schema)
		warns, errs := p.ValidateFn(rc)
		ret := providers.ValidateResourceTypeConfigResponse{}
		for _, warn := range warns {
			ret.Diagnostics = ret.Diagnostics.Append(tfdiags.SimpleWarning(warn))
		}
		for _, err := range errs {
			ret.Diagnostics = ret.Diagnostics.Append(err)
		}
	}
	if p.ValidateResourceTypeConfigFn != nil {
		return p.ValidateResourceTypeConfigFn(r)
	}

	return p.ValidateResourceTypeConfigResponse
}

func (p *MockProvider) ValidateDataSourceConfig(r providers.ValidateDataSourceConfigRequest) providers.ValidateDataSourceConfigResponse {
	p.Lock()
	defer p.Unlock()

	p.ValidateDataSourceConfigCalled = true
	p.ValidateDataSourceConfigRequest = r

	if p.ValidateDataSourceConfigFn != nil {
		return p.ValidateDataSourceConfigFn(r)
	}

	return p.ValidateDataSourceConfigResponse
}

func (p *MockProvider) UpgradeResourceState(r providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse {
	p.Lock()
	defer p.Unlock()

	p.UpgradeResourceStateCalled = true
	p.UpgradeResourceStateRequest = r

	if p.UpgradeResourceStateFn != nil {
		return p.UpgradeResourceStateFn(r)
	}

	return p.UpgradeResourceStateResponse
}

func (p *MockProvider) Configure(r providers.ConfigureRequest) providers.ConfigureResponse {
	p.Lock()
	defer p.Unlock()

	p.ConfigureCalled = true
	p.ConfigureRequest = r

	if p.ConfigureFn != nil {
		resp := p.getSchema()
		schema := resp.Provider.Block
		rc := NewResourceConfigShimmed(r.Config, schema)
		ret := providers.ConfigureResponse{}

		err := p.ConfigureFn(rc)
		if err != nil {
			ret.Diagnostics = ret.Diagnostics.Append(err)
		}
		return ret
	}
	if p.ConfigureNewFn != nil {
		return p.ConfigureNewFn(r)
	}

	return p.ConfigureResponse
}

func (p *MockProvider) Stop() error {
	p.Lock()
	defer p.Unlock()

	p.StopCalled = true
	if p.StopFn != nil {
		return p.StopFn()
	}

	return p.StopResponse
}

func (p *MockProvider) ReadResource(r providers.ReadResourceRequest) providers.ReadResourceResponse {
	p.Lock()
	defer p.Unlock()

	p.ReadResourceCalled = true
	p.ReadResourceRequest = r

	if p.ReadResourceFn != nil {
		return p.ReadResourceFn(r)
	}

	return p.ReadResourceResponse
}

func (p *MockProvider) PlanResourceChange(r providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
	p.PlanResourceChangeCalled = true
	p.PlanResourceChangeRequest = r

	if p.DiffFn != nil {
		ps := p.getSchema()
		if ps.ResourceTypes == nil || ps.ResourceTypes[r.TypeName].Block == nil {
			return providers.PlanResourceChangeResponse{
				Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Printf("mock provider has no schema for resource type %s", r.TypeName)),
			}
		}
		schema := ps.ResourceTypes[r.TypeName].Block
		info := &InstanceInfo{
			Type: r.TypeName,
		}
		priorState := NewInstanceStateShimmedFromValue(r.PriorState, 0)
		cfg := NewResourceConfigShimmed(r.Config, schema)
		legacyDiff, err := p.DiffFn(info, priorState, cfg)

		var res providers.PlanResourceChangeResponse
		res.PlannedState = cty.NullVal(schema.ImpliedType()) // mimic how an absent value would arrive over the GRPC channel
		if err != nil {
			res.Diagnostics = res.Diagnostics.Append(err)
		}
		if legacyDiff != nil {
			newVal, err := legacyDiff.ApplyToValue(r.PriorState, schema)
			if err != nil {
				res.Diagnostics = res.Diagnostics.Append(err)
			}
			res.PlannedState = newVal

			var requiresNew []string
			for attr, d := range legacyDiff.Attributes {
				if d.RequiresNew {
					requiresNew = append(requiresNew, attr)
				}
			}
			requiresReplace, err := hcl2shim.RequiresReplace(requiresNew, schema.ImpliedType())
			if err != nil {
				res.Diagnostics = res.Diagnostics.Append(err)
			}
			res.RequiresReplace = requiresReplace
		}
		return res

	}
	if p.PlanResourceChangeFn != nil {
		return p.PlanResourceChangeFn(r)
	}

	return p.PlanResourceChangeResponse
}

func (p *MockProvider) ApplyResourceChange(r providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
	p.Lock()
	p.ApplyResourceChangeCalled = true
	p.ApplyResourceChangeRequest = r
	p.Unlock()

	if p.ApplyFn != nil {
		// ApplyFn is a special callback fashioned after our old provider
		// interface, which expected to be given an actual diff rather than
		// separate old/new values to apply. Therefore we need to approximate
		// a diff here well enough that _most_ of our legacy ApplyFns in old
		// tests still see the behavior they are expecting. New tests should
		// not use this, and should instead use ApplyResourceChangeFn directly.
		providerSchema := p.getSchema()
		schema, ok := providerSchema.ResourceTypes[r.TypeName]
		if !ok {
			return providers.ApplyResourceChangeResponse{
				Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("no mocked schema available for resource type %s", r.TypeName)),
			}
		}

		info := &InstanceInfo{
			Type: r.TypeName,
		}

		priorVal := r.PriorState
		plannedVal := r.PlannedState
		priorMap := hcl2shim.FlatmapValueFromHCL2(priorVal)
		plannedMap := hcl2shim.FlatmapValueFromHCL2(plannedVal)
		s := NewInstanceStateShimmedFromValue(priorVal, 0)
		d := &InstanceDiff{
			Attributes: make(map[string]*ResourceAttrDiff),
		}
		if plannedMap == nil { // destroying, then
			d.Destroy = true
			// Destroy diffs don't have any attribute diffs
		} else {
			if priorMap == nil { // creating, then
				// We'll just make an empty prior map to make things easier below.
				priorMap = make(map[string]string)
			}

			for k, new := range plannedMap {
				old := priorMap[k]
				newComputed := false
				if new == config.UnknownVariableValue {
					new = ""
					newComputed = true
				}
				d.Attributes[k] = &ResourceAttrDiff{
					Old:         old,
					New:         new,
					NewComputed: newComputed,
					Type:        DiffAttrInput, // not generally used in tests, so just hard-coded
				}
			}
			// Also need any attributes that were removed in "planned"
			for k, old := range priorMap {
				if _, ok := plannedMap[k]; ok {
					continue
				}
				d.Attributes[k] = &ResourceAttrDiff{
					Old:        old,
					NewRemoved: true,
					Type:       DiffAttrInput,
				}
			}
		}
		newState, err := p.ApplyFn(info, s, d)
		resp := providers.ApplyResourceChangeResponse{}
		if err != nil {
			resp.Diagnostics = resp.Diagnostics.Append(err)
		}
		newVal, err := newState.AttrsAsObjectValue(schema.Block.ImpliedType())
		if err != nil {
			resp.Diagnostics = resp.Diagnostics.Append(err)
		}
		resp.NewState = newVal

		return resp
	}
	if p.ApplyResourceChangeFn != nil {
		return p.ApplyResourceChangeFn(r)
	}

	return p.ApplyResourceChangeResponse
}

func (p *MockProvider) ImportResourceState(r providers.ImportResourceStateRequest) providers.ImportResourceStateResponse {
	p.Lock()
	defer p.Unlock()

	if p.ImportStateReturn != nil {
		for _, is := range p.ImportStateReturn {
			if is.Attributes == nil {
				is.Attributes = make(map[string]string)
			}
			is.Attributes["id"] = is.ID
			schema := p.GetSchemaReturn.ResourceTypes[r.TypeName]
			private, err := json.Marshal(is.Meta)
			if err != nil {
				panic(err)
			}

			state, err := hcl2shim.HCL2ValueFromFlatmap(is.Attributes, schema.ImpliedType())
			if err != nil {
				panic(err)
			}
			p.ImportResourceStateResponse.ImportedResources = append(
				p.ImportResourceStateResponse.ImportedResources,
				providers.ImportedResource{
					TypeName: r.TypeName,
					State:    state,
					Private:  private,
				})
		}
	}

	p.ImportResourceStateCalled = true
	p.ImportResourceStateRequest = r
	if p.ImportResourceStateFn != nil {
		return p.ImportResourceStateFn(r)
	}

	return p.ImportResourceStateResponse
}

func (p *MockProvider) ReadDataSource(r providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
	p.Lock()
	defer p.Unlock()

	p.ReadDataSourceCalled = true
	p.ReadDataSourceRequest = r

	if p.ReadDataSourceFn != nil {
		return p.ReadDataSourceFn(r)
	}

	return p.ReadDataSourceResponse
}

func (p *MockProvider) Close() error {
	p.CloseCalled = true
	return p.CloseError
}
<|endoftext|>


<commit_before>package delay

import (
	"sync"
	"time"
)

// Delay makes it easy to add (threadsafe) configurable delays to other
// objects.
type D interface {
	Set(time.Duration) time.Duration
	Wait()
	Get() time.Duration
}

// Fixed returns a delay with fixed latency
func Fixed(t time.Duration) D {
	return &delay{t: t}
}

type delay struct {
	l sync.RWMutex
	t time.Duration
}

// TODO func Variable(time.Duration) D returns a delay with probablistic latency

func (d *delay) Set(t time.Duration) time.Duration {
	d.l.Lock()
	defer d.l.Unlock()
	prev := d.t
	d.t = t
	return prev
}

func (d *delay) Wait() {
	d.l.RLock()
	defer d.l.RUnlock()
	time.Sleep(d.t)
}

func (d *delay) Get() time.Duration {
	d.l.Lock()
	defer d.l.Unlock()
	return d.t
}
<commit_msg>Added variable latency delay, normal and uniform based<commit_after>package delay

import (
	"math/rand"
	"sync"
	"time"
)

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

// Delay makes it easy to add (threadsafe) configurable delays to other
// objects.
type D interface {
	Set(time.Duration) time.Duration
	Wait()
	Get() time.Duration
}

// Fixed returns a delay with fixed latency
func Fixed(t time.Duration) D {
	return &delay{t: t}
}

type delay struct {
	l sync.RWMutex
	t time.Duration
}

func (d *delay) Set(t time.Duration) time.Duration {
	d.l.Lock()
	defer d.l.Unlock()
	prev := d.t
	d.t = t
	return prev
}

func (d *delay) Wait() {
	d.l.RLock()
	defer d.l.RUnlock()
	time.Sleep(d.t)
}

func (d *delay) Get() time.Duration {
	d.l.Lock()
	defer d.l.Unlock()
	return d.t
}

// VariableNormal is a delay following a normal distribution
// Notice that to implement the D interface Set can only change the mean delay
// the standard deviation is set only at initialization
func VariableNormal(t, std time.Duration, rng *rand.Rand) D {
	if rng == nil {
		rng = sharedRNG
	}

	v := &variableNormal{
		std: std,
		rng: rng,
	}
	v.t = t
	return v
}

type variableNormal struct {
	delay
	std time.Duration
	rng *rand.Rand
}

func (d *variableNormal) Wait() {
	d.l.RLock()
	defer d.l.RUnlock()
	randomDelay := time.Duration(d.rng.NormFloat64() * float64(d.std))
	time.Sleep(randomDelay + d.t)
}

// VariableUniform is a delay following a uniform distribution
// Notice that to implement the D interface Set can only change the minimum delay
// the delta is set only at initialization
func VariableUniform(t, d time.Duration, rng *rand.Rand) D {
	if rng == nil {
		rng = sharedRNG
	}

	v := &variableUniform{
		d:   d,
		rng: rng,
	}
	v.t = t
	return v
}

type variableUniform struct {
	delay
	d   time.Duration // max delta
	rng *rand.Rand
}

func (d *variableUniform) Wait() {
	d.l.RLock()
	defer d.l.RUnlock()
	randomDelay := time.Duration(d.rng.Float64() * float64(d.d))
	time.Sleep(randomDelay + d.t)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
)

type DockerCompose struct {
	rawCmd      string
	composeFile string
	scope       string
}

func NewDockerCompose(composeFile, scope string) (*DockerCompose, error) {
	cmd, err := assertExecPreconditions()
	if err != nil {
		return nil, err
	}
	dc := &DockerCompose{
		rawCmd:      cmd,
		scope:       scope,
		composeFile: composeFile,
	}
	return dc, nil
}

func (d *DockerCompose) Pull(output io.Writer) error {
	args := d.makeArgs("pull", "--ignore-pull-failures")
	cmd := exec.Command(d.rawCmd, args...)
	cmd.Stderr = output
	cmd.Stdout = output
	return cmd.Run()
}

func (d *DockerCompose) Build(output io.Writer, services ...string) error {
	args := d.makeArgs("build", "--pull")
	cmd := exec.Command(d.rawCmd, args...)
	cmd.Stderr = output
	cmd.Stdout = output
	return cmd.Run()
}

func (d *DockerCompose) StartAll() error {
	args := d.makeArgs("up", "-d", "--force-recreate")
	cmd := exec.Command(d.rawCmd, args...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s\n%s", strings.TrimSpace(string(out)), err)
	}
	return nil
}

func (d *DockerCompose) StopAll() error {
	args := d.makeArgs("stop")
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) StopServices(name ...string) error {
	args := d.makeArgs("stop", name...)
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) StartServices(name ...string) error {
	args := d.makeArgs("start", name...)
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) SystemOutput() ([]byte, error) {
	args := d.makeArgs("logs")
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Output()
}

type OutputWrapper struct {
	taskName string
	reporter TaskReporter
}

func (o *OutputWrapper) Write(p []byte) (int, error) {
	o.reporter.TaskOutput(o.taskName, string(p))
	return len(p), nil
}

type TaskEnvironment []string

func (d *DockerCompose) ExecuteTask(task TaskConfig, env TaskEnvironment, reporter TaskReporter) error {
	args := []string{
		"-e",
		"DELMO_TEST_NAME=" + d.scope,
	}
	for _, variable := range env {
		args = append(args, "-e", variable)
	}
	args = append(args, task.Service)
	args = append(args, strings.Split(task.Cmd, " ")...)
	args = d.makeArgs("run", args...)
	cmd := exec.Command(d.rawCmd, args...)
	wrapper := &OutputWrapper{
		taskName: task.Name,
		reporter: reporter,
	}
	cmd.Stderr = wrapper
	cmd.Stdout = wrapper
	return cmd.Run()
}

func (d *DockerCompose) Cleanup() error {
	args := d.makeArgs("rm", "-f", "-v", "-a")
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) makeArgs(command string, args ...string) []string {
	return append([]string{
		"--file", d.composeFile, "--project-name", d.scope, command,
	}, args...)
}

func assertExecPreconditions() (string, error) {
	if host := os.Getenv("DOCKER_HOST"); host == "" {
		return "", fmt.Errorf("Environment not setup correctly! DOCKER_HOST is not set")
	}

	cmd, err := exec.LookPath("docker-compose")
	if err != nil {
		return "", err
	}
	return cmd, nil
}
<commit_msg>Add services to build command<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
)

type DockerCompose struct {
	rawCmd      string
	composeFile string
	scope       string
}

func NewDockerCompose(composeFile, scope string) (*DockerCompose, error) {
	cmd, err := assertExecPreconditions()
	if err != nil {
		return nil, err
	}
	dc := &DockerCompose{
		rawCmd:      cmd,
		scope:       scope,
		composeFile: composeFile,
	}
	return dc, nil
}

func (d *DockerCompose) Pull(output io.Writer) error {
	args := d.makeArgs("pull", "--ignore-pull-failures")
	cmd := exec.Command(d.rawCmd, args...)
	cmd.Stderr = output
	cmd.Stdout = output
	return cmd.Run()
}

func (d *DockerCompose) Build(output io.Writer, services ...string) error {
	args := d.makeArgs("build", services...)
	cmd := exec.Command(d.rawCmd, args...)
	cmd.Stderr = output
	cmd.Stdout = output
	return cmd.Run()
}

func (d *DockerCompose) StartAll() error {
	args := d.makeArgs("up", "-d", "--force-recreate")
	cmd := exec.Command(d.rawCmd, args...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s\n%s", strings.TrimSpace(string(out)), err)
	}
	return nil
}

func (d *DockerCompose) StopAll() error {
	args := d.makeArgs("stop")
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) StopServices(name ...string) error {
	args := d.makeArgs("stop", name...)
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) StartServices(name ...string) error {
	args := d.makeArgs("start", name...)
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) SystemOutput() ([]byte, error) {
	args := d.makeArgs("logs")
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Output()
}

type OutputWrapper struct {
	taskName string
	reporter TaskReporter
}

func (o *OutputWrapper) Write(p []byte) (int, error) {
	o.reporter.TaskOutput(o.taskName, string(p))
	return len(p), nil
}

type TaskEnvironment []string

func (d *DockerCompose) ExecuteTask(task TaskConfig, env TaskEnvironment, reporter TaskReporter) error {
	args := []string{
		"-e",
		"DELMO_TEST_NAME=" + d.scope,
	}
	for _, variable := range env {
		args = append(args, "-e", variable)
	}
	args = append(args, task.Service)
	args = append(args, strings.Split(task.Cmd, " ")...)
	args = d.makeArgs("run", args...)
	cmd := exec.Command(d.rawCmd, args...)
	wrapper := &OutputWrapper{
		taskName: task.Name,
		reporter: reporter,
	}
	cmd.Stderr = wrapper
	cmd.Stdout = wrapper
	return cmd.Run()
}

func (d *DockerCompose) Cleanup() error {
	args := d.makeArgs("rm", "-f", "-v", "-a")
	cmd := exec.Command(d.rawCmd, args...)
	return cmd.Run()
}

func (d *DockerCompose) makeArgs(command string, args ...string) []string {
	return append([]string{
		"--file", d.composeFile, "--project-name", d.scope, command,
	}, args...)
}

func assertExecPreconditions() (string, error) {
	if host := os.Getenv("DOCKER_HOST"); host == "" {
		return "", fmt.Errorf("Environment not setup correctly! DOCKER_HOST is not set")
	}

	cmd, err := exec.LookPath("docker-compose")
	if err != nil {
		return "", err
	}
	return cmd, nil
}
<|endoftext|>