<commit_before>package veneur

import (
	"math"
	"math/rand"
	"strconv"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestCounterEmpty(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})
	c.Sample(1, 1.0)

	assert.Equal(t, "a.b.c", c.name, "Name")
	assert.Len(t, c.tags, 1, "Tag length")
	assert.Equal(t, c.tags[0], "a:b", "Tag contents")

	metrics := c.Flush(10 * time.Second)
	assert.Len(t, metrics, 1, "Flushes 1 metric")

	m1 := metrics[0]
	assert.Equal(t, int32(10), m1.Interval, "Interval")
	assert.Equal(t, "rate", m1.MetricType, "Type")
	assert.Len(t, c.tags, 1, "Tag length")
	assert.Equal(t, c.tags[0], "a:b", "Tag contents")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, 0.1, m1.Value[0][1], "Metric value")
}

func TestCounterRate(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})

	c.Sample(5, 1.0)

	// The counter returns an array with a single tuple of timestamp,value
	metrics := c.Flush(10 * time.Second)
	assert.Equal(t, 0.5, metrics[0].Value[0][1], "Metric value")
}

func TestCounterSampleRate(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})

	c.Sample(5, 0.5)

	// The counter returns an array with a single tuple of timestamp,value
	metrics := c.Flush(10 * time.Second)
	assert.Equal(t, float64(1), metrics[0].Value[0][1], "Metric value")
}

func TestGauge(t *testing.T) {

	g := NewGauge("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", g.name, "Name")
	assert.Len(t, g.tags, 1, "Tag length")
	assert.Equal(t, g.tags[0], "a:b", "Tag contents")

	g.Sample(5, 1.0)

	metrics := g.Flush()
	assert.Len(t, metrics, 1, "Flushed metric count")

	m1 := metrics[0]
	// Interval is not meaningful for this
	assert.Equal(t, int32(0), m1.Interval, "Interval")
	assert.Equal(t, "gauge", m1.MetricType, "Type")
	tags := m1.Tags
	assert.Len(t, tags, 1, "Tag length")
	assert.Equal(t, tags[0], "a:b", "Tag contents")

	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(5), m1.Value[0][1], "Value")
}

func TestSet(t *testing.T) {
	s := NewSet("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", s.name, "Name")
	assert.Len(t, s.tags, 1, "Tag count")
	assert.Equal(t, "a:b", s.tags[0], "First tag")

	s.Sample("5", 1.0)

	s.Sample("5", 1.0)

	s.Sample("123", 1.0)

	s.Sample("2147483647", 1.0)
	s.Sample("-2147483648", 1.0)

	metrics := s.Flush()
	assert.Len(t, metrics, 1, "Flush")

	m1 := metrics[0]
	// Interval is not meaningful for this
	assert.Equal(t, int32(0), m1.Interval, "Interval")
	assert.Equal(t, "gauge", m1.MetricType, "Type")
	assert.Len(t, m1.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m1.Tags[0], "First tag")
	assert.Equal(t, float64(4), m1.Value[0][1], "Value")
}

func TestSetMerge(t *testing.T) {
	rand.Seed(time.Now().Unix())

	s := NewSet("a.b.c", []string{"a:b"})
	for i := 0; i < 100; i++ {
		s.Sample(strconv.Itoa(rand.Int()), 1.0)
	}
	assert.Equal(t, uint64(100), s.hll.Count(), "counts did not match")

	jm, err := s.Export()
	assert.NoError(t, err, "should have exported successfully")

	s2 := NewSet("a.b.c", []string{"a:b"})
	assert.NoError(t, s2.Combine(jm.Value), "should have combined successfully")
	// HLLs are approximate, and we've seen error of +-1 here in the past, so
	// we're giving the test some room for error to reduce flakes
	countDifference := int(s.hll.Count()) - int(s2.hll.Count())
	assert.True(t, -1 < countDifference && countDifference < 1, "counts did not match after merging")
}

func TestHisto(t *testing.T) {

	h := NewHist("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", h.name, "Name")
	assert.Len(t, h.tags, 1, "Tag count")
	assert.Equal(t, "a:b", h.tags[0], "First tag")

	h.Sample(5, 1.0)
	h.Sample(10, 1.0)
	h.Sample(15, 1.0)
	h.Sample(20, 1.0)
	h.Sample(25, 1.0)

	metrics := h.Flush(10*time.Second, []float64{0.50})
	// We get lots of metrics back for histograms!
	assert.Len(t, metrics, 4, "Flushed metrics length")

	// the max
	m2 := metrics[0]
	assert.Equal(t, "a.b.c.max", m2.Name, "Name")
	assert.Equal(t, int32(0), m2.Interval, "Interval")
	assert.Equal(t, "gauge", m2.MetricType, "Type")
	assert.Len(t, m2.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m2.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(25), m2.Value[0][1], "Value")

	// the min
	m3 := metrics[1]
	assert.Equal(t, "a.b.c.min", m3.Name, "Name")
	assert.Equal(t, int32(0), m3.Interval, "Interval")
	assert.Equal(t, "gauge", m3.MetricType, "Type")
	assert.Len(t, m3.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m3.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(5), m3.Value[0][1], "Value")

	// the count
	m1 := metrics[2]
	assert.Equal(t, "a.b.c.count", m1.Name, "Name")
	assert.Equal(t, int32(10), m1.Interval, "Interval")
	assert.Equal(t, "rate", m1.MetricType, "Type")
	assert.Len(t, m1.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m1.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(0.5), m1.Value[0][1], "Value")

	// And the percentile
	m4 := metrics[3]
	assert.Equal(t, "a.b.c.50percentile", m4.Name, "Name")
	assert.Equal(t, int32(0), m4.Interval, "Interval")
	assert.Equal(t, "gauge", m4.MetricType, "Type")
	assert.Len(t, m4.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m4.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(15), m4.Value[0][1], "Value")
}

func TestHistoSampleRate(t *testing.T) {

	h := NewHist("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", h.name, "Name")
	assert.Len(t, h.tags, 1, "Tag length")
	assert.Equal(t, h.tags[0], "a:b", "Tag contents")

	h.Sample(5, 0.5)
	h.Sample(10, 0.5)
	h.Sample(15, 0.5)
	h.Sample(20, 0.5)
	h.Sample(25, 0.5)

	metrics := h.Flush(10*time.Second, []float64{0.50})
	assert.Len(t, metrics, 4, "Metrics flush length")

	// First the max
	m1 := metrics[0]
	assert.Equal(t, "a.b.c.max", m1.Name, "Max name")
	assert.Equal(t, float64(25), m1.Value[0][1], "Sampled max as rate")

	count := metrics[2]
	assert.Equal(t, "a.b.c.count", count.Name, "count name")
	assert.Equal(t, float64(1), count.Value[0][1], "count value")
}

func TestHistoMerge(t *testing.T) {
	rand.Seed(time.Now().Unix())

	h := NewHist("a.b.c", []string{"a:b"})
	for i := 0; i < 100; i++ {
		h.Sample(rand.NormFloat64(), 1.0)
	}

	jm, err := h.Export()
	assert.NoError(t, err, "should have exported successfully")

	h2 := NewHist("a.b.c", []string{"a:b"})
	assert.NoError(t, h2.Combine(jm.Value), "should have combined successfully")
	assert.InEpsilon(t, h.value.Quantile(0.5), h2.value.Quantile(0.5), 0.02, "50th percentiles did not match after merging")
	assert.InDelta(t, 0, h2.localWeight, 0.02, "merged histogram should have count of zero")
	assert.True(t, math.IsInf(h2.localMin, +1), "merged histogram should have local minimum of +inf")
	assert.True(t, math.IsInf(h2.localMax, -1), "merged histogram should have local minimum of -inf")

	h2.Sample(1.0, 1.0)
	assert.InDelta(t, 1.0, h2.localWeight, 0.02, "merged histogram should have count of 1 after adding a value")
	assert.InDelta(t, 1.0, h2.localMin, 0.02, "merged histogram should have min of 1 after adding a value")
	assert.InDelta(t, 1.0, h2.localMax, 0.02, "merged histogram should have max of 1 after adding a value")
}
<commit_msg>Add difference to error message in TestSetMerge<commit_after>package veneur

import (
	"math"
	"math/rand"
	"strconv"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestCounterEmpty(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})
	c.Sample(1, 1.0)

	assert.Equal(t, "a.b.c", c.name, "Name")
	assert.Len(t, c.tags, 1, "Tag length")
	assert.Equal(t, c.tags[0], "a:b", "Tag contents")

	metrics := c.Flush(10 * time.Second)
	assert.Len(t, metrics, 1, "Flushes 1 metric")

	m1 := metrics[0]
	assert.Equal(t, int32(10), m1.Interval, "Interval")
	assert.Equal(t, "rate", m1.MetricType, "Type")
	assert.Len(t, c.tags, 1, "Tag length")
	assert.Equal(t, c.tags[0], "a:b", "Tag contents")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, 0.1, m1.Value[0][1], "Metric value")
}

func TestCounterRate(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})

	c.Sample(5, 1.0)

	// The counter returns an array with a single tuple of timestamp,value
	metrics := c.Flush(10 * time.Second)
	assert.Equal(t, 0.5, metrics[0].Value[0][1], "Metric value")
}

func TestCounterSampleRate(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})

	c.Sample(5, 0.5)

	// The counter returns an array with a single tuple of timestamp,value
	metrics := c.Flush(10 * time.Second)
	assert.Equal(t, float64(1), metrics[0].Value[0][1], "Metric value")
}

func TestGauge(t *testing.T) {

	g := NewGauge("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", g.name, "Name")
	assert.Len(t, g.tags, 1, "Tag length")
	assert.Equal(t, g.tags[0], "a:b", "Tag contents")

	g.Sample(5, 1.0)

	metrics := g.Flush()
	assert.Len(t, metrics, 1, "Flushed metric count")

	m1 := metrics[0]
	// Interval is not meaningful for this
	assert.Equal(t, int32(0), m1.Interval, "Interval")
	assert.Equal(t, "gauge", m1.MetricType, "Type")
	tags := m1.Tags
	assert.Len(t, tags, 1, "Tag length")
	assert.Equal(t, tags[0], "a:b", "Tag contents")

	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(5), m1.Value[0][1], "Value")
}

func TestSet(t *testing.T) {
	s := NewSet("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", s.name, "Name")
	assert.Len(t, s.tags, 1, "Tag count")
	assert.Equal(t, "a:b", s.tags[0], "First tag")

	s.Sample("5", 1.0)

	s.Sample("5", 1.0)

	s.Sample("123", 1.0)

	s.Sample("2147483647", 1.0)
	s.Sample("-2147483648", 1.0)

	metrics := s.Flush()
	assert.Len(t, metrics, 1, "Flush")

	m1 := metrics[0]
	// Interval is not meaningful for this
	assert.Equal(t, int32(0), m1.Interval, "Interval")
	assert.Equal(t, "gauge", m1.MetricType, "Type")
	assert.Len(t, m1.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m1.Tags[0], "First tag")
	assert.Equal(t, float64(4), m1.Value[0][1], "Value")
}

func TestSetMerge(t *testing.T) {
	rand.Seed(time.Now().Unix())

	s := NewSet("a.b.c", []string{"a:b"})
	for i := 0; i < 100; i++ {
		s.Sample(strconv.Itoa(rand.Int()), 1.0)
	}
	assert.Equal(t, uint64(100), s.hll.Count(), "counts did not match")

	jm, err := s.Export()
	assert.NoError(t, err, "should have exported successfully")

	s2 := NewSet("a.b.c", []string{"a:b"})
	assert.NoError(t, s2.Combine(jm.Value), "should have combined successfully")
	// HLLs are approximate, and we've seen error of +-1 here in the past, so
	// we're giving the test some room for error to reduce flakes
	count1 := int(s.hll.Count())
	count2 := int(s2.hll.Count())
	countDifference := count1 - count2
	assert.True(t, -1 < countDifference && countDifference < 1, "counts did not match after merging (%d and %d)", count1, count2)
}

func TestHisto(t *testing.T) {

	h := NewHist("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", h.name, "Name")
	assert.Len(t, h.tags, 1, "Tag count")
	assert.Equal(t, "a:b", h.tags[0], "First tag")

	h.Sample(5, 1.0)
	h.Sample(10, 1.0)
	h.Sample(15, 1.0)
	h.Sample(20, 1.0)
	h.Sample(25, 1.0)

	metrics := h.Flush(10*time.Second, []float64{0.50})
	// We get lots of metrics back for histograms!
	assert.Len(t, metrics, 4, "Flushed metrics length")

	// the max
	m2 := metrics[0]
	assert.Equal(t, "a.b.c.max", m2.Name, "Name")
	assert.Equal(t, int32(0), m2.Interval, "Interval")
	assert.Equal(t, "gauge", m2.MetricType, "Type")
	assert.Len(t, m2.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m2.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(25), m2.Value[0][1], "Value")

	// the min
	m3 := metrics[1]
	assert.Equal(t, "a.b.c.min", m3.Name, "Name")
	assert.Equal(t, int32(0), m3.Interval, "Interval")
	assert.Equal(t, "gauge", m3.MetricType, "Type")
	assert.Len(t, m3.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m3.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(5), m3.Value[0][1], "Value")

	// the count
	m1 := metrics[2]
	assert.Equal(t, "a.b.c.count", m1.Name, "Name")
	assert.Equal(t, int32(10), m1.Interval, "Interval")
	assert.Equal(t, "rate", m1.MetricType, "Type")
	assert.Len(t, m1.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m1.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(0.5), m1.Value[0][1], "Value")

	// And the percentile
	m4 := metrics[3]
	assert.Equal(t, "a.b.c.50percentile", m4.Name, "Name")
	assert.Equal(t, int32(0), m4.Interval, "Interval")
	assert.Equal(t, "gauge", m4.MetricType, "Type")
	assert.Len(t, m4.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m4.Tags[0], "First tag")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, float64(15), m4.Value[0][1], "Value")
}

func TestHistoSampleRate(t *testing.T) {

	h := NewHist("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", h.name, "Name")
	assert.Len(t, h.tags, 1, "Tag length")
	assert.Equal(t, h.tags[0], "a:b", "Tag contents")

	h.Sample(5, 0.5)
	h.Sample(10, 0.5)
	h.Sample(15, 0.5)
	h.Sample(20, 0.5)
	h.Sample(25, 0.5)

	metrics := h.Flush(10*time.Second, []float64{0.50})
	assert.Len(t, metrics, 4, "Metrics flush length")

	// First the max
	m1 := metrics[0]
	assert.Equal(t, "a.b.c.max", m1.Name, "Max name")
	assert.Equal(t, float64(25), m1.Value[0][1], "Sampled max as rate")

	count := metrics[2]
	assert.Equal(t, "a.b.c.count", count.Name, "count name")
	assert.Equal(t, float64(1), count.Value[0][1], "count value")
}

func TestHistoMerge(t *testing.T) {
	rand.Seed(time.Now().Unix())

	h := NewHist("a.b.c", []string{"a:b"})
	for i := 0; i < 100; i++ {
		h.Sample(rand.NormFloat64(), 1.0)
	}

	jm, err := h.Export()
	assert.NoError(t, err, "should have exported successfully")

	h2 := NewHist("a.b.c", []string{"a:b"})
	assert.NoError(t, h2.Combine(jm.Value), "should have combined successfully")
	assert.InEpsilon(t, h.value.Quantile(0.5), h2.value.Quantile(0.5), 0.02, "50th percentiles did not match after merging")
	assert.InDelta(t, 0, h2.localWeight, 0.02, "merged histogram should have count of zero")
	assert.True(t, math.IsInf(h2.localMin, +1), "merged histogram should have local minimum of +inf")
	assert.True(t, math.IsInf(h2.localMax, -1), "merged histogram should have local minimum of -inf")

	h2.Sample(1.0, 1.0)
	assert.InDelta(t, 1.0, h2.localWeight, 0.02, "merged histogram should have count of 1 after adding a value")
	assert.InDelta(t, 1.0, h2.localMin, 0.02, "merged histogram should have min of 1 after adding a value")
	assert.InDelta(t, 1.0, h2.localMax, 0.02, "merged histogram should have max of 1 after adding a value")
}
<|endoftext|>


<commit_before>package main

import (
	"example-apps/proxy/handlers"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
)

func launchHandler(port int, downloadHandler, digHandler, timedDigHandler, pingHandler, proxyHandler, statsHandler, uploadHandler, echoSourceIPHandler http.Handler) {
	mux := http.NewServeMux()
	mux.Handle("/download/", downloadHandler)
	mux.Handle("/dig/", digHandler)
	mux.Handle("/timed_dig/", timedDigHandler)
	mux.Handle("/ping/", pingHandler)
	mux.Handle("/proxy/", proxyHandler)
	mux.Handle("/stats", statsHandler)
	mux.Handle("/upload", uploadHandler)
	mux.Handle("/echosourceip", echoSourceIPHandler)
	mux.Handle("/", &handlers.InfoHandler{
		Port: port,
	})
	http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", port), mux)
}

func main() {
	systemPortString := os.Getenv("PORT")
	systemPort, err := strconv.Atoi(systemPortString)
	if err != nil {
		log.Fatal("invalid required env var PORT")
	}

	stats := &handlers.Stats{
		Latency: []float64{},
	}
	downloadHandler := &handlers.DownloadHandler{}
	pingHandler := &handlers.PingHandler{}
	digHandler := &handlers.DigHandler{}
	timedDigHandler := &handlers.TimedDigHandler{}
	proxyHandler := &handlers.ProxyHandler{
		Stats: stats,
	}
	statsHandler := &handlers.StatsHandler{
		Stats: stats,
	}
	uploadHandler := &handlers.UploadHandler{}

	echoSourceIPHandler := &handlers.EchoSourceIPHandler{}

	launchHandler(systemPort, downloadHandler, digHandler, timedDigHandler, pingHandler, proxyHandler, statsHandler, uploadHandler, echoSourceIPHandler)
}
<commit_msg>Add udp only dig handler to proxy main<commit_after>package main

import (
	"example-apps/proxy/handlers"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
)

func launchHandler(port int, downloadHandler, digHandler, digUDPHandler, timedDigHandler, pingHandler, proxyHandler, statsHandler, uploadHandler, echoSourceIPHandler http.Handler) {
	mux := http.NewServeMux()
	mux.Handle("/download/", downloadHandler)
	mux.Handle("/dig/", digHandler)
	mux.Handle("/digudp/", digUDPHandler)
	mux.Handle("/timed_dig/", timedDigHandler)
	mux.Handle("/ping/", pingHandler)
	mux.Handle("/proxy/", proxyHandler)
	mux.Handle("/stats", statsHandler)
	mux.Handle("/upload", uploadHandler)
	mux.Handle("/echosourceip", echoSourceIPHandler)
	mux.Handle("/", &handlers.InfoHandler{
		Port: port,
	})
	http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", port), mux)
}

func main() {
	systemPortString := os.Getenv("PORT")
	systemPort, err := strconv.Atoi(systemPortString)
	if err != nil {
		log.Fatal("invalid required env var PORT")
	}

	stats := &handlers.Stats{
		Latency: []float64{},
	}
	downloadHandler := &handlers.DownloadHandler{}
	pingHandler := &handlers.PingHandler{}
	digHandler := &handlers.DigHandler{}
	digUDPHandler := &handlers.DigUDPHandler{}
	timedDigHandler := &handlers.TimedDigHandler{}
	proxyHandler := &handlers.ProxyHandler{
		Stats: stats,
	}
	statsHandler := &handlers.StatsHandler{
		Stats: stats,
	}
	uploadHandler := &handlers.UploadHandler{}

	echoSourceIPHandler := &handlers.EchoSourceIPHandler{}

	launchHandler(systemPort, downloadHandler, digHandler, digUDPHandler, timedDigHandler, pingHandler, proxyHandler, statsHandler, uploadHandler, echoSourceIPHandler)
}
<|endoftext|>


<commit_before>package terraform_vix

import (
	"fmt"
	"log"
	"os/user"
	"path/filepath"
	"strconv"

	"github.com/c4milo/govix"
	"github.com/c4milo/terraform_vix/helper"
	"github.com/dustin/go-humanize"
	"github.com/hashicorp/terraform/flatmap"
	"github.com/hashicorp/terraform/helper/config"
	"github.com/hashicorp/terraform/helper/diff"
	"github.com/hashicorp/terraform/terraform"
)

func resource_vix_vm_validation() *config.Validator {
	return &config.Validator{
		Required: []string{
			"image.*",
			"image.*.url",
			"image.*.checksum",
			"image.*.checksum_type",
		},
		Optional: []string{
			"description",
			"image.*.password",
			"cpus",
			"memory",
			"hardware_version",
			"network_driver",
			"networks.*",
			"sharedfolders",
		},
	}
}

func resource_vix_vm_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	name := "coreos"
	description := rs.Attributes["description"]
	cpus, err := strconv.ParseUint(rs.Attributes["cpus"], 0, 8)
	memory := rs.Attributes["memory"]
	hwversion, err := strconv.ParseUint(rs.Attributes["hardware_version"], 0, 8)
	netdrv := rs.Attributes["network_driver"]
	sharedfolders, err := strconv.ParseBool(rs.Attributes["sharedfolders"])
	var networks []string

	if err != nil {
		return nil, err
	}

	if raw := flatmap.Expand(rs.Attributes, "networks"); raw != nil {
		if nets, ok := raw.([]interface{}); ok {
			for _, net := range nets {
				str, ok := net.(string)
				if !ok {
					continue
				}

				networks = append(networks, str)
			}
		}
	}

	// This is nasty but there doesn't seem to be a cleaner way to extract stuff
	// from the TF configuration
	image := flatmap.Expand(rs.Attributes, "image").([]interface{})[0].(map[string]interface{})

	log.Printf("[DEBUG] networks => %v", networks)

	if len(networks) == 0 {
		networks = append(networks, "bridged")
	}

	log.Printf("[DEBUG] name => %s", name)
	log.Printf("[DEBUG] description => %s", description)
	log.Printf("[DEBUG] image => %v", image)
	log.Printf("[DEBUG] cpus => %d", cpus)
	log.Printf("[DEBUG] memory => %s", memory)
	log.Printf("[DEBUG] hwversion => %d", hwversion)
	log.Printf("[DEBUG] netdrv => %s", netdrv)
	log.Printf("[DEBUG] sharedfolders => %t", sharedfolders)

	usr, err := user.Current()
	if err != nil {
		return nil, err
	}

	// FIXME(c4milo): There is an issue here whenever count is greater than 1
	// please see: https://github.com/hashicorp/terraform/issues/141
	vmPath := filepath.Join(usr.HomeDir, fmt.Sprintf(".terraform/vix/vms/%s", name))
	imagePath := filepath.Join(usr.HomeDir, fmt.Sprintf(".terraform/vix/images"))

	imageConfig := helper.Image{
		URL:          image["url"].(string),
		Checksum:     image["checksum"].(string),
		ChecksumType: image["checksum_type"].(string),
		DownloadPath: imagePath,
	}

	file, err := helper.FetchImage(imageConfig)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	err = helper.UnpackImage(file, vmPath)
	if err != nil {
		return nil, err
	}

	// Gets VIX instance
	p := meta.(*ResourceProvider)
	client := p.client

	// TODO(c4milo): Lookup VMX file in imagePath
	log.Printf("[INFO] Opening virtual machine from %s", imagePath)

	vm, err := client.OpenVm(imagePath, image["password"].(string))
	if err != nil {
		return nil, err
	}
	defer client.Disconnect()

	memoryInMb, err := humanize.ParseBytes(memory)
	if err != nil {
		log.Printf("[WARN] Unable to set memory size, defaulting to 1g: %s", err)
		memoryInMb = 1024
	} else {
		memoryInMb /= 1024
	}

	log.Printf("[DEBUG] Setting memory size to %d megabytes", memoryInMb)
	vm.SetMemorySize(uint(memoryInMb))

	log.Printf("[DEBUG] Setting vcpus to %d", cpus)
	vm.SetNumberVcpus(uint8(cpus))

	for _, netType := range networks {
		adapter := &vix.NetworkAdapter{
			VSwitch:        vix.VSwitch{},
			StartConnected: true,
		}

		switch netdrv {
		case "e1000":
			adapter.Vdevice = vix.NETWORK_DEVICE_E1000
		case "vmxnet3":
			adapter.Vdevice = vix.NETWORK_DEVICE_VMXNET3
		default:
			adapter.Vdevice = vix.NETWORK_DEVICE_E1000
		}

		switch netType {
		case "hostonly":
			adapter.ConnType = vix.NETWORK_HOSTONLY
		case "bridged":
			adapter.ConnType = vix.NETWORK_BRIDGED
		case "nat":
			adapter.ConnType = vix.NETWORK_NAT
		default:
			adapter.ConnType = vix.NETWORK_CUSTOM

		}

		err = vm.AddNetworkAdapter(adapter)
		if err != nil {
			return nil, err
		}
	}

	// TODO(c4milo): Set hardware version

	log.Println("[INFO] Powering virtual machine on...")
	err = vm.PowerOn(vix.VMPOWEROP_NORMAL)
	if err != nil {
		return rs, err
	}

	// rs.ConnInfo["type"] = "ssh"
	// rs.ConnInfo["host"] = ?

	return rs, nil
}

func resource_vix_vm_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	//p := meta.(*ResourceProvider)

	return nil, nil
}

func resource_vix_vm_destroy(
	s *terraform.ResourceState,
	meta interface{}) error {
	// p := meta.(*ResourceProvider)
	// client := p.client

	return nil
}

func resource_vix_vm_diff(
	s *terraform.ResourceState,
	c *terraform.ResourceConfig,
	meta interface{}) (*terraform.ResourceDiff, error) {

	b := &diff.ResourceBuilder{
		// We have to choose whether a change in an attribute triggers a new
		// resource creation or updates the existing resource.
		Attrs: map[string]diff.AttrType{
			"description":      diff.AttrTypeUpdate,
			"image":            diff.AttrTypeCreate,
			"cpus":             diff.AttrTypeUpdate,
			"memory":           diff.AttrTypeUpdate,
			"networks":         diff.AttrTypeUpdate,
			"hardware_version": diff.AttrTypeUpdate,
			"network_driver":   diff.AttrTypeUpdate,
			"sharedfolders":    diff.AttrTypeUpdate,
		},

		ComputedAttrs: []string{
			"ip_address",
		},
	}

	return b.Diff(s, c)
}

func resource_vix_vm_refresh(
	s *terraform.ResourceState,
	meta interface{}) (*terraform.ResourceState, error) {

	return nil, nil
}

func resource_vix_vm_update_state(
	s *terraform.ResourceState,
	vm *vix.VM) (*terraform.ResourceState, error) {

	return nil, nil
}
<commit_msg>Uses new API for fetching images<commit_after>package terraform_vix

import (
	"fmt"
	"log"
	"os/user"
	"path/filepath"
	"strconv"

	"github.com/c4milo/govix"
	"github.com/c4milo/terraform_vix/helper"
	"github.com/dustin/go-humanize"
	"github.com/hashicorp/terraform/flatmap"
	"github.com/hashicorp/terraform/helper/config"
	"github.com/hashicorp/terraform/helper/diff"
	"github.com/hashicorp/terraform/terraform"
)

func resource_vix_vm_validation() *config.Validator {
	return &config.Validator{
		Required: []string{
			"image.*",
			"image.*.url",
			"image.*.checksum",
			"image.*.checksum_type",
		},
		Optional: []string{
			"description",
			"image.*.password",
			"cpus",
			"memory",
			"hardware_version",
			"network_driver",
			"networks.*",
			"sharedfolders",
		},
	}
}

func resource_vix_vm_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	name := "coreos"
	description := rs.Attributes["description"]
	cpus, err := strconv.ParseUint(rs.Attributes["cpus"], 0, 8)
	memory := rs.Attributes["memory"]
	hwversion, err := strconv.ParseUint(rs.Attributes["hardware_version"], 0, 8)
	netdrv := rs.Attributes["network_driver"]
	sharedfolders, err := strconv.ParseBool(rs.Attributes["sharedfolders"])
	var networks []string

	if err != nil {
		return nil, err
	}

	if raw := flatmap.Expand(rs.Attributes, "networks"); raw != nil {
		if nets, ok := raw.([]interface{}); ok {
			for _, net := range nets {
				str, ok := net.(string)
				if !ok {
					continue
				}

				networks = append(networks, str)
			}
		}
	}

	// This is nasty but there doesn't seem to be a cleaner way to extract stuff
	// from the TF configuration
	image := flatmap.Expand(rs.Attributes, "image").([]interface{})[0].(map[string]interface{})

	log.Printf("[DEBUG] networks => %v", networks)

	if len(networks) == 0 {
		networks = append(networks, "bridged")
	}

	log.Printf("[DEBUG] name => %s", name)
	log.Printf("[DEBUG] description => %s", description)
	log.Printf("[DEBUG] image => %v", image)
	log.Printf("[DEBUG] cpus => %d", cpus)
	log.Printf("[DEBUG] memory => %s", memory)
	log.Printf("[DEBUG] hwversion => %d", hwversion)
	log.Printf("[DEBUG] netdrv => %s", netdrv)
	log.Printf("[DEBUG] sharedfolders => %t", sharedfolders)

	usr, err := user.Current()
	if err != nil {
		return nil, err
	}

	// FIXME(c4milo): There is an issue here whenever count is greater than 1
	// please see: https://github.com/hashicorp/terraform/issues/141
	vmPath := filepath.Join(usr.HomeDir, fmt.Sprintf(".terraform/vix/vms/%s", name))
	imagePath := filepath.Join(usr.HomeDir, fmt.Sprintf(".terraform/vix/images"))

	imageConfig := helper.FetchConfig{
		URL:          image["url"].(string),
		Checksum:     image["checksum"].(string),
		ChecksumType: image["checksum_type"].(string),
		DownloadPath: imagePath,
	}

	file, err := helper.FetchFile(imageConfig)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	err = helper.UnpackFile(file, vmPath)
	if err != nil {
		return nil, err
	}

	// Gets VIX instance
	p := meta.(*ResourceProvider)
	client := p.client

	// TODO(c4milo): Lookup VMX file in imagePath
	log.Printf("[INFO] Opening virtual machine from %s", imagePath)

	vm, err := client.OpenVm(imagePath, image["password"].(string))
	if err != nil {
		return nil, err
	}
	defer client.Disconnect()

	memoryInMb, err := humanize.ParseBytes(memory)
	if err != nil {
		log.Printf("[WARN] Unable to set memory size, defaulting to 1g: %s", err)
		memoryInMb = 1024
	} else {
		memoryInMb /= 1024
	}

	log.Printf("[DEBUG] Setting memory size to %d megabytes", memoryInMb)
	vm.SetMemorySize(uint(memoryInMb))

	log.Printf("[DEBUG] Setting vcpus to %d", cpus)
	vm.SetNumberVcpus(uint8(cpus))

	for _, netType := range networks {
		adapter := &vix.NetworkAdapter{
			VSwitch:        vix.VSwitch{},
			StartConnected: true,
		}

		switch netdrv {
		case "e1000":
			adapter.Vdevice = vix.NETWORK_DEVICE_E1000
		case "vmxnet3":
			adapter.Vdevice = vix.NETWORK_DEVICE_VMXNET3
		default:
			adapter.Vdevice = vix.NETWORK_DEVICE_E1000
		}

		switch netType {
		case "hostonly":
			adapter.ConnType = vix.NETWORK_HOSTONLY
		case "bridged":
			adapter.ConnType = vix.NETWORK_BRIDGED
		case "nat":
			adapter.ConnType = vix.NETWORK_NAT
		default:
			adapter.ConnType = vix.NETWORK_CUSTOM

		}

		err = vm.AddNetworkAdapter(adapter)
		if err != nil {
			return nil, err
		}
	}

	// TODO(c4milo): Set hardware version

	log.Println("[INFO] Powering virtual machine on...")
	err = vm.PowerOn(vix.VMPOWEROP_NORMAL)
	if err != nil {
		return rs, err
	}

	// rs.ConnInfo["type"] = "ssh"
	// rs.ConnInfo["host"] = ?

	return rs, nil
}

func resource_vix_vm_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	//p := meta.(*ResourceProvider)

	return nil, nil
}

func resource_vix_vm_destroy(
	s *terraform.ResourceState,
	meta interface{}) error {
	// p := meta.(*ResourceProvider)
	// client := p.client

	return nil
}

func resource_vix_vm_diff(
	s *terraform.ResourceState,
	c *terraform.ResourceConfig,
	meta interface{}) (*terraform.ResourceDiff, error) {

	b := &diff.ResourceBuilder{
		// We have to choose whether a change in an attribute triggers a new
		// resource creation or updates the existing resource.
		Attrs: map[string]diff.AttrType{
			"description":      diff.AttrTypeUpdate,
			"image":            diff.AttrTypeCreate,
			"cpus":             diff.AttrTypeUpdate,
			"memory":           diff.AttrTypeUpdate,
			"networks":         diff.AttrTypeUpdate,
			"hardware_version": diff.AttrTypeUpdate,
			"network_driver":   diff.AttrTypeUpdate,
			"sharedfolders":    diff.AttrTypeUpdate,
		},

		ComputedAttrs: []string{
			"ip_address",
		},
	}

	return b.Diff(s, c)
}

func resource_vix_vm_refresh(
	s *terraform.ResourceState,
	meta interface{}) (*terraform.ResourceState, error) {

	return nil, nil
}

func resource_vix_vm_update_state(
	s *terraform.ResourceState,
	vm *vix.VM) (*terraform.ResourceState, error) {

	return nil, nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"strconv"

	"github.com/MJKWoolnough/gopherjs/overlay"
	"github.com/MJKWoolnough/gopherjs/tabs"
	"github.com/MJKWoolnough/gopherjs/xjs"
	"honnef.co/go/js/dom"
)

func maps(c dom.Element) {
	xjs.RemoveChildren(c)
	mapsDiv := xjs.CreateElement("div")
	defer c.AppendChild(mapsDiv)
	list, err := MapList()
	if err != nil {
		xjs.SetInnerText(mapsDiv, err.Error())
		return
	}

	newButton := xjs.CreateElement("input").(*dom.HTMLInputElement)
	newButton.Type = "button"
	newButton.Value = "New Map"
	newButton.AddEventListener("click", false, newMap(c))

	mapsDiv.AppendChild(newButton)

	for _, m := range list {
		sd := xjs.CreateElement("div")
		xjs.SetInnerText(sd, m.Name)
		sd.AddEventListener("click", false, viewMap(m))
		mapsDiv.AppendChild(sd)
	}
	c.AppendChild(mapsDiv)
}

func newMap(c dom.Element) func(dom.Event) {
	return func(dom.Event) {
		f := xjs.CreateElement("div")
		o := overlay.New(f)
		f.AppendChild(xjs.SetInnerText(xjs.CreateElement("h1"), "New Map"))
		f.AppendChild(tabs.MakeTabs([]tabs.Tab{
			{"Create", createMap(o)},
			{"Upload/Download", uploadMap(o)},
			{"Generate", generate},
		}))
		o.OnClose(func() {
			maps(c)
		})
		c.AppendChild(o)
	}
}

var gameModes = [...]string{"Survival", "Creative", "Adventure", "Hardcore", "Spectator"}

func createMap(o overlay.Overlay) func(dom.Element) {
	c := xjs.CreateElement("div")
	nameLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	nameLabel.For = "name"
	xjs.SetInnerText(nameLabel, "Level Name")

	name := xjs.CreateElement("input").(*dom.HTMLInputElement)
	name.Type = "text"
	name.SetID("name")

	gameModeLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	gameModeLabel.For = "gameMode"
	xjs.SetInnerText(gameModeLabel, "Game Mode")

	gameMode := xjs.CreateElement("select").(*dom.HTMLSelectElement)
	for k, v := range gameModes {
		o := xjs.CreateElement("option").(*dom.HTMLOptionElement)
		o.Value = strconv.Itoa(k)
		xjs.SetInnerText(o, v)
		gameMode.AppendChild(o)
	}

	seedLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	seedLabel.For = "seed"
	xjs.SetInnerText(seedLabel, "Level Seed")

	seed := xjs.CreateElement("input").(*dom.HTMLInputElement)
	seed.Type = "text"
	seed.SetID("seed")
	seed.Value = ""

	structuresLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	structuresLabel.For = "structures"
	xjs.SetInnerText(structuresLabel, "Generate Structures")

	structures := xjs.CreateElement("input").(*dom.HTMLInputElement)
	structures.Type = "checkbox"
	structures.Checked = true
	structures.SetID("structures")

	cheatsLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	cheatsLabel.For = "cheats"
	xjs.SetInnerText(cheatsLabel, "Allow Cheats")

	cheats := xjs.CreateElement("input").(*dom.HTMLInputElement)
	cheats.Type = "checkbox"
	cheats.Checked = false
	cheats.SetID("cheats")

	c.AppendChild(nameLabel)
	c.AppendChild(name)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(gameModeLabel)
	c.AppendChild(gameMode)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(seedLabel)
	c.AppendChild(seed)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(structuresLabel)
	c.AppendChild(structures)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(cheatsLabel)
	c.AppendChild(cheats)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(xjs.CreateElement("br"))

	dataParser := func(mode int) func() (DefaultMap, error) {
		return func() (DefaultMap, error) {
			data := DefaultMap{
				Mode: mode,
			}
			var err error
			data.Name = name.Value
			si := gameMode.SelectedIndex
			if si < 0 || si >= len(gameModes) {
				return data, ErrInvalidGameMode
			}
			if seed.Value == "" {
				seed.Value = "0"
			}
			data.Seed, err = strconv.ParseInt(seed.Value, 10, 64)
			if err != nil {
				return data, err
			}
			data.Structures = structures.Checked
			data.Cheats = cheats.Checked
			return data, nil
		}
	}

	c.AppendChild(tabs.MakeTabs([]tabs.Tab{
		{"Default", createMapMode(0, o, dataParser(0))},
		{"Super Flat", createSuperFlatMap(o, dataParser(1))},
		{"Large Biomes", createMapMode(2, o, dataParser(2))},
		{"Amplified", createMapMode(3, o, dataParser(3))},
		{"Customised", createCustomisedMap(o, dataParser(4))},
	}))
	return func(d dom.Element) {
		d.AppendChild(c)
	}
}

var worldTypes = [...]string{
	"The standard minecraft map generation.",
	"A simple generator allowing customised levels of blocks.",
	"The standard minecraft map generation, but tweaked to allow for much larger biomes.",
	"The standard minecraft map generation, but tweaked to stretch the land upwards.",
	"A completely customiseable generator.",
}

func createMapMode(mode int, o overlay.Overlay, dataParser func() (DefaultMap, error)) func(dom.Element) {
	submit := xjs.CreateElement("input").(*dom.HTMLInputElement)
	submit.Type = "button"
	submit.Value = "Create Map"
	submit.AddEventListener("click", false, func(dom.Event) {
		data, err := dataParser()
		if err != nil {
			return
		}
		go func() {
			err = CreateDefaultMap(data)
			if err != nil {
				dom.GetWindow().Alert(err.Error())
			}
			o.Close()
		}()
	})
	return func(c dom.Element) {
		d := xjs.CreateElement("div")
		xjs.SetPreText(d, worldTypes[mode])
		c.AppendChild(d)
		c.AppendChild(xjs.CreateElement("br"))
		c.AppendChild(submit)
	}
}

func createSuperFlatMap(o overlay.Overlay, dataParser func() (DefaultMap, error)) func(dom.Element) {
	d := xjs.CreateElement("div")
	return func(c dom.Element) {
		c.AppendChild(d)
	}
}

func createCustomisedMap(o overlay.Overlay, dataParser func() (DefaultMap, error)) func(dom.Element) {
	d := xjs.CreateElement("div")
	return func(c dom.Element) {
		c.AppendChild(d)
	}
	// Sea Level - 0-255
	// Caves, Strongholds, Villages, Mineshafts, Temples, Ocean Monuments, Ravines
	// Dungeons + Count 1-100
	// Water Lakes + Rarity 1-100
	// Lava Lakes + Rarity 1-100
	// Lava Oceans
	// Biome - All/Choose
	// Biome Size 1-8
	// River Size 1-5
	// Ores -> Dirt/Gravel/Granite/Diorite/Andesite/Coal Ore/Iron Ore/Gold Ore/Redstone Ore/Diamond Ore/Lapis Lazuli Ore ->
	//           Spawn Size - 1-50
	//           Spawn Tries - 0-40
	//           Min-Height - 0-255
	//           Max-Height - 0-255
	// Advanced ->
	//           Main Noise Scale X - 1-5000
	//           Main Noise Scale Y - 1-5000
	//           Main Noise Scale Z - 1-5000
	//           Depth Noise Scale X - 1-2000
	//           Depth Noise Scale Y - 1-2000
	//           Depth Noise Scale Z - 1-2000
	//           Depth Base Size - 1-25
	//           Coordinate Scale - 1-6000
	//           Height Scale - 1-6000
	//           Height Stretch - 0.01-50
	//           Upper Limit Scale - 1-5000
	//           Lower Limit Scale - 1-5000
	//           Biome Depth Weight - 1-20
	//           Biome Depth Offset - 1-20
	//           Biome Scale Weight - 1-20
	//           Biome Scale Offset - 1-20

}

func uploadMap(o overlay.Overlay) func(dom.Element) {
	return func(c dom.Element) {
	}
}

func viewMap(m Map) func(dom.Event) {
	return func(dom.Event) {
		servers, err := ServerList()
		if err != nil {
			return
		}
		d := xjs.CreateElement("div")
		od := overlay.New(d)
		d.AppendChild(xjs.SetInnerText(xjs.CreateElement("h1"), "Map Details"))

		nameLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
		nameLabel.For = "name"
		xjs.SetInnerText(nameLabel, "Name")
		name := xjs.CreateElement("input").(*dom.HTMLInputElement)
		xjs.SetInnerText(nameLabel, "Name")
		name.SetID("name")
		name.Value = m.Name
		name.Type = "text"

		serverLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
		serverLabel.For = "server"
		xjs.SetInnerText(serverLabel, "Server")
		serverEditable := true
		var (
			selServer Server
			server    dom.Element
		)
		if m.Server != -1 {
			for _, s := range servers {
				if s.ID == m.Server {
					selServer = s
					serverEditable = !s.IsRunning()
					break
				}
			}
		}
		if serverEditable {
			sel := xjs.CreateElement("select").(*dom.HTMLSelectElement)
			sel.SetID("server")
			for _, s := range servers {
				if s.Map != -1 {
					continue
				}
				o := xjs.CreateElement("option").(*dom.HTMLOptionElement)
				o.Value = strconv.Itoa(s.ID)
				xjs.SetInnerText(o, s.Name)
				if s.ID == m.Server {
					o.Selected = true
				}
				sel.AppendChild(o)
			}
			server = sel
		} else {
			server.AppendChild(xjs.SetInnerText(xjs.CreateElement("div"), selServer.Name))
		}

		d.AppendChild(nameLabel)
		d.AppendChild(name)
		d.AppendChild(xjs.CreateElement("br"))
		d.AppendChild(serverLabel)
		d.AppendChild(server)

		dom.GetWindow().Document().DocumentElement().AppendChild(od)
	}
}

// Errors
var ErrInvalidGameMode = errors.New("invalid game mode")
<commit_msg>Added server set button<commit_after>package main

import (
	"errors"
	"strconv"

	"github.com/MJKWoolnough/gopherjs/overlay"
	"github.com/MJKWoolnough/gopherjs/tabs"
	"github.com/MJKWoolnough/gopherjs/xjs"
	"honnef.co/go/js/dom"
)

func maps(c dom.Element) {
	xjs.RemoveChildren(c)
	mapsDiv := xjs.CreateElement("div")
	defer c.AppendChild(mapsDiv)
	list, err := MapList()
	if err != nil {
		xjs.SetInnerText(mapsDiv, err.Error())
		return
	}

	newButton := xjs.CreateElement("input").(*dom.HTMLInputElement)
	newButton.Type = "button"
	newButton.Value = "New Map"
	newButton.AddEventListener("click", false, newMap(c))

	mapsDiv.AppendChild(newButton)

	for _, m := range list {
		sd := xjs.CreateElement("div")
		xjs.SetInnerText(sd, m.Name)
		sd.AddEventListener("click", false, viewMap(m))
		mapsDiv.AppendChild(sd)
	}
	c.AppendChild(mapsDiv)
}

func newMap(c dom.Element) func(dom.Event) {
	return func(dom.Event) {
		f := xjs.CreateElement("div")
		o := overlay.New(f)
		f.AppendChild(xjs.SetInnerText(xjs.CreateElement("h1"), "New Map"))
		f.AppendChild(tabs.MakeTabs([]tabs.Tab{
			{"Create", createMap(o)},
			{"Upload/Download", uploadMap(o)},
			{"Generate", generate},
		}))
		o.OnClose(func() {
			maps(c)
		})
		c.AppendChild(o)
	}
}

var gameModes = [...]string{"Survival", "Creative", "Adventure", "Hardcore", "Spectator"}

func createMap(o overlay.Overlay) func(dom.Element) {
	c := xjs.CreateElement("div")
	nameLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	nameLabel.For = "name"
	xjs.SetInnerText(nameLabel, "Level Name")

	name := xjs.CreateElement("input").(*dom.HTMLInputElement)
	name.Type = "text"
	name.SetID("name")

	gameModeLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	gameModeLabel.For = "gameMode"
	xjs.SetInnerText(gameModeLabel, "Game Mode")

	gameMode := xjs.CreateElement("select").(*dom.HTMLSelectElement)
	for k, v := range gameModes {
		o := xjs.CreateElement("option").(*dom.HTMLOptionElement)
		o.Value = strconv.Itoa(k)
		xjs.SetInnerText(o, v)
		gameMode.AppendChild(o)
	}

	seedLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	seedLabel.For = "seed"
	xjs.SetInnerText(seedLabel, "Level Seed")

	seed := xjs.CreateElement("input").(*dom.HTMLInputElement)
	seed.Type = "text"
	seed.SetID("seed")
	seed.Value = ""

	structuresLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	structuresLabel.For = "structures"
	xjs.SetInnerText(structuresLabel, "Generate Structures")

	structures := xjs.CreateElement("input").(*dom.HTMLInputElement)
	structures.Type = "checkbox"
	structures.Checked = true
	structures.SetID("structures")

	cheatsLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
	cheatsLabel.For = "cheats"
	xjs.SetInnerText(cheatsLabel, "Allow Cheats")

	cheats := xjs.CreateElement("input").(*dom.HTMLInputElement)
	cheats.Type = "checkbox"
	cheats.Checked = false
	cheats.SetID("cheats")

	c.AppendChild(nameLabel)
	c.AppendChild(name)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(gameModeLabel)
	c.AppendChild(gameMode)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(seedLabel)
	c.AppendChild(seed)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(structuresLabel)
	c.AppendChild(structures)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(cheatsLabel)
	c.AppendChild(cheats)
	c.AppendChild(xjs.CreateElement("br"))
	c.AppendChild(xjs.CreateElement("br"))

	dataParser := func(mode int) func() (DefaultMap, error) {
		return func() (DefaultMap, error) {
			data := DefaultMap{
				Mode: mode,
			}
			var err error
			data.Name = name.Value
			si := gameMode.SelectedIndex
			if si < 0 || si >= len(gameModes) {
				return data, ErrInvalidGameMode
			}
			if seed.Value == "" {
				seed.Value = "0"
			}
			data.Seed, err = strconv.ParseInt(seed.Value, 10, 64)
			if err != nil {
				return data, err
			}
			data.Structures = structures.Checked
			data.Cheats = cheats.Checked
			return data, nil
		}
	}

	c.AppendChild(tabs.MakeTabs([]tabs.Tab{
		{"Default", createMapMode(0, o, dataParser(0))},
		{"Super Flat", createSuperFlatMap(o, dataParser(1))},
		{"Large Biomes", createMapMode(2, o, dataParser(2))},
		{"Amplified", createMapMode(3, o, dataParser(3))},
		{"Customised", createCustomisedMap(o, dataParser(4))},
	}))
	return func(d dom.Element) {
		d.AppendChild(c)
	}
}

var worldTypes = [...]string{
	"The standard minecraft map generation.",
	"A simple generator allowing customised levels of blocks.",
	"The standard minecraft map generation, but tweaked to allow for much larger biomes.",
	"The standard minecraft map generation, but tweaked to stretch the land upwards.",
	"A completely customiseable generator.",
}

func createMapMode(mode int, o overlay.Overlay, dataParser func() (DefaultMap, error)) func(dom.Element) {
	submit := xjs.CreateElement("input").(*dom.HTMLInputElement)
	submit.Type = "button"
	submit.Value = "Create Map"
	submit.AddEventListener("click", false, func(dom.Event) {
		data, err := dataParser()
		if err != nil {
			return
		}
		go func() {
			err = CreateDefaultMap(data)
			if err != nil {
				dom.GetWindow().Alert(err.Error())
			}
			o.Close()
		}()
	})
	return func(c dom.Element) {
		d := xjs.CreateElement("div")
		xjs.SetPreText(d, worldTypes[mode])
		c.AppendChild(d)
		c.AppendChild(xjs.CreateElement("br"))
		c.AppendChild(submit)
	}
}

func createSuperFlatMap(o overlay.Overlay, dataParser func() (DefaultMap, error)) func(dom.Element) {
	d := xjs.CreateElement("div")
	return func(c dom.Element) {
		c.AppendChild(d)
	}
}

func createCustomisedMap(o overlay.Overlay, dataParser func() (DefaultMap, error)) func(dom.Element) {
	d := xjs.CreateElement("div")
	return func(c dom.Element) {
		c.AppendChild(d)
	}
	// Sea Level - 0-255
	// Caves, Strongholds, Villages, Mineshafts, Temples, Ocean Monuments, Ravines
	// Dungeons + Count 1-100
	// Water Lakes + Rarity 1-100
	// Lava Lakes + Rarity 1-100
	// Lava Oceans
	// Biome - All/Choose
	// Biome Size 1-8
	// River Size 1-5
	// Ores -> Dirt/Gravel/Granite/Diorite/Andesite/Coal Ore/Iron Ore/Gold Ore/Redstone Ore/Diamond Ore/Lapis Lazuli Ore ->
	//           Spawn Size - 1-50
	//           Spawn Tries - 0-40
	//           Min-Height - 0-255
	//           Max-Height - 0-255
	// Advanced ->
	//           Main Noise Scale X - 1-5000
	//           Main Noise Scale Y - 1-5000
	//           Main Noise Scale Z - 1-5000
	//           Depth Noise Scale X - 1-2000
	//           Depth Noise Scale Y - 1-2000
	//           Depth Noise Scale Z - 1-2000
	//           Depth Base Size - 1-25
	//           Coordinate Scale - 1-6000
	//           Height Scale - 1-6000
	//           Height Stretch - 0.01-50
	//           Upper Limit Scale - 1-5000
	//           Lower Limit Scale - 1-5000
	//           Biome Depth Weight - 1-20
	//           Biome Depth Offset - 1-20
	//           Biome Scale Weight - 1-20
	//           Biome Scale Offset - 1-20

}

func uploadMap(o overlay.Overlay) func(dom.Element) {
	return func(c dom.Element) {
	}
}

func viewMap(m Map) func(dom.Event) {
	return func(dom.Event) {
		servers, err := ServerList()
		if err != nil {
			return
		}
		d := xjs.CreateElement("div")
		od := overlay.New(d)
		d.AppendChild(xjs.SetInnerText(xjs.CreateElement("h1"), "Map Details"))

		nameLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
		nameLabel.For = "name"
		xjs.SetInnerText(nameLabel, "Name")
		name := xjs.CreateElement("input").(*dom.HTMLInputElement)
		xjs.SetInnerText(nameLabel, "Name")
		name.SetID("name")
		name.Value = m.Name
		name.Type = "text"

		serverLabel := xjs.CreateElement("label").(*dom.HTMLLabelElement)
		serverLabel.For = "server"
		xjs.SetInnerText(serverLabel, "Server")
		serverEditable := true
		serverSet := xjs.DocumentFragment()
		var (
			selServer Server
			server    dom.Element
		)
		if m.Server != -1 {
			for _, s := range servers {
				if s.ID == m.Server {
					selServer = s
					serverEditable = !s.IsRunning()
					break
				}
			}
		}
		if serverEditable {
			sel := xjs.CreateElement("select").(*dom.HTMLSelectElement)
			sel.SetID("server")
			for _, s := range servers {
				if s.Map != -1 {
					continue
				}
				o := xjs.CreateElement("option").(*dom.HTMLOptionElement)
				o.Value = strconv.Itoa(s.ID)
				xjs.SetInnerText(o, s.Name)
				if s.ID == m.Server {
					o.Selected = true
				}
				sel.AppendChild(o)
			}
			if len(servers) > 0 {
				c := xjs.CreateElement("input").(*dom.HTMLInputElement)
				c.Value = "Set Server"
				serverSet.AppendChild(c)
				c.AddEventListener("click", false, func(dom.Event) {

				})
			}
			server = sel
		} else {
			server.AppendChild(xjs.SetInnerText(xjs.CreateElement("div"), selServer.Name))
		}

		d.AppendChild(nameLabel)
		d.AppendChild(name)
		d.AppendChild(xjs.CreateElement("br"))
		d.AppendChild(serverLabel)
		d.AppendChild(server)
		d.AppendChild(serverSet)

		dom.GetWindow().Document().DocumentElement().AppendChild(od)
	}
}

// Errors
var ErrInvalidGameMode = errors.New("invalid game mode")
<|endoftext|>


<commit_before>package rel

import (
	"testing"
)

func TestAttributeNotEqSql(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" != 10"
	if sql != expected {
		t.Logf("TestAttributeNotEqSql sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeNotEqAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEqAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" != 1 OR \"users\".\"id\" != 2)"
	if sql != expected {
		t.Logf("TestAttributeNotEqAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeNotEqNil(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEq(nil))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" IS NOT NULL"
	if sql != expected {
		t.Logf("TestAttributeNotEqNil sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeNotEqAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEqAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" != 1 AND \"users\".\"id\" != 2)"
	if sql != expected {
		t.Logf("TestAttributeNotEqAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGt(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").Gt(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" > 10"
	if sql != expected {
		t.Logf("TestAttributeGt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtEq(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtEq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" >= 10"
	if sql != expected {
		t.Logf("TestAttributeGtEq sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtEqAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtEqAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" >= 1 OR \"users\".\"id\" >= 2)"
	if sql != expected {
		t.Logf("TestAttributeGtEqAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtEqAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtEqAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" >= 1 AND \"users\".\"id\" >= 2)"
	if sql != expected {
		t.Logf("TestAttributeGtEqAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" > 1 AND \"users\".\"id\" > 2)"
	if sql != expected {
		t.Logf("TestAttributeGtAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" > 1 OR \"users\".\"id\" > 2)"
	if sql != expected {
		t.Logf("TestAttributeGtAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLt(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").Lt(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" < 10"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtEq(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtEq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" <= 10"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtEqAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtEqAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" <= 1 OR \"users\".\"id\" <= 2)"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtEqAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtEqAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" <= 1 AND \"users\".\"id\" <= 2)"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" < 1 OR \"users\".\"id\" < 2)"
	if sql != expected {
		t.Logf("TestAttributeLtAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" < 1 AND \"users\".\"id\" < 2)"
	if sql != expected {
		t.Logf("TestAttributeLtAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeCount(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id").Count())
	sql := mgr.ToSql()
	expected := "SELECT COUNT(\"users\".\"id\") FROM \"users\""
	if sql != expected {
		t.Logf("TestAttributeCount sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeEq(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").Eq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" = 10"
	if sql != expected {
		t.Logf("TestAttributeEq sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}
<commit_msg>Created test for AttributeNode#Eq to nil<commit_after>package rel

import (
	"testing"
)

func TestAttributeNotEqSql(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" != 10"
	if sql != expected {
		t.Logf("TestAttributeNotEqSql sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeNotEqAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEqAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" != 1 OR \"users\".\"id\" != 2)"
	if sql != expected {
		t.Logf("TestAttributeNotEqAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeNotEqNil(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEq(nil))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" IS NOT NULL"
	if sql != expected {
		t.Logf("TestAttributeNotEqNil sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeNotEqAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").NotEqAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" != 1 AND \"users\".\"id\" != 2)"
	if sql != expected {
		t.Logf("TestAttributeNotEqAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGt(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").Gt(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" > 10"
	if sql != expected {
		t.Logf("TestAttributeGt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtEq(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtEq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" >= 10"
	if sql != expected {
		t.Logf("TestAttributeGtEq sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtEqAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtEqAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" >= 1 OR \"users\".\"id\" >= 2)"
	if sql != expected {
		t.Logf("TestAttributeGtEqAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtEqAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtEqAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" >= 1 AND \"users\".\"id\" >= 2)"
	if sql != expected {
		t.Logf("TestAttributeGtEqAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" > 1 AND \"users\".\"id\" > 2)"
	if sql != expected {
		t.Logf("TestAttributeGtAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeGtAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").GtAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" > 1 OR \"users\".\"id\" > 2)"
	if sql != expected {
		t.Logf("TestAttributeGtAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLt(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").Lt(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" < 10"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtEq(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtEq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" <= 10"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtEqAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtEqAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" <= 1 OR \"users\".\"id\" <= 2)"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtEqAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtEqAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" <= 1 AND \"users\".\"id\" <= 2)"
	if sql != expected {
		t.Logf("TestAttributeLt sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtAny(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtAny(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" < 1 OR \"users\".\"id\" < 2)"
	if sql != expected {
		t.Logf("TestAttributeLtAny sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeLtAll(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").LtAll(Sql(1), Sql(2)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE (\"users\".\"id\" < 1 AND \"users\".\"id\" < 2)"
	if sql != expected {
		t.Logf("TestAttributeLtAll sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeCount(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id").Count())
	sql := mgr.ToSql()
	expected := "SELECT COUNT(\"users\".\"id\") FROM \"users\""
	if sql != expected {
		t.Logf("TestAttributeCount sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeEq(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").Eq(Sql(10)))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" = 10"
	if sql != expected {
		t.Logf("TestAttributeEq sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}

func TestAttributeEqNil(t *testing.T) {
	users := NewTable("users")
	mgr := users.Select(users.Attr("id"))
	mgr.Where(users.Attr("id").Eq(nil))
	sql := mgr.ToSql()
	expected := "SELECT \"users\".\"id\" FROM \"users\" WHERE \"users\".\"id\" IS NULL"
	if sql != expected {
		t.Logf("TestAttributeEqNil sql: \n%s != \n%s", sql, expected)
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package sockjs

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
)
import "testing"

func TestInfoGet(t *testing.T) {
	recorder := httptest.NewRecorder()
	request, _ := http.NewRequest("GET", "", nil)
	DefaultOptions.info(recorder, request)

	if recorder.Code != http.StatusOK {
		t.Errorf("Wrong status code, got '%d' expected '%d'", recorder.Code, http.StatusOK)
	}

	decoder := json.NewDecoder(recorder.Body)
	var a info
	decoder.Decode(&a)
	if !a.Websocket {
		t.Errorf("Websocket field should be set true")
	}
	if a.CookieNeeded {
		t.Errorf("CookieNeede should be set to false")
	}
}

func TestInfoOptions(t *testing.T) {
	recorder := httptest.NewRecorder()
	request, _ := http.NewRequest("OPTIONS", "", nil)
	DefaultOptions.info(recorder, request)
	if recorder.Code != http.StatusNoContent {
		t.Errorf("Incorrect status code received, got '%d' expected '%d'", recorder.Code, http.StatusNoContent)
	}
}

func TestInfoUnknown(t *testing.T) {
	req, _ := http.NewRequest("PUT", "", nil)
	rec := httptest.NewRecorder()
	DefaultOptions.info(rec, req)
	if rec.Code != http.StatusNotFound {
		t.Errorf("Incorrec response status, got '%d' expected '%d'", rec.Code, http.StatusNotFound)
	}
}

func TestCookies(t *testing.T) {
	rec := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "", nil)
	optionsWithCookies := DefaultOptions
	optionsWithCookies.JSessionID = DefaultJSessionID
	optionsWithCookies.cookie(rec, req)
	if rec.Header().Get("set-cookie") != "JSESSIONID=dummy; Path=/" {
		t.Errorf("Cookie not properly set in response")
	}
	// cookie value set in request
	req.AddCookie(&http.Cookie{Name: "JSESSIONID", Value: "some_jsession_id", Path: "/"})
	rec = httptest.NewRecorder()
	optionsWithCookies.cookie(rec, req)
	if rec.Header().Get("set-cookie") != "JSESSIONID=some_jsession_id; Path=/" {
		t.Errorf("Cookie not properly set in response")
	}
}
<commit_msg>Fix typo in options_test.go<commit_after>package sockjs

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
)
import "testing"

func TestInfoGet(t *testing.T) {
	recorder := httptest.NewRecorder()
	request, _ := http.NewRequest("GET", "", nil)
	DefaultOptions.info(recorder, request)

	if recorder.Code != http.StatusOK {
		t.Errorf("Wrong status code, got '%d' expected '%d'", recorder.Code, http.StatusOK)
	}

	decoder := json.NewDecoder(recorder.Body)
	var a info
	decoder.Decode(&a)
	if !a.Websocket {
		t.Errorf("Websocket field should be set true")
	}
	if a.CookieNeeded {
		t.Errorf("CookieNeeded should be set to false")
	}
}

func TestInfoOptions(t *testing.T) {
	recorder := httptest.NewRecorder()
	request, _ := http.NewRequest("OPTIONS", "", nil)
	DefaultOptions.info(recorder, request)
	if recorder.Code != http.StatusNoContent {
		t.Errorf("Incorrect status code received, got '%d' expected '%d'", recorder.Code, http.StatusNoContent)
	}
}

func TestInfoUnknown(t *testing.T) {
	req, _ := http.NewRequest("PUT", "", nil)
	rec := httptest.NewRecorder()
	DefaultOptions.info(rec, req)
	if rec.Code != http.StatusNotFound {
		t.Errorf("Incorrec response status, got '%d' expected '%d'", rec.Code, http.StatusNotFound)
	}
}

func TestCookies(t *testing.T) {
	rec := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "", nil)
	optionsWithCookies := DefaultOptions
	optionsWithCookies.JSessionID = DefaultJSessionID
	optionsWithCookies.cookie(rec, req)
	if rec.Header().Get("set-cookie") != "JSESSIONID=dummy; Path=/" {
		t.Errorf("Cookie not properly set in response")
	}
	// cookie value set in request
	req.AddCookie(&http.Cookie{Name: "JSESSIONID", Value: "some_jsession_id", Path: "/"})
	rec = httptest.NewRecorder()
	optionsWithCookies.cookie(rec, req)
	if rec.Header().Get("set-cookie") != "JSESSIONID=some_jsession_id; Path=/" {
		t.Errorf("Cookie not properly set in response")
	}
}
<|endoftext|>


<commit_before>package smtpapi

import (
	"bytes"
	"encoding/json"
	"fmt"
	"unicode/utf16"
)

const Version = "0.4.0"

// SMTPAPIHeader will be used to set up X-SMTPAPI params
type SMTPAPIHeader struct {
	To         []string            `json:"to,omitempty"`
	Sub        map[string][]string `json:"sub,omitempty"`
	Section    map[string]string   `json:"section,omitempty"`
	Category   []string            `json:"category,omitempty"`
	UniqueArgs map[string]string   `json:"unique_args,omitempty"`
	Filters    map[string]Filter   `json:"filters,omitempty"`
	ASMGroupID int                 `json:"asm_group_id,omitempty"`
	SendAt     int64               `json:"send_at,omitempty"`
	SendEachAt []int64             `json:"send_each_at,omitempty"`
	IpPool     string              `json:"ip_pool,omitempty"`
}

// Filter represents an App/Filter and its settings
type Filter struct {
	Settings map[string]string `json:"settings,omitempty"`
}

// NewSMTPAPIHeader creates a new header struct
func NewSMTPAPIHeader() *SMTPAPIHeader {
	return &SMTPAPIHeader{}
}

// AddTo appends a single email to the To header
func (h *SMTPAPIHeader) AddTo(email string) {
	h.To = append(h.To, email)
}

// AddTos appends multiple emails to the To header
func (h *SMTPAPIHeader) AddTos(emails []string) {
	for i := 0; i < len(emails); i++ {
		h.AddTo(emails[i])
	}
}

// SetTos sets the value of the To header
func (h *SMTPAPIHeader) SetTos(emails []string) {
	h.To = emails
}

// AddSubstitution adds a new substitution to a specific key
func (h *SMTPAPIHeader) AddSubstitution(key, sub string) {
	if h.Sub == nil {
		h.Sub = make(map[string][]string)
	}
	h.Sub[key] = append(h.Sub[key], sub)
}

// AddSubstitutions adds a multiple substitutions to a specific key
func (h *SMTPAPIHeader) AddSubstitutions(key string, subs []string) {
	for i := 0; i < len(subs); i++ {
		h.AddSubstitution(key, subs[i])
	}
}

// SetSubstitutions sets the value of the substitutions on the Sub header
func (h *SMTPAPIHeader) SetSubstitutions(sub map[string][]string) {
	h.Sub = sub
}

// AddSection sets the value for a specific section
func (h *SMTPAPIHeader) AddSection(section, value string) {
	if h.Section == nil {
		h.Section = make(map[string]string)
	}
	h.Section[section] = value
}

// SetSections sets the value for the Section header
func (h *SMTPAPIHeader) SetSections(sections map[string]string) {
	h.Section = sections
}

// AddCategory adds a new category to the Category header
func (h *SMTPAPIHeader) AddCategory(category string) {
	h.Category = append(h.Category, category)
}

// AddCategories adds multiple categories to the Category header
func (h *SMTPAPIHeader) AddCategories(categories []string) {
	for i := 0; i < len(categories); i++ {
		h.AddCategory(categories[i])
	}
}

// SetCategories will set the value of the Categories field
func (h *SMTPAPIHeader) SetCategories(categories []string) {
	h.Category = categories
}

// SetASMGroupID will set the value of the ASMGroupID field
func (h *SMTPAPIHeader) SetASMGroupID(groupID int) {
	h.ASMGroupID = groupID
}

// AddUniqueArg will set the value of a specific argument
func (h *SMTPAPIHeader) AddUniqueArg(arg, value string) {
	if h.UniqueArgs == nil {
		h.UniqueArgs = make(map[string]string)
	}
	h.UniqueArgs[arg] = value
}

// SetUniqueArgs will set the value of the Unique_args header
func (h *SMTPAPIHeader) SetUniqueArgs(args map[string]string) {
	h.UniqueArgs = args
}

// AddFilter will set the specific setting for a filter
func (h *SMTPAPIHeader) AddFilter(filter, setting, value string) {
	if h.Filters == nil {
		h.Filters = make(map[string]Filter)
	}
	if _, ok := h.Filters[filter]; !ok {
		h.Filters[filter] = Filter{
			Settings: make(map[string]string),
		}
	}
	h.Filters[filter].Settings[setting] = value
}

// SetFilter takes in a Filter struct with predetermined settings and sets it for such Filter key
func (h *SMTPAPIHeader) SetFilter(filter string, value *Filter) {
	if h.Filters == nil {
		h.Filters = make(map[string]Filter)
	}
	h.Filters[filter] = *value
}

// SetSendAt takes in a timestamp which determines when the email will be sent
func (h *SMTPAPIHeader) SetSendAt(sendAt int64) {
	h.SendAt = sendAt
}

// AddSendEachAt takes in a timestamp and pushes it into a list Must match length of To emails
func (h *SMTPAPIHeader) AddSendEachAt(sendEachAt int64) {
	h.SendEachAt = append(h.SendEachAt, sendEachAt)
}

// SetSendEachAt takes an array of timestamps. Must match length of To emails
func (h *SMTPAPIHeader) SetSendEachAt(sendEachAt []int64) {
	h.SendEachAt = sendEachAt
}

// SetIpPool takes a strings and sets the IpPool field
func (h *SMTPAPIHeader) SetIpPool(ipPool string) {
	h.IpPool = ipPool
}

// Unicode escape
func escapeUnicode(input string) string {
	//var buffer bytes.Buffer
	buffer := bytes.NewBufferString("")
	for _, r := range input {
		if r > 65535 {
			// surrogate pair
			var r1, r2 = utf16.EncodeRune(r)
			var s = fmt.Sprintf("\\u%x\\u%x", r1, r2)
			buffer.WriteString(s)
		} else if r > 127 {
			var s = fmt.Sprintf("\\u%04x", r)
			buffer.WriteString(s)
		} else {
			var s = fmt.Sprintf("%c", r)
			buffer.WriteString(s)
		}
	}
	return buffer.String()
}

// JSONString returns the representation of the Header
func (h *SMTPAPIHeader) JSONString() (string, error) {
	headers, e := json.Marshal(h)
	return escapeUnicode(string(headers)), e
}
<commit_msg>add loader<commit_after>package smtpapi

import (
	"bytes"
	"encoding/json"
	"fmt"
	"unicode/utf16"
)

const Version = "0.4.0"

// SMTPAPIHeader will be used to set up X-SMTPAPI params
type SMTPAPIHeader struct {
	To         []string            `json:"to,omitempty"`
	Sub        map[string][]string `json:"sub,omitempty"`
	Section    map[string]string   `json:"section,omitempty"`
	Category   []string            `json:"category,omitempty"`
	UniqueArgs map[string]string   `json:"unique_args,omitempty"`
	Filters    map[string]Filter   `json:"filters,omitempty"`
	ASMGroupID int                 `json:"asm_group_id,omitempty"`
	SendAt     int64               `json:"send_at,omitempty"`
	SendEachAt []int64             `json:"send_each_at,omitempty"`
	IpPool     string              `json:"ip_pool,omitempty"`
}

// Filter represents an App/Filter and its settings
type Filter struct {
	Settings map[string]string `json:"settings,omitempty"`
}

// NewSMTPAPIHeader creates a new header struct
func NewSMTPAPIHeader() *SMTPAPIHeader {
	return &SMTPAPIHeader{}
}

// AddTo appends a single email to the To header
func (h *SMTPAPIHeader) AddTo(email string) {
	h.To = append(h.To, email)
}

// AddTos appends multiple emails to the To header
func (h *SMTPAPIHeader) AddTos(emails []string) {
	for i := 0; i < len(emails); i++ {
		h.AddTo(emails[i])
	}
}

// SetTos sets the value of the To header
func (h *SMTPAPIHeader) SetTos(emails []string) {
	h.To = emails
}

// AddSubstitution adds a new substitution to a specific key
func (h *SMTPAPIHeader) AddSubstitution(key, sub string) {
	if h.Sub == nil {
		h.Sub = make(map[string][]string)
	}
	h.Sub[key] = append(h.Sub[key], sub)
}

// AddSubstitutions adds a multiple substitutions to a specific key
func (h *SMTPAPIHeader) AddSubstitutions(key string, subs []string) {
	for i := 0; i < len(subs); i++ {
		h.AddSubstitution(key, subs[i])
	}
}

// SetSubstitutions sets the value of the substitutions on the Sub header
func (h *SMTPAPIHeader) SetSubstitutions(sub map[string][]string) {
	h.Sub = sub
}

// AddSection sets the value for a specific section
func (h *SMTPAPIHeader) AddSection(section, value string) {
	if h.Section == nil {
		h.Section = make(map[string]string)
	}
	h.Section[section] = value
}

// SetSections sets the value for the Section header
func (h *SMTPAPIHeader) SetSections(sections map[string]string) {
	h.Section = sections
}

// AddCategory adds a new category to the Category header
func (h *SMTPAPIHeader) AddCategory(category string) {
	h.Category = append(h.Category, category)
}

// AddCategories adds multiple categories to the Category header
func (h *SMTPAPIHeader) AddCategories(categories []string) {
	for i := 0; i < len(categories); i++ {
		h.AddCategory(categories[i])
	}
}

// SetCategories will set the value of the Categories field
func (h *SMTPAPIHeader) SetCategories(categories []string) {
	h.Category = categories
}

// SetASMGroupID will set the value of the ASMGroupID field
func (h *SMTPAPIHeader) SetASMGroupID(groupID int) {
	h.ASMGroupID = groupID
}

// AddUniqueArg will set the value of a specific argument
func (h *SMTPAPIHeader) AddUniqueArg(arg, value string) {
	if h.UniqueArgs == nil {
		h.UniqueArgs = make(map[string]string)
	}
	h.UniqueArgs[arg] = value
}

// SetUniqueArgs will set the value of the Unique_args header
func (h *SMTPAPIHeader) SetUniqueArgs(args map[string]string) {
	h.UniqueArgs = args
}

// AddFilter will set the specific setting for a filter
func (h *SMTPAPIHeader) AddFilter(filter, setting, value string) {
	if h.Filters == nil {
		h.Filters = make(map[string]Filter)
	}
	if _, ok := h.Filters[filter]; !ok {
		h.Filters[filter] = Filter{
			Settings: make(map[string]string),
		}
	}
	h.Filters[filter].Settings[setting] = value
}

// SetFilter takes in a Filter struct with predetermined settings and sets it for such Filter key
func (h *SMTPAPIHeader) SetFilter(filter string, value *Filter) {
	if h.Filters == nil {
		h.Filters = make(map[string]Filter)
	}
	h.Filters[filter] = *value
}

// SetSendAt takes in a timestamp which determines when the email will be sent
func (h *SMTPAPIHeader) SetSendAt(sendAt int64) {
	h.SendAt = sendAt
}

// AddSendEachAt takes in a timestamp and pushes it into a list Must match length of To emails
func (h *SMTPAPIHeader) AddSendEachAt(sendEachAt int64) {
	h.SendEachAt = append(h.SendEachAt, sendEachAt)
}

// SetSendEachAt takes an array of timestamps. Must match length of To emails
func (h *SMTPAPIHeader) SetSendEachAt(sendEachAt []int64) {
	h.SendEachAt = sendEachAt
}

// SetIpPool takes a strings and sets the IpPool field
func (h *SMTPAPIHeader) SetIpPool(ipPool string) {
	h.IpPool = ipPool
}

// Unicode escape
func escapeUnicode(input string) string {
	//var buffer bytes.Buffer
	buffer := bytes.NewBufferString("")
	for _, r := range input {
		if r > 65535 {
			// surrogate pair
			var r1, r2 = utf16.EncodeRune(r)
			var s = fmt.Sprintf("\\u%x\\u%x", r1, r2)
			buffer.WriteString(s)
		} else if r > 127 {
			var s = fmt.Sprintf("\\u%04x", r)
			buffer.WriteString(s)
		} else {
			var s = fmt.Sprintf("%c", r)
			buffer.WriteString(s)
		}
	}
	return buffer.String()
}

// JSONString returns the representation of the Header
func (h *SMTPAPIHeader) JSONString() (string, error) {
	headers, e := json.Marshal(h)
	return escapeUnicode(string(headers)), e
}

// Load allows you to load a pre-formed x-smtpapi header
func (h *SMTPAPIHeader) Load(b []byte) error {
	return json.Unmarshal(b, h)
}
<|endoftext|>


<commit_before>package jose

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/json"
	"errors"
	"fmt"
	"hash"
	"math/big"
	"strings"
)

// JWS

type JwsHeader struct {
	Algorithm JoseAlgorithm `json:"alg,omitempty"`
	Nonce     string        `json:"nonce,omitempty"`
	Key       JsonWebKey    `json:"jwk,omitempty"`
}

// rawJsonWebSignature and JsonWebSignature are the same.
// We just use rawJsonWebSignature for the basic parse,
// and JsonWebSignature for the full parse
type rawJsonWebSignature struct {
	signed    bool
	Header    JwsHeader  `json:"header,omitempty"`
	Protected JsonBuffer `json:"protected,omitempty"`
	Payload   JsonBuffer `json:"payload,omitempty"`
	Signature JsonBuffer `json:"signature,omitempty"`
}

type JsonWebSignature rawJsonWebSignature

// No need for special MarshalJSON handling; it's OK for
// elements to remain in the unprotected header, since they'll
// just be overwritten.
// func (jwk JsonWebKey) MarshalJSON() ([]byte, error) {}

// On unmarshal, copy protected header fields to protected
func (jws *JsonWebSignature) UnmarshalJSON(data []byte) error {
	var raw rawJsonWebSignature
	err := json.Unmarshal(data, &raw)
	if err != nil {
		return err
	}

	// Copy over simple fields
	jws.Header = raw.Header
	jws.Protected = raw.Protected
	jws.Payload = raw.Payload
	jws.Signature = raw.Signature

	if len(jws.Protected) > 0 {
		// This overwrites fields in jwk.Header if there is a conflict
		err = json.Unmarshal(jws.Protected, &jws.Header)
		if err != nil {
			return err
		}
	}

	// Check that required fields are present
	if len(jws.Signature) == 0 || len(jws.Payload) == 0 {
		return errors.New("JWS missing required fields")
	}

	return nil
}

func (jws JsonWebSignature) MarshalCompact() ([]byte, error) {
	if !jws.signed {
		return []byte{}, errors.New("Cannot marshal unsigned JWS")
	}

	return []byte(B64enc(jws.Protected) + "." + B64enc(jws.Payload) + "." + B64enc(jws.Signature)), nil
}

func UnmarshalCompact(data []byte) (JsonWebSignature, error) {
	jws := JsonWebSignature{}
	parts := strings.Split(string(data), ".")
	if len(parts) != 3 {
		return jws, errors.New("Mal-formed compact JWS")
	}

	// Decode simple fields
	var err error
	jws.Protected, err = B64dec(parts[0])
	if err != nil {
		return jws, err
	}
	jws.Payload, err = B64dec(parts[1])
	if err != nil {
		return jws, err
	}
	jws.Signature, err = B64dec(parts[2])
	if err != nil {
		return jws, err
	}

	// Populate header from protected
	err = json.Unmarshal(jws.Protected, &jws.Header)
	if err != nil {
		return jws, err
	}

	jws.signed = true
	return jws, nil
}

func prepareInput(jws JsonWebSignature) (crypto.Hash, []byte, error) {
	input := []byte(B64enc(jws.Protected) + "." + B64enc(jws.Payload))
	zeroh := crypto.Hash(0)
	zerob := []byte{}

	// TODO: Check for valid algorithm

	// Hash the payload
	hashAlg := string(jws.Header.Algorithm[2:])
	var hashID crypto.Hash
	var hash hash.Hash
	switch hashAlg {
	case "256":
		hashID = crypto.SHA256
		hash = sha256.New()
	case "384":
		hashID = crypto.SHA384
		hash = sha512.New384()
	case "512":
		hashID = crypto.SHA512
		hash = sha512.New()
	default:
		return zeroh, zerob, errors.New("Invalid hash length " + hashAlg)
	}
	hash.Write(input)
	inputHash := hash.Sum(nil)

	return hashID, inputHash, nil
}

func Sign(alg JoseAlgorithm, privateKey interface{}, payload []byte) (JsonWebSignature, error) {
	zero := JsonWebSignature{}

	// Create a working JWS
	jws := JsonWebSignature{Payload: payload}
	jws.Header.Algorithm = alg

	// Cast the private key to the appropriate type, and
	// add the corresponding public key to the header
	var rsaPriv *rsa.PrivateKey
	var ecPriv *ecdsa.PrivateKey
	switch privateKey := privateKey.(type) {
	case rsa.PrivateKey:
		rsaPriv = &privateKey
		jws.Header.Key = JsonWebKey{KeyType: KeyTypeRSA, Rsa: &rsaPriv.PublicKey}
	case ecdsa.PrivateKey:
		ecPriv = &privateKey
		jws.Header.Key = JsonWebKey{KeyType: KeyTypeEC, Ec: &ecPriv.PublicKey}
	default:
		return zero, errors.New(fmt.Sprintf("Unsupported key type for %+v\n", privateKey))
	}

	// Base64-encode the header -> protected
	// NOTE: This implies that unprotected headers are not supported
	protected, err := json.Marshal(jws.Header)
	if err != nil {
		return zero, err
	}
	jws.Protected = protected

	// Compute the signature input
	hashID, inputHash, err := prepareInput(jws)
	if err != nil {
		return zero, err
	}

	// Sign
	// TODO: Check that key type is compatible
	var sig []byte
	switch jws.Header.Algorithm[:1] {
	case "R":
		if rsaPriv == nil {
			return zero, errors.New(fmt.Sprintf("Algorithm %s requres RSA private key", jws.Header.Algorithm))
		}
		sig, err = rsa.SignPKCS1v15(rand.Reader, rsaPriv, hashID, inputHash)
	case "P":
		if rsaPriv == nil {
			return zero, errors.New(fmt.Sprintf("Algorithm %s requres RSA private key", jws.Header.Algorithm))
		}
		sig, err = rsa.SignPSS(rand.Reader, rsaPriv, hashID, inputHash, &rsa.PSSOptions{})
	case "E":
		if ecPriv == nil {
			return zero, errors.New(fmt.Sprintf("Algorithm %s requres EC private key", jws.Header.Algorithm))
		}
		r, s, err := ecdsa.Sign(rand.Reader, ecPriv, inputHash)
		if err == nil {
			sig = concatRS(r, s)
		}
	default:
		return zero, errors.New("Invalid signature algorithm " + string(jws.Header.Algorithm[:1]))
	}

	if err != nil {
		return zero, err
	}
	jws.Signature = sig
	jws.signed = true

	return jws, nil
}

func concatRS(r, s *big.Int) []byte {
	rb, sb := r.Bytes(), s.Bytes()

	if padSize := len(rb) - len(sb); padSize > 0 {
		sb = append(make([]byte, padSize), sb...)
	} else if padSize < 0 {
		rb = append(make([]byte, -padSize), rb...)
	}

	return append(rb, sb...)
}

func (jws *JsonWebSignature) Verify() error {
	hashID, inputHash, err := prepareInput(*jws)
	if err != nil {
		return err
	}
	sig := jws.Signature

	// Check the signature, branching from the first character in the alg value
	// For example: "RS256" => "R" => PKCS1v15
	switch jws.Header.Algorithm[:1] {
	case "R":
		if jws.Header.Key.Rsa == nil {
			return errors.New(fmt.Sprintf("Algorithm %s requires RSA key", jws.Header.Algorithm))
		}
		return rsa.VerifyPKCS1v15(jws.Header.Key.Rsa, hashID, inputHash, sig)
	case "P":
		if jws.Header.Key.Rsa == nil {
			return errors.New(fmt.Sprintf("Algorithm %s requires RSA key", jws.Header.Algorithm))
		}
		return rsa.VerifyPSS(jws.Header.Key.Rsa, hashID, inputHash, sig, nil)
	case "E":
		if jws.Header.Key.Ec == nil {
			return errors.New(fmt.Sprintf("Algorithm %s requires EC key", jws.Header.Algorithm))
		}
		intlen := len(sig) / 2
		rBytes, sBytes := sig[:intlen], sig[intlen:]
		r, s := big.NewInt(0), big.NewInt(0)
		r.SetBytes(rBytes)
		s.SetBytes(sBytes)
		if ecdsa.Verify(jws.Header.Key.Ec, inputHash, r, s) {
			return nil
		} else {
			return errors.New("ECDSA signature validation failed")
		}
	default:
		return errors.New("Invalid signature algorithm " + string(jws.Header.Algorithm[:1]))
	}
}
<commit_msg>Add comment about PSSOptions to jws.go.<commit_after>package jose

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/json"
	"errors"
	"fmt"
	"hash"
	"math/big"
	"strings"
)

// JWS

type JwsHeader struct {
	Algorithm JoseAlgorithm `json:"alg,omitempty"`
	Nonce     string        `json:"nonce,omitempty"`
	Key       JsonWebKey    `json:"jwk,omitempty"`
}

// rawJsonWebSignature and JsonWebSignature are the same.
// We just use rawJsonWebSignature for the basic parse,
// and JsonWebSignature for the full parse
type rawJsonWebSignature struct {
	signed    bool
	Header    JwsHeader  `json:"header,omitempty"`
	Protected JsonBuffer `json:"protected,omitempty"`
	Payload   JsonBuffer `json:"payload,omitempty"`
	Signature JsonBuffer `json:"signature,omitempty"`
}

type JsonWebSignature rawJsonWebSignature

// No need for special MarshalJSON handling; it's OK for
// elements to remain in the unprotected header, since they'll
// just be overwritten.
// func (jwk JsonWebKey) MarshalJSON() ([]byte, error) {}

// On unmarshal, copy protected header fields to protected
func (jws *JsonWebSignature) UnmarshalJSON(data []byte) error {
	var raw rawJsonWebSignature
	err := json.Unmarshal(data, &raw)
	if err != nil {
		return err
	}

	// Copy over simple fields
	jws.Header = raw.Header
	jws.Protected = raw.Protected
	jws.Payload = raw.Payload
	jws.Signature = raw.Signature

	if len(jws.Protected) > 0 {
		// This overwrites fields in jwk.Header if there is a conflict
		err = json.Unmarshal(jws.Protected, &jws.Header)
		if err != nil {
			return err
		}
	}

	// Check that required fields are present
	if len(jws.Signature) == 0 || len(jws.Payload) == 0 {
		return errors.New("JWS missing required fields")
	}

	return nil
}

func (jws JsonWebSignature) MarshalCompact() ([]byte, error) {
	if !jws.signed {
		return []byte{}, errors.New("Cannot marshal unsigned JWS")
	}

	return []byte(B64enc(jws.Protected) + "." + B64enc(jws.Payload) + "." + B64enc(jws.Signature)), nil
}

func UnmarshalCompact(data []byte) (JsonWebSignature, error) {
	jws := JsonWebSignature{}
	parts := strings.Split(string(data), ".")
	if len(parts) != 3 {
		return jws, errors.New("Mal-formed compact JWS")
	}

	// Decode simple fields
	var err error
	jws.Protected, err = B64dec(parts[0])
	if err != nil {
		return jws, err
	}
	jws.Payload, err = B64dec(parts[1])
	if err != nil {
		return jws, err
	}
	jws.Signature, err = B64dec(parts[2])
	if err != nil {
		return jws, err
	}

	// Populate header from protected
	err = json.Unmarshal(jws.Protected, &jws.Header)
	if err != nil {
		return jws, err
	}

	jws.signed = true
	return jws, nil
}

func prepareInput(jws JsonWebSignature) (crypto.Hash, []byte, error) {
	input := []byte(B64enc(jws.Protected) + "." + B64enc(jws.Payload))
	zeroh := crypto.Hash(0)
	zerob := []byte{}

	// TODO: Check for valid algorithm

	// Hash the payload
	hashAlg := string(jws.Header.Algorithm[2:])
	var hashID crypto.Hash
	var hash hash.Hash
	switch hashAlg {
	case "256":
		hashID = crypto.SHA256
		hash = sha256.New()
	case "384":
		hashID = crypto.SHA384
		hash = sha512.New384()
	case "512":
		hashID = crypto.SHA512
		hash = sha512.New()
	default:
		return zeroh, zerob, errors.New("Invalid hash length " + hashAlg)
	}
	hash.Write(input)
	inputHash := hash.Sum(nil)

	return hashID, inputHash, nil
}

func Sign(alg JoseAlgorithm, privateKey interface{}, payload []byte) (JsonWebSignature, error) {
	zero := JsonWebSignature{}

	// Create a working JWS
	jws := JsonWebSignature{Payload: payload}
	jws.Header.Algorithm = alg

	// Cast the private key to the appropriate type, and
	// add the corresponding public key to the header
	var rsaPriv *rsa.PrivateKey
	var ecPriv *ecdsa.PrivateKey
	switch privateKey := privateKey.(type) {
	case rsa.PrivateKey:
		rsaPriv = &privateKey
		jws.Header.Key = JsonWebKey{KeyType: KeyTypeRSA, Rsa: &rsaPriv.PublicKey}
	case ecdsa.PrivateKey:
		ecPriv = &privateKey
		jws.Header.Key = JsonWebKey{KeyType: KeyTypeEC, Ec: &ecPriv.PublicKey}
	default:
		return zero, errors.New(fmt.Sprintf("Unsupported key type for %+v\n", privateKey))
	}

	// Base64-encode the header -> protected
	// NOTE: This implies that unprotected headers are not supported
	protected, err := json.Marshal(jws.Header)
	if err != nil {
		return zero, err
	}
	jws.Protected = protected

	// Compute the signature input
	hashID, inputHash, err := prepareInput(jws)
	if err != nil {
		return zero, err
	}

	// Sign
	// TODO: Check that key type is compatible
	var sig []byte
	switch jws.Header.Algorithm[:1] {
	case "R":
		if rsaPriv == nil {
			return zero, errors.New(fmt.Sprintf("Algorithm %s requres RSA private key", jws.Header.Algorithm))
		}
		sig, err = rsa.SignPKCS1v15(rand.Reader, rsaPriv, hashID, inputHash)
	case "P":
		if rsaPriv == nil {
			return zero, errors.New(fmt.Sprintf("Algorithm %s requres RSA private key", jws.Header.Algorithm))
		}
		// Contrary to docs, you can't pass a nil instead of the PSSOptions; You'll
		// get a nil dereference.
		sig, err = rsa.SignPSS(rand.Reader, rsaPriv, hashID, inputHash, &rsa.PSSOptions{})
	case "E":
		if ecPriv == nil {
			return zero, errors.New(fmt.Sprintf("Algorithm %s requres EC private key", jws.Header.Algorithm))
		}
		r, s, err := ecdsa.Sign(rand.Reader, ecPriv, inputHash)
		if err == nil {
			sig = concatRS(r, s)
		}
	default:
		return zero, errors.New("Invalid signature algorithm " + string(jws.Header.Algorithm[:1]))
	}

	if err != nil {
		return zero, err
	}
	jws.Signature = sig
	jws.signed = true

	return jws, nil
}

func concatRS(r, s *big.Int) []byte {
	rb, sb := r.Bytes(), s.Bytes()

	if padSize := len(rb) - len(sb); padSize > 0 {
		sb = append(make([]byte, padSize), sb...)
	} else if padSize < 0 {
		rb = append(make([]byte, -padSize), rb...)
	}

	return append(rb, sb...)
}

func (jws *JsonWebSignature) Verify() error {
	hashID, inputHash, err := prepareInput(*jws)
	if err != nil {
		return err
	}
	sig := jws.Signature

	// Check the signature, branching from the first character in the alg value
	// For example: "RS256" => "R" => PKCS1v15
	switch jws.Header.Algorithm[:1] {
	case "R":
		if jws.Header.Key.Rsa == nil {
			return errors.New(fmt.Sprintf("Algorithm %s requires RSA key", jws.Header.Algorithm))
		}
		return rsa.VerifyPKCS1v15(jws.Header.Key.Rsa, hashID, inputHash, sig)
	case "P":
		if jws.Header.Key.Rsa == nil {
			return errors.New(fmt.Sprintf("Algorithm %s requires RSA key", jws.Header.Algorithm))
		}
		return rsa.VerifyPSS(jws.Header.Key.Rsa, hashID, inputHash, sig, nil)
	case "E":
		if jws.Header.Key.Ec == nil {
			return errors.New(fmt.Sprintf("Algorithm %s requires EC key", jws.Header.Algorithm))
		}
		intlen := len(sig) / 2
		rBytes, sBytes := sig[:intlen], sig[intlen:]
		r, s := big.NewInt(0), big.NewInt(0)
		r.SetBytes(rBytes)
		s.SetBytes(sBytes)
		if ecdsa.Verify(jws.Header.Key.Ec, inputHash, r, s) {
			return nil
		} else {
			return errors.New("ECDSA signature validation failed")
		}
	default:
		return errors.New("Invalid signature algorithm " + string(jws.Header.Algorithm[:1]))
	}
}
<|endoftext|>


<commit_before>package scheme

import (
	"fmt"
	"github.com/orc/db"
	"github.com/orc/mvc/controllers"
)

func Init() {
	//Drop()
	for i, _ := range db.Tables {
		controllers.GetModel(db.Tables[i]).Create()
	}
}

func Drop() {
	for _, v := range db.Tables {
		db.Query(fmt.Sprintf("DROP TABLE IF EXISTS %s CASCADE;", v), nil)
		db.Query(fmt.Sprintf("DROP SEQUENCE IF EXISTS %s_id_seq;", v), nil)
	}
}
<commit_msg>scheme: fix whitespace, uncomment<commit_after>package scheme

import (
    "fmt"
    "github.com/orc/db"
    "github.com/orc/mvc/controllers"
)

func Init() {
    Drop()
    for i, _ := range db.Tables {
        controllers.GetModel(db.Tables[i]).Create()
    }
}

func Drop() {
    for _, v := range db.Tables {
        db.Query(fmt.Sprintf("DROP TABLE IF EXISTS %s CASCADE;", v), nil)
        db.Query(fmt.Sprintf("DROP SEQUENCE IF EXISTS %s_id_seq;", v), nil)
    }
}
<|endoftext|>