<commit_before>package sdl

import (
	"testing"
)

func TestEventsPushEvent(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	// Remove existing events in the queue
	if _, err := PeepEvents(make([]Event, 100), GETEVENT, FIRSTEVENT, LASTEVENT); err != nil {
		t.Errorf("PeepEvents:", err)
	}

	PushEvent(&in)

	out, ok := PollEvent().(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if out.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, out.Code)
	}
}

type simpleTestFilter struct{}

func (s *simpleTestFilter) FilterEvent(e Event, userdata interface{}) bool {
	return true
}

func TestEventsSetGetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filter := &simpleTestFilter{}
	SetEventFilter(filter, nil)

	if filter != GetEventFilter() {
		t.Errorf("Could not round-trip the event filter.")
	}

	if !isCEventFilterSet() {
		t.Errorf("Event filter was not actually set in C.")
	}

	SetEventFilter(nil, nil)

	if nil != GetEventFilter() {
		t.Errorf("Event filter was not cleared.")
	}

	if isCEventFilterSet() {
		t.Errorf("Event filter was not actually cleared in C.")
	}
}

func countEventsInQ(wait bool) int {
	var e Event
	if wait {
		e = WaitEvent()
	} else {
		e = PollEvent()
	}

	count := 0
	for ; e != nil; e = PollEvent() {
		count++
	}
	return count
}

func TestEventsSetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestSetEventFilter received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}
	SetEventFilterFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsGetEventFilterNilOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
	SetEventFilterFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()
	Init(INIT_EVERYTHING)

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
}

func TestEventsFilterEventsFuncQ(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestEventsFilterEventsFuncQ received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	FilterEventsFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsAddEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddEventWatch received", e)
		out = e
		if val, ok := userdata.(int); !ok || val != 0xDEADBEEF {
			t.Errorf("Failed to get userdata")
		}
		return true
	}

	AddEventWatchFunc(watch, 0xDEADBEEF)
	PushEvent(&in)

	if out == nil {
		t.Errorf("Event from event watch was nil but expected it to be non-nil.")
	}

	outue, ok := out.(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if outue.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, outue.Code)
	}
}

func TestEventsEventWatchClearOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)

	AddEventWatchFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()

	if len(eventWatches) != 0 {
		t.Errorf("Expected go event watches to be cleared but it contains %d contexts", len(eventWatches))
	}
}

func TestEventsAddDelEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddDelEventWatch received", e)
		out = e
		return true
	}

	handle := AddEventWatchFunc(watch, nil)
	DelEventWatch(handle)
	PushEvent(&in)

	if out != nil {
		t.Errorf("Event was received from event watch after it had been removed.")
	}
}
<commit_msg>sdl: events_test: use testing.Error since there's no format string<commit_after>package sdl

import (
	"testing"
)

func TestEventsPushEvent(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	// Remove existing events in the queue
	if _, err := PeepEvents(make([]Event, 100), GETEVENT, FIRSTEVENT, LASTEVENT); err != nil {
		t.Error("PeepEvents:", err)
	}

	PushEvent(&in)

	out, ok := PollEvent().(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if out.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, out.Code)
	}
}

type simpleTestFilter struct{}

func (s *simpleTestFilter) FilterEvent(e Event, userdata interface{}) bool {
	return true
}

func TestEventsSetGetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filter := &simpleTestFilter{}
	SetEventFilter(filter, nil)

	if filter != GetEventFilter() {
		t.Errorf("Could not round-trip the event filter.")
	}

	if !isCEventFilterSet() {
		t.Errorf("Event filter was not actually set in C.")
	}

	SetEventFilter(nil, nil)

	if nil != GetEventFilter() {
		t.Errorf("Event filter was not cleared.")
	}

	if isCEventFilterSet() {
		t.Errorf("Event filter was not actually cleared in C.")
	}
}

func countEventsInQ(wait bool) int {
	var e Event
	if wait {
		e = WaitEvent()
	} else {
		e = PollEvent()
	}

	count := 0
	for ; e != nil; e = PollEvent() {
		count++
	}
	return count
}

func TestEventsSetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestSetEventFilter received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}
	SetEventFilterFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsGetEventFilterNilOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
	SetEventFilterFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()
	Init(INIT_EVERYTHING)

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
}

func TestEventsFilterEventsFuncQ(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestEventsFilterEventsFuncQ received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	FilterEventsFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsAddEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddEventWatch received", e)
		out = e
		if val, ok := userdata.(int); !ok || val != 0xDEADBEEF {
			t.Errorf("Failed to get userdata")
		}
		return true
	}

	AddEventWatchFunc(watch, 0xDEADBEEF)
	PushEvent(&in)

	if out == nil {
		t.Errorf("Event from event watch was nil but expected it to be non-nil.")
	}

	outue, ok := out.(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if outue.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, outue.Code)
	}
}

func TestEventsEventWatchClearOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)

	AddEventWatchFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()

	if len(eventWatches) != 0 {
		t.Errorf("Expected go event watches to be cleared but it contains %d contexts", len(eventWatches))
	}
}

func TestEventsAddDelEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddDelEventWatch received", e)
		out = e
		return true
	}

	handle := AddEventWatchFunc(watch, nil)
	DelEventWatch(handle)
	PushEvent(&in)

	if out != nil {
		t.Errorf("Event was received from event watch after it had been removed.")
	}
}
<|endoftext|>


<commit_before>package gopher

import (
	f "github.com/gopherlabs/gopher-framework"
	"github.com/gopherlabs/gopher-services"
)

var (
	c       *f.Container
	App     *app
	Log     f.Loggable
	Route   f.Routable
	Context f.Mappable
	Render  f.Renderable
)

type app struct {
	ctnr     *f.Container
	LOGGER   string
	ROUTER   string
	RENDERER string
	PARAMS   string
	SAMPLE   string
}

func init() {
	initApp()
	App.Config()
}

func initApp() {
	app := new(app)
	app.LOGGER = f.LOGGER
	app.ROUTER = f.ROUTER
	app.RENDERER = f.RENDERER
	app.PARAMS = f.PARAMS
	app.SAMPLE = f.SAMPLE
	App = app
}

func (m *app) Config(config ...f.Config) {
	appConf := f.Config{}
	if len(config) > 0 {
		appConf = config[0]
	}
	c = f.NewContainer(appConf)
	App.ctnr = c
	c.Use(f.LoggerMiddleware)
	registerProviders()
}

func (m *app) Use(mw f.MiddlewareHandler, args ...interface{}) {
	m.ctnr.Use(mw, args...)
}

func registerProviders() {

	c.RegisterProvider(new(services.LogProvider))
	Log = c.Log

	c.RegisterProvider(new(services.MapProvider))
	Context = c.Context

	c.RegisterProvider(new(services.RouteProvider))
	Route = c.Route

	c.RegisterProvider(new(services.ParameterProvider))

	c.RegisterProvider(new(services.RenderProvider))
	Render = c.Render
}

func ListenAndServe() {
	Route.(f.Servable).Serve()
}
<commit_msg>Removed SAMPLE constants<commit_after>package gopher

import (
	f "github.com/gopherlabs/gopher-framework"
	"github.com/gopherlabs/gopher-services"
)

var (
	c       *f.Container
	App     *app
	Log     f.Loggable
	Route   f.Routable
	Context f.Mappable
	Render  f.Renderable
)

type app struct {
	ctnr     *f.Container
	LOGGER   string
	ROUTER   string
	RENDERER string
	PARAMS   string
	SAMPLE   string
}

func init() {
	initApp()
	App.Config()
}

func initApp() {
	app := new(app)
	app.LOGGER = f.LOGGER
	app.ROUTER = f.ROUTER
	app.RENDERER = f.RENDERER
	app.PARAMS = f.PARAMS
	App = app
}

func (m *app) Config(config ...f.Config) {
	appConf := f.Config{}
	if len(config) > 0 {
		appConf = config[0]
	}
	c = f.NewContainer(appConf)
	App.ctnr = c
	c.Use(f.LoggerMiddleware)
	registerProviders()
}

func (m *app) Use(mw f.MiddlewareHandler, args ...interface{}) {
	m.ctnr.Use(mw, args...)
}

func registerProviders() {

	c.RegisterProvider(new(services.LogProvider))
	Log = c.Log

	c.RegisterProvider(new(services.MapProvider))
	Context = c.Context

	c.RegisterProvider(new(services.RouteProvider))
	Route = c.Route

	c.RegisterProvider(new(services.ParameterProvider))

	c.RegisterProvider(new(services.RenderProvider))
	Render = c.Render
}

func ListenAndServe() {
	Route.(f.Servable).Serve()
}
<|endoftext|>


<commit_before>// Copyright ©2014 Dan Kortschak. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// gopher.png Copyright ©2009 The Go Authors. All rights reserved.
// Used under the Go LICENSE available at http://golang.org/LICENSE

// +build ignore

package main

import (
	"fmt"
	"github.com/kortschak/ct"
	"image"
	"image/color"
	_ "image/png"
	"os"
)

var (
	valueRange = [...]byte{0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
	table      = [16]color.RGBA{
		0x0: {R: 0x00, G: 0x00, B: 0x00, A: 0xff},
		0x1: {R: 0x80, G: 0x00, B: 0x00, A: 0xff},
		0x2: {R: 0x00, G: 0x80, B: 0x00, A: 0xff},
		0x3: {R: 0x80, G: 0x80, B: 0x00, A: 0xff},
		0x4: {R: 0x00, G: 0x00, B: 0x80, A: 0xff},
		0x5: {R: 0x80, G: 0x00, B: 0x80, A: 0xff},
		0x6: {R: 0x00, G: 0x80, B: 0x80, A: 0xff},
		0x7: {R: 0xc0, G: 0xc0, B: 0xc0, A: 0xff},
		0x8: {R: 0x80, G: 0x80, B: 0x80, A: 0xff},
		0x9: {R: 0xff, G: 0x00, B: 0x00, A: 0xff},
		0xa: {R: 0x00, G: 0xff, B: 0x00, A: 0xff},
		0xb: {R: 0xff, G: 0xff, B: 0x00, A: 0xff},
		0xc: {R: 0x00, G: 0x00, B: 0xff, A: 0xff},
		0xd: {R: 0xff, G: 0x00, B: 0xff, A: 0xff},
		0xe: {R: 0x00, G: 0xff, B: 0xff, A: 0xff},
		0xf: {R: 0xff, G: 0xff, B: 0xff, A: 0xff},
	}
	xterm = make(color.Palette, 255)
)

type xTermColor byte

func (c xTermColor) RGBA() (r, g, b, a uint32) {
	if c < 16 {
		return table[c].RGBA()
	}
	if c < 232 {
		c -= 16
		return color.RGBA{
			R: valueRange[(c/36)%6],
			G: valueRange[(c/6)%6],
			B: valueRange[c%6],
			A: 0xff,
		}.RGBA()
	}
	cb := byte(8 + (c-232)*10)
	return color.RGBA{cb, cb, cb, 0xff}.RGBA()
}

func init() {
	for i := range xterm {
		xterm[i] = xTermColor(i)
	}
}

func main() {
	var fn = "gopher.png"
	if len(os.Args) > 1 {
		fn = os.Args[1]
	}
	f, err := os.Open(fn)
	if err != nil {
		fmt.Printf("Couldn't find image file %q: %v\n", fn, err)
		os.Exit(1)
	}
	m, s, err := image.Decode(f)
	if err != nil {
		fmt.Printf("Couldn't decode image file for %q: %v\n", s, err)
		os.Exit(1)
	}
	b := m.Bounds()
	for y := 0; y < b.Dy(); y++ {
		fmt.Print(" ")
		for x := 0; x < b.Dx(); x++ {
			c := m.At(x, y)
			if _, _, _, a := c.RGBA(); a < 0x80 {
				fmt.Print(" ")
				continue
			}
			fmt.Print(ct.XTermBg(byte(xterm.Index(c))).Paint(" "))
		}
		fmt.Println()
	}
}
<commit_msg>Add attribution to Renée French<commit_after>// Copyright ©2014 Dan Kortschak. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// gopher.png Copyright ©2009 The Go Authors. All rights reserved.
// Used under the Go LICENSE available at http://golang.org/LICENSE
// Gopher artwork originally by Renée French. Used under the Creative
// Commons Attributions 3.0 license.

// +build ignore

package main

import (
	"fmt"
	"github.com/kortschak/ct"
	"image"
	"image/color"
	_ "image/png"
	"os"
)

var (
	valueRange = [...]byte{0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
	table      = [16]color.RGBA{
		0x0: {R: 0x00, G: 0x00, B: 0x00, A: 0xff},
		0x1: {R: 0x80, G: 0x00, B: 0x00, A: 0xff},
		0x2: {R: 0x00, G: 0x80, B: 0x00, A: 0xff},
		0x3: {R: 0x80, G: 0x80, B: 0x00, A: 0xff},
		0x4: {R: 0x00, G: 0x00, B: 0x80, A: 0xff},
		0x5: {R: 0x80, G: 0x00, B: 0x80, A: 0xff},
		0x6: {R: 0x00, G: 0x80, B: 0x80, A: 0xff},
		0x7: {R: 0xc0, G: 0xc0, B: 0xc0, A: 0xff},
		0x8: {R: 0x80, G: 0x80, B: 0x80, A: 0xff},
		0x9: {R: 0xff, G: 0x00, B: 0x00, A: 0xff},
		0xa: {R: 0x00, G: 0xff, B: 0x00, A: 0xff},
		0xb: {R: 0xff, G: 0xff, B: 0x00, A: 0xff},
		0xc: {R: 0x00, G: 0x00, B: 0xff, A: 0xff},
		0xd: {R: 0xff, G: 0x00, B: 0xff, A: 0xff},
		0xe: {R: 0x00, G: 0xff, B: 0xff, A: 0xff},
		0xf: {R: 0xff, G: 0xff, B: 0xff, A: 0xff},
	}
	xterm = make(color.Palette, 255)
)

type xTermColor byte

func (c xTermColor) RGBA() (r, g, b, a uint32) {
	if c < 16 {
		return table[c].RGBA()
	}
	if c < 232 {
		c -= 16
		return color.RGBA{
			R: valueRange[(c/36)%6],
			G: valueRange[(c/6)%6],
			B: valueRange[c%6],
			A: 0xff,
		}.RGBA()
	}
	cb := byte(8 + (c-232)*10)
	return color.RGBA{cb, cb, cb, 0xff}.RGBA()
}

func init() {
	for i := range xterm {
		xterm[i] = xTermColor(i)
	}
}

func main() {
	var fn = "gopher.png"
	if len(os.Args) > 1 {
		fn = os.Args[1]
	}
	f, err := os.Open(fn)
	if err != nil {
		fmt.Printf("Couldn't find image file %q: %v\n", fn, err)
		os.Exit(1)
	}
	m, s, err := image.Decode(f)
	if err != nil {
		fmt.Printf("Couldn't decode image file for %q: %v\n", s, err)
		os.Exit(1)
	}
	b := m.Bounds()
	for y := 0; y < b.Dy(); y++ {
		fmt.Print(" ")
		for x := 0; x < b.Dx(); x++ {
			c := m.At(x, y)
			if _, _, _, a := c.RGBA(); a < 0x80 {
				fmt.Print(" ")
				continue
			}
			fmt.Print(ct.XTermBg(byte(xterm.Index(c))).Paint(" "))
		}
		fmt.Println()
	}
}
<|endoftext|>


<commit_before>package main

import "bufio"
import "compress/gzip"
import "encoding/binary"
import "fmt"
import "io"
import "log"
import "os"
import "runtime"
import "sync"

type Edge struct {
	From uint32
	To   uint32
}

func ReadU(r io.ByteReader) (uint64, error) {
	var x uint64
	var count int
	//
	b, err := r.ReadByte()
	if err != nil {
		return x, err
	}
	for b == 0 {
		b, err = r.ReadByte()
		if err != nil {
			return x, err
		}
		count += 1
	}
	//
	for c := 0; c < count; c++ {
		x = (x << 8) + uint64(b)
		b, err = r.ReadByte()
		if err != nil {
			return x, err
		}
	}
	x = (x << 8) + uint64(b)
	return x, nil
}

func sendEdges(filename string, hashOnSource bool, chans [](chan Edge), senderGroup *sync.WaitGroup) {
	defer senderGroup.Done()
	f, _ := os.Open(filename)
	defer f.Close()
	gunzip, _ := gzip.NewReader(f)
	// Adds the ReadByte method requird by io.ByteReader interface
	wrappedByteReader := bufio.NewReader(gunzip)
	edge := uint64(0)
	chanLen := uint32(len(chans))
	for {
		// Read the variable integer and undo the delta encoding by adding the previous edge
		rawEdge, err := binary.ReadUvarint(wrappedByteReader)
		//rawEdge, err := ReadU(wrappedByteReader)
		edge += rawEdge
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}
		// Seperate the two 32 bit nodes from the 64 bit edge
		eFrom := uint32(edge >> 32)
		// Converting uint64 to uint32 drops the top 32 bits
		// Had (edge & 0xFFFFFFFF) for clarity but Go compiler doesn't optimize it away ...
		eTo := uint32(edge)
		// Edges are distributed across workers according to either source or destination node
		if hashOnSource {
			chans[eFrom%chanLen] <- Edge{eFrom, eTo}
		} else {
			chans[eTo%chanLen] <- Edge{eFrom, eTo}
		}
	}
}

func applyFunctionToEdges(f func(c chan Edge), workers int, hashOnSource bool) {
	// The work for each of the workers is deposited onto their channel
	chans := make([]chan Edge, workers, workers)
	for i := range chans {
		chans[i] = make(chan Edge, 1024)
	}
	//
	var senderGroup sync.WaitGroup
	for i := 0; i < 8; i++ {
		senderGroup.Add(1)
		go sendEdges(fmt.Sprintf("pld-arc.%d.bin.gz", i), hashOnSource, chans, &senderGroup)
	}
	//
	var readerGroup sync.WaitGroup
	for _, c := range chans {
		readerGroup.Add(1)
		go func(c chan Edge) {
			defer readerGroup.Done()
			f(c)
		}(c)
	}
	//
	senderGroup.Wait()
	for _, c := range chans {
		close(c)
	}
	readerGroup.Wait()
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	// We can either have total nodes supplied by the user or perform a full traversal of the data
	total := uint32(42889799 + 1)
	alpha := float32(0.85)
	//
	src := make([]float32, total, total)
	dest := make([]float32, total, total)
	degree := make([]float32, total, total)
	//
	log.Printf("Calculating degree of each source node\n")
	applyFunctionToEdges(func(c chan Edge) {
		for edge := range c {
			degree[edge.From] += 1
		}
	}, 8, true)
	//
	for iter := 0; iter < 20; iter++ {
		log.Printf("PageRank Iteration: %d\n", iter+1)
		log.Printf("Calculating the source and destination vectors\n")
		for i := range dest {
			src[i] = alpha * dest[i] / degree[i]
			dest[i] = 1 - alpha
		}
		log.Printf("Calculating the probability mass gifted by incoming edges\n")
		applyFunctionToEdges(func(c chan Edge) {
			for edge := range c {
				dest[edge.To] += src[edge.From]
			}
		}, 8, false)
	}
}
<commit_msg>Remove channels as they're a major bottleneck (93s => 59s per iteration)<commit_after>package main

import "bufio"
import "compress/gzip"
import "encoding/binary"
import "fmt"
import "io"
import "log"
import "os"
import "runtime"
import "sync"

type Edge struct {
	From uint32
	To   uint32
}

func sendEdges(filename string, f func(uint32, uint32), senderGroup *sync.WaitGroup) {
	defer senderGroup.Done()
	file, _ := os.Open(filename)
	defer file.Close()
	gunzip, _ := gzip.NewReader(file)
	// Adds the ReadByte method requird by io.ByteReader interface
	wrappedByteReader := bufio.NewReader(gunzip)
	edge := uint64(0)
	for {
		// Read the variable integer and undo the delta encoding by adding the previous edge
		rawEdge, err := binary.ReadUvarint(wrappedByteReader)
		edge += rawEdge
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}
		// Seperate the two 32 bit nodes from the 64 bit edge
		eFrom := uint32(edge >> 32)
		// Converting uint64 to uint32 drops the top 32 bits
		// Had (edge & 0xFFFFFFFF) for clarity but Go compiler doesn't optimize it away ...
		eTo := uint32(edge)
		// Edges are distributed across workers according to either source or destination node
		f(eFrom, eTo)
	}
}

func applyFunctionToEdges(f func(uint32, uint32), workers int) {
	var senderGroup sync.WaitGroup
	for i := 0; i < 8; i++ {
		senderGroup.Add(1)
		go sendEdges(fmt.Sprintf("pld-arc.%d.bin.gz", i), f, &senderGroup)
	}
	//
	senderGroup.Wait()
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	// We can either have total nodes supplied by the user or perform a full traversal of the data
	total := uint32(42889799 + 1)
	alpha := float32(0.85)
	//
	src := make([]float32, total, total)
	dest := make([]float32, total, total)
	degree := make([]float32, total, total)
	//
	log.Printf("Calculating degree of each source node\n")
	applyFunctionToEdges(func(from uint32, to uint32) {
		degree[from] += 1
	}, 8)
	//
	for iter := 0; iter < 20; iter++ {
		log.Printf("PageRank Iteration: %d\n", iter+1)
		log.Printf("Calculating the source and destination vectors\n")
		for i := range dest {
			src[i] = alpha * dest[i] / degree[i]
			dest[i] = 1 - alpha
		}
		log.Printf("Calculating the probability mass gifted by incoming edges\n")
		applyFunctionToEdges(func(from uint32, to uint32) {
			dest[to] += src[from]
		}, 8)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/GeertJohan/go.linenoise"
	"github.com/jessevdk/go-flags"
	"github.com/k0kubun/gosick/scheme"
	"io/ioutil"
	"log"
	"strings"
)

type Options struct {
	FileName   string   `short:"f" long:"file" description:"interpret selected scheme source file"`
	Expression []string `short:"e" long:"expression" description:"excecute given expression"`
	DumpAST    bool     `short:"a" long:"ast" default:"false" description:"whether leaf nodes are plotted"`
}

func main() {
	options := new(Options)
	if _, err := flags.Parse(options); err != nil {
		return
	}

	if len(options.FileName) > 0 {
		executeSourceCode(options)
	} else if len(options.Expression) > 0 {
		executeExpression(strings.Join(options.Expression, " "), options.DumpAST)
	} else {
		invokeInteractiveShell(options)
	}
}

func executeSourceCode(options *Options) {
	buffer, err := ioutil.ReadFile(options.FileName)
	if err != nil {
		log.Fatal(err)
	}

	executeExpression(string(buffer), options.DumpAST)
}

func executeExpression(expression string, dumpAST bool) {
	interpreter := scheme.NewInterpreter(expression)
	interpreter.Eval(dumpAST)
}

func invokeInteractiveShell(options *Options) {
	for {
		indentLevel := 0
		expression := ""

		for {
			currentLine, err := linenoise.Line(shellPrompt(indentLevel))
			if err != nil {
				log.Fatal(err)
				return
			}
			if currentLine == "exit" {
				return
			}
			expression += " "
			expression += currentLine

			interpreter := scheme.NewInterpreter(expression)
			indentLevel = interpreter.IndentLevel()
			if indentLevel == 0 {
				executeExpression(expression, options.DumpAST)
				break
			} else if indentLevel < 0 {
				fmt.Println("*** ERROR: extra close parentheses")
				expression = ""
				indentLevel = 0
			}
		}
	}
}

func shellPrompt(indentLevel int) string {
	if indentLevel == 0 {
		return "gosick> "
	} else if indentLevel > 0 {
		return fmt.Sprintf("gosick* %s", strings.Repeat("  ", indentLevel))
	} else {
		panic("Negative indent level")
	}
}
<commit_msg>Push execution log into REPL<commit_after>package main

import (
	"fmt"
	"github.com/GeertJohan/go.linenoise"
	"github.com/jessevdk/go-flags"
	"github.com/k0kubun/gosick/scheme"
	"io/ioutil"
	"log"
	"strings"
)

type Options struct {
	FileName   string   `short:"f" long:"file" description:"interpret selected scheme source file"`
	Expression []string `short:"e" long:"expression" description:"excecute given expression"`
	DumpAST    bool     `short:"a" long:"ast" default:"false" description:"whether leaf nodes are plotted"`
}

func main() {
	options := new(Options)
	if _, err := flags.Parse(options); err != nil {
		return
	}

	if len(options.FileName) > 0 {
		executeSourceCode(options)
	} else if len(options.Expression) > 0 {
		executeExpression(strings.Join(options.Expression, " "), options.DumpAST)
	} else {
		invokeInteractiveShell(options)
	}
}

func executeSourceCode(options *Options) {
	buffer, err := ioutil.ReadFile(options.FileName)
	if err != nil {
		log.Fatal(err)
	}

	executeExpression(string(buffer), options.DumpAST)
}

func executeExpression(expression string, dumpAST bool) {
	interpreter := scheme.NewInterpreter(expression)
	interpreter.Eval(dumpAST)
}

func invokeInteractiveShell(options *Options) {
	for {
		indentLevel := 0
		expression := ""

		for {
			currentLine, err := linenoise.Line(shellPrompt(indentLevel))
			if err != nil {
				log.Fatal(err)
				return
			}
			if currentLine == "exit" {
				return
			}
			linenoise.AddHistory(currentLine)
			expression += " "
			expression += currentLine

			interpreter := scheme.NewInterpreter(expression)
			indentLevel = interpreter.IndentLevel()
			if indentLevel == 0 {
				executeExpression(expression, options.DumpAST)
				break
			} else if indentLevel < 0 {
				fmt.Println("*** ERROR: extra close parentheses")
				expression = ""
				indentLevel = 0
			}
		}
	}
}

func shellPrompt(indentLevel int) string {
	if indentLevel == 0 {
		return "gosick> "
	} else if indentLevel > 0 {
		return fmt.Sprintf("gosick* %s", strings.Repeat("  ", indentLevel))
	} else {
		panic("Negative indent level")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"os"

	"github.com/codegangsta/cli"
	"github.com/op/go-logging"
)

const (
	PENDING = iota
	FAIL
	SUCCESS

	// TODO - DEFAULT_CONF_LOCATION = "/etc/gotter/gotter.conf"
)

var (
	exitStatus int

	log = logging.MustGetLogger("gotter")

	WORKSPACE = os.Getenv("WORKSPACE")
	GOPATH    = os.Getenv("GOPATH")
)

func main() {
	initLogger()

	app := cli.NewApp()
	app.Name = "gotter"
	app.Author = "John-Alan Simmons <simmons.johnalan@gmail.com>"
	app.Usage = "Utlity to unify and manage Go projects into a single workspace"
	app.Version = "0.1.0-rc1"

	// Overwrite default 'version' shorthand 'v' flag
	cli.VersionFlag.Name = "version"
	app.Flags = []cli.Flag{
		cli.BoolFlag{"verbose, v", "Enable verbose logging"},
		cli.BoolFlag{"extra-verbose, vv", "Enable more verbose logging"},
	}
	app.Before = func(c *cli.Context) error {
		cmd := c.Args().First()
		if cmd == "" || cmd == "help" || cmd == "h" {
			return nil
		}

		if c.Bool("extra-verbose") {
			logging.SetLevel(logging.DEBUG, "gotter")
		} else if c.Bool("verbose") {
			logging.SetLevel(logging.INFO, "gotter")
		} else {
			logging.SetLevel(logging.WARNING, "gotter")
		}

		// Make sure environment variable is set
		if WORKSPACE == "" {
			log.Error("[ERROR]: WORKSPACE enviromental variable not set!")
			return errors.New("WORKSPACE enviromental variable not set!")
		}
		if GOPATH == "" {
			log.Error("[ERROR]: GOPATH enviromental variable not set!")
			return errors.New("GOPATH enviromental variable not set!")
		}

		return nil
	}

	app.Commands = []cli.Command{getCommand, cloneCommand, linkCommand, updateRemoteCommand}

	defer func() {
		if exitStatus == FAIL {
			log.Error("Status: FAILED")
		}
	}()

	app.Run(os.Args)
}

func initLogger() {
	logBackend := logging.NewLogBackend(os.Stderr, "", 0)
	syslogBackend, err := logging.NewSyslogBackend("")
	if err != nil {
		panic(err)
	}
	logging.SetBackend(logBackend, syslogBackend)
}
<commit_msg>Fixed typo<commit_after>package main

import (
	"errors"
	"os"

	"github.com/codegangsta/cli"
	"github.com/op/go-logging"
)

const (
	PENDING = iota
	FAIL
	SUCCESS

	// TODO - DEFAULT_CONF_LOCATION = "/etc/gotter/gotter.conf"
)

var (
	exitStatus int

	log = logging.MustGetLogger("gotter")

	WORKSPACE = os.Getenv("WORKSPACE")
	GOPATH    = os.Getenv("GOPATH")
)

func main() {
	initLogger()

	app := cli.NewApp()
	app.Name = "gotter"
	app.Author = "John-Alan Simmons <simmons.johnalan@gmail.com>"
	app.Usage = "Utlity to unify and manage Go projects into a single workspace"
	app.Version = "0.1.0-rc1"

	// Overwrite default 'version' shorthand 'v' flag
	cli.VersionFlag.Name = "version"
	app.Flags = []cli.Flag{
		cli.BoolFlag{"verbose, v", "Enable verbose logging"},
		cli.BoolFlag{"extra-verbose, vv", "Enable more verbose logging"},
	}
	app.Before = func(c *cli.Context) error {
		cmd := c.Args().First()
		if cmd == "" || cmd == "help" || cmd == "h" {
			return nil
		}

		if c.Bool("extra-verbose") {
			logging.SetLevel(logging.DEBUG, "gotter")
		} else if c.Bool("verbose") {
			logging.SetLevel(logging.INFO, "gotter")
		} else {
			logging.SetLevel(logging.WARNING, "gotter")
		}

		// Make sure environment variable is set
		if WORKSPACE == "" {
			log.Error("[ERROR]: WORKSPACE enviroment variable not set!")
			return errors.New("WORKSPACE enviroment variable not set!")
		}
		if GOPATH == "" {
			log.Error("[ERROR]: GOPATH enviroment variable not set!")
			return errors.New("GOPATH enviroment variable not set!")
		}

		return nil
	}

	app.Commands = []cli.Command{getCommand, cloneCommand, linkCommand, updateRemoteCommand}

	defer func() {
		if exitStatus == FAIL {
			log.Error("Status: FAILED")
		}
	}()

	app.Run(os.Args)
}

func initLogger() {
	logBackend := logging.NewLogBackend(os.Stderr, "", 0)
	syslogBackend, err := logging.NewSyslogBackend("")
	if err != nil {
		panic(err)
	}
	logging.SetBackend(logBackend, syslogBackend)
}
<|endoftext|>


<commit_before>package goutil

import (
	"os"
)

// FileExists returns true if the file exists.
func FileExists(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}
<commit_msg>New method IsFile()<commit_after>package goutil

import (
	"os"
)

// IsFile returns true if the file exists and is not a directory.
func IsFile(path string) bool {
	exists, fi := fileExists(path)
	if exists && !fi.IsDir() {
		return true
	}
	return false
}

// FileExists returns true if the file exists.
func FileExists(path string) bool {
	exists,_ := fileExists(path)
	return exists
}

func fileExists(path string) (bool, os.FileInfo) {
	fi, err := os.Stat(path)
	os.IsNotExist(err)
	if err != nil && os.IsNotExist(err) {
		return false, nil
	}
	return true, fi
}
<|endoftext|>


<commit_before>package gowork

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/oleiade/lane"
	"github.com/peter-edge/go-encrypt"
	"github.com/satori/go.uuid"
	"gopkg.in/mgo.v2/bson"
)

type WorkServer struct {
	Queue         *lane.Queue
	Handlers      map[string]func(*Event, map[string]interface{})
	HandlerParams map[string]interface{}
	Workers       *WorkersStruct
}

type WorkersStruct struct {
	Members     map[int]*Worker
	Transformer encrypt.Transformer
	WorkerCount int
}

type Worker struct {
	Id                       int
	Registered               bool
	Transformer              encrypt.Transformer
	SessionAuthenticationKey string
	Verification             *ClientTest
}

type ClientTest struct {
	PlaintextVerification string `json:"Verification"`
	ClientResponse        string `json:"Response"`
}

type Work struct {
	Id       bson.ObjectId `json:"-" bson:"_id"`
	IdHex    string
	WorkJSON string
	Result   *WorkResult
	Time     *TimeStats
}

type WorkResult struct {
	ResultJSON string
	Status     string
	Error      string
}

type TimeStats struct {
	Added    int64
	Recieved int64
	Complete int64
	Timeout  int64
}

type Event struct {
	Work   *Work
	Worker *Worker
	Error  string
	Time   int64
}

func GenerateSecret() (string, error) {
	EncodedSecret, err := encrypt.GenerateAESKey(encrypt.AES256Bits)
	if err != nil {
		return "", err
	}
	Secret, err := encrypt.DecodeString(EncodedSecret)
	if err != nil {
		return "", err
	}
	return string(Secret), nil
}

func NewEventError(msg string) *Event {
	return &Event{Error: msg, Time: time.Now().UTC().Unix()}
}

func NewEventWork(w *Work) *Event {
	return &Event{Work: w, Time: time.Now().UTC().Unix()}
}

func NewEventWorker(w *Worker) *Event {
	return &Event{Worker: w, Time: time.Now().UTC().Unix()}
}

func NewServer(Secret string) (*WorkServer, error) {
	Transformer, err := NewTransformer(Secret)
	if err != nil {
		return &WorkServer{}, err
	}
	return NewServerInit(Transformer), nil
}

func MustNewServer(Secret string) *WorkServer {
	return NewServerInit(MustNewTransformer(Secret))
}

func NewServerInit(Transformer encrypt.Transformer) *WorkServer {
	Queue := lane.NewQueue()
	WorkerMembers := make(map[int]*Worker)
	Workers := &WorkersStruct{WorkerMembers, Transformer, 0}
	HandlerFuncs := make(map[string]func(*Event, map[string]interface{}))
	HandlerParams := make(map[string]interface{})
	WorkServerInst := &WorkServer{Queue, HandlerFuncs, HandlerParams, Workers}
	return WorkServerInst
}

func (ws *WorkServer) NewHandler(event_id string, hf func(*Event, map[string]interface{})) error {
	if _, exists := ws.Handlers[event_id]; exists {
		ws.Event("add_handler_error", NewEventError("HandlerExists"))
		return errors.New("Handler already exists")
	}
	ws.Handlers[event_id] = hf
	return nil
}

func (ws *WorkServer) AddParams(params map[string]interface{}) *WorkServer {
	ws.HandlerParams = params
	return ws
}

func (ws *WorkServer) Event(event_id string, event *Event) {
	if handlerFunc, exists := ws.Handlers[event_id]; exists {
		handlerFunc(event, ws.HandlerParams)
	}
}

func (ws *WorkServer) Add(w *Work) {
	w.Time.Added = time.Now().UTC().Unix()
	ws.Event("add_work", NewEventWork(w))
	ws.Queue.Enqueue(w)
}

func (ws *WorkServer) Get(Id string, AuthenticationKey string) (*Work, error) {
	IdInt, err := strconv.Atoi(Id)
	if err != nil {
		ws.Event("get_work_error", NewEventError("StrconvError"))
		return &Work{}, errors.New("Failed to convert Worker ID string to int:" + err.Error())
	}
	if ws.Workers.Members[IdInt].SessionAuthenticationKey != AuthenticationKey {
		ws.Event("get_work_error", NewEventError("AuthFailed"))
		return &Work{}, errors.New("Failed authentication")
	}
	WorkObj := ws.Queue.Dequeue()
	if WorkObj == nil {
		ws.Event("get_work_empty", NewEventError("NoWork"))
		return &Work{}, nil
	}
	if (WorkObj.(*Work).Time.Added + WorkObj.(*Work).Time.Timeout) > time.Now().UTC().Unix() {
		ws.Event("get_work", NewEventWork(WorkObj.(*Work)))
		return WorkObj.(*Work), nil
	}
	ws.Event("work_timeout", NewEventWork(WorkObj.(*Work)))
	return WorkObj.(*Work), errors.New("Work Timeout")
}

func (ws *WorkServer) Submit(w *Work) {
	if (w.Time.Added + w.Time.Timeout) <= time.Now().UTC().Unix() {
		w.Result.Error = "Timeout"
		w.Result.Status = "Timeout"
		ws.Event("work_timeout", NewEventWork(w))
		return
	}
	w.Id = bson.ObjectIdHex(w.IdHex)
	ws.Event("work_complete", NewEventWork(w))
}

func (ws *WorkServer) QueueSize() int {
	return ws.Queue.Size()
}

func (wrs *WorkersStruct) Register(ws *WorkServer) (string, string) {
	TempWC := wrs.WorkerCount
	wrs.WorkerCount += 1
	w := &Worker{
		Id:           TempWC + 1,
		Verification: &ClientTest{PlaintextVerification: uuid.NewV4().String()},
		Registered:   false,
	}
	wrs.Members[w.Id] = w
	ws.Event("worker_register", NewEventWorker(w))
	return strconv.Itoa(w.Id), w.Verification.PlaintextVerification
}

func (wrs *WorkersStruct) Verify(ws *WorkServer, Id string, Response string) (string, error) {
	IdInt, err := strconv.Atoi(Id)
	if err != nil {
		ws.Event("worker_verify_error", NewEventError("StrconvError"))
		return "", errors.New("Failed to convert Worker ID string to int:" + err.Error())
	}
	ClientResp, err := wrs.Transformer.Decrypt([]byte(Response))
	if err != nil {
		ws.Event("worker_verify_error", NewEventError("DecryptionError"))
		return "", errors.New("Failed to decrypt worker verification string:" + err.Error())
	}
	wrs.Members[IdInt].Verification.ClientResponse = string(ClientResp)
	if wrs.Members[IdInt].Verification.PlaintextVerification != string(wrs.Members[IdInt].Verification.ClientResponse) {
		ws.Event("worker_verify_error", NewEventError("KeyMismatch"))
		return "", errors.New("Client key incorrect")
	}
	wrs.Members[IdInt].Registered = true
	wrs.Members[IdInt].SessionAuthenticationKey = uuid.NewV4().String()
	ws.Event("worker_verify", NewEventWorker(wrs.Members[IdInt]))
	return wrs.Members[IdInt].SessionAuthenticationKey, nil
}

func NewWorker(Secret string, ID string, PlaintextVerification string) (*Worker, error) {
	wrk := &Worker{}
	Transformer, err := NewTransformer(Secret)
	if err != nil {
		return wrk, err
	}
	wrk.Transformer = Transformer
	wrk.Verification = &ClientTest{PlaintextVerification: PlaintextVerification}
	IdInt, err := strconv.Atoi(ID)
	if err != nil {
		return &Worker{}, errors.New("Failed to convert Worker ID string to int:" + err.Error())
	}
	wrk.Id = IdInt
	ClientResponse, err := wrk.Transformer.Encrypt([]byte(wrk.Verification.PlaintextVerification))
	if err != nil {
		return &Worker{}, errors.New("Failed to encrypt verification string:" + err.Error())
	}
	wrk.Verification.ClientResponse = string(ClientResponse)
	return wrk, nil
}

func (wrk *Worker) SetAuthenticationKey(key string) *Worker {
	wrk.SessionAuthenticationKey = key
	return wrk
}

func (wrk *Worker) Process(w *Work) (*Work, map[string]interface{}, error) {
	WorkParams := make(map[string]interface{})
	if (w.Time.Added + w.Time.Timeout) <= time.Now().UTC().Unix() {
		return w, WorkParams, errors.New("Work Timeout")
	}
	err := json.Unmarshal([]byte(w.WorkJSON), &WorkParams)
	if err != nil {
		return w, WorkParams, errors.New("Failed to unmarshal Work Params JSON:" + err.Error())
	}
	w.Time.Recieved = time.Now().UTC().Unix()
	return w, WorkParams, nil
}

func (wrk *Worker) Submit(w *Work, ResultJSON string, Error string) (*Work, error) {
	wr := &WorkResult{}
	wr.ResultJSON = ResultJSON
	w.Time.Complete = time.Now().UTC().Unix()
	if (w.Time.Added + w.Time.Timeout) > time.Now().UTC().Unix() {
		wr.Error = Error
		wr.Status = "Complete"
		w.Result = wr
		return w, nil
	}
	wr.Error = "Timeout"
	wr.Status = "Timeout"
	w.Result = wr
	return w, errors.New("Timeout")
}

func CreateWork(WorkData interface{}, Timeout int64) (*Work, error) {
	NewWork := &Work{}
	NewWork.IdHex = bson.NewObjectId().Hex()
	NewWork.Result = &WorkResult{"", "Pending", ""}
	NewWork.Time = &TimeStats{Timeout: Timeout}
	WorkDataJSON, err := json.Marshal(WorkData)
	if err != nil {
		return &Work{}, errors.New("Failed to marshal work data:" + err.Error())
	}
	NewWork.WorkJSON = string(WorkDataJSON)
	return NewWork, nil
}

func (w *Work) Marshal() string {
	MarshalledWork, _ := json.Marshal(w)
	return string(MarshalledWork)
}

func Unmarshal(w string) *Work {
	WorkObject := &Work{}
	_ = json.Unmarshal([]byte(w), &WorkObject)
	return WorkObject
}

func NewTransformer(Secret string) (encrypt.Transformer, error) {
	if len(Secret) != 32 {
		return nil, fmt.Errorf("Length of secret must be 32, length was %d", len(Secret))
	}
	return encrypt.NewAESTransformer(encrypt.EncodeToString([]byte(Secret)))
}

func MustNewTransformer(Secret string) encrypt.Transformer {
	Transformer, err := NewTransformer(Secret)
	if err != nil {
		panic(err.Error())
	}
	return Transformer
}
<commit_msg>update go-encrypt import path for custom url<commit_after>package gowork

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/oleiade/lane"
	"github.com/satori/go.uuid"
	"go.pedge.io/encrypt"
	"gopkg.in/mgo.v2/bson"
)

type WorkServer struct {
	Queue         *lane.Queue
	Handlers      map[string]func(*Event, map[string]interface{})
	HandlerParams map[string]interface{}
	Workers       *WorkersStruct
}

type WorkersStruct struct {
	Members     map[int]*Worker
	Transformer encrypt.Transformer
	WorkerCount int
}

type Worker struct {
	Id                       int
	Registered               bool
	Transformer              encrypt.Transformer
	SessionAuthenticationKey string
	Verification             *ClientTest
}

type ClientTest struct {
	PlaintextVerification string `json:"Verification"`
	ClientResponse        string `json:"Response"`
}

type Work struct {
	Id       bson.ObjectId `json:"-" bson:"_id"`
	IdHex    string
	WorkJSON string
	Result   *WorkResult
	Time     *TimeStats
}

type WorkResult struct {
	ResultJSON string
	Status     string
	Error      string
}

type TimeStats struct {
	Added    int64
	Recieved int64
	Complete int64
	Timeout  int64
}

type Event struct {
	Work   *Work
	Worker *Worker
	Error  string
	Time   int64
}

func GenerateSecret() (string, error) {
	EncodedSecret, err := encrypt.GenerateAESKey(encrypt.AES256Bits)
	if err != nil {
		return "", err
	}
	Secret, err := encrypt.DecodeString(EncodedSecret)
	if err != nil {
		return "", err
	}
	return string(Secret), nil
}

func NewEventError(msg string) *Event {
	return &Event{Error: msg, Time: time.Now().UTC().Unix()}
}

func NewEventWork(w *Work) *Event {
	return &Event{Work: w, Time: time.Now().UTC().Unix()}
}

func NewEventWorker(w *Worker) *Event {
	return &Event{Worker: w, Time: time.Now().UTC().Unix()}
}

func NewServer(Secret string) (*WorkServer, error) {
	Transformer, err := NewTransformer(Secret)
	if err != nil {
		return &WorkServer{}, err
	}
	return NewServerInit(Transformer), nil
}

func MustNewServer(Secret string) *WorkServer {
	return NewServerInit(MustNewTransformer(Secret))
}

func NewServerInit(Transformer encrypt.Transformer) *WorkServer {
	Queue := lane.NewQueue()
	WorkerMembers := make(map[int]*Worker)
	Workers := &WorkersStruct{WorkerMembers, Transformer, 0}
	HandlerFuncs := make(map[string]func(*Event, map[string]interface{}))
	HandlerParams := make(map[string]interface{})
	WorkServerInst := &WorkServer{Queue, HandlerFuncs, HandlerParams, Workers}
	return WorkServerInst
}

func (ws *WorkServer) NewHandler(event_id string, hf func(*Event, map[string]interface{})) error {
	if _, exists := ws.Handlers[event_id]; exists {
		ws.Event("add_handler_error", NewEventError("HandlerExists"))
		return errors.New("Handler already exists")
	}
	ws.Handlers[event_id] = hf
	return nil
}

func (ws *WorkServer) AddParams(params map[string]interface{}) *WorkServer {
	ws.HandlerParams = params
	return ws
}

func (ws *WorkServer) Event(event_id string, event *Event) {
	if handlerFunc, exists := ws.Handlers[event_id]; exists {
		handlerFunc(event, ws.HandlerParams)
	}
}

func (ws *WorkServer) Add(w *Work) {
	w.Time.Added = time.Now().UTC().Unix()
	ws.Event("add_work", NewEventWork(w))
	ws.Queue.Enqueue(w)
}

func (ws *WorkServer) Get(Id string, AuthenticationKey string) (*Work, error) {
	IdInt, err := strconv.Atoi(Id)
	if err != nil {
		ws.Event("get_work_error", NewEventError("StrconvError"))
		return &Work{}, errors.New("Failed to convert Worker ID string to int:" + err.Error())
	}
	if ws.Workers.Members[IdInt].SessionAuthenticationKey != AuthenticationKey {
		ws.Event("get_work_error", NewEventError("AuthFailed"))
		return &Work{}, errors.New("Failed authentication")
	}
	WorkObj := ws.Queue.Dequeue()
	if WorkObj == nil {
		ws.Event("get_work_empty", NewEventError("NoWork"))
		return &Work{}, nil
	}
	if (WorkObj.(*Work).Time.Added + WorkObj.(*Work).Time.Timeout) > time.Now().UTC().Unix() {
		ws.Event("get_work", NewEventWork(WorkObj.(*Work)))
		return WorkObj.(*Work), nil
	}
	ws.Event("work_timeout", NewEventWork(WorkObj.(*Work)))
	return WorkObj.(*Work), errors.New("Work Timeout")
}

func (ws *WorkServer) Submit(w *Work) {
	if (w.Time.Added + w.Time.Timeout) <= time.Now().UTC().Unix() {
		w.Result.Error = "Timeout"
		w.Result.Status = "Timeout"
		ws.Event("work_timeout", NewEventWork(w))
		return
	}
	w.Id = bson.ObjectIdHex(w.IdHex)
	ws.Event("work_complete", NewEventWork(w))
}

func (ws *WorkServer) QueueSize() int {
	return ws.Queue.Size()
}

func (wrs *WorkersStruct) Register(ws *WorkServer) (string, string) {
	TempWC := wrs.WorkerCount
	wrs.WorkerCount += 1
	w := &Worker{
		Id:           TempWC + 1,
		Verification: &ClientTest{PlaintextVerification: uuid.NewV4().String()},
		Registered:   false,
	}
	wrs.Members[w.Id] = w
	ws.Event("worker_register", NewEventWorker(w))
	return strconv.Itoa(w.Id), w.Verification.PlaintextVerification
}

func (wrs *WorkersStruct) Verify(ws *WorkServer, Id string, Response string) (string, error) {
	IdInt, err := strconv.Atoi(Id)
	if err != nil {
		ws.Event("worker_verify_error", NewEventError("StrconvError"))
		return "", errors.New("Failed to convert Worker ID string to int:" + err.Error())
	}
	ClientResp, err := wrs.Transformer.Decrypt([]byte(Response))
	if err != nil {
		ws.Event("worker_verify_error", NewEventError("DecryptionError"))
		return "", errors.New("Failed to decrypt worker verification string:" + err.Error())
	}
	wrs.Members[IdInt].Verification.ClientResponse = string(ClientResp)
	if wrs.Members[IdInt].Verification.PlaintextVerification != string(wrs.Members[IdInt].Verification.ClientResponse) {
		ws.Event("worker_verify_error", NewEventError("KeyMismatch"))
		return "", errors.New("Client key incorrect")
	}
	wrs.Members[IdInt].Registered = true
	wrs.Members[IdInt].SessionAuthenticationKey = uuid.NewV4().String()
	ws.Event("worker_verify", NewEventWorker(wrs.Members[IdInt]))
	return wrs.Members[IdInt].SessionAuthenticationKey, nil
}

func NewWorker(Secret string, ID string, PlaintextVerification string) (*Worker, error) {
	wrk := &Worker{}
	Transformer, err := NewTransformer(Secret)
	if err != nil {
		return wrk, err
	}
	wrk.Transformer = Transformer
	wrk.Verification = &ClientTest{PlaintextVerification: PlaintextVerification}
	IdInt, err := strconv.Atoi(ID)
	if err != nil {
		return &Worker{}, errors.New("Failed to convert Worker ID string to int:" + err.Error())
	}
	wrk.Id = IdInt
	ClientResponse, err := wrk.Transformer.Encrypt([]byte(wrk.Verification.PlaintextVerification))
	if err != nil {
		return &Worker{}, errors.New("Failed to encrypt verification string:" + err.Error())
	}
	wrk.Verification.ClientResponse = string(ClientResponse)
	return wrk, nil
}

func (wrk *Worker) SetAuthenticationKey(key string) *Worker {
	wrk.SessionAuthenticationKey = key
	return wrk
}

func (wrk *Worker) Process(w *Work) (*Work, map[string]interface{}, error) {
	WorkParams := make(map[string]interface{})
	if (w.Time.Added + w.Time.Timeout) <= time.Now().UTC().Unix() {
		return w, WorkParams, errors.New("Work Timeout")
	}
	err := json.Unmarshal([]byte(w.WorkJSON), &WorkParams)
	if err != nil {
		return w, WorkParams, errors.New("Failed to unmarshal Work Params JSON:" + err.Error())
	}
	w.Time.Recieved = time.Now().UTC().Unix()
	return w, WorkParams, nil
}

func (wrk *Worker) Submit(w *Work, ResultJSON string, Error string) (*Work, error) {
	wr := &WorkResult{}
	wr.ResultJSON = ResultJSON
	w.Time.Complete = time.Now().UTC().Unix()
	if (w.Time.Added + w.Time.Timeout) > time.Now().UTC().Unix() {
		wr.Error = Error
		wr.Status = "Complete"
		w.Result = wr
		return w, nil
	}
	wr.Error = "Timeout"
	wr.Status = "Timeout"
	w.Result = wr
	return w, errors.New("Timeout")
}

func CreateWork(WorkData interface{}, Timeout int64) (*Work, error) {
	NewWork := &Work{}
	NewWork.IdHex = bson.NewObjectId().Hex()
	NewWork.Result = &WorkResult{"", "Pending", ""}
	NewWork.Time = &TimeStats{Timeout: Timeout}
	WorkDataJSON, err := json.Marshal(WorkData)
	if err != nil {
		return &Work{}, errors.New("Failed to marshal work data:" + err.Error())
	}
	NewWork.WorkJSON = string(WorkDataJSON)
	return NewWork, nil
}

func (w *Work) Marshal() string {
	MarshalledWork, _ := json.Marshal(w)
	return string(MarshalledWork)
}

func Unmarshal(w string) *Work {
	WorkObject := &Work{}
	_ = json.Unmarshal([]byte(w), &WorkObject)
	return WorkObject
}

func NewTransformer(Secret string) (encrypt.Transformer, error) {
	if len(Secret) != 32 {
		return nil, fmt.Errorf("Length of secret must be 32, length was %d", len(Secret))
	}
	return encrypt.NewAESTransformer(encrypt.EncodeToString([]byte(Secret)))
}

func MustNewTransformer(Secret string) encrypt.Transformer {
	Transformer, err := NewTransformer(Secret)
	if err != nil {
		panic(err.Error())
	}
	return Transformer
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"strings"
	"testing"
	"time"
)

type nopCloser struct {
	io.Reader
}

func (nopCloser) Close() error { return nil }

func TestParseAlivePost(t *testing.T) {
	var body io.ReadCloser = nopCloser{strings.NewReader(`{"device_id": "abc123", "timeout": 300}`)}
	var ar AliveRequest = parseAlivePost(body)

	if ar.DeviceID != "abc123" || ar.Timeout != 300 {
		t.Fatalf("Expected: DeviceID: %s, Timeout: %d, got DeviceID: %s, Timeout: %d", "abc123", 300, ar.DeviceID, ar.Timeout)
	}
}

func TestCreateTimerInsertMapRetrive(t *testing.T) {
	var timers_map = make(map[string]DeviceTimer)
	timer := time.NewTimer(time.Second * 2)
	device_timer := DeviceTimer{"abc123", timer, 2000}
	timers_map["abc123"] = device_timer
	my_timer := timers_map["abc123"]

	if my_timer.DeviceTimeout != 2000 || my_timer.DeviceID != "abc123" {
		t.Fatalf("Expected: DeviceID: %s, Timeout: %d, got DeviceID: %s, Timeout: %d", "abc123", 2000, my_timer.DeviceID, my_timer.DeviceTimeout)
	}
}
<commit_msg>Fix indentation in test file<commit_after>package main

import (
	"io"
	"strings"
	"testing"
	"time"
)

type nopCloser struct {
	io.Reader
}

func (nopCloser) Close() error { return nil }

func TestParseAlivePost(t *testing.T) {
	var body io.ReadCloser = nopCloser{strings.NewReader(`{"device_id": "abc123", "timeout": 300}`)}
	var ar AliveRequest = parseAlivePost(body)

	if ar.DeviceID != "abc123" || ar.Timeout != 300 {
		t.Fatalf("Expected: DeviceID: %s, Timeout: %d, got DeviceID: %s, Timeout: %d",
			"abc123", 300, ar.DeviceID, ar.Timeout)
	}
}

func TestCreateTimerInsertMapRetrive(t *testing.T) {
	var timers_map = make(map[string]DeviceTimer)
	timer := time.NewTimer(time.Second * 2)
	device_timer := DeviceTimer{"abc123", timer, 2000}
	timers_map["abc123"] = device_timer
	my_timer := timers_map["abc123"]

	if my_timer.DeviceTimeout != 2000 || my_timer.DeviceID != "abc123" {
		t.Fatalf("Expected: DeviceID: %s, Timeout: %d, got DeviceID: %s, Timeout: %d",
			"abc123", 2000, my_timer.DeviceID, my_timer.DeviceTimeout)
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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.

// +build darwin linux windows
// +build !js

package opengl

import (
	"errors"
	"fmt"

	"github.com/go-gl/gl/v2.1/gl"
)

type Texture uint32
type Framebuffer uint32
type Shader uint32
type Program uint32
type Buffer uint32

var ZeroFramebuffer Framebuffer

// TODO: Remove this after the GopherJS bug was fixed (#159)
func (p Program) Equals(other Program) bool {
	return p == other
}

type uniformLocation int32
type attribLocation int32

type programID uint32

func (p Program) id() programID {
	return programID(p)
}

type context struct {
	locationCache     *locationCache
	funcs             chan func()
	lastCompositeMode CompositeMode
}

func NewContext() (*Context, error) {
	c := &Context{
		Nearest:            gl.NEAREST,
		Linear:             gl.LINEAR,
		VertexShader:       gl.VERTEX_SHADER,
		FragmentShader:     gl.FRAGMENT_SHADER,
		ArrayBuffer:        gl.ARRAY_BUFFER,
		ElementArrayBuffer: gl.ELEMENT_ARRAY_BUFFER,
		DynamicDraw:        gl.DYNAMIC_DRAW,
		StaticDraw:         gl.STATIC_DRAW,
		Triangles:          gl.TRIANGLES,
		Lines:              gl.LINES,
		zero:               gl.ZERO,
		one:                gl.ONE,
		srcAlpha:           gl.SRC_ALPHA,
		dstAlpha:           gl.DST_ALPHA,
		oneMinusSrcAlpha:   gl.ONE_MINUS_SRC_ALPHA,
		oneMinusDstAlpha:   gl.ONE_MINUS_DST_ALPHA,
	}
	c.locationCache = newLocationCache()
	c.funcs = make(chan func())
	c.lastCompositeMode = CompositeModeUnknown
	return c, nil
}

func (c *Context) Loop() {
	for {
		select {
		case f := <-c.funcs:
			f()
		}
	}
}

func (c *Context) RunOnContextThread(f func()) {
	ch := make(chan struct{})
	c.funcs <- func() {
		f()
		close(ch)
	}
	<-ch
	return
}

func (c *Context) Init() error {
	var err error
	c.RunOnContextThread(func() {
		// This initialization must be done after Loop is called.
		// This is why Init is separated from NewContext.

		if err := gl.Init(); err != nil {
			err = fmt.Errorf("opengl: initializing error %v", err)
			return
		}
		// Textures' pixel formats are alpha premultiplied.
		gl.Enable(gl.BLEND)
	})
	if err != nil {
		return err
	}
	c.BlendFunc(CompositeModeSourceOver)
	return nil
}

func (c *Context) BlendFunc(mode CompositeMode) {
	c.RunOnContextThread(func() {
		if c.lastCompositeMode == mode {
			return
		}
		c.lastCompositeMode = mode
		s, d := c.operations(mode)
		gl.BlendFunc(uint32(s), uint32(d))
	})
}

func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (texture Texture, err error) {
	c.RunOnContextThread(func() {
		var t uint32
		gl.GenTextures(1, &t)
		// TOOD: Use gl.IsTexture
		if t <= 0 {
			err = errors.New("opengl: creating texture failed")
			return
		}
		gl.PixelStorei(gl.UNPACK_ALIGNMENT, 4)
		gl.BindTexture(gl.TEXTURE_2D, t)

		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, int32(filter))
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, int32(filter))

		var p interface{}
		if pixels != nil {
			p = pixels
		}
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p))

		texture = Texture(t)
		return
	})
	return
}

func (c *Context) FramebufferPixels(f Framebuffer, width, height int) (pixels []uint8, err error) {
	c.RunOnContextThread(func() {
		gl.Flush()
		gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(f))
		pixels = make([]uint8, 4*width*height)
		gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels))
		if e := gl.GetError(); e != gl.NO_ERROR {
			pixels = nil
			err = fmt.Errorf("opengl: glReadPixels: %d", e)
			return
		}
		return
	})
	return
}

func (c *Context) BindTexture(t Texture) {
	c.RunOnContextThread(func() {
		gl.BindTexture(gl.TEXTURE_2D, uint32(t))
	})
}

func (c *Context) DeleteTexture(t Texture) {
	c.RunOnContextThread(func() {
		tt := uint32(t)
		gl.DeleteTextures(1, &tt)
	})
}

func (c *Context) TexSubImage2D(p []uint8, width, height int) {
	c.RunOnContextThread(func() {
		gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p))
	})
}

func (c *Context) BindZeroFramebuffer() {
	c.RunOnContextThread(func() {
		gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(ZeroFramebuffer))
	})
}

func (c *Context) NewFramebuffer(texture Texture) (framebuffer Framebuffer, err error) {
	c.RunOnContextThread(func() {
		var f uint32
		gl.GenFramebuffers(1, &f)
		// TODO: Use gl.IsFramebuffer
		if f <= 0 {
			err = errors.New("opengl: creating framebuffer failed: gl.IsFramebuffer returns false")
			return
		}
		gl.BindFramebuffer(gl.FRAMEBUFFER, f)

		gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
		s := gl.CheckFramebufferStatus(gl.FRAMEBUFFER)
		if s != gl.FRAMEBUFFER_COMPLETE {
			if s != 0 {
				err = fmt.Errorf("opengl: creating framebuffer failed: %v", s)
				return
			}
			if e := gl.GetError(); e != gl.NO_ERROR {
				err = fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
				return
			}
			err = fmt.Errorf("opengl: creating framebuffer failed: unknown error")
			return
		}
		framebuffer = Framebuffer(f)
		return
	})
	return
}

func (c *Context) SetViewport(f Framebuffer, width, height int) (err error) {
	c.RunOnContextThread(func() {
		gl.Flush()
		gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(f))
		if st := gl.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE {
			if e := gl.GetError(); e != 0 {
				err = fmt.Errorf("opengl: glBindFramebuffer failed: %d", e)
				return
			}
			err = errors.New("opengl: glBindFramebuffer failed: the context is different?")
			return
		}
		gl.Viewport(0, 0, int32(width), int32(height))
		return
	})
	return
}

func (c *Context) FillFramebuffer(r, g, b, a float64) error {
	c.RunOnContextThread(func() {
		gl.ClearColor(float32(r), float32(g), float32(b), float32(a))
		gl.Clear(gl.COLOR_BUFFER_BIT)
		return
	})
	return nil
}

func (c *Context) DeleteFramebuffer(f Framebuffer) {
	c.RunOnContextThread(func() {
		ff := uint32(f)
		gl.DeleteFramebuffers(1, &ff)
	})
}

func (c *Context) NewShader(shaderType ShaderType, source string) (shader Shader, err error) {
	c.RunOnContextThread(func() {
		s := gl.CreateShader(uint32(shaderType))
		if s == 0 {
			err = errors.New("opengl: glCreateShader failed")
			return
		}
		cSources, free := gl.Strs(source + "\x00")
		gl.ShaderSource(uint32(s), 1, cSources, nil)
		free()
		gl.CompileShader(s)

		var v int32
		gl.GetShaderiv(s, gl.COMPILE_STATUS, &v)
		if v == gl.FALSE {
			log := []uint8{}
			gl.GetShaderiv(uint32(s), gl.INFO_LOG_LENGTH, &v)
			if v != 0 {
				log = make([]uint8, int(v))
				gl.GetShaderInfoLog(uint32(s), v, nil, (*uint8)(gl.Ptr(log)))
			}
			err = fmt.Errorf("opengl: shader compile failed: %s", log)
			return
		}
		shader = Shader(s)
		return
	})
	return
}

func (c *Context) DeleteShader(s Shader) {
	c.RunOnContextThread(func() {
		gl.DeleteShader(uint32(s))
	})
}

func (c *Context) GlslHighpSupported() bool {
	return false
}

func (c *Context) NewProgram(shaders []Shader) (program Program, err error) {
	c.RunOnContextThread(func() {
		p := gl.CreateProgram()
		if p == 0 {
			err = errors.New("opengl: glCreateProgram failed")
			return
		}

		for _, shader := range shaders {
			gl.AttachShader(p, uint32(shader))
		}
		gl.LinkProgram(p)
		var v int32
		gl.GetProgramiv(p, gl.LINK_STATUS, &v)
		if v == gl.FALSE {
			err = errors.New("opengl: program error")
			return
		}
		program = Program(p)
		return
	})
	return
}

func (c *Context) UseProgram(p Program) {
	c.RunOnContextThread(func() {
		gl.UseProgram(uint32(p))
	})
}

func (c *Context) getUniformLocation(p Program, location string) uniformLocation {
	uniform := uniformLocation(gl.GetUniformLocation(uint32(p), gl.Str(location+"\x00")))
	if uniform == -1 {
		panic("opengl: invalid uniform location: " + location)
	}
	return uniform
}

func (c *Context) UniformInt(p Program, location string, v int) {
	c.RunOnContextThread(func() {
		l := int32(c.locationCache.GetUniformLocation(c, p, location))
		gl.Uniform1i(l, int32(v))
	})
}

func (c *Context) UniformFloats(p Program, location string, v []float32) {
	c.RunOnContextThread(func() {
		l := int32(c.locationCache.GetUniformLocation(c, p, location))
		switch len(v) {
		case 4:
			gl.Uniform4fv(l, 1, (*float32)(gl.Ptr(v)))
		case 16:
			gl.UniformMatrix4fv(l, 1, false, (*float32)(gl.Ptr(v)))
		default:
			panic("not reach")
		}
	})
}

func (c *Context) getAttribLocation(p Program, location string) attribLocation {
	attrib := attribLocation(gl.GetAttribLocation(uint32(p), gl.Str(location+"\x00")))
	if attrib == -1 {
		panic("opengl: invalid attrib location: " + location)
	}
	return attrib
}

func (c *Context) VertexAttribPointer(p Program, location string, normalize bool, stride int, size int, v int) {
	c.RunOnContextThread(func() {
		l := c.locationCache.GetAttribLocation(c, p, location)
		gl.VertexAttribPointer(uint32(l), int32(size), gl.SHORT, normalize, int32(stride), gl.PtrOffset(v))
	})
}

func (c *Context) EnableVertexAttribArray(p Program, location string) {
	c.RunOnContextThread(func() {
		l := c.locationCache.GetAttribLocation(c, p, location)
		gl.EnableVertexAttribArray(uint32(l))
	})
}

func (c *Context) DisableVertexAttribArray(p Program, location string) {
	c.RunOnContextThread(func() {
		l := c.locationCache.GetAttribLocation(c, p, location)
		gl.DisableVertexAttribArray(uint32(l))
	})
}

func (c *Context) NewBuffer(bufferType BufferType, v interface{}, bufferUsage BufferUsage) (buffer Buffer) {
	c.RunOnContextThread(func() {
		var b uint32
		gl.GenBuffers(1, &b)
		gl.BindBuffer(uint32(bufferType), b)
		switch v := v.(type) {
		case int:
			gl.BufferData(uint32(bufferType), v, nil, uint32(bufferUsage))
		case []uint16:
			gl.BufferData(uint32(bufferType), 2*len(v), gl.Ptr(v), uint32(bufferUsage))
		default:
			panic("not reach")
		}
		buffer = Buffer(b)
		return
	})
	return
}

func (c *Context) BindElementArrayBuffer(b Buffer) {
	c.RunOnContextThread(func() {
		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(b))
	})
}

func (c *Context) BufferSubData(bufferType BufferType, data []int16) {
	c.RunOnContextThread(func() {
		gl.BufferSubData(uint32(bufferType), 0, 2*len(data), gl.Ptr(data))
	})
}

func (c *Context) DrawElements(mode Mode, len int) {
	c.RunOnContextThread(func() {
		gl.DrawElements(uint32(mode), int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(0))
	})
}
<commit_msg>opengl: Refactoring<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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.

// +build darwin linux windows
// +build !js

package opengl

import (
	"errors"
	"fmt"

	"github.com/go-gl/gl/v2.1/gl"
)

type Texture uint32
type Framebuffer uint32
type Shader uint32
type Program uint32
type Buffer uint32

var ZeroFramebuffer Framebuffer

// TODO: Remove this after the GopherJS bug was fixed (#159)
func (p Program) Equals(other Program) bool {
	return p == other
}

type uniformLocation int32
type attribLocation int32

type programID uint32

func (p Program) id() programID {
	return programID(p)
}

type context struct {
	locationCache     *locationCache
	funcs             chan func()
	lastCompositeMode CompositeMode
}

func NewContext() (*Context, error) {
	c := &Context{
		Nearest:            gl.NEAREST,
		Linear:             gl.LINEAR,
		VertexShader:       gl.VERTEX_SHADER,
		FragmentShader:     gl.FRAGMENT_SHADER,
		ArrayBuffer:        gl.ARRAY_BUFFER,
		ElementArrayBuffer: gl.ELEMENT_ARRAY_BUFFER,
		DynamicDraw:        gl.DYNAMIC_DRAW,
		StaticDraw:         gl.STATIC_DRAW,
		Triangles:          gl.TRIANGLES,
		Lines:              gl.LINES,
		zero:               gl.ZERO,
		one:                gl.ONE,
		srcAlpha:           gl.SRC_ALPHA,
		dstAlpha:           gl.DST_ALPHA,
		oneMinusSrcAlpha:   gl.ONE_MINUS_SRC_ALPHA,
		oneMinusDstAlpha:   gl.ONE_MINUS_DST_ALPHA,
	}
	c.locationCache = newLocationCache()
	c.funcs = make(chan func())
	c.lastCompositeMode = CompositeModeUnknown
	return c, nil
}

func (c *Context) Loop() {
	for f := range c.funcs {
		f()
	}
}

func (c *Context) RunOnContextThread(f func()) {
	ch := make(chan struct{})
	c.funcs <- func() {
		f()
		close(ch)
	}
	<-ch
	return
}

func (c *Context) Init() error {
	var err error
	c.RunOnContextThread(func() {
		// This initialization must be done after Loop is called.
		// This is why Init is separated from NewContext.

		if err := gl.Init(); err != nil {
			err = fmt.Errorf("opengl: initializing error %v", err)
			return
		}
		// Textures' pixel formats are alpha premultiplied.
		gl.Enable(gl.BLEND)
	})
	if err != nil {
		return err
	}
	c.BlendFunc(CompositeModeSourceOver)
	return nil
}

func (c *Context) BlendFunc(mode CompositeMode) {
	c.RunOnContextThread(func() {
		if c.lastCompositeMode == mode {
			return
		}
		c.lastCompositeMode = mode
		s, d := c.operations(mode)
		gl.BlendFunc(uint32(s), uint32(d))
	})
}

func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (texture Texture, err error) {
	c.RunOnContextThread(func() {
		var t uint32
		gl.GenTextures(1, &t)
		// TOOD: Use gl.IsTexture
		if t <= 0 {
			err = errors.New("opengl: creating texture failed")
			return
		}
		gl.PixelStorei(gl.UNPACK_ALIGNMENT, 4)
		gl.BindTexture(gl.TEXTURE_2D, t)

		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, int32(filter))
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, int32(filter))

		var p interface{}
		if pixels != nil {
			p = pixels
		}
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p))

		texture = Texture(t)
		return
	})
	return
}

func (c *Context) FramebufferPixels(f Framebuffer, width, height int) (pixels []uint8, err error) {
	c.RunOnContextThread(func() {
		gl.Flush()
		gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(f))
		pixels = make([]uint8, 4*width*height)
		gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels))
		if e := gl.GetError(); e != gl.NO_ERROR {
			pixels = nil
			err = fmt.Errorf("opengl: glReadPixels: %d", e)
			return
		}
		return
	})
	return
}

func (c *Context) BindTexture(t Texture) {
	c.RunOnContextThread(func() {
		gl.BindTexture(gl.TEXTURE_2D, uint32(t))
	})
}

func (c *Context) DeleteTexture(t Texture) {
	c.RunOnContextThread(func() {
		tt := uint32(t)
		gl.DeleteTextures(1, &tt)
	})
}

func (c *Context) TexSubImage2D(p []uint8, width, height int) {
	c.RunOnContextThread(func() {
		gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p))
	})
}

func (c *Context) BindZeroFramebuffer() {
	c.RunOnContextThread(func() {
		gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(ZeroFramebuffer))
	})
}

func (c *Context) NewFramebuffer(texture Texture) (framebuffer Framebuffer, err error) {
	c.RunOnContextThread(func() {
		var f uint32
		gl.GenFramebuffers(1, &f)
		// TODO: Use gl.IsFramebuffer
		if f <= 0 {
			err = errors.New("opengl: creating framebuffer failed: gl.IsFramebuffer returns false")
			return
		}
		gl.BindFramebuffer(gl.FRAMEBUFFER, f)

		gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
		s := gl.CheckFramebufferStatus(gl.FRAMEBUFFER)
		if s != gl.FRAMEBUFFER_COMPLETE {
			if s != 0 {
				err = fmt.Errorf("opengl: creating framebuffer failed: %v", s)
				return
			}
			if e := gl.GetError(); e != gl.NO_ERROR {
				err = fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
				return
			}
			err = fmt.Errorf("opengl: creating framebuffer failed: unknown error")
			return
		}
		framebuffer = Framebuffer(f)
		return
	})
	return
}

func (c *Context) SetViewport(f Framebuffer, width, height int) (err error) {
	c.RunOnContextThread(func() {
		gl.Flush()
		gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(f))
		if st := gl.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE {
			if e := gl.GetError(); e != 0 {
				err = fmt.Errorf("opengl: glBindFramebuffer failed: %d", e)
				return
			}
			err = errors.New("opengl: glBindFramebuffer failed: the context is different?")
			return
		}
		gl.Viewport(0, 0, int32(width), int32(height))
		return
	})
	return
}

func (c *Context) FillFramebuffer(r, g, b, a float64) error {
	c.RunOnContextThread(func() {
		gl.ClearColor(float32(r), float32(g), float32(b), float32(a))
		gl.Clear(gl.COLOR_BUFFER_BIT)
		return
	})
	return nil
}

func (c *Context) DeleteFramebuffer(f Framebuffer) {
	c.RunOnContextThread(func() {
		ff := uint32(f)
		gl.DeleteFramebuffers(1, &ff)
	})
}

func (c *Context) NewShader(shaderType ShaderType, source string) (shader Shader, err error) {
	c.RunOnContextThread(func() {
		s := gl.CreateShader(uint32(shaderType))
		if s == 0 {
			err = errors.New("opengl: glCreateShader failed")
			return
		}
		cSources, free := gl.Strs(source + "\x00")
		gl.ShaderSource(uint32(s), 1, cSources, nil)
		free()
		gl.CompileShader(s)

		var v int32
		gl.GetShaderiv(s, gl.COMPILE_STATUS, &v)
		if v == gl.FALSE {
			log := []uint8{}
			gl.GetShaderiv(uint32(s), gl.INFO_LOG_LENGTH, &v)
			if v != 0 {
				log = make([]uint8, int(v))
				gl.GetShaderInfoLog(uint32(s), v, nil, (*uint8)(gl.Ptr(log)))
			}
			err = fmt.Errorf("opengl: shader compile failed: %s", log)
			return
		}
		shader = Shader(s)
		return
	})
	return
}

func (c *Context) DeleteShader(s Shader) {
	c.RunOnContextThread(func() {
		gl.DeleteShader(uint32(s))
	})
}

func (c *Context) GlslHighpSupported() bool {
	return false
}

func (c *Context) NewProgram(shaders []Shader) (program Program, err error) {
	c.RunOnContextThread(func() {
		p := gl.CreateProgram()
		if p == 0 {
			err = errors.New("opengl: glCreateProgram failed")
			return
		}

		for _, shader := range shaders {
			gl.AttachShader(p, uint32(shader))
		}
		gl.LinkProgram(p)
		var v int32
		gl.GetProgramiv(p, gl.LINK_STATUS, &v)
		if v == gl.FALSE {
			err = errors.New("opengl: program error")
			return
		}
		program = Program(p)
		return
	})
	return
}

func (c *Context) UseProgram(p Program) {
	c.RunOnContextThread(func() {
		gl.UseProgram(uint32(p))
	})
}

func (c *Context) getUniformLocation(p Program, location string) uniformLocation {
	uniform := uniformLocation(gl.GetUniformLocation(uint32(p), gl.Str(location+"\x00")))
	if uniform == -1 {
		panic("opengl: invalid uniform location: " + location)
	}
	return uniform
}

func (c *Context) UniformInt(p Program, location string, v int) {
	c.RunOnContextThread(func() {
		l := int32(c.locationCache.GetUniformLocation(c, p, location))
		gl.Uniform1i(l, int32(v))
	})
}

func (c *Context) UniformFloats(p Program, location string, v []float32) {
	c.RunOnContextThread(func() {
		l := int32(c.locationCache.GetUniformLocation(c, p, location))
		switch len(v) {
		case 4:
			gl.Uniform4fv(l, 1, (*float32)(gl.Ptr(v)))
		case 16:
			gl.UniformMatrix4fv(l, 1, false, (*float32)(gl.Ptr(v)))
		default:
			panic("not reach")
		}
	})
}

func (c *Context) getAttribLocation(p Program, location string) attribLocation {
	attrib := attribLocation(gl.GetAttribLocation(uint32(p), gl.Str(location+"\x00")))
	if attrib == -1 {
		panic("opengl: invalid attrib location: " + location)
	}
	return attrib
}

func (c *Context) VertexAttribPointer(p Program, location string, normalize bool, stride int, size int, v int) {
	c.RunOnContextThread(func() {
		l := c.locationCache.GetAttribLocation(c, p, location)
		gl.VertexAttribPointer(uint32(l), int32(size), gl.SHORT, normalize, int32(stride), gl.PtrOffset(v))
	})
}

func (c *Context) EnableVertexAttribArray(p Program, location string) {
	c.RunOnContextThread(func() {
		l := c.locationCache.GetAttribLocation(c, p, location)
		gl.EnableVertexAttribArray(uint32(l))
	})
}

func (c *Context) DisableVertexAttribArray(p Program, location string) {
	c.RunOnContextThread(func() {
		l := c.locationCache.GetAttribLocation(c, p, location)
		gl.DisableVertexAttribArray(uint32(l))
	})
}

func (c *Context) NewBuffer(bufferType BufferType, v interface{}, bufferUsage BufferUsage) (buffer Buffer) {
	c.RunOnContextThread(func() {
		var b uint32
		gl.GenBuffers(1, &b)
		gl.BindBuffer(uint32(bufferType), b)
		switch v := v.(type) {
		case int:
			gl.BufferData(uint32(bufferType), v, nil, uint32(bufferUsage))
		case []uint16:
			gl.BufferData(uint32(bufferType), 2*len(v), gl.Ptr(v), uint32(bufferUsage))
		default:
			panic("not reach")
		}
		buffer = Buffer(b)
		return
	})
	return
}

func (c *Context) BindElementArrayBuffer(b Buffer) {
	c.RunOnContextThread(func() {
		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(b))
	})
}

func (c *Context) BufferSubData(bufferType BufferType, data []int16) {
	c.RunOnContextThread(func() {
		gl.BufferSubData(uint32(bufferType), 0, 2*len(data), gl.Ptr(data))
	})
}

func (c *Context) DrawElements(mode Mode, len int) {
	c.RunOnContextThread(func() {
		gl.DrawElements(uint32(mode), int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(0))
	})
}
<|endoftext|>


<commit_before>package gocyclo_test

import (
	"reflect"
	"strings"
	"testing"

	"github.com/fzipp/gocyclo"
)

func TestAnalyze(t *testing.T) {
	tests := []struct {
		paths []string
		want  string
	}{
		{
			[]string{"testdata/ifs.go"},
			`3 testdata f3nested testdata/ifs.go:24:1
3 testdata f3 testdata/ifs.go:17:1
2 testdata f2else testdata/ifs.go:11:1
2 testdata f2 testdata/ifs.go:6:1
1 testdata f1 testdata/ifs.go:3:1`,
		},
		{
			[]string{"testdata/loops.go"},
			`4 testdata l4 testdata/loops.go:19:1
3 testdata l3 testdata/loops.go:8:1
2 testdata l2range testdata/loops.go:14:1
2 testdata l2 testdata/loops.go:3:1`,
		},
		{
			[]string{"testdata/cases.go"},
			`3 testdata c3default testdata/cases.go:32:1
3 testdata c3 testdata/cases.go:25:1
3 testdata c3nested testdata/cases.go:40:1
2 testdata c2multi testdata/cases.go:19:1
2 testdata c2default testdata/cases.go:12:1
2 testdata c2 testdata/cases.go:6:1
1 testdata c1 testdata/cases.go:3:1`,
		},
		{
			[]string{"testdata/comms.go"},
			`3 testdata comm3nested testdata/comms.go:33:1
3 testdata comm3default testdata/comms.go:25:1
3 testdata comm3 testdata/comms.go:18:1
2 testdata comm2default testdata/comms.go:11:1
2 testdata comm2 testdata/comms.go:5:1`,
		},
		{
			[]string{"testdata/methods.go"},
			`2 testdata (*S).m2ptr testdata/methods.go:16:1
2 testdata (S).m2 testdata/methods.go:8:1
1 testdata (*S).m1ptr testdata/methods.go:13:1
1 testdata (S).m1 testdata/methods.go:5:1`,
		},
		{
			[]string{"testdata/literals.go"},
			`3 testdata lit3 testdata/literals.go:13:12
2 testdata lit2 testdata/literals.go:8:12
1 testdata lit1 testdata/literals.go:5:12`,
		},
		{
			[]string{"testdata/ignores.go"},
			`1 testdata notIgnoredNotADirective testdata/ignores.go:13:1
1 testdata notIgnoredUnknownDirective testdata/ignores.go:10:1`,
		},
		{
			[]string{"testdata/operators.go"},
			`3 testdata op3mixed testdata/operators.go:11:1
2 testdata op2and testdata/operators.go:7:1
2 testdata op2or testdata/operators.go:3:1`,
		},
		{
			[]string{"testdata/directory"},
			`1 directory b testdata/directory/file2.go:3:1
1 directory a testdata/directory/file1.go:3:1`,
		},
	}

	for _, tt := range tests {
		stats := gocyclo.Analyze(tt.paths, nil).
			SortAndFilter(-1, 0)
		statLines := make([]string, len(stats))
		for i, s := range stats {
			statLines[i] = s.String()
		}
		got := strings.Join(statLines, "\n")
		if !reflect.DeepEqual(got, tt.want) {
			t.Errorf("Analyzed %q and got:\n%s\n\twant:\n%s", tt.paths, got, tt.want)
		}
	}
}
<commit_msg>update test for changed line numbers<commit_after>package gocyclo_test

import (
	"reflect"
	"strings"
	"testing"

	"github.com/fzipp/gocyclo"
)

func TestAnalyze(t *testing.T) {
	tests := []struct {
		paths []string
		want  string
	}{
		{
			[]string{"testdata/ifs.go"},
			`3 testdata f3nested testdata/ifs.go:24:1
3 testdata f3 testdata/ifs.go:17:1
2 testdata f2else testdata/ifs.go:11:1
2 testdata f2 testdata/ifs.go:6:1
1 testdata f1 testdata/ifs.go:3:1`,
		},
		{
			[]string{"testdata/loops.go"},
			`4 testdata l4 testdata/loops.go:20:1
3 testdata l3 testdata/loops.go:8:1
2 testdata l2range testdata/loops.go:15:1
2 testdata l2 testdata/loops.go:3:1`,
		},
		{
			[]string{"testdata/cases.go"},
			`3 testdata c3default testdata/cases.go:32:1
3 testdata c3 testdata/cases.go:25:1
3 testdata c3nested testdata/cases.go:40:1
2 testdata c2multi testdata/cases.go:19:1
2 testdata c2default testdata/cases.go:12:1
2 testdata c2 testdata/cases.go:6:1
1 testdata c1 testdata/cases.go:3:1`,
		},
		{
			[]string{"testdata/comms.go"},
			`3 testdata comm3nested testdata/comms.go:33:1
3 testdata comm3default testdata/comms.go:25:1
3 testdata comm3 testdata/comms.go:18:1
2 testdata comm2default testdata/comms.go:11:1
2 testdata comm2 testdata/comms.go:5:1`,
		},
		{
			[]string{"testdata/methods.go"},
			`2 testdata (*S).m2ptr testdata/methods.go:16:1
2 testdata (S).m2 testdata/methods.go:8:1
1 testdata (*S).m1ptr testdata/methods.go:13:1
1 testdata (S).m1 testdata/methods.go:5:1`,
		},
		{
			[]string{"testdata/literals.go"},
			`3 testdata lit3 testdata/literals.go:13:12
2 testdata lit2 testdata/literals.go:8:12
1 testdata lit1 testdata/literals.go:5:12`,
		},
		{
			[]string{"testdata/ignores.go"},
			`1 testdata notIgnoredNotADirective testdata/ignores.go:13:1
1 testdata notIgnoredUnknownDirective testdata/ignores.go:10:1`,
		},
		{
			[]string{"testdata/operators.go"},
			`3 testdata op3mixed testdata/operators.go:11:1
2 testdata op2and testdata/operators.go:7:1
2 testdata op2or testdata/operators.go:3:1`,
		},
		{
			[]string{"testdata/directory"},
			`1 directory b testdata/directory/file2.go:3:1
1 directory a testdata/directory/file1.go:3:1`,
		},
	}

	for _, tt := range tests {
		stats := gocyclo.Analyze(tt.paths, nil).
			SortAndFilter(-1, 0)
		statLines := make([]string, len(stats))
		for i, s := range stats {
			statLines[i] = s.String()
		}
		got := strings.Join(statLines, "\n")
		if !reflect.DeepEqual(got, tt.want) {
			t.Errorf("Analyzed %q and got:\n%s\n\twant:\n%s", tt.paths, got, tt.want)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2018 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 conversion

import (
	"fmt"

	autoscalingv1 "k8s.io/api/autoscaling/v1"
	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
	apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	utilfeature "k8s.io/apiserver/pkg/util/feature"
	"k8s.io/apiserver/pkg/util/webhook"
	typedscheme "k8s.io/client-go/kubernetes/scheme"
)

// CRConverterFactory is the factory for all CR converters.
type CRConverterFactory struct {
	// webhookConverterFactory is the factory for webhook converters.
	// This field should not be used if CustomResourceWebhookConversion feature is disabled.
	webhookConverterFactory *webhookConverterFactory
	converterMetricFactory  *converterMetricFactory
}

// NewCRConverterFactory creates a new CRConverterFactory
func NewCRConverterFactory(serviceResolver webhook.ServiceResolver, authResolverWrapper webhook.AuthenticationInfoResolverWrapper) (*CRConverterFactory, error) {
	converterFactory := &CRConverterFactory{
		converterMetricFactory: newConverterMertricFactory(),
	}
	if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) {
		webhookConverterFactory, err := newWebhookConverterFactory(serviceResolver, authResolverWrapper)
		if err != nil {
			return nil, err
		}
		converterFactory.webhookConverterFactory = webhookConverterFactory
	}
	return converterFactory, nil
}

// NewConverter returns a new CR converter based on the conversion settings in crd object.
func (m *CRConverterFactory) NewConverter(crd *apiextensions.CustomResourceDefinition) (safe, unsafe runtime.ObjectConvertor, err error) {
	validVersions := map[schema.GroupVersion]bool{}
	for _, version := range crd.Spec.Versions {
		validVersions[schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}] = true
	}

	var converter crConverterInterface
	switch crd.Spec.Conversion.Strategy {
	case apiextensions.NoneConverter:
		converter = &nopConverter{}
	case apiextensions.WebhookConverter:
		if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) {
			return nil, nil, fmt.Errorf("webhook conversion is disabled on this cluster")
		}
		converter, err = m.webhookConverterFactory.NewWebhookConverter(crd)
		if err != nil {
			return nil, nil, err
		}
		converter, err = m.converterMetricFactory.addMetrics("webhook", crd.Name, converter)
		if err != nil {
			return nil, nil, err
		}
	default:
		return nil, nil, fmt.Errorf("unknown conversion strategy %q for CRD %s", crd.Spec.Conversion.Strategy, crd.Name)
	}

	// Determine whether we should expect to be asked to "convert" autoscaling/v1 Scale types
	convertScale := false
	if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
		convertScale = crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil
		for _, version := range crd.Spec.Versions {
			if version.Subresources != nil && version.Subresources.Scale != nil {
				convertScale = true
			}
		}
	}

	unsafe = &crConverter{
		convertScale:  convertScale,
		validVersions: validVersions,
		clusterScoped: crd.Spec.Scope == apiextensions.ClusterScoped,
		converter:     converter,
	}
	return &safeConverterWrapper{unsafe}, unsafe, nil
}

// crConverterInterface is the interface all cr converters must implement
type crConverterInterface interface {
	// Convert converts in object to the given gvk and returns the converted object.
	// Note that the function may mutate in object and return it. A safe wrapper will make sure
	// a safe converter will be returned.
	Convert(in runtime.Object, targetGVK schema.GroupVersion) (runtime.Object, error)
}

// crConverter extends the delegate converter with generic CR conversion behaviour. The delegate will implement the
// user defined conversion strategy given in the CustomResourceDefinition.
type crConverter struct {
	convertScale  bool
	converter     crConverterInterface
	validVersions map[schema.GroupVersion]bool
	clusterScoped bool
}

func (c *crConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
	// We currently only support metadata.namespace and metadata.name.
	switch {
	case label == "metadata.name":
		return label, value, nil
	case !c.clusterScoped && label == "metadata.namespace":
		return label, value, nil
	default:
		return "", "", fmt.Errorf("field label not supported: %s", label)
	}
}

func (c *crConverter) Convert(in, out, context interface{}) error {
	// Special-case typed scale conversion if this custom resource supports a scale endpoint
	if c.convertScale {
		_, isInScale := in.(*autoscalingv1.Scale)
		_, isOutScale := out.(*autoscalingv1.Scale)
		if isInScale || isOutScale {
			return typedscheme.Scheme.Convert(in, out, context)
		}
	}

	unstructIn, ok := in.(*unstructured.Unstructured)
	if !ok {
		return fmt.Errorf("input type %T in not valid for unstructured conversion to %T", in, out)
	}

	unstructOut, ok := out.(*unstructured.Unstructured)
	if !ok {
		return fmt.Errorf("output type %T in not valid for unstructured conversion from %T", out, in)
	}

	outGVK := unstructOut.GroupVersionKind()
	converted, err := c.ConvertToVersion(unstructIn, outGVK.GroupVersion())
	if err != nil {
		return err
	}
	unstructuredConverted, ok := converted.(runtime.Unstructured)
	if !ok {
		// this should not happened
		return fmt.Errorf("CR conversion failed")
	}
	unstructOut.SetUnstructuredContent(unstructuredConverted.UnstructuredContent())
	return nil
}

// ConvertToVersion converts in object to the given gvk in place and returns the same `in` object.
// The in object can be a single object or a UnstructuredList. CRD storage implementation creates an
// UnstructuredList with the request's GV, populates it from storage, then calls conversion to convert
// the individual items. This function assumes it never gets a v1.List.
func (c *crConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
	fromGVK := in.GetObjectKind().GroupVersionKind()
	toGVK, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{fromGVK})
	if !ok {
		// TODO: should this be a typed error?
		return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", fromGVK.String(), target)
	}
	if !c.validVersions[toGVK.GroupVersion()] {
		return nil, fmt.Errorf("request to convert CR to an invalid group/version: %s", toGVK.GroupVersion().String())
	}
	// Note that even if the request is for a list, the GV of the request UnstructuredList is what
	// is expected to convert to. As mentioned in the function's document, it is not expected to
	// get a v1.List.
	if !c.validVersions[fromGVK.GroupVersion()] {
		return nil, fmt.Errorf("request to convert CR from an invalid group/version: %s", fromGVK.GroupVersion().String())
	}
	// Check list item's apiVersion
	if list, ok := in.(*unstructured.UnstructuredList); ok {
		for i := range list.Items {
			expectedGV := list.Items[i].GroupVersionKind().GroupVersion()
			if !c.validVersions[expectedGV] {
				return nil, fmt.Errorf("request to convert CR list failed, list index %d has invalid group/version: %s", i, expectedGV.String())
			}
		}
	}
	return c.converter.Convert(in, toGVK.GroupVersion())
}

// safeConverterWrapper is a wrapper over an unsafe object converter that makes copy of the input and then delegate to the unsafe converter.
type safeConverterWrapper struct {
	unsafe runtime.ObjectConvertor
}

var _ runtime.ObjectConvertor = &safeConverterWrapper{}

// ConvertFieldLabel delegate the call to the unsafe converter.
func (c *safeConverterWrapper) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
	return c.unsafe.ConvertFieldLabel(gvk, label, value)
}

// Convert makes a copy of in object and then delegate the call to the unsafe converter.
func (c *safeConverterWrapper) Convert(in, out, context interface{}) error {
	inObject, ok := in.(runtime.Object)
	if !ok {
		return fmt.Errorf("input type %T in not valid for object conversion", in)
	}
	return c.unsafe.Convert(inObject.DeepCopyObject(), out, context)
}

// ConvertToVersion makes a copy of in object and then delegate the call to the unsafe converter.
func (c *safeConverterWrapper) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
	return c.unsafe.ConvertToVersion(in.DeepCopyObject(), target)
}
<commit_msg>apiextensions: fix metrics double registration during tests<commit_after>/*
Copyright 2018 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 conversion

import (
	"fmt"

	autoscalingv1 "k8s.io/api/autoscaling/v1"
	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
	apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	utilfeature "k8s.io/apiserver/pkg/util/feature"
	"k8s.io/apiserver/pkg/util/webhook"
	typedscheme "k8s.io/client-go/kubernetes/scheme"
)

// CRConverterFactory is the factory for all CR converters.
type CRConverterFactory struct {
	// webhookConverterFactory is the factory for webhook converters.
	// This field should not be used if CustomResourceWebhookConversion feature is disabled.
	webhookConverterFactory *webhookConverterFactory
}

// converterMetricFactorySingleton protects us from reregistration of metrics on repeated
// apiextensions-apiserver runs.
var converterMetricFactorySingleton = newConverterMertricFactory()

// NewCRConverterFactory creates a new CRConverterFactory
func NewCRConverterFactory(serviceResolver webhook.ServiceResolver, authResolverWrapper webhook.AuthenticationInfoResolverWrapper) (*CRConverterFactory, error) {
	converterFactory := &CRConverterFactory{}
	if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) {
		webhookConverterFactory, err := newWebhookConverterFactory(serviceResolver, authResolverWrapper)
		if err != nil {
			return nil, err
		}
		converterFactory.webhookConverterFactory = webhookConverterFactory
	}
	return converterFactory, nil
}

// NewConverter returns a new CR converter based on the conversion settings in crd object.
func (m *CRConverterFactory) NewConverter(crd *apiextensions.CustomResourceDefinition) (safe, unsafe runtime.ObjectConvertor, err error) {
	validVersions := map[schema.GroupVersion]bool{}
	for _, version := range crd.Spec.Versions {
		validVersions[schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}] = true
	}

	var converter crConverterInterface
	switch crd.Spec.Conversion.Strategy {
	case apiextensions.NoneConverter:
		converter = &nopConverter{}
	case apiextensions.WebhookConverter:
		if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) {
			return nil, nil, fmt.Errorf("webhook conversion is disabled on this cluster")
		}
		converter, err = m.webhookConverterFactory.NewWebhookConverter(crd)
		if err != nil {
			return nil, nil, err
		}
		converter, err = converterMetricFactorySingleton.addMetrics("webhook", crd.Name, converter)
		if err != nil {
			return nil, nil, err
		}
	default:
		return nil, nil, fmt.Errorf("unknown conversion strategy %q for CRD %s", crd.Spec.Conversion.Strategy, crd.Name)
	}

	// Determine whether we should expect to be asked to "convert" autoscaling/v1 Scale types
	convertScale := false
	if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
		convertScale = crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil
		for _, version := range crd.Spec.Versions {
			if version.Subresources != nil && version.Subresources.Scale != nil {
				convertScale = true
			}
		}
	}

	unsafe = &crConverter{
		convertScale:  convertScale,
		validVersions: validVersions,
		clusterScoped: crd.Spec.Scope == apiextensions.ClusterScoped,
		converter:     converter,
	}
	return &safeConverterWrapper{unsafe}, unsafe, nil
}

// crConverterInterface is the interface all cr converters must implement
type crConverterInterface interface {
	// Convert converts in object to the given gvk and returns the converted object.
	// Note that the function may mutate in object and return it. A safe wrapper will make sure
	// a safe converter will be returned.
	Convert(in runtime.Object, targetGVK schema.GroupVersion) (runtime.Object, error)
}

// crConverter extends the delegate converter with generic CR conversion behaviour. The delegate will implement the
// user defined conversion strategy given in the CustomResourceDefinition.
type crConverter struct {
	convertScale  bool
	converter     crConverterInterface
	validVersions map[schema.GroupVersion]bool
	clusterScoped bool
}

func (c *crConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
	// We currently only support metadata.namespace and metadata.name.
	switch {
	case label == "metadata.name":
		return label, value, nil
	case !c.clusterScoped && label == "metadata.namespace":
		return label, value, nil
	default:
		return "", "", fmt.Errorf("field label not supported: %s", label)
	}
}

func (c *crConverter) Convert(in, out, context interface{}) error {
	// Special-case typed scale conversion if this custom resource supports a scale endpoint
	if c.convertScale {
		_, isInScale := in.(*autoscalingv1.Scale)
		_, isOutScale := out.(*autoscalingv1.Scale)
		if isInScale || isOutScale {
			return typedscheme.Scheme.Convert(in, out, context)
		}
	}

	unstructIn, ok := in.(*unstructured.Unstructured)
	if !ok {
		return fmt.Errorf("input type %T in not valid for unstructured conversion to %T", in, out)
	}

	unstructOut, ok := out.(*unstructured.Unstructured)
	if !ok {
		return fmt.Errorf("output type %T in not valid for unstructured conversion from %T", out, in)
	}

	outGVK := unstructOut.GroupVersionKind()
	converted, err := c.ConvertToVersion(unstructIn, outGVK.GroupVersion())
	if err != nil {
		return err
	}
	unstructuredConverted, ok := converted.(runtime.Unstructured)
	if !ok {
		// this should not happened
		return fmt.Errorf("CR conversion failed")
	}
	unstructOut.SetUnstructuredContent(unstructuredConverted.UnstructuredContent())
	return nil
}

// ConvertToVersion converts in object to the given gvk in place and returns the same `in` object.
// The in object can be a single object or a UnstructuredList. CRD storage implementation creates an
// UnstructuredList with the request's GV, populates it from storage, then calls conversion to convert
// the individual items. This function assumes it never gets a v1.List.
func (c *crConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
	fromGVK := in.GetObjectKind().GroupVersionKind()
	toGVK, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{fromGVK})
	if !ok {
		// TODO: should this be a typed error?
		return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", fromGVK.String(), target)
	}
	if !c.validVersions[toGVK.GroupVersion()] {
		return nil, fmt.Errorf("request to convert CR to an invalid group/version: %s", toGVK.GroupVersion().String())
	}
	// Note that even if the request is for a list, the GV of the request UnstructuredList is what
	// is expected to convert to. As mentioned in the function's document, it is not expected to
	// get a v1.List.
	if !c.validVersions[fromGVK.GroupVersion()] {
		return nil, fmt.Errorf("request to convert CR from an invalid group/version: %s", fromGVK.GroupVersion().String())
	}
	// Check list item's apiVersion
	if list, ok := in.(*unstructured.UnstructuredList); ok {
		for i := range list.Items {
			expectedGV := list.Items[i].GroupVersionKind().GroupVersion()
			if !c.validVersions[expectedGV] {
				return nil, fmt.Errorf("request to convert CR list failed, list index %d has invalid group/version: %s", i, expectedGV.String())
			}
		}
	}
	return c.converter.Convert(in, toGVK.GroupVersion())
}

// safeConverterWrapper is a wrapper over an unsafe object converter that makes copy of the input and then delegate to the unsafe converter.
type safeConverterWrapper struct {
	unsafe runtime.ObjectConvertor
}

var _ runtime.ObjectConvertor = &safeConverterWrapper{}

// ConvertFieldLabel delegate the call to the unsafe converter.
func (c *safeConverterWrapper) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
	return c.unsafe.ConvertFieldLabel(gvk, label, value)
}

// Convert makes a copy of in object and then delegate the call to the unsafe converter.
func (c *safeConverterWrapper) Convert(in, out, context interface{}) error {
	inObject, ok := in.(runtime.Object)
	if !ok {
		return fmt.Errorf("input type %T in not valid for object conversion", in)
	}
	return c.unsafe.Convert(inObject.DeepCopyObject(), out, context)
}

// ConvertToVersion makes a copy of in object and then delegate the call to the unsafe converter.
func (c *safeConverterWrapper) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
	return c.unsafe.ConvertToVersion(in.DeepCopyObject(), target)
}
<|endoftext|>