<commit_before>package spectrum

import (
	"testing"
	"sdl"
	"io/ioutil"
	"image"
	"image/png"
	"os"
	"strings"
	"unsafe"
)

func (s *SDLSurface) At(x, y int) image.Color {
	var bpp = int(s.Surface.Format.BytesPerPixel)

	var pixel = uintptr(unsafe.Pointer(s.Surface.Pixels))

	pixel += uintptr(y*int(s.Surface.Pitch) + x*bpp)

	var color = *((*uint32)(unsafe.Pointer(pixel)))

	var r uint8
	var g uint8
	var b uint8
	var a uint8

	sdl.GetRGBA(color, s.Surface.Format, &r, &g, &b, &a)

	return image.RGBAColor{uint8(r), uint8(g), uint8(b), uint8(a)}
}

func initSDL() {
	if sdl.Init(sdl.INIT_VIDEO) != 0 {
		panic(sdl.GetError())
	}
}

func newSurface() *sdl.Surface {
	return sdl.SetVideoMode(TotalScreenWidth, TotalScreenHeight, 32, 0)
}

func readOutputImage(filename string) image.Image {
	var file *os.File
	var err os.Error
	var image image.Image

	if file, err = os.Open(filename, os.O_RDONLY, 0); err != nil {
		panic(err)
	}

	if image, err = png.Decode(file); err != nil {
		panic(err)
	}
	return image
}

func readInputImage(filename string) *Display {
	display := &Display{}
	display.memory, _ = ioutil.ReadFile(filename)
	return display
}

func colorsAreNotEqual(got, expected image.Color) bool {
	got_r, got_g, got_b, got_a := got.RGBA()
	expected_r, expected_g, expected_b, expected_a := expected.RGBA()
	if (got_r != expected_r) || (got_g != expected_g) || (got_b != expected_b) || (got_a != expected_a) {
		return true
	}
	return false
}

func imagesAreNotEqual(got *SDLScreen, expected image.Image) image.Image {
	diff := false
	diffImage := image.NewRGBA(TotalScreenWidth, TotalScreenHeight)

	for y := 0; y < TotalScreenHeight; y++ {
		for x := 0; x < TotalScreenWidth; x++ {
			if colorsAreNotEqual(got.ScreenSurface.At(x, y), expected.At(x, y)) {
				diff = true
				diffImage.Set(x, y, image.Red)
			}
		}
	}

	if diff {
		return diffImage
	}

	return nil

}

type RenderTest struct {
	in, out     string
	borderColor RGBA
	flash       bool
	diffImage   image.Image
}

func (r *RenderTest) renderInputImage() bool {
	renderedScreen := &SDLScreen{nil, SDLSurface{newSurface()}}

	expectedImage := readOutputImage(r.out)
	inputImage := readInputImage(r.in)

	inputImage.borderColor = r.borderColor

	if r.flash {
		inputImage.flashFrame = 0x10
		inputImage.prepare()
	}

	displayData := inputImage.prepare()

	renderedScreen.render(displayData, nil)

	if diffImage := imagesAreNotEqual(renderedScreen, expectedImage); diffImage != nil {
		r.diffImage = diffImage
		return true
	}

	return false
}

func (r *RenderTest) getDiffFn() string {
	return strings.TrimRight(r.out, ".png") + "_diff.png"
}

func (r *RenderTest) reportError(t *testing.T) {
	t.Errorf("Expected image %s is not equal to the rendered one! Check %s\n", r.out, r.getDiffFn())

	if file, err := os.Open(r.getDiffFn(), os.O_CREATE|os.O_WRONLY, 0666); err != nil {
		panic(err)
	} else {
		if err := png.Encode(file, r.diffImage); err != nil {
			panic(err)
		}
	}
}

var RenderTests = []RenderTest{
	RenderTest{in: "testdata/initial.scr", out: "testdata/initial.png", borderColor: RGBA{192, 192, 192, 255}},
	RenderTest{in: "testdata/flash.scr", out: "testdata/flash_0.png", borderColor: RGBA{192, 192, 192, 255}},
	RenderTest{in: "testdata/flash.scr", out: "testdata/flash_1.png", borderColor: RGBA{192, 192, 192, 255}, flash: true},
}

func TestSDLRenderer(t *testing.T) {

	initSDL()

	for _, r := range RenderTests {
		if notEqual := r.renderInputImage(); notEqual {
			r.reportError(t)
		}
	}

	sdl.Quit()

}

func BenchmarkRender(b *testing.B) {

	b.StopTimer()

	const numFrames = 1000

	var (
		frames    [numFrames]DisplayData
		prevFrame *DisplayData = nil
	)

	sdlScreen := &SDLScreen{make(chan *DisplayData), SDLSurface{newSurface()}}

	if speccy, err := NewSpectrum48k(); err != nil {
		panic(err)
	} else {
		speccy.SetDisplayReceiver(sdlScreen)
		speccy.LoadSna("testdata/fire.sna")

		go func() {
			for i := 0; i < numFrames; i++ {
				speccy.RenderFrame()
			}
		}()

		go func() {
			for i := 0; i < numFrames; i++ {
				frames[i] = *<-sdlScreen.getDisplayDataCh()
			}
		}()

		var j int

		b.StartTimer()
		for i := 0; i < b.N; i++ {
			j %= numFrames / 2
			sdlScreen.render(&frames[j], prevFrame)
			prevFrame = &frames[j]
			j++
		}

	}

}
<commit_msg>Run receive/render code on the same goroutine on sdldisplay_test.go<commit_after>package spectrum

import (
	"testing"
	"sdl"
	"io/ioutil"
	"image"
	"image/png"
	"os"
	"strings"
	"unsafe"
)

func (s *SDLSurface) At(x, y int) image.Color {
	var bpp = int(s.Surface.Format.BytesPerPixel)

	var pixel = uintptr(unsafe.Pointer(s.Surface.Pixels))

	pixel += uintptr(y*int(s.Surface.Pitch) + x*bpp)

	var color = *((*uint32)(unsafe.Pointer(pixel)))

	var r uint8
	var g uint8
	var b uint8
	var a uint8

	sdl.GetRGBA(color, s.Surface.Format, &r, &g, &b, &a)

	return image.RGBAColor{uint8(r), uint8(g), uint8(b), uint8(a)}
}

func initSDL() {
	if sdl.Init(sdl.INIT_VIDEO) != 0 {
		panic(sdl.GetError())
	}
}

func newSurface() *sdl.Surface {
	return sdl.SetVideoMode(TotalScreenWidth, TotalScreenHeight, 32, 0)
}

func readOutputImage(filename string) image.Image {
	var file *os.File
	var err os.Error
	var image image.Image

	if file, err = os.Open(filename, os.O_RDONLY, 0); err != nil {
		panic(err)
	}

	if image, err = png.Decode(file); err != nil {
		panic(err)
	}
	return image
}

func readInputImage(filename string) *Display {
	display := &Display{}
	display.memory, _ = ioutil.ReadFile(filename)
	return display
}

func colorsAreNotEqual(got, expected image.Color) bool {
	got_r, got_g, got_b, got_a := got.RGBA()
	expected_r, expected_g, expected_b, expected_a := expected.RGBA()
	if (got_r != expected_r) || (got_g != expected_g) || (got_b != expected_b) || (got_a != expected_a) {
		return true
	}
	return false
}

func imagesAreNotEqual(got *SDLScreen, expected image.Image) image.Image {
	diff := false
	diffImage := image.NewRGBA(TotalScreenWidth, TotalScreenHeight)

	for y := 0; y < TotalScreenHeight; y++ {
		for x := 0; x < TotalScreenWidth; x++ {
			if colorsAreNotEqual(got.ScreenSurface.At(x, y), expected.At(x, y)) {
				diff = true
				diffImage.Set(x, y, image.Red)
			}
		}
	}

	if diff {
		return diffImage
	}

	return nil

}

type RenderTest struct {
	in, out     string
	borderColor RGBA
	flash       bool
	diffImage   image.Image
}

func (r *RenderTest) renderInputImage() bool {
	renderedScreen := &SDLScreen{nil, SDLSurface{newSurface()}}

	expectedImage := readOutputImage(r.out)
	inputImage := readInputImage(r.in)

	inputImage.borderColor = r.borderColor

	if r.flash {
		inputImage.flashFrame = 0x10
		inputImage.prepare()
	}

	displayData := inputImage.prepare()

	renderedScreen.render(displayData, nil)

	if diffImage := imagesAreNotEqual(renderedScreen, expectedImage); diffImage != nil {
		r.diffImage = diffImage
		return true
	}

	return false
}

func (r *RenderTest) getDiffFn() string {
	return strings.TrimRight(r.out, ".png") + "_diff.png"
}

func (r *RenderTest) reportError(t *testing.T) {
	t.Errorf("Expected image %s is not equal to the rendered one! Check %s\n", r.out, r.getDiffFn())

	if file, err := os.Open(r.getDiffFn(), os.O_CREATE|os.O_WRONLY, 0666); err != nil {
		panic(err)
	} else {
		if err := png.Encode(file, r.diffImage); err != nil {
			panic(err)
		}
	}
}

var RenderTests = []RenderTest{
	RenderTest{in: "testdata/initial.scr", out: "testdata/initial.png", borderColor: RGBA{192, 192, 192, 255}},
	RenderTest{in: "testdata/flash.scr", out: "testdata/flash_0.png", borderColor: RGBA{192, 192, 192, 255}},
	RenderTest{in: "testdata/flash.scr", out: "testdata/flash_1.png", borderColor: RGBA{192, 192, 192, 255}, flash: true},
}

func TestSDLRenderer(t *testing.T) {

	initSDL()

	for _, r := range RenderTests {
		if notEqual := r.renderInputImage(); notEqual {
			r.reportError(t)
		}
	}

	sdl.Quit()

}

func BenchmarkRender(b *testing.B) {

	b.StopTimer()

	const numFrames = 1000

	var (
		frames    [numFrames]DisplayData
		prevFrame *DisplayData = nil
	)

	sdlScreen := &SDLScreen{make(chan *DisplayData), SDLSurface{newSurface()}}

	if speccy, err := NewSpectrum48k(); err != nil {
		panic(err)
	} else {
		speccy.SetDisplayReceiver(sdlScreen)
		speccy.LoadSna("testdata/fire.sna")

		go func() {
			for i := 0; i < numFrames; i++ {
				speccy.RenderFrame()
			}
		}()

		for i := 0; i < numFrames; i++ {
			frames[i] = *<-sdlScreen.getDisplayDataCh()
		}

		var j int

		b.StartTimer()
		for i := 0; i < b.N; i++ {
			j %= numFrames / 2
			sdlScreen.render(&frames[j], prevFrame)
			prevFrame = &frames[j]
			j++
		}

	}

}
<|endoftext|>


<commit_before>package gocd

import (
	"encoding/json"
	"fmt"
	"strings"
)

// Equal is true if the two materials are logically equivalent. Not neccesarily literally equal.
func (m Material) Equal(a *Material) (isEqual bool, err error) {
	if m.Type != a.Type {
		return
	}

	return m.Attributes.equal(a.Attributes)
}

// UnmarshalJSON string into a Material struct
func (m *Material) UnmarshalJSON(b []byte) (err error) {
	raw := map[string]interface{}{}
	if err = json.Unmarshal(b, &raw); err == nil {
		err = m.Ingest(raw)
	}

	return
}

// Ingest an abstract structure
func (m *Material) Ingest(payload map[string]interface{}) (err error) {

	m.IngestMaterial(payload)

	for key, value := range payload {
		if value == nil {
			continue
		}
		switch key {
		case "attributes":
			err = m.IngestAttributeGenerics(value)
		case "fingerprint":
			m.Fingerprint = value.(string)
		case "description":
			m.Description = value.(string)
		case "type":
			continue
		default:
			err = fmt.Errorf("unexpected key: '%s'", key)
		}
		if err != nil {
			break
		}
	}
	return
}

// IngestType of Material
func (m *Material) IngestMaterial(payload map[string]interface{}) {
	if mType, hasMType := payload["type"]; hasMType {
		m.Type = mType.(string)
		m.IngestAttributes(map[string]interface{}{})
	}
}

// IngestAttributeGenerics to Material and perform some error checking
func (m *Material) IngestAttributeGenerics(i interface{}) (err error) {
	if v1, ok1 := i.(map[string]interface{}); ok1 {
		if err = m.IngestAttributes(v1); err != nil {
			return
		}
	}
}

// IngestAttributes to Material from an abstract structure
func (m *Material) IngestAttributes(rawAttributes map[string]interface{}) (err error) {
	switch strings.ToLower(m.Type) {
	case "git":
		mag := &MaterialAttributesGit{}
		unmarshallMaterialAttributesGit(mag, rawAttributes)
		m.Attributes = mag
	case "svn":
		mas := &MaterialAttributesSvn{}
		unmarshallMaterialAttributesSvn(mas, rawAttributes)
		m.Attributes = mas
	case "hg":
		mah := &MaterialAttributesHg{}
		unmarshallMaterialAttributesHg(mah, rawAttributes)
		m.Attributes = mah
	case "p4":
		map4 := &MaterialAttributesP4{}
		unmarshallMaterialAttributesP4(map4, rawAttributes)
		m.Attributes = map4
	case "tfs":
		mat := &MaterialAttributesTfs{}
		unmarshallMaterialAttributesTfs(mat, rawAttributes)
		m.Attributes = mat
	case "dependency":
		mad := &MaterialAttributesDependency{}
		unmarshallMaterialAttributesDependency(mad, rawAttributes)
		m.Attributes = mad
	case "package":
		mapp := &MaterialAttributesPackage{}
		unmarshallMaterialAttributesPackage(mapp, rawAttributes)
		m.Attributes = mapp
	case "plugin":
		mapl := &MaterialAttributesPlugin{}
		unmarshallMaterialAttributesPlugin(mapl, rawAttributes)
		m.Attributes = mapl
	default:
		err = fmt.Errorf("Unexpected Material type: '%s'", m.Type)
	}

	return
}

// GenerateGeneric form (map[string]interface) of the material filter
func (mf *MaterialFilter) GenerateGeneric() (g map[string]interface{}) {
	if mf != nil {
		ignores := []interface{}{}
		for _, ig := range mf.Ignore {
			ignores = append(ignores, ig)
		}
		g = map[string]interface{}{
			"ignore": ignores,
		}
	}
	return
}

func unmarshallMaterialFilter(i map[string]interface{}) (m *MaterialFilter) {
	m = &MaterialFilter{}
	if ignoreI, ok1 := i["ignore"]; ok1 {
		if ignoreIs, ok2 := ignoreI.([]interface{}); ok2 {
			m.Ignore = decodeConfigStringList(ignoreIs)
		} else if ignores, ok3 := ignoreI.([]string); ok3 {
			m.Ignore = ignores
		}
	}
	return m
}

// Give an abstract list of strings cast as []interface{}, convert them back to []string{}.
func decodeConfigStringList(lI []interface{}) (ret []string) {

	if len(lI) == 1 {
		return []string{lI[0].(string)}
	}
	ret = make([]string, len(lI))
	for i, vI := range lI {
		ret[i] = vI.(string)
	}
	return ret
}
<commit_msg>Removed excess code<commit_after>package gocd

import (
	"encoding/json"
	"fmt"
	"strings"
)

// Equal is true if the two materials are logically equivalent. Not neccesarily literally equal.
func (m Material) Equal(a *Material) (isEqual bool, err error) {
	if m.Type != a.Type {
		return
	}

	return m.Attributes.equal(a.Attributes)
}

// UnmarshalJSON string into a Material struct
func (m *Material) UnmarshalJSON(b []byte) (err error) {
	raw := map[string]interface{}{}
	if err = json.Unmarshal(b, &raw); err == nil {
		err = m.Ingest(raw)
	}

	return
}

// Ingest an abstract structure
func (m *Material) Ingest(payload map[string]interface{}) (err error) {

	m.IngestType(payload)

	for key, value := range payload {
		if value == nil {
			continue
		}
		switch key {
		case "attributes":
			err = m.IngestAttributeGenerics(value)
		case "fingerprint":
			m.Fingerprint = value.(string)
		case "description":
			m.Description = value.(string)
		case "type":
			continue
		default:
			err = fmt.Errorf("unexpected key: '%s'", key)
		}
		if err != nil {
			break
		}
	}
	return
}

// IngestType of Material if it is provided
func (m *Material) IngestType(payload map[string]interface{}) {
	if mType, hasMType := payload["type"]; hasMType {
		m.Type = mType.(string)
		m.IngestAttributes(map[string]interface{}{})
	}
}

// IngestAttributeGenerics to Material and perform some error checking
func (m *Material) IngestAttributeGenerics(i interface{}) (err error) {
	if v1, ok1 := i.(map[string]interface{}); ok1 {
		if err = m.IngestAttributes(v1); err != nil {
			return
		}
	}
}

// IngestAttributes to Material from an abstract structure
func (m *Material) IngestAttributes(rawAttributes map[string]interface{}) (err error) {
	switch strings.ToLower(m.Type) {
	case "git":
		mag := &MaterialAttributesGit{}
		unmarshallMaterialAttributesGit(mag, rawAttributes)
		m.Attributes = mag
	case "svn":
		mas := &MaterialAttributesSvn{}
		unmarshallMaterialAttributesSvn(mas, rawAttributes)
		m.Attributes = mas
	case "hg":
		mah := &MaterialAttributesHg{}
		unmarshallMaterialAttributesHg(mah, rawAttributes)
		m.Attributes = mah
	case "p4":
		map4 := &MaterialAttributesP4{}
		unmarshallMaterialAttributesP4(map4, rawAttributes)
		m.Attributes = map4
	case "tfs":
		mat := &MaterialAttributesTfs{}
		unmarshallMaterialAttributesTfs(mat, rawAttributes)
		m.Attributes = mat
	case "dependency":
		mad := &MaterialAttributesDependency{}
		unmarshallMaterialAttributesDependency(mad, rawAttributes)
		m.Attributes = mad
	case "package":
		mapp := &MaterialAttributesPackage{}
		unmarshallMaterialAttributesPackage(mapp, rawAttributes)
		m.Attributes = mapp
	case "plugin":
		mapl := &MaterialAttributesPlugin{}
		unmarshallMaterialAttributesPlugin(mapl, rawAttributes)
		m.Attributes = mapl
	default:
		err = fmt.Errorf("Unexpected Material type: '%s'", m.Type)
	}

	return
}

// GenerateGeneric form (map[string]interface) of the material filter
func (mf *MaterialFilter) GenerateGeneric() (g map[string]interface{}) {
	if mf != nil {
		ignores := []interface{}{}
		for _, ig := range mf.Ignore {
			ignores = append(ignores, ig)
		}
		g = map[string]interface{}{
			"ignore": ignores,
		}
	}
	return
}

func unmarshallMaterialFilter(i map[string]interface{}) (m *MaterialFilter) {
	m = &MaterialFilter{}
	if ignoreI, ok1 := i["ignore"]; ok1 {
		if ignoreIs, ok2 := ignoreI.([]interface{}); ok2 {
			m.Ignore = decodeConfigStringList(ignoreIs)
		} else if ignores, ok3 := ignoreI.([]string); ok3 {
			m.Ignore = ignores
		}
	}
	return
}

// Give an abstract list of strings cast as []interface{}, convert them back to []string{}.
func decodeConfigStringList(lI []interface{}) (ret []string) {

	if len(lI) == 1 {
		return []string{lI[0].(string)}
	}
	ret = make([]string, len(lI))
	for i, vI := range lI {
		ret[i] = vI.(string)
	}
	return
}
<|endoftext|>


<commit_before>package processfiles

import (
	"fmt"
	_ "time"
	_ "list"

	"github.com/keenstart/keennodes/dirnfiles"
	"github.com/keenstart/keennodes/khash"

	_ "github.com/keenstart/keennodes/gopfile"
	_ "github.com/keenstart/keennodes/blah"
)

// Create a struct to store load blah( are hash name files)
// to memory instead of keep open  and close blab file.
// Make all go routine be able to access the struct
// lock

const (
	PROCESSROOT   = "/Users/garethharris/"
	MAXPROCCESSES = 170 // To limit the amount of goroutine
)

type ProcesService struct {
	dspro *dirnfiles.Dirs

	//BlahMemoryList *list.List; //Type to add is (GlobalBlahBlock )

}

func NewProSerives() (*ProcesService, error) {

	p := &ProcesService{
		dspro: dirnfiles.NewDirs(),
	}

	err := p.dspro.GetFiles()

	if err != nil {
		return p, err
	}

	return p, nil
}

func (p *ProcesService) ProFileSerives() {
	maxprocessch := make(chan int, MAXPROCCESSES) // To limit the amount of goroutine

	for _, files := range p.dspro.Files {

		maxprocessch <- 1 // To limit the amount of goroutine
		go func(files *dirnfiles.Dirinfo) {
			process(files)
			<-maxprocessch // To limit the amount of goroutine
		}(files)

	}

}

func process(files *dirnfiles.Dirinfo) {

	x := khash.Sha512fn(khash.Filebytes(files.Path))

	fmt.Printf("\nKey: %d = %s with %d bytes. CRC %x \n\n",
		files.Key, files.Path, files.Fsize, x)

	//time.Sleep(1000 * time.Millisecond)

	/*for { //loop 1024 bytes at a time move 1 byte at a time

		break // when  slice less than 1024
		- get BlockHashSha512
		- get BlockFNV64
		- start position
		- location - files.Key

		if ok := HashBlahmap[GlobalBlahBlock]; !ok{
	 		if HashBlahmap fileexist (the filename = GlobalBlahBlock.BlockHashSha512)  {
				//open file to save to HashBlahmap
			}else{

				//create HashBlahmap to save to file (the filename = GlobalBlahBlock.BlockHashSha512)
			}

			//add to back of list BlahMemoryList
			collision := 1

		}else{
			- check for collision
			-if collision{
				collision++ // increment collison
			}
		}
		//sync.lock

		//Add to HashBlahmap with func AddHashBlahmap below
		//AddHashBlahmap(globalBlahBlk GlobalBlahBlock, collision Collisions,
					location Locations, blockStatus BlockStatus)

		// 1. Save to file.
		//2. remove element(GlobalBlahBlock) from the front of list BlahMemoryList if list is greater than MAXMEMORYBLAH
			//and also delete from map

		//sync.unlock

	}*/

}
<commit_msg>Update processfiles.go<commit_after>package processfiles

import (
	"fmt"
	_ "time"
	_ "list"

	"github.com/keenstart/keennodes/dirnfiles"
	"github.com/keenstart/keennodes/khash"

	_ "github.com/keenstart/keennodes/gopfile"
	_ "github.com/keenstart/keennodes/blah"
)

// Create a struct to store load blah( are hash name files)
// to memory instead of keep open  and close blab file.
// Make all go routine be able to access the struct
// lock

const (
	PROCESSROOT   = "/Users/garethharris/"
	MAXPROCCESSES = 170 // To limit the amount of goroutine
)

type ProcesService struct {
	dspro *dirnfiles.Dirs

	//BlahMemoryList *list.List; //Type to add is (GlobalBlahBlock )

}

func NewProSerives() (*ProcesService, error) {

	p := &ProcesService{
		dspro: dirnfiles.NewDirs(),
	}

	err := p.dspro.GetFiles()

	if err != nil {
		return p, err
	}

	return p, nil
}

func (p *ProcesService) ProFileSerives() {
	maxprocessch := make(chan int, MAXPROCCESSES) // To limit the amount of goroutine

	for _, files := range p.dspro.Files {

		maxprocessch <- 1 // To limit the amount of goroutine
		go func(files *dirnfiles.Dirinfo) {
			process(files)
			<-maxprocessch // To limit the amount of goroutine
		}(files)

	}

}

func process(files *dirnfiles.Dirinfo) {

	x := khash.Sha512fn(khash.Filebytes(files.Path))

	fmt.Printf("\nKey: %d = %s with %d bytes. CRC %x \n\n",
		files.Key, files.Path, files.Fsize, x)

	//time.Sleep(1000 * time.Millisecond)

	/*for { //loop 1024 bytes at a time move 1 byte at a time

		break // when  slice less than 1024
		- get BlockHashSha512
		- get BlockFNV64
		- start position
		- location - files.Key

		if ok := HashBlahmap[GlobalBlahBlock]; !ok{
	 		if HashBlahmap fileexist (the filename = GlobalBlahBlock.BlockHashSha512)  {
	 			//sync.Rlock
				//open file to read and save to HashBlahmap
				//sync.RUnlock

				 //check for collision
				-if collision{ //make this a func
					collision++ // increment collison
				}
			}else{

				//create HashBlahmap to save to file (the filename = GlobalBlahBlock.BlockHashSha512)
				collision := 1
			}

			//add to back of list BlahMemoryList

		}else{
			- check for collision
			-if collision{//make this a func
				collision++ // increment collison
			}
		}
		//sync.lock

		//Add to HashBlahmap with func AddHashBlahmap below
		//AddHashBlahmap(globalBlahBlk GlobalBlahBlock, collision Collisions,
					location Locations, blockStatus BlockStatus)

		// 1. Save to file.
		//2. remove element(GlobalBlahBlock) from the front of list BlahMemoryList if list is greater than MAXMEMORYBLAH
			//and also delete from map

		//sync.unlock

	}*/

}
<|endoftext|>


<commit_before>package sarama

import "github.com/rcrowley/go-metrics"

// PacketEncoder is the interface providing helpers for writing with Kafka's encoding rules.
// Types implementing Encoder only need to worry about calling methods like PutString,
// not about how a string is represented in Kafka.
type packetEncoder interface {
	// Primitives
	putInt8(in int8)
	putInt16(in int16)
	putInt32(in int32)
	putInt64(in int64)
	putVarint(in int64)
	putArrayLength(in int) error

	// Collections
	putBytes(in []byte) error
	putVarintBytes(in []byte) error
	putRawBytes(in []byte) error
	putString(in string) error
	putStringArray(in []string) error
	putInt32Array(in []int32) error
	putInt64Array(in []int64) error

	// Provide the current offset to record the batch size metric
	offset() int

	// Stacks, see PushEncoder
	push(in pushEncoder)
	pop() error

	// To record metrics when provided
	metricRegistry() metrics.Registry
}

// PushEncoder is the interface for encoding fields like CRCs and lengths where the value
// of the field depends on what is encoded after it in the packet. Start them with PacketEncoder.Push() where
// the actual value is located in the packet, then PacketEncoder.Pop() them when all the bytes they
// depend upon have been written.
type pushEncoder interface {
	// Saves the offset into the input buffer as the location to actually write the calculated value when able.
	saveOffset(in int)

	// Returns the length of data to reserve for the output of this encoder (eg 4 bytes for a CRC32).
	reserveLength() int

	// Indicates that all required data is now available to calculate and write the field.
	// SaveOffset is guaranteed to have been called first. The implementation should write ReserveLength() bytes
	// of data to the saved offset, based on the data between the saved offset and curOffset.
	run(curOffset int, buf []byte) error
}

// dynamicPushEncoder extends the interface of pushEncoder for uses cases where the length of the
// fields itself is unknown until its value was computed (for instance varint encoded lenght
// fields).
type dynamicPushEncoder interface {
	pushEncoder

	// Called during pop() to adjust the length of the field.
	// It should return the difference in bytes between the last computed length and current length.
	adjustLength(currOffset int) int
}
<commit_msg>Fix typo<commit_after>package sarama

import "github.com/rcrowley/go-metrics"

// PacketEncoder is the interface providing helpers for writing with Kafka's encoding rules.
// Types implementing Encoder only need to worry about calling methods like PutString,
// not about how a string is represented in Kafka.
type packetEncoder interface {
	// Primitives
	putInt8(in int8)
	putInt16(in int16)
	putInt32(in int32)
	putInt64(in int64)
	putVarint(in int64)
	putArrayLength(in int) error

	// Collections
	putBytes(in []byte) error
	putVarintBytes(in []byte) error
	putRawBytes(in []byte) error
	putString(in string) error
	putStringArray(in []string) error
	putInt32Array(in []int32) error
	putInt64Array(in []int64) error

	// Provide the current offset to record the batch size metric
	offset() int

	// Stacks, see PushEncoder
	push(in pushEncoder)
	pop() error

	// To record metrics when provided
	metricRegistry() metrics.Registry
}

// PushEncoder is the interface for encoding fields like CRCs and lengths where the value
// of the field depends on what is encoded after it in the packet. Start them with PacketEncoder.Push() where
// the actual value is located in the packet, then PacketEncoder.Pop() them when all the bytes they
// depend upon have been written.
type pushEncoder interface {
	// Saves the offset into the input buffer as the location to actually write the calculated value when able.
	saveOffset(in int)

	// Returns the length of data to reserve for the output of this encoder (eg 4 bytes for a CRC32).
	reserveLength() int

	// Indicates that all required data is now available to calculate and write the field.
	// SaveOffset is guaranteed to have been called first. The implementation should write ReserveLength() bytes
	// of data to the saved offset, based on the data between the saved offset and curOffset.
	run(curOffset int, buf []byte) error
}

// dynamicPushEncoder extends the interface of pushEncoder for uses cases where the length of the
// fields itself is unknown until its value was computed (for instance varint encoded length
// fields).
type dynamicPushEncoder interface {
	pushEncoder

	// Called during pop() to adjust the length of the field.
	// It should return the difference in bytes between the last computed length and current length.
	adjustLength(currOffset int) int
}
<|endoftext|>


<commit_before>package link

import (
	"encoding/json"
	"net"

	"github.com/juju/errors"
	"github.com/service-exposer/exposer"
	"github.com/service-exposer/exposer/service"
)

const (
	CMD_LINK       = "link"
	CMD_LINK_REPLY = "link:reply"
)

var (
	ErrServiceIsNotExist = errors.New("service is not exist")
)

type Reply struct {
	OK  bool
	Err string
}

type LinkReq struct {
	Name string
}

func ServerSide(router *service.Router) exposer.HandshakeHandleFunc {
	return func(proto *exposer.Protocal, cmd string, details []byte) error {
		switch cmd {
		case CMD_LINK:
			var req LinkReq
			err := json.Unmarshal(details, &req)
			if err != nil {
				return errors.Trace(err)
			}

			service := router.Get(req.Name)
			if service == nil {
				proto.Reply(CMD_LINK_REPLY, &Reply{
					OK:  false,
					Err: ErrServiceIsNotExist.Error(),
				})

				return errors.Annotatef(ErrServiceIsNotExist, "%q", req.Name)
			}

			err = proto.Reply(CMD_LINK_REPLY, &Reply{
				OK: true,
			})
			if err != nil {
				return errors.Trace(err)
			}

			return func() (err error) {
				/*
					defer func() {
							// recover for service.Open,if you are sure that will not panic
							// just delete this recover defer
							if r := recover(); r != nil {
									err = errors.New(fmt.Sprint("panic:", r))
							}
					}()
				*/

				session := proto.Multiplex(false)
				for {
					remote, err := session.Accept()
					if err != nil {
						return errors.Trace(err)
					}

					local, err := service.Open()
					if err != nil {
						remote.Close()
						return errors.Trace(err)
					}

					go exposer.Forward(remote, local)
				}
			}()
		}
		return errors.New("unknow cmd: " + cmd)
	}
}

func ClientSide(ln net.Listener) exposer.HandshakeHandleFunc {
	return func(proto *exposer.Protocal, cmd string, details []byte) error {
		switch cmd {
		case CMD_LINK_REPLY:
			var reply Reply
			err := json.Unmarshal(details, &reply)
			if err != nil {
				return errors.Trace(err)
			}

			if !reply.OK {
				return errors.New(reply.Err)
			}

			session := proto.Multiplex(true)
			for {
				local, err := ln.Accept()
				if err != nil {
					return errors.Trace(err)
				}
				remote, err := session.Open()
				if err != nil {
					return errors.Trace(err)
				}

				go exposer.Forward(remote, local)
			}
			return nil
		}
		return errors.New("unknow cmd: " + cmd)
	}
}
<commit_msg>fix: link inmediately shutdown while daemon close<commit_after>package link

import (
	"encoding/json"
	"net"
	"sync"

	"github.com/juju/errors"
	"github.com/service-exposer/exposer"
	"github.com/service-exposer/exposer/service"
)

const (
	CMD_LINK       = "link"
	CMD_LINK_REPLY = "link:reply"
)

var (
	ErrServiceIsNotExist = errors.New("service is not exist")
)

type Reply struct {
	OK  bool
	Err string
}

type LinkReq struct {
	Name string
}

func ServerSide(router *service.Router) exposer.HandshakeHandleFunc {
	return func(proto *exposer.Protocal, cmd string, details []byte) error {
		switch cmd {
		case CMD_LINK:
			var req LinkReq
			err := json.Unmarshal(details, &req)
			if err != nil {
				return errors.Trace(err)
			}

			service := router.Get(req.Name)
			if service == nil {
				proto.Reply(CMD_LINK_REPLY, &Reply{
					OK:  false,
					Err: ErrServiceIsNotExist.Error(),
				})

				return errors.Annotatef(ErrServiceIsNotExist, "%q", req.Name)
			}

			err = proto.Reply(CMD_LINK_REPLY, &Reply{
				OK: true,
			})
			if err != nil {
				return errors.Trace(err)
			}

			return func() (err error) {
				/*
					defer func() {
							// recover for service.Open,if you are sure that will not panic
							// just delete this recover defer
							if r := recover(); r != nil {
									err = errors.New(fmt.Sprint("panic:", r))
							}
					}()
				*/

				session := proto.Multiplex(false)
				for {
					remote, err := session.Accept()
					if err != nil {
						return errors.Trace(err)
					}

					local, err := service.Open()
					if err != nil {
						remote.Close()
						return errors.Trace(err)
					}

					go exposer.Forward(remote, local)
				}
			}()
		}
		return errors.New("unknow cmd: " + cmd)
	}
}

func ClientSide(ln net.Listener) exposer.HandshakeHandleFunc {
	return func(proto *exposer.Protocal, cmd string, details []byte) error {
		switch cmd {
		case CMD_LINK_REPLY:
			var reply Reply
			err := json.Unmarshal(details, &reply)
			if err != nil {
				return errors.Trace(err)
			}

			if !reply.OK {
				return errors.New(reply.Err)
			}

			session := proto.Multiplex(true)

			errch := make(chan error, 1)
			wg := new(sync.WaitGroup)

			wg.Add(1)
			go func() {
				defer wg.Done()

				// detect session closed
				// in fact,it's detecting underly conn closed
				// so,it will immediately reactive while
				// connection to server is closed
				err, _, _ := session.Wait()
				errch <- errors.Trace(err)
				ln.Close()
			}()

			wg.Add(1)
			go func() {
				defer wg.Done()

				for {
					local, err := ln.Accept()
					if err != nil {
						errch <- errors.Trace(err)
						session.Close()
						return
					}
					remote, err := session.Open()
					if err != nil {
						errch <- errors.Trace(err)
						return
					}

					go exposer.Forward(remote, local)
				}
			}()

			go func() {
				wg.Wait()
				close(errch)
			}()

			defer func() {
				go func() {
					for range errch {
					}
				}()
			}()

			return <-errch
		}
		return errors.New("unknow cmd: " + cmd)
	}
}
<|endoftext|>


<commit_before>package mbus_test

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	. "github.com/cloudfoundry/bosh-agent/mbus"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	boshagentblobstore "github.com/cloudfoundry/bosh-agent/agent/blobstore"
	boshhandler "github.com/cloudfoundry/bosh-agent/handler"
	"github.com/cloudfoundry/bosh-agent/platform/fakes"
	"github.com/cloudfoundry/bosh-agent/settings"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"
)

var _ = Describe("HTTPSHandler", func() {
	var (
		serverURL       string
		tmpdir          string
		handler         HTTPSHandler
		receivedRequest boshhandler.Request
		httpClient      http.Client
		blobManager     boshagentblobstore.BlobManagerInterface
	)

	BeforeEach(func() {
		var err error
		tmpdir, err = ioutil.TempDir("", "mbus-http-handler-test")
		Expect(err).NotTo(HaveOccurred())

		serverURL = "https://user:pass@localhost:6900"
		blobManager, err = boshagentblobstore.NewBlobManager(tmpdir)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		handler.Stop()

		err := os.Chmod(tmpdir, 0700)
		Expect(err).NotTo(HaveOccurred())

		err = os.RemoveAll(tmpdir)
		Expect(err).NotTo(HaveOccurred())
	})

	Context("when the agent creates the handler with custom cert", func() {
		BeforeEach(func() {
			configCert, err := ioutil.ReadFile("test_assets/custom_cert.pem")
			Expect(err).NotTo(HaveOccurred())
			configPrivateKey, err := ioutil.ReadFile("test_assets/custom_key.pem")
			Expect(err).NotTo(HaveOccurred())

			mbusKeyPair := settings.CertKeyPair{
				Certificate: string(configCert),
				PrivateKey:  string(configPrivateKey),
			}

			mbusURL, _ := url.Parse(serverURL)
			logger := boshlog.NewWriterLogger(boshlog.LevelDebug, GinkgoWriter)
			handler = NewHTTPSHandler(mbusURL, mbusKeyPair, blobManager, logger, fakes.NewFakeAuditLogger())

			go handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) {
				receivedRequest = req
				return boshhandler.NewValueResponse("expected value")
			})

			caCert, err := ioutil.ReadFile("test_assets/custom_ca.pem")
			Expect(err).NotTo(HaveOccurred())
			authority := x509.NewCertPool()
			Expect(authority.AppendCertsFromPEM(caCert)).To(BeTrue())

			httpTransport := &http.Transport{TLSClientConfig: &tls.Config{RootCAs: authority}}
			httpClient = http.Client{Timeout: 1 * time.Second, Transport: httpTransport}

			waitForServerToStart(serverURL, httpClient)
		})

		It("handshakes for a ping using that custom cert", func() {
			postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
			postPayload := strings.NewReader(postBody)

			httpResponse, err := httpClient.Post(serverURL+"/agent", "application/json", postPayload)
			for err != nil {
				httpResponse, err = httpClient.Post(serverURL+"/agent", "application/json", postPayload)
			}

			defer httpResponse.Body.Close()

			Expect(receivedRequest.ReplyTo).To(Equal("reply to me!"))
			Expect(receivedRequest.Method).To(Equal("ping"))
			Expect(receivedRequest.GetPayload()).To(Equal([]byte(postBody)))

			httpBody, readErr := ioutil.ReadAll(httpResponse.Body)
			Expect(readErr).ToNot(HaveOccurred())
			Expect(httpBody).To(Equal([]byte(`{"value":"expected value"}`)))
		})

		Describe("POST /agent", func() {
			It("receives request and responds", func() {
				postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
				postPayload := strings.NewReader(postBody)

				httpResponse, err := httpClient.Post(serverURL+"/agent", "application/json", postPayload)
				for err != nil {
					httpResponse, err = httpClient.Post(serverURL+"/agent", "application/json", postPayload)
				}

				defer httpResponse.Body.Close()

				Expect(receivedRequest.ReplyTo).To(Equal("reply to me!"))
				Expect(receivedRequest.Method).To(Equal("ping"))
				Expect(receivedRequest.GetPayload()).To(Equal([]byte(postBody)))

				httpBody, readErr := ioutil.ReadAll(httpResponse.Body)
				Expect(readErr).ToNot(HaveOccurred())
				Expect(httpBody).To(Equal([]byte(`{"value":"expected value"}`)))
			})

			Context("when incorrect http method is used", func() {
				It("returns a 404", func() {
					httpResponse, err := httpClient.Get(serverURL + "/agent")
					Expect(err).ToNot(HaveOccurred())
					Expect(httpResponse.StatusCode).To(Equal(404))
				})
			})
		})

		Describe("blob access", func() {
			Describe("GET /blobs", func() {
				It("returns data from file system", func() {
					err := blobManager.Write("123-456-789", strings.NewReader("Some data"))
					Expect(err).NotTo(HaveOccurred())

					httpResponse, err := httpClient.Get(serverURL + "/blobs/123-456-789")
					Expect(err).ToNot(HaveOccurred())
					defer httpResponse.Body.Close()

					httpBody, readErr := ioutil.ReadAll(httpResponse.Body)
					Expect(readErr).ToNot(HaveOccurred())
					Expect(httpResponse.StatusCode).To(Equal(200))
					Expect(httpBody).To(Equal([]byte("Some data")))
				})

				Context("when incorrect http method is used", func() {
					It("returns a 404", func() {
						postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
						postPayload := strings.NewReader(postBody)

						httpResponse, err := httpClient.Post(serverURL+"/blobs/123", "application/json", postPayload)
						Expect(err).ToNot(HaveOccurred())

						defer httpResponse.Body.Close()

						Expect(httpResponse.StatusCode).To(Equal(404))
					})
				})

				Context("when file does not exist", func() {
					It("returns a 404", func() {
						httpResponse, err := httpClient.Get(serverURL + "/blobs/a-file-that-does-not-exist")
						Expect(err).ToNot(HaveOccurred())

						defer httpResponse.Body.Close()
						Expect(httpResponse.StatusCode).To(Equal(404))
					})
				})
			})

			Describe("PUT /blobs", func() {
				It("updates the blob on the file system", func() {
					err := blobManager.Write("123-456-789", strings.NewReader("Some data"))
					Expect(err).NotTo(HaveOccurred())

					putBody := `Updated data`
					putPayload := strings.NewReader(putBody)

					request, err := http.NewRequest("PUT", serverURL+"/blobs/a5/123-456-789", putPayload)
					Expect(err).ToNot(HaveOccurred())

					httpResponse, err := httpClient.Do(request)
					Expect(err).ToNot(HaveOccurred())

					defer httpResponse.Body.Close()
					Expect(httpResponse.StatusCode).To(Equal(201))

					file, _, err := blobManager.Fetch("123-456-789")
					Expect(err).NotTo(HaveOccurred())
					defer file.Close()

					contents, err := ioutil.ReadAll(file)
					Expect(err).ToNot(HaveOccurred())
					Expect(string(contents)).To(Equal("Updated data"))
				})

				Context("when an incorrect username and password is provided", func() {
					It("returns a 401", func() {
						err := blobManager.Write("123-456-789", strings.NewReader("Some data"))
						Expect(err).NotTo(HaveOccurred())

						putBody := `Updated data`
						putPayload := strings.NewReader(putBody)

						httpRequest, err := http.NewRequest("PUT", strings.Replace(serverURL, "pass", "wrong", -1)+"/blobs/a5/123-456-789", putPayload)
						Expect(err).NotTo(HaveOccurred())
						httpResponse, err := httpClient.Do(httpRequest)
						Expect(err).ToNot(HaveOccurred())

						defer httpResponse.Body.Close()

						Expect(httpResponse.StatusCode).To(Equal(401))
						Expect(httpResponse.Header.Get("WWW-Authenticate")).To(Equal(`Basic realm=""`))
					})
				})
			})
		})

		Describe("routing and auth", func() {
			Context("when an incorrect uri is specificed", func() {
				It("returns a 404", func() {
					postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
					postPayload := strings.NewReader(postBody)
					httpResponse, err := httpClient.Post(serverURL+"/bad_url", "application/json", postPayload)
					Expect(err).ToNot(HaveOccurred())

					defer httpResponse.Body.Close()

					Expect(httpResponse.StatusCode).To(Equal(404))
				})
			})

			Context("when an incorrect username/password was provided", func() {
				It("returns a 401", func() {
					postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
					postPayload := strings.NewReader(postBody)

					httpResponse, err := httpClient.Post(strings.Replace(serverURL, "pass", "wrong", -1)+"/agent", "application/json", postPayload)
					Expect(err).ToNot(HaveOccurred())

					defer httpResponse.Body.Close()

					Expect(httpResponse.StatusCode).To(Equal(401))
					Expect(httpResponse.Header.Get("WWW-Authenticate")).To(Equal(`Basic realm=""`))
				})
			})
		})
	})
})

func waitForServerToStart(serverURL string, httpClient http.Client) {
	Eventually(func() error {
		httpResponse, err := httpClient.Get(serverURL + "/healthz")
		if err == nil {
			httpResponse.Body.Close()
		}
		return err
	}, time.Second*5).Should(Succeed())
}
<commit_msg>Increase mbus/https_handler_test timeout to 5s to appease windows tests<commit_after>package mbus_test

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	. "github.com/cloudfoundry/bosh-agent/mbus"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	boshagentblobstore "github.com/cloudfoundry/bosh-agent/agent/blobstore"
	boshhandler "github.com/cloudfoundry/bosh-agent/handler"
	"github.com/cloudfoundry/bosh-agent/platform/fakes"
	"github.com/cloudfoundry/bosh-agent/settings"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"
)

var _ = Describe("HTTPSHandler", func() {
	var (
		serverURL       string
		tmpdir          string
		handler         HTTPSHandler
		receivedRequest boshhandler.Request
		httpClient      http.Client
		blobManager     boshagentblobstore.BlobManagerInterface
	)

	BeforeEach(func() {
		var err error
		tmpdir, err = ioutil.TempDir("", "mbus-http-handler-test")
		Expect(err).NotTo(HaveOccurred())

		serverURL = "https://user:pass@localhost:6900"
		blobManager, err = boshagentblobstore.NewBlobManager(tmpdir)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		handler.Stop()

		err := os.Chmod(tmpdir, 0700)
		Expect(err).NotTo(HaveOccurred())

		err = os.RemoveAll(tmpdir)
		Expect(err).NotTo(HaveOccurred())
	})

	Context("when the agent creates the handler with custom cert", func() {
		BeforeEach(func() {
			configCert, err := ioutil.ReadFile("test_assets/custom_cert.pem")
			Expect(err).NotTo(HaveOccurred())
			configPrivateKey, err := ioutil.ReadFile("test_assets/custom_key.pem")
			Expect(err).NotTo(HaveOccurred())

			mbusKeyPair := settings.CertKeyPair{
				Certificate: string(configCert),
				PrivateKey:  string(configPrivateKey),
			}

			mbusURL, _ := url.Parse(serverURL)
			logger := boshlog.NewWriterLogger(boshlog.LevelDebug, GinkgoWriter)
			handler = NewHTTPSHandler(mbusURL, mbusKeyPair, blobManager, logger, fakes.NewFakeAuditLogger())

			go handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) {
				receivedRequest = req
				return boshhandler.NewValueResponse("expected value")
			})

			caCert, err := ioutil.ReadFile("test_assets/custom_ca.pem")
			Expect(err).NotTo(HaveOccurred())
			authority := x509.NewCertPool()
			Expect(authority.AppendCertsFromPEM(caCert)).To(BeTrue())

			httpTransport := &http.Transport{TLSClientConfig: &tls.Config{RootCAs: authority}}
			httpClient = http.Client{Timeout: 5 * time.Second, Transport: httpTransport}

			waitForServerToStart(serverURL, httpClient)
		})

		It("handshakes for a ping using that custom cert", func() {
			postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
			postPayload := strings.NewReader(postBody)

			httpResponse, err := httpClient.Post(serverURL+"/agent", "application/json", postPayload)
			for err != nil {
				httpResponse, err = httpClient.Post(serverURL+"/agent", "application/json", postPayload)
			}

			defer httpResponse.Body.Close()

			Expect(receivedRequest.ReplyTo).To(Equal("reply to me!"))
			Expect(receivedRequest.Method).To(Equal("ping"))
			Expect(receivedRequest.GetPayload()).To(Equal([]byte(postBody)))

			httpBody, readErr := ioutil.ReadAll(httpResponse.Body)
			Expect(readErr).ToNot(HaveOccurred())
			Expect(httpBody).To(Equal([]byte(`{"value":"expected value"}`)))
		})

		Describe("POST /agent", func() {
			It("receives request and responds", func() {
				postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
				postPayload := strings.NewReader(postBody)

				httpResponse, err := httpClient.Post(serverURL+"/agent", "application/json", postPayload)
				for err != nil {
					httpResponse, err = httpClient.Post(serverURL+"/agent", "application/json", postPayload)
				}

				defer httpResponse.Body.Close()

				Expect(receivedRequest.ReplyTo).To(Equal("reply to me!"))
				Expect(receivedRequest.Method).To(Equal("ping"))
				Expect(receivedRequest.GetPayload()).To(Equal([]byte(postBody)))

				httpBody, readErr := ioutil.ReadAll(httpResponse.Body)
				Expect(readErr).ToNot(HaveOccurred())
				Expect(httpBody).To(Equal([]byte(`{"value":"expected value"}`)))
			})

			Context("when incorrect http method is used", func() {
				It("returns a 404", func() {
					httpResponse, err := httpClient.Get(serverURL + "/agent")
					Expect(err).ToNot(HaveOccurred())
					Expect(httpResponse.StatusCode).To(Equal(404))
				})
			})
		})

		Describe("blob access", func() {
			Describe("GET /blobs", func() {
				It("returns data from file system", func() {
					err := blobManager.Write("123-456-789", strings.NewReader("Some data"))
					Expect(err).NotTo(HaveOccurred())

					httpResponse, err := httpClient.Get(serverURL + "/blobs/123-456-789")
					Expect(err).ToNot(HaveOccurred())
					defer httpResponse.Body.Close()

					httpBody, readErr := ioutil.ReadAll(httpResponse.Body)
					Expect(readErr).ToNot(HaveOccurred())
					Expect(httpResponse.StatusCode).To(Equal(200))
					Expect(httpBody).To(Equal([]byte("Some data")))
				})

				Context("when incorrect http method is used", func() {
					It("returns a 404", func() {
						postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
						postPayload := strings.NewReader(postBody)

						httpResponse, err := httpClient.Post(serverURL+"/blobs/123", "application/json", postPayload)
						Expect(err).ToNot(HaveOccurred())

						defer httpResponse.Body.Close()

						Expect(httpResponse.StatusCode).To(Equal(404))
					})
				})

				Context("when file does not exist", func() {
					It("returns a 404", func() {
						httpResponse, err := httpClient.Get(serverURL + "/blobs/a-file-that-does-not-exist")
						Expect(err).ToNot(HaveOccurred())

						defer httpResponse.Body.Close()
						Expect(httpResponse.StatusCode).To(Equal(404))
					})
				})
			})

			Describe("PUT /blobs", func() {
				It("updates the blob on the file system", func() {
					err := blobManager.Write("123-456-789", strings.NewReader("Some data"))
					Expect(err).NotTo(HaveOccurred())

					putBody := `Updated data`
					putPayload := strings.NewReader(putBody)

					request, err := http.NewRequest("PUT", serverURL+"/blobs/a5/123-456-789", putPayload)
					Expect(err).ToNot(HaveOccurred())

					httpResponse, err := httpClient.Do(request)
					Expect(err).ToNot(HaveOccurred())

					defer httpResponse.Body.Close()
					Expect(httpResponse.StatusCode).To(Equal(201))

					file, _, err := blobManager.Fetch("123-456-789")
					Expect(err).NotTo(HaveOccurred())
					defer file.Close()

					contents, err := ioutil.ReadAll(file)
					Expect(err).ToNot(HaveOccurred())
					Expect(string(contents)).To(Equal("Updated data"))
				})

				Context("when an incorrect username and password is provided", func() {
					It("returns a 401", func() {
						err := blobManager.Write("123-456-789", strings.NewReader("Some data"))
						Expect(err).NotTo(HaveOccurred())

						putBody := `Updated data`
						putPayload := strings.NewReader(putBody)

						httpRequest, err := http.NewRequest("PUT", strings.Replace(serverURL, "pass", "wrong", -1)+"/blobs/a5/123-456-789", putPayload)
						Expect(err).NotTo(HaveOccurred())
						httpResponse, err := httpClient.Do(httpRequest)
						Expect(err).ToNot(HaveOccurred())

						defer httpResponse.Body.Close()

						Expect(httpResponse.StatusCode).To(Equal(401))
						Expect(httpResponse.Header.Get("WWW-Authenticate")).To(Equal(`Basic realm=""`))
					})
				})
			})
		})

		Describe("routing and auth", func() {
			Context("when an incorrect uri is specificed", func() {
				It("returns a 404", func() {
					postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
					postPayload := strings.NewReader(postBody)
					httpResponse, err := httpClient.Post(serverURL+"/bad_url", "application/json", postPayload)
					Expect(err).ToNot(HaveOccurred())

					defer httpResponse.Body.Close()

					Expect(httpResponse.StatusCode).To(Equal(404))
				})
			})

			Context("when an incorrect username/password was provided", func() {
				It("returns a 401", func() {
					postBody := `{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`
					postPayload := strings.NewReader(postBody)

					httpResponse, err := httpClient.Post(strings.Replace(serverURL, "pass", "wrong", -1)+"/agent", "application/json", postPayload)
					Expect(err).ToNot(HaveOccurred())

					defer httpResponse.Body.Close()

					Expect(httpResponse.StatusCode).To(Equal(401))
					Expect(httpResponse.Header.Get("WWW-Authenticate")).To(Equal(`Basic realm=""`))
				})
			})
		})
	})
})

func waitForServerToStart(serverURL string, httpClient http.Client) {
	Eventually(func() error {
		httpResponse, err := httpClient.Get(serverURL + "/healthz")
		if err == nil {
			httpResponse.Body.Close()
		}
		return err
	}, time.Second*5).Should(Succeed())
}
<|endoftext|>


<commit_before>// Package gpio implements a timer/counter unit.
// Tested compatibility:
//   ATmega48/88/168
// Untested compatability:
//   ATtiny4/5/9/10
package timer

import (
    "fmt"
    "github.com/kierdavis/avr/clock"
    "github.com/kierdavis/avr/emulator"
    "github.com/kierdavis/avr/hardware/gpio"
    "log"
)

// TODO: for a OSCx output, require corresponding DDR bit to be set to output

// TODO: writing to TCNT prevents a compare match on the next clock

// TODO: thread-safety!!

// TODO: OCFy/TOV flags should not be cleared upon interrupt execution if the
// emulator's global interrupt enable flag is cleared

type Timer struct {
    em *emulator.Emulator
    digit uint
    controlA uint8
    controlB uint8
    count uint8
    compareValA uint8
    compareValB uint8
    interruptMask uint8
    interruptFlags uint8
    downwards bool // count direction
    ocPinStates [2]bool
    ocPinCallbacks [2]func(bool)
    logging bool
}

func New(digit uint) (t *Timer) {
    return &Timer{
        digit: digit,
    }
}

func (t *Timer) SetLogging(enabled bool) {
    t.logging = enabled
}

func (t *Timer) AddTo(em *emulator.Emulator) {
    t.em = em

    em.RegisterPortByName(fmt.Sprintf("TCCR%dA", t.digit), tccra{t})
    em.RegisterPortByName(fmt.Sprintf("TCCR%dB", t.digit), tccrb{t})
    em.RegisterPortByName(fmt.Sprintf("TCNT%d", t.digit), tcnt{t})
    em.RegisterPortByName(fmt.Sprintf("OCR%dA", t.digit), ocra{t})
    em.RegisterPortByName(fmt.Sprintf("OCR%dB", t.digit), ocrb{t})
    em.RegisterPortByName(fmt.Sprintf("TIMSK%d", t.digit), timsk{t})
    em.RegisterPortByName(fmt.Sprintf("TIFR%d", t.digit), tifr{t})
}

// Connect an output-compare pin to a GPIO port by calling the GPIO's
// OverrideOutput method.
func (t *Timer) OverrideOCPin(ocPinNum uint, gpioPinNum uint, g *gpio.GPIO) {
    t.ocPinCallbacks[ocPinNum] = g.OverrideOutput(gpioPinNum)
}

// Run the timer off the specified clock.
func (t *Timer) Run(clk clock.Clock) {
    // TODO: implement clock source selector again

    for {
        now := clk.Now()
        t.Tick()
        clk.Await(now + 1)
    }
}

// Note: in PWM modes, OCRA/OCRB do not exhibit a newly written value until the count overflows

// TODO: in PC-PWM mode, an OCRx bit may transition without a compare match for two reasons (see datasheet page 98)

// Tick the timer.
func (t *Timer) Tick() {
    // Get the waveform generation mode bits
    wgmA := t.controlA & 0x03 // bits 1 and 0
    wgmB := (t.controlB & 0x08) >> 1 // bit 3 (shifted to bit 2)
    wgm := wgmB | wgmA

    // Handle match-compare interrupts
    if t.count == t.compareValA {
        t.setOCF(0)
    }
    if t.count == t.compareValB {
        t.setOCF(1)
    }

    // Prepare to tick counter
    switch wgm {
    case 0: // Normal
        t.tickNormalMode()
    case 1: // Phase-correct PWM (TOP = 0xFF)
        t.tickPCPWMMode(0xFF)
    case 2: // Clear timer on compare
        t.tickCTCMode()
    case 3: // Fast PWM (TOP = 0xFF)
        t.tickFastPWMMode(0xFF)
    case 5: // Phase-correct PWM (TOP = OCRA)
        t.tickPCPWMMode(t.compareValA)
    case 7: // Fast PWM (TOP = OCRA)
        t.tickPCPWMMode(t.compareValA)
    }

    // Actually tick the counter
    if t.downwards {
        t.count--
    } else {
        t.count++
    }

    // Trigger interrupts, if possible
    if t.em != nil && t.em.InterruptsEnabled() {
        intName := ""
        if t.interruptFlags & 0x01 != 0 && t.interruptMask & 0x01 != 0 {
            t.interruptFlags &= 0xFE // clear flag
            intName = fmt.Sprintf("TIMER%d_OVF", t.digit)
        } else if t.interruptFlags & 0x02 != 0 && t.interruptMask & 0x02 != 0 {
            t.interruptFlags &= 0xFD // clear flag
            intName = fmt.Sprintf("TIMER%d_COMPA", t.digit)
        } else if t.interruptFlags & 0x04 != 0 && t.interruptMask & 0x04 != 0 {
            t.interruptFlags &= 0xFB // clear flag
            intName = fmt.Sprintf("TIMER%d_COMPB", t.digit)
        }

        if intName != "" {
            ok := t.em.InterruptByName(intName)
            if !ok && t.logging {
                log.Printf("[avr/hardware/timer:(*Timer).Tick] failed to trigger interrupt %s", intName)
            }
        }
    }

    /*
    if t.logging {
        log.Printf("[avr/hardware/timer:(*Timer).tick] ticked, count is now $%02X", t.count)
    }
    */
}

// Tick the timer in Normal mode.
func (t *Timer) tickNormalMode() {
    t.downwards = false
    if t.count == 0xFF { // Overflow
        t.setTOV()
    }

    t.checkOCPinNormalMode(0, t.compareValA)
    t.checkOCPinNormalMode(1, t.compareValB)
}

// Check for output-compare in normal mode.
func (t *Timer) checkOCPinNormalMode(ocPinNum uint, compareVal uint8) {
    if t.count == compareVal {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // toggle OCy
            t.toggleOCPin(ocPinNum)
        case 2: // clear OCy
            t.clearOCPin(ocPinNum)
        case 3: // set OCy
            t.setOCPin(ocPinNum)
        }
    }
}

// Tick the timer in phase-corrected PWM mode.
func (t *Timer) tickPCPWMMode(top uint8) {
    if t.downwards {
        if t.count == 0x00 { // Reached BOTTOM
            t.downwards = false // Begin counting upwards
            t.setTOV()
        }
    } else {
        if t.count == top { // Reached TOP
            t.downwards = true // Begin counting downwards
        }
    }

    t.checkOCPinPCPWMMode(0, t.compareValA)
    t.checkOCPinPCPWMMode(1, t.compareValB)
}

// TODO: there is a special case in the OC pin checking for both PWM modes when OCRy == TOP and COMxy1 is set (see datasheet page 101)

// Check for output-compare in phase-corrected PWM mode.
func (t *Timer) checkOCPinPCPWMMode(ocPinNum uint, compareVal uint8) {
    if t.count == compareVal {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // Toggle OCy (only on OC pin 0 with WGM2 bit set)
            if ocPinNum == 0 && (t.controlB & 0x80) != 0 {
                t.toggleOCPin(ocPinNum)
            }
        case 2: // Clear OCy if counting upwards or set OCy if counting downwards
            if t.downwards {
                t.setOCPin(ocPinNum)
            } else {
                t.clearOCPin(ocPinNum)
            }
        case 3: // Set OCy if counting upwards or clear OCy if counting downwards
            if t.downwards {
                t.clearOCPin(ocPinNum)
            } else {
                t.setOCPin(ocPinNum)
            }
        }
    }
}

// Tick the timer in clear-timer-on-compare mode.
func (t *Timer) tickCTCMode() {
    t.downwards = false

    if t.count == 0xFF { // Overflow
        t.setTOV()
    }

    if t.count == t.compareValA {
        // this tick should set counter to 0
        t.count = 0xFF
    }
}

// Tick the timer in fast PWM mode.
func (t *Timer) tickFastPWMMode(top uint8) {
    t.downwards = false

    if t.count == top {
        // this tick should set counter to 0
        t.count = 0xFF
        t.setTOV()
    }

    t.checkOCPinFastPWMMode(0, t.compareValA)
    t.checkOCPinFastPWMMode(1, t.compareValB)
}

// Check for output-compare in fast PWM mode.
func (t *Timer) checkOCPinFastPWMMode(ocPinNum uint, compareVal uint8) {
    // BOTTOM
    if t.count == 0x00 {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // Toggle OCy on compare match (only on OC pin 0 with WGM2 bit set)
            // do nothing
        case 2: // Clear OCy on compare match, set OCy at BOTTOM
            t.setOCPin(ocPinNum)
        case 3: // Set OCy on compare match, clear OCy at BOTTOM
            t.clearOCPin(ocPinNum)
        }
    }

    // Compare match
    if t.count == compareVal {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // Toggle OCy on compare match (only on OC pin 0 with WGM2 bit set)
            if ocPinNum == 0 && (t.controlB & 0x80) != 0 {
                t.toggleOCPin(ocPinNum)
            }
        case 2: // Clear OCy on compare match, set OCy at BOTTOM
            t.clearOCPin(ocPinNum)
        case 3: // Set OCy on compare match, clear OCy at BOTTOM
            t.setOCPin(ocPinNum)
        }
    }
}

// Toggle an output-compare pin.
func (t *Timer) toggleOCPin(ocPinNum uint) {
    t.ocPinStates[ocPinNum] = !t.ocPinStates[ocPinNum]
    t.updateOCPin(ocPinNum)
}

// Set an output-compare pin to low.
func (t *Timer) clearOCPin(ocPinNum uint) {
    if t.ocPinStates[ocPinNum] {
        t.ocPinStates[ocPinNum] = false
        t.updateOCPin(ocPinNum)
    }
}

// Set an output-compare pin to high.
func (t *Timer) setOCPin(ocPinNum uint) {
    if !t.ocPinStates[ocPinNum] {
        t.ocPinStates[ocPinNum] = true
        t.updateOCPin(ocPinNum)
    }
}

// Push the new status of an output-compare pin to the GPIO layer.
func (t *Timer) updateOCPin(ocPinNum uint) {
    callback := t.ocPinCallbacks[ocPinNum]
    if callback != nil {
        callback(t.ocPinStates[ocPinNum])
    }
}

// Set an output compare match (OCFy) flag.
func (t *Timer) setOCF(ocPinNum uint) {
    if ocPinNum == 0 { // A
        t.interruptFlags |= 0x02 // set flag
    } else { // B
        t.interruptFlags |= 0x04 // set flag
    }
}

// Set the timer overflow (TOV) flag.
func (t *Timer) setTOV() {
    t.interruptFlags |= 0x01 // set flag
}

// Implementation of TCCRxA port
type tccra struct {
    t *Timer
}

func (p tccra) Read() uint8 {
    return p.t.controlA
}

func (p tccra) Write(x uint8) {
    if p.t.logging {
        log.Printf("[avr/hardware/timer:tccra.Write] $%02X (%08b) written to TCCRxA", x, x)
    }
    p.t.controlA = x
}

// Implementation of TCCRxB port
type tccrb struct {
    t *Timer
}

func (p tccrb) Read() uint8 {
    return p.t.controlB
}

func (p tccrb) Write(x uint8) {
    if p.t.logging {
        log.Printf("[avr/hardware/timer:tccrb.Write] $%02X (%08b) written to TCCRxB", x, x)
    }
    p.t.controlB = x
}

// Implementation of TCNTx port
type tcnt struct {
    t *Timer
}

func (p tcnt) Read() uint8 {
    return p.t.count
}

func (p tcnt) Write(x uint8) {
    p.t.count = x
}

// Implementation of OCRxA port
type ocra struct {
    t *Timer
}

func (p ocra) Read() uint8 {
    return p.t.compareValA
}

func (p ocra) Write(x uint8) {
    p.t.compareValA = x
}

// Implementation of OCRxb port
type ocrb struct {
    t *Timer
}

func (p ocrb) Read() uint8 {
    return p.t.compareValB
}

func (p ocrb) Write(x uint8) {
    p.t.compareValB = x
}

// Implementation of TIMSKx port
type timsk struct {
    t *Timer
}

func (p timsk) Read() uint8 {
    return p.t.interruptMask
}

func (p timsk) Write(x uint8) {
    p.t.interruptMask = x
}

// Implementation of TIFRx port
type tifr struct {
    t *Timer
}

func (p tifr) Read() uint8 {
    return p.t.interruptFlags
}

func (p tifr) Write(x uint8) {
    // Bits in TIFRx are cleared by writing a one to them.
    p.t.interruptFlags &= ^x
}
<commit_msg>Continue debugging the clock package; still not acceptable yet<commit_after>// Package gpio implements a timer/counter unit.
// Tested compatibility:
//   ATmega48/88/168
// Untested compatability:
//   ATtiny4/5/9/10
package timer

import (
    "fmt"
    "github.com/kierdavis/avr/clock"
    "github.com/kierdavis/avr/emulator"
    "github.com/kierdavis/avr/hardware/gpio"
    "log"

    "time"
)

// TODO: for a OSCx output, require corresponding DDR bit to be set to output

// TODO: writing to TCNT prevents a compare match on the next clock

// TODO: thread-safety!!

// TODO: OCFy/TOV flags should not be cleared upon interrupt execution if the
// emulator's global interrupt enable flag is cleared

type Timer struct {
    em *emulator.Emulator
    digit uint
    controlA uint8
    controlB uint8
    count uint8
    compareValA uint8
    compareValB uint8
    interruptMask uint8
    interruptFlags uint8
    downwards bool // count direction
    ocPinStates [2]bool
    ocPinCallbacks [2]func(bool)
    logging bool
}

func New(digit uint) (t *Timer) {
    return &Timer{
        digit: digit,
    }
}

func (t *Timer) SetLogging(enabled bool) {
    t.logging = enabled
}

func (t *Timer) AddTo(em *emulator.Emulator) {
    t.em = em

    em.RegisterPortByName(fmt.Sprintf("TCCR%dA", t.digit), tccra{t})
    em.RegisterPortByName(fmt.Sprintf("TCCR%dB", t.digit), tccrb{t})
    em.RegisterPortByName(fmt.Sprintf("TCNT%d", t.digit), tcnt{t})
    em.RegisterPortByName(fmt.Sprintf("OCR%dA", t.digit), ocra{t})
    em.RegisterPortByName(fmt.Sprintf("OCR%dB", t.digit), ocrb{t})
    em.RegisterPortByName(fmt.Sprintf("TIMSK%d", t.digit), timsk{t})
    em.RegisterPortByName(fmt.Sprintf("TIFR%d", t.digit), tifr{t})
}

// Connect an output-compare pin to a GPIO port by calling the GPIO's
// OverrideOutput method.
func (t *Timer) OverrideOCPin(ocPinNum uint, gpioPinNum uint, g *gpio.GPIO) {
    t.ocPinCallbacks[ocPinNum] = g.OverrideOutput(gpioPinNum)
}

// Run the timer off the specified clock.
func (t *Timer) Run(clk clock.Clock) {
    // TODO: implement clock source selector again

    k := 1000

    for {
        t1 := time.Now()
        for i := 0; i < k; i++ {
            //now := clk.Now()
            t.Tick()
            //clk.Await(now + 1)
        }
        t2 := time.Now()

        secs := float64(t2.Sub(t1)) / float64(time.Second)
        fmt.Printf("%d ticks in %f secs (%f Mticks/sec)\n", k, secs, (float64(k) / secs) / 1e6)
    }
}

// Note: in PWM modes, OCRA/OCRB do not exhibit a newly written value until the count overflows

// TODO: in PC-PWM mode, an OCRx bit may transition without a compare match for two reasons (see datasheet page 98)

// Tick the timer.
func (t *Timer) Tick() {
    // Get the waveform generation mode bits
    wgmA := t.controlA & 0x03 // bits 1 and 0
    wgmB := (t.controlB & 0x08) >> 1 // bit 3 (shifted to bit 2)
    wgm := wgmB | wgmA

    // Handle match-compare interrupts
    if t.count == t.compareValA {
        t.setOCF(0)
    }
    if t.count == t.compareValB {
        t.setOCF(1)
    }

    // Prepare to tick counter
    switch wgm {
    case 0: // Normal
        t.tickNormalMode()
    case 1: // Phase-correct PWM (TOP = 0xFF)
        t.tickPCPWMMode(0xFF)
    case 2: // Clear timer on compare
        t.tickCTCMode()
    case 3: // Fast PWM (TOP = 0xFF)
        t.tickFastPWMMode(0xFF)
    case 5: // Phase-correct PWM (TOP = OCRA)
        t.tickPCPWMMode(t.compareValA)
    case 7: // Fast PWM (TOP = OCRA)
        t.tickPCPWMMode(t.compareValA)
    }

    // Actually tick the counter
    if t.downwards {
        t.count--
    } else {
        t.count++
    }

    // Trigger interrupts, if possible
    if t.em != nil && t.em.InterruptsEnabled() {
        intName := ""
        if t.interruptFlags & 0x01 != 0 && t.interruptMask & 0x01 != 0 {
            t.interruptFlags &= 0xFE // clear flag
            intName = fmt.Sprintf("TIMER%d_OVF", t.digit)
        } else if t.interruptFlags & 0x02 != 0 && t.interruptMask & 0x02 != 0 {
            t.interruptFlags &= 0xFD // clear flag
            intName = fmt.Sprintf("TIMER%d_COMPA", t.digit)
        } else if t.interruptFlags & 0x04 != 0 && t.interruptMask & 0x04 != 0 {
            t.interruptFlags &= 0xFB // clear flag
            intName = fmt.Sprintf("TIMER%d_COMPB", t.digit)
        }

        if intName != "" {
            ok := t.em.InterruptByName(intName)
            if !ok && t.logging {
                log.Printf("[avr/hardware/timer:(*Timer).Tick] failed to trigger interrupt %s", intName)
            }
        }
    }

    /*
    if t.logging {
        log.Printf("[avr/hardware/timer:(*Timer).tick] ticked, count is now $%02X", t.count)
    }
    */
}

// Tick the timer in Normal mode.
func (t *Timer) tickNormalMode() {
    t.downwards = false
    if t.count == 0xFF { // Overflow
        t.setTOV()
    }

    t.checkOCPinNormalMode(0, t.compareValA)
    t.checkOCPinNormalMode(1, t.compareValB)
}

// Check for output-compare in normal mode.
func (t *Timer) checkOCPinNormalMode(ocPinNum uint, compareVal uint8) {
    if t.count == compareVal {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // toggle OCy
            t.toggleOCPin(ocPinNum)
        case 2: // clear OCy
            t.clearOCPin(ocPinNum)
        case 3: // set OCy
            t.setOCPin(ocPinNum)
        }
    }
}

// Tick the timer in phase-corrected PWM mode.
func (t *Timer) tickPCPWMMode(top uint8) {
    if t.downwards {
        if t.count == 0x00 { // Reached BOTTOM
            t.downwards = false // Begin counting upwards
            t.setTOV()
        }
    } else {
        if t.count == top { // Reached TOP
            t.downwards = true // Begin counting downwards
        }
    }

    t.checkOCPinPCPWMMode(0, t.compareValA)
    t.checkOCPinPCPWMMode(1, t.compareValB)
}

// TODO: there is a special case in the OC pin checking for both PWM modes when OCRy == TOP and COMxy1 is set (see datasheet page 101)

// Check for output-compare in phase-corrected PWM mode.
func (t *Timer) checkOCPinPCPWMMode(ocPinNum uint, compareVal uint8) {
    if t.count == compareVal {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // Toggle OCy (only on OC pin 0 with WGM2 bit set)
            if ocPinNum == 0 && (t.controlB & 0x80) != 0 {
                t.toggleOCPin(ocPinNum)
            }
        case 2: // Clear OCy if counting upwards or set OCy if counting downwards
            if t.downwards {
                t.setOCPin(ocPinNum)
            } else {
                t.clearOCPin(ocPinNum)
            }
        case 3: // Set OCy if counting upwards or clear OCy if counting downwards
            if t.downwards {
                t.clearOCPin(ocPinNum)
            } else {
                t.setOCPin(ocPinNum)
            }
        }
    }
}

// Tick the timer in clear-timer-on-compare mode.
func (t *Timer) tickCTCMode() {
    t.downwards = false

    if t.count == 0xFF { // Overflow
        t.setTOV()
    }

    if t.count == t.compareValA {
        // this tick should set counter to 0
        t.count = 0xFF
    }
}

// Tick the timer in fast PWM mode.
func (t *Timer) tickFastPWMMode(top uint8) {
    t.downwards = false

    if t.count == top {
        // this tick should set counter to 0
        t.count = 0xFF
        t.setTOV()
    }

    t.checkOCPinFastPWMMode(0, t.compareValA)
    t.checkOCPinFastPWMMode(1, t.compareValB)
}

// Check for output-compare in fast PWM mode.
func (t *Timer) checkOCPinFastPWMMode(ocPinNum uint, compareVal uint8) {
    // BOTTOM
    if t.count == 0x00 {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // Toggle OCy on compare match (only on OC pin 0 with WGM2 bit set)
            // do nothing
        case 2: // Clear OCy on compare match, set OCy at BOTTOM
            t.setOCPin(ocPinNum)
        case 3: // Set OCy on compare match, clear OCy at BOTTOM
            t.clearOCPin(ocPinNum)
        }
    }

    // Compare match
    if t.count == compareVal {
        // Get COMxy bits
        shiftAmt := 6 - 2*ocPinNum // 0 => 6, 1 => 4
        com := (t.controlA >> shiftAmt) & 0x03
        switch com {
        case 0: // OCy disabled
            // do nothing
        case 1: // Toggle OCy on compare match (only on OC pin 0 with WGM2 bit set)
            if ocPinNum == 0 && (t.controlB & 0x80) != 0 {
                t.toggleOCPin(ocPinNum)
            }
        case 2: // Clear OCy on compare match, set OCy at BOTTOM
            t.clearOCPin(ocPinNum)
        case 3: // Set OCy on compare match, clear OCy at BOTTOM
            t.setOCPin(ocPinNum)
        }
    }
}

// Toggle an output-compare pin.
func (t *Timer) toggleOCPin(ocPinNum uint) {
    t.ocPinStates[ocPinNum] = !t.ocPinStates[ocPinNum]
    t.updateOCPin(ocPinNum)
}

// Set an output-compare pin to low.
func (t *Timer) clearOCPin(ocPinNum uint) {
    if t.ocPinStates[ocPinNum] {
        t.ocPinStates[ocPinNum] = false
        t.updateOCPin(ocPinNum)
    }
}

// Set an output-compare pin to high.
func (t *Timer) setOCPin(ocPinNum uint) {
    if !t.ocPinStates[ocPinNum] {
        t.ocPinStates[ocPinNum] = true
        t.updateOCPin(ocPinNum)
    }
}

// Push the new status of an output-compare pin to the GPIO layer.
func (t *Timer) updateOCPin(ocPinNum uint) {
    callback := t.ocPinCallbacks[ocPinNum]
    if callback != nil {
        callback(t.ocPinStates[ocPinNum])
    }
}

// Set an output compare match (OCFy) flag.
func (t *Timer) setOCF(ocPinNum uint) {
    if ocPinNum == 0 { // A
        t.interruptFlags |= 0x02 // set flag
    } else { // B
        t.interruptFlags |= 0x04 // set flag
    }
}

// Set the timer overflow (TOV) flag.
func (t *Timer) setTOV() {
    t.interruptFlags |= 0x01 // set flag
}

// Implementation of TCCRxA port
type tccra struct {
    t *Timer
}

func (p tccra) Read() uint8 {
    return p.t.controlA
}

func (p tccra) Write(x uint8) {
    if p.t.logging {
        log.Printf("[avr/hardware/timer:tccra.Write] $%02X (%08b) written to TCCRxA", x, x)
    }
    p.t.controlA = x
}

// Implementation of TCCRxB port
type tccrb struct {
    t *Timer
}

func (p tccrb) Read() uint8 {
    return p.t.controlB
}

func (p tccrb) Write(x uint8) {
    if p.t.logging {
        log.Printf("[avr/hardware/timer:tccrb.Write] $%02X (%08b) written to TCCRxB", x, x)
    }
    p.t.controlB = x
}

// Implementation of TCNTx port
type tcnt struct {
    t *Timer
}

func (p tcnt) Read() uint8 {
    return p.t.count
}

func (p tcnt) Write(x uint8) {
    p.t.count = x
}

// Implementation of OCRxA port
type ocra struct {
    t *Timer
}

func (p ocra) Read() uint8 {
    return p.t.compareValA
}

func (p ocra) Write(x uint8) {
    p.t.compareValA = x
}

// Implementation of OCRxb port
type ocrb struct {
    t *Timer
}

func (p ocrb) Read() uint8 {
    return p.t.compareValB
}

func (p ocrb) Write(x uint8) {
    p.t.compareValB = x
}

// Implementation of TIMSKx port
type timsk struct {
    t *Timer
}

func (p timsk) Read() uint8 {
    return p.t.interruptMask
}

func (p timsk) Write(x uint8) {
    p.t.interruptMask = x
}

// Implementation of TIFRx port
type tifr struct {
    t *Timer
}

func (p tifr) Read() uint8 {
    return p.t.interruptFlags
}

func (p tifr) Write(x uint8) {
    // Bits in TIFRx are cleared by writing a one to them.
    p.t.interruptFlags &= ^x
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"net"
	"net/url"
	"os"
	"runtime"
	"strings"
	"time"

	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
)

type host struct {
	name     string
	protocol string
	endpoint string
	addrs    []string
	resps    []resp
}

type resp struct {
	id   int
	seq  int
	code int
	sent time.Time
	recv time.Time
	dur  time.Duration
	to   string
	from string
	body string // TODO: Find a more optimal storage. Works well for ICMP, but not for GET.
}

var hosts []host

// readHosts reads in hosts from filename and populates hosts []host.
func readHosts() {
	f, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		hosts = append(hosts, host{name: scanner.Text()})
	}
	if err := scanner.Err(); err != nil {
		log.Printf("error reading hosts from %s:%s\n", filename, err)
	}
}

var filename string

func init() {
	// Check for '-f' flag for host file
	flag.StringVar(&filename, "f", "hosts", "File with hosts and urls to check.")
	flag.Parse()
}

// TODO: parse h.name{}'s for urls, set host.protocol and host.endpoint. net/url.Parse seems like a good fit.
func (h *host) unpackUrls() error {
	var isUrl bool
	// loop over host name
	for i := 0; i < len(h.name)-1; i++ {
		if string(h.name[i]) == ":" {
			isUrl = true
			break
		}
	}
	if isUrl {
		url, err := url.Parse(h.name)
		h.protocol = url.Scheme
		h.endpoint = url.Path
		h.name = url.Host
		return err
	}
	return nil
}

func (h *host) htoi() error {
	if len(h.addrs) == 0 {
		addrs, err := net.LookupHost(h.name)
		for _, i := range addrs {
			// Skip if address is ipv6.
			if strings.Contains(i, ":") {
				continue
			}
			h.addrs = append(h.addrs, i)
		}
		return err
	}
	return nil
}

func (h *host) ping() {
	switch runtime.GOOS {
	case "darwin":
	case "linux":
		log.Println("you may need to adjust the net.ipv4.ping_group_range kernel state")
	default:
		log.Println("not supported on", runtime.GOOS)
		return
	}

	c, err := icmp.ListenPacket("udp4", "0.0.0.0")
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()

	s := fmt.Sprintf("Ranger-Chooch-%s", h.name)
	var to net.IP
	var from string
	var sent, recv time.Time

	// TODO: icmp echo forever
	for i := 0; i < 1; i++ {
		wm := icmp.Message{
			Type: ipv4.ICMPTypeEcho, Code: 0,
			/* Using ID was from the example from golang.org, and /sbin/ping uses its PID as ICMP's ID.
			 * Maybe there's a reason for this, and we should keep ID as our PID.
			 */
			Body: &icmp.Echo{
				ID: os.Getpid() & 0xffff, Seq: i & 0xffff,
				Data: []byte(s),
			},
		}
		wb, err := wm.Marshal(nil)
		if err != nil {
			log.Fatal(err)
		}

		// Cowardly taking the first address.
		to = net.ParseIP(h.addrs[0])

		if _, err := c.WriteTo(wb, &net.UDPAddr{IP: to}); err != nil {
			log.Fatal(err)
		}
		sent = time.Now()
	}

	rb := make([]byte, 1500)
	// TODO: icmp echoreply forever
	for i := 0; i < 1; i++ {
		n, peer, err := c.ReadFrom(rb)
		if err != nil {
			log.Fatal(err)
		}
		recv = time.Now()
		rm, err := icmp.ParseMessage(1, rb[:n])
		if err != nil {
			log.Fatal(err)
		}

		from, _, _ = net.SplitHostPort(peer.String())
		if h.addrs[0] != from {
			log.Printf("got echo reply from %s; want %s", from, to)
		}
		if rm.Type != ipv4.ICMPTypeEchoReply {
			log.Printf("received something other than ping: %d", rm.Type)
			continue
		}

		body := string(rm.Body.(*icmp.Echo).Data)
		if s != body {
			log.Printf("got echo reply body %s; want %s", body, s)
		}
		seq := rm.Body.(*icmp.Echo).Seq
		id := rm.Body.(*icmp.Echo).ID
		dur := sent.Sub(recv)
		h.addResp(id, seq, rm.Code, sent, recv, dur, to.String(), from, body)
		time.Sleep(time.Second)

	}
}

func (h *host) addResp(id, seq, code int, sent, recv time.Time, dur time.Duration, to, from, body string) {
	r := resp{
		id:   id,
		seq:  seq,
		code: code,
		sent: sent,
		recv: recv,
		dur:  dur,
		to:   to,
		from: from,
		body: body,
	}
	h.resps = append(h.resps, r)
}

func main() {
	// if an entry is a url, send a GET request
	// if an entry is a hostname, send an ICMP ping
	// TODO: Add license
	// TODO: Add badges
	// TODO: add directions to README.md
}
<commit_msg>Remove completed TODOs<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"net"
	"net/url"
	"os"
	"runtime"
	"strings"
	"time"

	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
)

type host struct {
	name     string
	protocol string
	endpoint string
	addrs    []string
	resps    []resp
}

type resp struct {
	id   int
	seq  int
	code int
	sent time.Time
	recv time.Time
	dur  time.Duration
	to   string
	from string
	body string // TODO: Find a more optimal storage. Works well for ICMP, but not for GET.
}

var hosts []host

// readHosts reads in hosts from filename and populates hosts []host.
func readHosts() {
	f, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		hosts = append(hosts, host{name: scanner.Text()})
	}
	if err := scanner.Err(); err != nil {
		log.Printf("error reading hosts from %s:%s\n", filename, err)
	}
}

var filename string

func init() {
	// Check for '-f' flag for host file
	flag.StringVar(&filename, "f", "hosts", "File with hosts and urls to check.")
	flag.Parse()
}

// TODO: parse h.name{}'s for urls, set host.protocol and host.endpoint. net/url.Parse seems like a good fit.
func (h *host) unpackUrls() error {
	var isUrl bool
	// loop over host name
	for i := 0; i < len(h.name)-1; i++ {
		if string(h.name[i]) == ":" {
			isUrl = true
			break
		}
	}
	if isUrl {
		url, err := url.Parse(h.name)
		h.protocol = url.Scheme
		h.endpoint = url.Path
		h.name = url.Host
		return err
	}
	return nil
}

func (h *host) htoi() error {
	if len(h.addrs) == 0 {
		addrs, err := net.LookupHost(h.name)
		for _, i := range addrs {
			// Skip if address is ipv6.
			if strings.Contains(i, ":") {
				continue
			}
			h.addrs = append(h.addrs, i)
		}
		return err
	}
	return nil
}

func (h *host) ping() {
	switch runtime.GOOS {
	case "darwin":
	case "linux":
		log.Println("you may need to adjust the net.ipv4.ping_group_range kernel state")
	default:
		log.Println("not supported on", runtime.GOOS)
		return
	}

	c, err := icmp.ListenPacket("udp4", "0.0.0.0")
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()

	s := fmt.Sprintf("Ranger-Chooch-%s", h.name)
	var to net.IP
	var from string
	var sent, recv time.Time

	// TODO: icmp echo forever
	for i := 0; i < 1; i++ {
		wm := icmp.Message{
			Type: ipv4.ICMPTypeEcho, Code: 0,
			/* Using ID was from the example from golang.org, and /sbin/ping uses its PID as ICMP's ID.
			 * Maybe there's a reason for this, and we should keep ID as our PID.
			 */
			Body: &icmp.Echo{
				ID: os.Getpid() & 0xffff, Seq: i & 0xffff,
				Data: []byte(s),
			},
		}
		wb, err := wm.Marshal(nil)
		if err != nil {
			log.Fatal(err)
		}

		// Cowardly taking the first address.
		to = net.ParseIP(h.addrs[0])

		if _, err := c.WriteTo(wb, &net.UDPAddr{IP: to}); err != nil {
			log.Fatal(err)
		}
		sent = time.Now()
	}

	rb := make([]byte, 1500)
	// TODO: icmp echoreply forever
	for i := 0; i < 1; i++ {
		n, peer, err := c.ReadFrom(rb)
		if err != nil {
			log.Fatal(err)
		}
		recv = time.Now()
		rm, err := icmp.ParseMessage(1, rb[:n])
		if err != nil {
			log.Fatal(err)
		}

		from, _, _ = net.SplitHostPort(peer.String())
		if h.addrs[0] != from {
			log.Printf("got echo reply from %s; want %s", from, to)
		}
		if rm.Type != ipv4.ICMPTypeEchoReply {
			log.Printf("received something other than ping: %d", rm.Type)
			continue
		}

		body := string(rm.Body.(*icmp.Echo).Data)
		if s != body {
			log.Printf("got echo reply body %s; want %s", body, s)
		}
		seq := rm.Body.(*icmp.Echo).Seq
		id := rm.Body.(*icmp.Echo).ID
		dur := sent.Sub(recv)
		h.addResp(id, seq, rm.Code, sent, recv, dur, to.String(), from, body)
		time.Sleep(time.Second)

	}
}

func (h *host) addResp(id, seq, code int, sent, recv time.Time, dur time.Duration, to, from, body string) {
	r := resp{
		id:   id,
		seq:  seq,
		code: code,
		sent: sent,
		recv: recv,
		dur:  dur,
		to:   to,
		from: from,
		body: body,
	}
	h.resps = append(h.resps, r)
}

func main() {
	// if an entry is a url, send a GET request
	// if an entry is a hostname, send an ICMP ping
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package printers

import (
	"encoding/json"
	"fmt"
	"io"
	"reflect"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/util/jsonpath"
)

// exists returns true if it would be possible to call the index function
// with these arguments.
//
// TODO: how to document this for users?
//
// index returns the result of indexing its first argument by the following
// arguments.  Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
// indexed item must be a map, slice, or array.
func exists(item interface{}, indices ...interface{}) bool {
	v := reflect.ValueOf(item)
	for _, i := range indices {
		index := reflect.ValueOf(i)
		var isNil bool
		if v, isNil = indirect(v); isNil {
			return false
		}
		switch v.Kind() {
		case reflect.Array, reflect.Slice, reflect.String:
			var x int64
			switch index.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				x = index.Int()
			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
				x = int64(index.Uint())
			default:
				return false
			}
			if x < 0 || x >= int64(v.Len()) {
				return false
			}
			v = v.Index(int(x))
		case reflect.Map:
			if !index.IsValid() {
				index = reflect.Zero(v.Type().Key())
			}
			if !index.Type().AssignableTo(v.Type().Key()) {
				return false
			}
			if x := v.MapIndex(index); x.IsValid() {
				v = x
			} else {
				v = reflect.Zero(v.Type().Elem())
			}
		default:
			return false
		}
	}
	if _, isNil := indirect(v); isNil {
		return false
	}
	return true
}

// stolen from text/template
// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
// We indirect through pointers and empty interfaces (only) because
// non-empty interfaces have methods we might need.
func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
	for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
		if v.IsNil() {
			return v, true
		}
		if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
			break
		}
	}
	return v, false
}

// JSONPathPrinter is an implementation of ResourcePrinter which formats data with jsonpath expression.
type JSONPathPrinter struct {
	rawTemplate string
	*jsonpath.JSONPath
}

func NewJSONPathPrinter(tmpl string) (*JSONPathPrinter, error) {
	j := jsonpath.New("out")
	if err := j.Parse(tmpl); err != nil {
		return nil, err
	}
	return &JSONPathPrinter{
		rawTemplate: tmpl,
		JSONPath:    j,
	}, nil
}

// PrintObj formats the obj with the JSONPath Template.
func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
	// we use reflect.Indirect here in order to obtain the actual value from a pointer.
	// we need an actual value in order to retrieve the package path for an object.
	// using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers.
	if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) {
		return fmt.Errorf(InternalObjectPrinterErr)
	}

	var queryObj interface{} = obj
	if unstructured, ok := obj.(runtime.Unstructured); ok {
		queryObj = unstructured.UnstructuredContent()
	} else {
		data, err := json.Marshal(obj)
		if err != nil {
			return err
		}
		queryObj = map[string]interface{}{}
		if err := json.Unmarshal(data, &queryObj); err != nil {
			return err
		}
	}

	if err := j.JSONPath.Execute(w, queryObj); err != nil {
		fmt.Fprintf(w, "Error executing template: %v. Printing more information for debugging the template:\n", err)
		fmt.Fprintf(w, "\ttemplate was:\n\t\t%v\n", j.rawTemplate)
		fmt.Fprintf(w, "\tobject given to jsonpath engine was:\n\t\t%#v\n\n", queryObj)
		return fmt.Errorf("error executing jsonpath %q: %v\n", j.rawTemplate, err)
	}
	return nil
}
<commit_msg>Remove error output from stdout to stderr<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package printers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"reflect"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/util/jsonpath"
)

// exists returns true if it would be possible to call the index function
// with these arguments.
//
// TODO: how to document this for users?
//
// index returns the result of indexing its first argument by the following
// arguments.  Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
// indexed item must be a map, slice, or array.
func exists(item interface{}, indices ...interface{}) bool {
	v := reflect.ValueOf(item)
	for _, i := range indices {
		index := reflect.ValueOf(i)
		var isNil bool
		if v, isNil = indirect(v); isNil {
			return false
		}
		switch v.Kind() {
		case reflect.Array, reflect.Slice, reflect.String:
			var x int64
			switch index.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				x = index.Int()
			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
				x = int64(index.Uint())
			default:
				return false
			}
			if x < 0 || x >= int64(v.Len()) {
				return false
			}
			v = v.Index(int(x))
		case reflect.Map:
			if !index.IsValid() {
				index = reflect.Zero(v.Type().Key())
			}
			if !index.Type().AssignableTo(v.Type().Key()) {
				return false
			}
			if x := v.MapIndex(index); x.IsValid() {
				v = x
			} else {
				v = reflect.Zero(v.Type().Elem())
			}
		default:
			return false
		}
	}
	if _, isNil := indirect(v); isNil {
		return false
	}
	return true
}

// stolen from text/template
// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
// We indirect through pointers and empty interfaces (only) because
// non-empty interfaces have methods we might need.
func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
	for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
		if v.IsNil() {
			return v, true
		}
		if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
			break
		}
	}
	return v, false
}

// JSONPathPrinter is an implementation of ResourcePrinter which formats data with jsonpath expression.
type JSONPathPrinter struct {
	rawTemplate string
	*jsonpath.JSONPath
}

func NewJSONPathPrinter(tmpl string) (*JSONPathPrinter, error) {
	j := jsonpath.New("out")
	if err := j.Parse(tmpl); err != nil {
		return nil, err
	}
	return &JSONPathPrinter{
		rawTemplate: tmpl,
		JSONPath:    j,
	}, nil
}

// PrintObj formats the obj with the JSONPath Template.
func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
	// we use reflect.Indirect here in order to obtain the actual value from a pointer.
	// we need an actual value in order to retrieve the package path for an object.
	// using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers.
	if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) {
		return fmt.Errorf(InternalObjectPrinterErr)
	}

	var queryObj interface{} = obj
	if unstructured, ok := obj.(runtime.Unstructured); ok {
		queryObj = unstructured.UnstructuredContent()
	} else {
		data, err := json.Marshal(obj)
		if err != nil {
			return err
		}
		queryObj = map[string]interface{}{}
		if err := json.Unmarshal(data, &queryObj); err != nil {
			return err
		}
	}

	if err := j.JSONPath.Execute(w, queryObj); err != nil {
		buf := bytes.NewBuffer(nil)
		fmt.Fprintf(buf, "Error executing template: %v. Printing more information for debugging the template:\n", err)
		fmt.Fprintf(buf, "\ttemplate was:\n\t\t%v\n", j.rawTemplate)
		fmt.Fprintf(buf, "\tobject given to jsonpath engine was:\n\t\t%#v\n\n", queryObj)
		return fmt.Errorf("error executing jsonpath %q: %v\n", j.rawTemplate, buf.String())
	}
	return nil
}
<|endoftext|>


<commit_before>package mapping

import (
	"testing"
)

func TestBool(t *testing.T) {
	match := Match{}
	if false != Bool("", nil, match) {
		t.Fatal()
	}
	if false != Bool("false", nil, match) {
		t.Fatal()
	}
	if false != Bool("no", nil, match) {
		t.Fatal()
	}
	if false != Bool("0", nil, match) {
		t.Fatal()
	}

	if true != Bool("yes", nil, match) {
		t.Fatal()
	}
	if true != Bool("1", nil, match) {
		t.Fatal()
	}
	if true != Bool("true", nil, match) {
		t.Fatal()
	}

	// Bool defaults to true
	if true != Bool("other", nil, match) {
		t.Fatal()
	}

}

func TestMakeSuffixReplace(t *testing.T) {
	field := Field{
		"name", "name", "string_suffixreplace",
		map[string]interface{}{"suffixes": map[string]string{"Straße": "Str.", "straße": "str."}}}
	suffixReplace, err := MakeSuffixReplace("name", FieldType{}, field)

	if err != nil {
		t.Fatal(err)
	}

	if result := suffixReplace("Hauptstraße", nil, Match{}); result != "Hauptstr." {
		t.Fatal(result)
	}
	if result := suffixReplace("", nil, Match{}); result != "" {
		t.Fatal(result)
	}
	if result := suffixReplace("Foostraßeee", nil, Match{}); result != "Foostraßeee" {
		t.Fatal(result)
	}
}
<commit_msg>fixed MakeSuffixReplace test<commit_after>package mapping

import (
	"testing"
)

func TestBool(t *testing.T) {
	match := Match{}
	if false != Bool("", nil, match) {
		t.Fatal()
	}
	if false != Bool("false", nil, match) {
		t.Fatal()
	}
	if false != Bool("no", nil, match) {
		t.Fatal()
	}
	if false != Bool("0", nil, match) {
		t.Fatal()
	}

	if true != Bool("yes", nil, match) {
		t.Fatal()
	}
	if true != Bool("1", nil, match) {
		t.Fatal()
	}
	if true != Bool("true", nil, match) {
		t.Fatal()
	}

	// Bool defaults to true
	if true != Bool("other", nil, match) {
		t.Fatal()
	}

}

func TestMakeSuffixReplace(t *testing.T) {
	field := Field{
		"name", "name", "string_suffixreplace",
		map[string]interface{}{"suffixes": map[string]interface{}{"Straße": "Str.", "straße": "str."}}}
	suffixReplace, err := MakeSuffixReplace("name", FieldType{}, field)

	if err != nil {
		t.Fatal(err)
	}

	if result := suffixReplace("Hauptstraße", nil, Match{}); result != "Hauptstr." {
		t.Fatal(result)
	}
	if result := suffixReplace("", nil, Match{}); result != "" {
		t.Fatal(result)
	}
	if result := suffixReplace("Foostraßeee", nil, Match{}); result != "Foostraßeee" {
		t.Fatal(result)
	}
}
<|endoftext|>


<commit_before>package urknall

import (
	"fmt"
	"github.com/dynport/dgtk/dockerclient"
	"strings"
)

type dockerClient struct {
	tag        string
	host       *Host
	dockerHost *dockerclient.DockerHost

	dockerfile string
}

func newDockerClient(host *Host) (client *dockerClient, e error) {
	dh, e := dockerclient.NewViaTunnel(host.IP, host.user())
	if e != nil {
		return nil, e
	}
	if host.Docker.WithRegistry {
		dh.Registry = host.IP + ":5000"
	}
	return &dockerClient{host: host, dockerHost: dh}, nil
}

func (dc *dockerClient) provisionImage(baseImage, tag string, pkg Package) (imageId string, e error) {
	logger.PushPrefix(dc.host.IP)
	defer logger.PopPrefix()

	if tag != "" {
		if !strings.Contains(tag, "/") && dc.dockerHost.Registry != "" {
			tag = dc.dockerHost.Registry + "/" + tag
		}
		dc.tag = tag
	}

	runlist := &Runlist{name: tag, pkg: pkg}
	if e := runlist.compile(); e != nil {
		return "", e
	}

	aLen := len(runlist.commands)
	if aLen >= 42 {
		return "", fmt.Errorf("docker only supports runlists with up to 42 commands (found %d)", aLen)
	}

	if baseImage == "" {
		baseImage = "ubuntu"
	}
	dc.dockerfile = fmt.Sprintf("FROM %s\n", baseImage)

	runlists := append([]*Runlist{}, runlist)

	// Provisioning the runlist actually means building a dockerfile.
	if e = provisionRunlists(runlists, dc.buildDockerFile); e != nil {
		return "", e
	}

	// Use the generated dockerfile to build the image.
	imageId, e = dc.dockerHost.BuildImage(dc.dockerfile, dc.tag)
	if e != nil {
		return "", e
	}

	if dc.tag != "" {
		e = dc.dockerHost.PushImage(dc.tag)
	}

	return imageId, e
}

func countActions(runLists []*Runlist) (i int) {
	for idx := range runLists {
		i += len(runLists[idx].commands)
	}
	return i
}

func (dc *dockerClient) buildDockerFile(rl *Runlist) (e error) {
	for i := range rl.commands {
		dc.dockerfile += rl.commands[i].Docker() + "\n"
	}
	return nil
}
<commit_msg>use urknall logger for docker host<commit_after>package urknall

import (
	"fmt"
	"github.com/dynport/dgtk/dockerclient"
	"strings"
)

type dockerClient struct {
	tag        string
	host       *Host
	dockerHost *dockerclient.DockerHost

	dockerfile string
}

func newDockerClient(host *Host) (client *dockerClient, e error) {
	dh, e := dockerclient.NewViaTunnel(host.IP, host.user())
	if e != nil {
		return nil, e
	}
	dh.Logger = logger
	if host.Docker.WithRegistry {
		dh.Registry = host.IP + ":5000"
	}
	return &dockerClient{host: host, dockerHost: dh}, nil
}

func (dc *dockerClient) provisionImage(baseImage, tag string, pkg Package) (imageId string, e error) {
	logger.PushPrefix(dc.host.IP)
	defer logger.PopPrefix()

	if tag != "" {
		if !strings.Contains(tag, "/") && dc.dockerHost.Registry != "" {
			tag = dc.dockerHost.Registry + "/" + tag
		}
		dc.tag = tag
	}

	runlist := &Runlist{name: tag, pkg: pkg}
	if e := runlist.compile(); e != nil {
		return "", e
	}

	aLen := len(runlist.commands)
	if aLen >= 42 {
		return "", fmt.Errorf("docker only supports runlists with up to 42 commands (found %d)", aLen)
	}

	if baseImage == "" {
		baseImage = "ubuntu"
	}
	dc.dockerfile = fmt.Sprintf("FROM %s\n", baseImage)

	runlists := append([]*Runlist{}, runlist)

	// Provisioning the runlist actually means building a dockerfile.
	if e = provisionRunlists(runlists, dc.buildDockerFile); e != nil {
		return "", e
	}

	// Use the generated dockerfile to build the image.
	imageId, e = dc.dockerHost.BuildImage(dc.dockerfile, dc.tag)
	if e != nil {
		return "", e
	}

	if dc.tag != "" {
		e = dc.dockerHost.PushImage(dc.tag)
	}

	return imageId, e
}

func countActions(runLists []*Runlist) (i int) {
	for idx := range runLists {
		i += len(runLists[idx].commands)
	}
	return i
}

func (dc *dockerClient) buildDockerFile(rl *Runlist) (e error) {
	for i := range rl.commands {
		dc.dockerfile += rl.commands[i].Docker() + "\n"
	}
	return nil
}
<|endoftext|>