<commit_before>package blockdiag

import (
	"sort"
	"strings"
	"testing"
)

func TestShouldParser(t *testing.T) {
	for _, test := range []struct {
		description string
		input       string
		nodes       []string
		edges       []string
		attributes  map[string]string
	}{
		{
			"Empty diagram",
			`
blockdiag {}
`,
			[]string{},
			[]string{},
			map[string]string{},
		},
		{
			"Single Node",
			`
blockdiag {
	A;
}
`,
			[]string{"A"},
			[]string{},
			map[string]string{},
		},
		{
			// TODO Add test case for node chain without tailing ;
			"Node chain",
			`
blockdiag {
	A -> B;
}
`,
			[]string{"A", "B"},
			[]string{"A|B"},
			map[string]string{},
		},
		{
			"Multiple chains, using same nodes",
			`
blockdiag {
	A -> B -> C;
	A -> D;
}
`,
			[]string{"A", "B", "C", "D"},
			[]string{"A|B", "A|D", "B|C"},
			map[string]string{},
		},
		{
			"Self reference",
			`
blockdiag {
	A -> A;
}
`,
			[]string{"A"},
			[]string{"A|A"},
			map[string]string{},
		},
		{
			"Comment",
			`
# Comment
blockdiag # Comment
{
# Comment
	A; # Comment
# Comment
} # Comment
`,
			[]string{"A"},
			[]string{},
			map[string]string{},
		},
		{
			"Multi Char Node Names",
			`
blockdiag
{
	MultiCharNodeName1;
}
`,
			[]string{"MultiCharNodeName1"},
			[]string{},
			map[string]string{},
		},
		{
			"Digramm Attributes",
			`
blockdiag
{
	node_width = 128;
	A;
}
`,
			[]string{"A"},
			[]string{},
			map[string]string{
				"node_width": "128",
			},
		},
		{
			"Digramm type 'diagram'",
			`
diagram
{
	A;
}
`,
			[]string{"A"},
			[]string{},
			map[string]string{},
		},
	} {
		got, err := ParseReader("shouldparse.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("%s: parse error: %s with input %s", test.description, err, test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("%s: assertion error: %s should parse to diag", test.description, test.input)
		}
		if gotDiag.NodesString() != strings.Join(test.nodes, ", ") {
			t.Fatalf("%s: nodes error: %s, expected '%s', got: '%s'", test.description, test.input, strings.Join(test.nodes, ", "), gotDiag.NodesString())
		}
		if gotDiag.EdgesString() != strings.Join(test.edges, ", ") {
			t.Fatalf("%s edges error: %s, expected '%s', got: '%s'", test.description, test.input, strings.Join(test.edges, ", "), gotDiag.EdgesString())
		}

		var attributes []string
		for key, value := range test.attributes {
			attributes = append(attributes, key+"="+value)
		}
		sort.Strings(attributes)
		if gotDiag.AttributesString() != strings.Join(attributes, "\n") {
			t.Fatalf("%s attributes error: %s, expected '%s', got: '%s'", test.description, test.input, strings.Join(attributes, "\n"), gotDiag.AttributesString())
		}
	}
}

func TestShouldNotParse(t *testing.T) {
	for _, test := range []struct {
		description string
		input       string
	}{
		{
			"No block",
			`
blockdiag
`,
		},
	} {
		_, err := ParseReader("shouldnotparse.diag", strings.NewReader(test.input))
		if err == nil {
			t.Fatalf("%s: should not parse, but didn't give an error with input %s", test.description, test.input)
		}
	}
}

func TestCircular(t *testing.T) {
	for _, test := range []struct {
		input    string
		circular bool
	}{
		{
			`
blockdiag{
	A;
}
`,
			false,
		},
		{
			`
blockdiag{
	A -> B -> C;
}
`,
			false,
		},
		{
			`
blockdiag{
	A -> A;
}
`,
			false,
		},
		{
			`
blockdiag{
	A -> B -> C -> A;
}
`,
			true,
		},
	} {
		got, err := ParseReader("shouldnotparse.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		if gotDiag.FindCircular() != test.circular {
			t.Fatalf("expect %s to be circular == %t", test.input, test.circular)
		}
	}
}

func TestGetStartNodes(t *testing.T) {
	for _, test := range []struct {
		input      string
		startNodes []string
	}{
		{
			`
blockdiag{
	A -> B -> C;
}
`,
			[]string{"A"},
		},
		{
			`
blockdiag {
	A -> B -> C;
	D;
	E -> F;
}
`,
			[]string{"A", "D", "E"},
		},
		{
			`
blockdiag {
	D;
	E -> F;
	A -> B -> C;
}
`,
			[]string{"A", "D", "E"},
		},
	} {
		got, err := ParseReader("placeingrid.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		// if gotDiag.PlaceInGrid() != test.circular {
		// 	t.Fatalf("expect %s to be circular == %t", test.input, test.circular)
		// }
		startNodes := gotDiag.getStartNodes()
		if len(startNodes) != len(test.startNodes) {
			t.Fatalf("Start Nodes count wrong, expected: %s, got: %s", strings.Join(test.startNodes, ", "), startNodes)
		}
		sort.Strings(test.startNodes)
		for i, n := range startNodes {
			if n.Name != test.startNodes[i] {
				t.Fatalf("Start Nodes do not match, expected: %s, got: %s", strings.Join(test.startNodes, ", "), startNodes)
			}
		}
	}
}

func TestPlaceInGrid(t *testing.T) {
	for _, test := range []struct {
		input  string
		output string
	}{
		{
			`
blockdiag{
	A -> B -> C;
}
`, `[A] [B] [C]
`,
		},
		{
			`
blockdiag{
	A -> B -> C;
	B -> D;
	A -> E -> C;
}
`, `[A] [B] [C]
        [D]
    [E]
`,
		}, {
			`
blockdiag{
	A -> B -> C -> B; # Circular with proper Start-Node
}
`, `[A] [B] [C]
`,
		}, {
			`
blockdiag{
	A -> B -> C -> A; # Circular without Start-Node
}
`, `[A] [B] [C]
`,
		}, {
			`
blockdiag{
	A; B; C; D; E; F; G; H; I; J; K; # 11 Rows
}
`, `[A]
[B]
[C]
[D]
[E]
[F]
[G]
[H]
[I]
[J]
[K]
`,
		}, {
			`
blockdiag{
	A -> B -> C -> D -> E -> F -> G -> H -> I -> J -> K; # 11 Cols
}
`, `[A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K]
`,
		},
	} {
		got, err := ParseReader("placeingrid.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		gotDiag.PlaceInGrid()
		if gotDiag.GridString() != test.output {
			t.Fatalf("expected: \n%s, got: \n%s", strings.Replace(test.output, " ", "\u00B7", -1), strings.Replace(gotDiag.GridString(), " ", "\u00B7", -1))
		}
	}
}

func TestDiagString(t *testing.T) {
	for _, test := range []struct {
		input  string
		output string
	}{
		{
			`
blockdiag{
	# One node, no connections
	A;
}
`, `
[A]
`,
		},
		{
			`
blockdiag{
	# Two nodes, no connections
	A;
	B;
}
`, `
[A]

[B]
`,
		},
		{
			`
blockdiag{
	# Two connected nodes
	A -> B;
}
`, `
[A]───>[B]
`,
		},
		{
			`
blockdiag{
	# Two seperate streams
	A -> B;
	C -> D;
}
`, `
[A]───>[B]

[C]───>[D]
`,
		},
		{
			`
blockdiag{
	# From one node to two nodes
	A -> B;
	A -> C;
}
`, `
[A]─┬─>[B]
    │
    └─>[C]
`,
		}, {
			`
blockdiag{
	# From one node to three nodes
	A -> B;
	A -> C;
	A -> D;
}
`, `
[A]─┬─>[B]
    │
    ├─>[C]
    │
    └─>[D]
`,
		}, {
			`
blockdiag{
	# Branch and merge
	A -> B -> D;
	A -> C -> D;
}
`, `
[A]─┬─>[B]─┬─>[D]
    │      │
    └─>[C]─┘
`,
		}, {
			`
blockdiag{
	# Branch and merge two rows
	A -> B -> C -> E;
	A -> D -> E;
}
`, `
[A]─┬─>[B]───>[C]─┬─>[E]
    │             │
    └─>[D]────────┘
`,
		},
		{
			`
blockdiag {
	# Branch and merge two rows with alternative way
	A -> B -> C -> D;
	A -> E -> D;
	E -> F;
}
`, `
[A]─┬─>[B]───>[C]─┬─>[D]
    │      ┌──────┘
    └─>[E]─┴─>[F]
`,
		}, {
			`
blockdiag{
	# Branch and merge over two cols
	A -> B -> E;
	A -> C;
	A -> D -> E;
}
`, `
[A]─┬─>[B]─┬─>[E]
    │      │
    ├─>[C] │
    │      │
    └─>[D]─┘
`,
		},
	} {
		got, err := ParseReader("diagstring.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		gotDiag.PlaceInGrid()
		if gotDiag.String() != test.output {
			t.Fatalf("expected: \n%s, got: \n%s", strings.Replace(test.output, " ", "\u00B7", -1), strings.Replace(gotDiag.String(), " ", "\u00B7", -1))
		}
	}
}
<commit_msg>Better output for error case<commit_after>package blockdiag

import (
	"sort"
	"strings"
	"testing"
)

func TestShouldParser(t *testing.T) {
	for _, test := range []struct {
		description string
		input       string
		nodes       []string
		edges       []string
		attributes  map[string]string
	}{
		{
			"Empty diagram",
			`
blockdiag {}
`,
			[]string{},
			[]string{},
			map[string]string{},
		},
		{
			"Single Node",
			`
blockdiag {
	A;
}
`,
			[]string{"A"},
			[]string{},
			map[string]string{},
		},
		{
			// TODO Add test case for node chain without tailing ;
			"Node chain",
			`
blockdiag {
	A -> B;
}
`,
			[]string{"A", "B"},
			[]string{"A|B"},
			map[string]string{},
		},
		{
			"Multiple chains, using same nodes",
			`
blockdiag {
	A -> B -> C;
	A -> D;
}
`,
			[]string{"A", "B", "C", "D"},
			[]string{"A|B", "A|D", "B|C"},
			map[string]string{},
		},
		{
			"Self reference",
			`
blockdiag {
	A -> A;
}
`,
			[]string{"A"},
			[]string{"A|A"},
			map[string]string{},
		},
		{
			"Comment",
			`
# Comment
blockdiag # Comment
{
# Comment
	A; # Comment
# Comment
} # Comment
`,
			[]string{"A"},
			[]string{},
			map[string]string{},
		},
		{
			"Multi Char Node Names",
			`
blockdiag
{
	MultiCharNodeName1;
}
`,
			[]string{"MultiCharNodeName1"},
			[]string{},
			map[string]string{},
		},
		{
			"Digramm Attributes",
			`
blockdiag
{
	node_width = 128;
	A;
}
`,
			[]string{"A"},
			[]string{},
			map[string]string{
				"node_width": "128",
			},
		},
		{
			"Digramm type 'diagram'",
			`
diagram
{
	A;
}
`,
			[]string{"A"},
			[]string{},
			map[string]string{},
		},
	} {
		got, err := ParseReader("shouldparse.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("%s: parse error: %s with input %s", test.description, err, test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("%s: assertion error: %s should parse to diag", test.description, test.input)
		}
		if gotDiag.NodesString() != strings.Join(test.nodes, ", ") {
			t.Fatalf("%s: nodes error: %s, expected '%s', got: '%s'", test.description, test.input, strings.Join(test.nodes, ", "), gotDiag.NodesString())
		}
		if gotDiag.EdgesString() != strings.Join(test.edges, ", ") {
			t.Fatalf("%s edges error: %s, expected '%s', got: '%s'", test.description, test.input, strings.Join(test.edges, ", "), gotDiag.EdgesString())
		}

		var attributes []string
		for key, value := range test.attributes {
			attributes = append(attributes, key+"="+value)
		}
		sort.Strings(attributes)
		if gotDiag.AttributesString() != strings.Join(attributes, "\n") {
			t.Fatalf("%s attributes error: %s, expected '%s', got: '%s'", test.description, test.input, strings.Join(attributes, "\n"), gotDiag.AttributesString())
		}
	}
}

func TestShouldNotParse(t *testing.T) {
	for _, test := range []struct {
		description string
		input       string
	}{
		{
			"No block",
			`
blockdiag
`,
		},
	} {
		_, err := ParseReader("shouldnotparse.diag", strings.NewReader(test.input))
		if err == nil {
			t.Fatalf("%s: should not parse, but didn't give an error with input %s", test.description, test.input)
		}
	}
}

func TestCircular(t *testing.T) {
	for _, test := range []struct {
		input    string
		circular bool
	}{
		{
			`
blockdiag{
	A;
}
`,
			false,
		},
		{
			`
blockdiag{
	A -> B -> C;
}
`,
			false,
		},
		{
			`
blockdiag{
	A -> A;
}
`,
			false,
		},
		{
			`
blockdiag{
	A -> B -> C -> A;
}
`,
			true,
		},
	} {
		got, err := ParseReader("shouldnotparse.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		if gotDiag.FindCircular() != test.circular {
			t.Fatalf("expect %s to be circular == %t", test.input, test.circular)
		}
	}
}

func TestGetStartNodes(t *testing.T) {
	for _, test := range []struct {
		input      string
		startNodes []string
	}{
		{
			`
blockdiag{
	A -> B -> C;
}
`,
			[]string{"A"},
		},
		{
			`
blockdiag {
	A -> B -> C;
	D;
	E -> F;
}
`,
			[]string{"A", "D", "E"},
		},
		{
			`
blockdiag {
	D;
	E -> F;
	A -> B -> C;
}
`,
			[]string{"A", "D", "E"},
		},
	} {
		got, err := ParseReader("placeingrid.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		// if gotDiag.PlaceInGrid() != test.circular {
		// 	t.Fatalf("expect %s to be circular == %t", test.input, test.circular)
		// }
		startNodes := gotDiag.getStartNodes()
		if len(startNodes) != len(test.startNodes) {
			t.Fatalf("Start Nodes count wrong, expected: %s, got: %s", strings.Join(test.startNodes, ", "), startNodes)
		}
		sort.Strings(test.startNodes)
		for i, n := range startNodes {
			if n.Name != test.startNodes[i] {
				t.Fatalf("Start Nodes do not match, expected: %s, got: %s", strings.Join(test.startNodes, ", "), startNodes)
			}
		}
	}
}

func TestPlaceInGrid(t *testing.T) {
	for _, test := range []struct {
		input  string
		output string
	}{
		{
			`
blockdiag{
	A -> B -> C;
}
`, `[A] [B] [C]
`,
		},
		{
			`
blockdiag{
	A -> B -> C;
	B -> D;
	A -> E -> C;
}
`, `[A] [B] [C]
        [D]
    [E]
`,
		}, {
			`
blockdiag{
	A -> B -> C -> B; # Circular with proper Start-Node
}
`, `[A] [B] [C]
`,
		}, {
			`
blockdiag{
	A -> B -> C -> A; # Circular without Start-Node
}
`, `[A] [B] [C]
`,
		}, {
			`
blockdiag{
	A; B; C; D; E; F; G; H; I; J; K; # 11 Rows
}
`, `[A]
[B]
[C]
[D]
[E]
[F]
[G]
[H]
[I]
[J]
[K]
`,
		}, {
			`
blockdiag{
	A -> B -> C -> D -> E -> F -> G -> H -> I -> J -> K; # 11 Cols
}
`, `[A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K]
`,
		},
	} {
		got, err := ParseReader("placeingrid.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		gotDiag.PlaceInGrid()
		if gotDiag.GridString() != test.output {
			t.Fatalf("expected: \n%s, got: \n%s", strings.Replace(test.output, " ", "\u00B7", -1), strings.Replace(gotDiag.GridString(), " ", "\u00B7", -1))
		}
	}
}

func TestDiagString(t *testing.T) {
	for _, test := range []struct {
		input  string
		output string
	}{
		{
			`
blockdiag{
	# One node, no connections
	A;
}
`, `
[A]
`,
		},
		{
			`
blockdiag{
	# Two nodes, no connections
	A;
	B;
}
`, `
[A]

[B]
`,
		},
		{
			`
blockdiag{
	# Two connected nodes
	A -> B;
}
`, `
[A]───>[B]
`,
		},
		{
			`
blockdiag{
	# Two seperate streams
	A -> B;
	C -> D;
}
`, `
[A]───>[B]

[C]───>[D]
`,
		},
		{
			`
blockdiag{
	# From one node to two nodes
	A -> B;
	A -> C;
}
`, `
[A]─┬─>[B]
    │
    └─>[C]
`,
		}, {
			`
blockdiag{
	# From one node to three nodes
	A -> B;
	A -> C;
	A -> D;
}
`, `
[A]─┬─>[B]
    │
    ├─>[C]
    │
    └─>[D]
`,
		}, {
			`
blockdiag{
	# Branch and merge
	A -> B -> D;
	A -> C -> D;
}
`, `
[A]─┬─>[B]─┬─>[D]
    │      │
    └─>[C]─┘
`,
		}, {
			`
blockdiag{
	# Branch and merge two rows
	A -> B -> C -> E;
	A -> D -> E;
}
`, `
[A]─┬─>[B]───>[C]─┬─>[E]
    │             │
    └─>[D]────────┘
`,
		},
		{
			`
blockdiag {
	# Branch and merge two rows with alternative way
	A -> B -> C -> D;
	A -> E -> D;
	E -> F;
}
`, `
[A]─┬─>[B]───>[C]─┬─>[D]
    │      ┌──────┘
    └─>[E]─┴─>[F]
`,
		}, {
			`
blockdiag{
	# Branch and merge over two cols
	A -> B -> E;
	A -> C;
	A -> D -> E;
}
`, `
[A]─┬─>[B]─┬─>[E]
    │      │
    ├─>[C] │
    │      │
    └─>[D]─┘
`,
		},
	} {
		got, err := ParseReader("diagstring.diag", strings.NewReader(test.input))
		if err != nil {
			t.Fatalf("should not parse, but didn't give an error with input %s", test.input)
		}
		gotDiag, ok := got.(Diag)
		if !ok {
			t.Fatalf("assertion error: %s should parse to diag", test.input)
		}
		gotDiag.PlaceInGrid()
		if gotDiag.String() != test.output {
			t.Fatalf("for: \n%s\nexpected: \n%s\ngot: \n%s", test.input, strings.Replace(test.output, " ", "\u00B7", -1), strings.Replace(gotDiag.String(), " ", "\u00B7", -1))
		}
	}
}
<|endoftext|>


<commit_before>// Streaming relation (overlap, distance, KNN) testing of (any number of) sorted files of intervals.
package irelate

import (
	"container/heap"
	"fmt"
	"io"
	"log"
	"os"

	. "github.com/brentp/irelate/interfaces"
)

func relate(a Relatable, b Relatable, relativeTo int) {
	if a.Source() != b.Source() {
		if relativeTo == -1 {
			a.AddRelated(b)
			b.AddRelated(a)
		} else {
			if uint32(relativeTo) == a.Source() {
				a.AddRelated(b)
			}
			if uint32(relativeTo) == b.Source() {
				b.AddRelated(a)
			}
		}
	}
}

func Less(a Relatable, b Relatable) bool {
	if a.Chrom() != b.Chrom() {
		return a.Chrom() < b.Chrom()
	}
	return a.Start() < b.Start() // || (a.Start() == b.Start() && a.End() < b.End())
}

// 1, 2, 3 ... 9, 10, 11...
func NaturalLessPrefix(a Relatable, b Relatable) bool {
	if !SameChrom(a.Chrom(), b.Chrom()) {
		return NaturalLess(StripChr(a.Chrom()), StripChr(b.Chrom()))
	}
	return a.Start() < b.Start() || (a.Start() == b.Start() && a.End() < b.End())

}

// 1, 10, 11... 19, 2, 20, 21 ...
func LessPrefix(a Relatable, b Relatable) bool {
	if !SameChrom(a.Chrom(), b.Chrom()) {
		return StripChr(a.Chrom()) < StripChr(b.Chrom())
	}
	return a.Start() < b.Start() || (a.Start() == b.Start() && a.End() < b.End())
}

// CheckRelatedByOverlap returns true if Relatables overlap.
func CheckRelatedByOverlap(a Relatable, b Relatable) bool {
	return (b.Start() < a.End()) && (b.Chrom() == a.Chrom())
	// note with distance == 0 this just overlap.
	//distance := uint32(0)
	//return (b.Start()-distance < a.End()) && (b.Chrom() == a.Chrom())
}

// handles chromomomes like 'chr1' from one org and '1' from another.
func CheckOverlapPrefix(a Relatable, b Relatable) bool {
	if b.Start() < a.End() {
		return SameChrom(a.Chrom(), b.Chrom())
	}
	return false
}

// CheckKNN relates an interval to its k-nearest neighbors.
// The reporting function will have to do some filtering since this is only
// guaranteed to associate *at least* k neighbors, but it could be returning extra.
func CheckKNN(a Relatable, b Relatable) bool {
	// the first n checked would be the n_closest, but need to consider ties
	// the report function can decide what to do with them.
	k := 4
	r := a.Related()
	if len(r) >= k {
		// TODO: double-check this.
		return r[len(r)-1].Start()-a.End() < b.Start()-a.End()
	}
	return true
}

// filter rewrites the input-slice to remove nils.
func filter(s []Relatable, nils int) []Relatable {
	j := 0
	if len(s) != nils {

		for _, v := range s {
			if v != nil {
				s[j] = v
				j++
			}
		}
	}
	for k := j; k < len(s); k++ {
		s[k] = nil
	}
	return s[:j]
}

type irelate struct {
	checkRelated func(a, b Relatable) bool
	// relativeTo indicates which stream is the query stream. A value of -1 means
	// all vs all.
	relativeTo int
	less       func(a, b Relatable) bool
	// cache holds the set of Relatables we must test for overlap. A Relatable
	// is ejected from the cache when it is not related to the interval that's
	// about to be added.
	cache []Relatable
	// an item eject from the cache gets put on the sendQ if it's from the query
	// stream.
	sendQ *relatableQueue
	// mergeStream creates a single (sorted) stream of all incoming intervals.
	mergeStream RelatableIterator
	//merger RelatableChannel
	nils int
}

// IRelate provides the basis for flexible overlap/proximity/k-nearest neighbor
// testing. IRelate receives merged, ordered Relatables via stream and takes
// function that checks if they are related (see CheckRelatedByOverlap).
// It is guaranteed that !Less(b, a) is true (we can't guarantee that Less(a, b)
// is true since they may have the same start). Once checkRelated returns false,
// it is assumed that no other `b` Relatables could possibly be related to `a`
// and so `a` is sent to the returnQ.
// streams are a variable number of iterators that send intervals.
func IRelate(checkRelated func(a, b Relatable) bool,
	relativeTo int,
	less func(a, b Relatable) bool,
	streams ...RelatableIterator) RelatableIterator {

	mergeStream := newMerger(less, relativeTo, streams...)

	ir := &irelate{checkRelated: checkRelated, relativeTo: relativeTo,
		mergeStream: mergeStream,
		cache:       make([]Relatable, 0, 1024), sendQ: &relatableQueue{make([]Relatable, 0, 1024), less},
		less: less}
	return ir
}

func (ir *irelate) Close() error {
	return nil
}

func (ir *irelate) Next() (Relatable, error) {

	for {
		interval, err := ir.mergeStream.Next()
		if err == io.EOF {
			break
		}
		// check the interval against everything in the cache.
		for i, c := range ir.cache {
			if c == nil {
				continue
			}
			if ir.checkRelated(c, interval) {
				relate(c, interval, ir.relativeTo)
			} else {
				// if it's not related, we remove it from the cache
				// if it's a query interval, we push it onto the sendQ.
				if ir.relativeTo == -1 || int(c.Source()) == ir.relativeTo {
					heap.Push(ir.sendQ, c)
				}
				ir.cache[i] = nil
				ir.nils++
			}
		}

		// only do this when we have a lot of nils as it's expensive to create a new slice.
		// nils are spaces that we've removed from the cache.
		if ir.nils < 2 {
			ir.cache = append(ir.cache, interval)
			continue
		}
		// remove nils from the cache (must do this before sending)
		ir.cache, ir.nils = filter(ir.cache, ir.nils), 0
		var o Relatable
		if len(ir.sendQ.rels) > 0 {
			o = ir.sendQ.rels[0]
		}
		// if the first thing in the sendQ is less than the first thing in the cache
		// then we can send Pop the lowest thing off the sendQ.
		// otherwise, we continue to read from the stream.
		if o != nil && (len(ir.cache) == 0 || ir.less(o, ir.cache[0])) {
			ir.cache = append(ir.cache, interval)
			return heap.Pop(ir.sendQ).(Relatable), nil
		}
		ir.cache = append(ir.cache, interval)
	}
	// stream is done so we empty the cache by pushing onto the sendQ
	if len(ir.cache) > 0 {
		ir.cache, ir.nils = filter(ir.cache, ir.nils), 0
		for _, c := range ir.cache {
			if ir.relativeTo == -1 || int(c.Source()) == ir.relativeTo {
				heap.Push(ir.sendQ, c)
			}
		}
		ir.cache = ir.cache[:0]
	}
	// ... then we clear the sendQ
	if len(ir.sendQ.rels) > 0 {
		return heap.Pop(ir.sendQ).(Relatable), nil
	}
	return nil, io.EOF
}

type merger struct {
	less       func(a, b Relatable) bool
	relativeTo int
	streams    []RelatableIterator
	q          relatableQueue
	seen       map[string]struct{}
	j          int
	lastChrom  string
	verbose    bool
}

func newMerger(less func(a, b Relatable) bool, relativeTo int, streams ...RelatableIterator) *merger {
	q := relatableQueue{make([]Relatable, 0, len(streams)), less}
	verbose := os.Getenv("IRELATE_VERBOSE") == "TRUE"

	for i, stream := range streams {
		interval, err := stream.Next()
		if interval != nil {
			interval.SetSource(uint32(i))
			heap.Push(&q, interval)
		}
		if err == io.EOF {
			stream.Close()
		}
	}
	m := &merger{less: less, relativeTo: relativeTo, streams: streams, q: q, seen: make(map[string]struct{}), j: -1000, lastChrom: "", verbose: verbose}

	return m
}

func (m *merger) Close() error {
	return nil
}

func (m *merger) Next() (Relatable, error) {
	if len(m.q.rels) == 0 {
		return nil, io.EOF
	}
	interval := heap.Pop(&m.q).(Relatable)
	source := interval.Source()
	if !SameChrom(interval.Chrom(), m.lastChrom) {
		if m.verbose && m.lastChrom != "" {
			log.Printf("on chromosome: %s\n", m.lastChrom)
		}
		m.lastChrom = StripChr(interval.Chrom())
		if _, ok := m.seen[m.lastChrom]; ok {
			log.Println("warning: chromosomes must be in different order between files or the chromosome sort order is not as expected.")
			log.Printf("warning: overlaps will likely be missed after this chrom: %s from source: %d\n", m.lastChrom, interval.Source())
		}
		m.seen[m.lastChrom] = struct{}{}
	}
	// pull the next interval from the same source.
	next_interval, err := m.streams[source].Next()
	if err == nil {
		if next_interval.Start() < interval.Start() {
			if SameChrom(next_interval.Chrom(), interval.Chrom()) {
				panic(fmt.Sprintf("intervals out of order within file: starts at: %d and %d from source: %d", interval.Start(), next_interval.Start(), source))
			}
		}
		next_interval.SetSource(source)
		heap.Push(&m.q, next_interval)
		m.j--
		if m.j == 0 {
			return nil, io.EOF
		}
	} else {
		if int(source) == m.relativeTo {
			// we pull in 200K more records and then stop. to make sure we get anything that might
			// relate to last query
			m.j = 200000
		}
	}
	if err == io.EOF {
		m.streams[source].Close()
	}
	return interval, nil
}
<commit_msg>special case -2 for self-overlaps<commit_after>// Streaming relation (overlap, distance, KNN) testing of (any number of) sorted files of intervals.
package irelate

import (
	"container/heap"
	"fmt"
	"io"
	"log"
	"os"

	. "github.com/brentp/irelate/interfaces"
)

// Set relativeTo so SelfRelations constant to allow reporting overlaps within a stream
const SelfRelations = -2

func relate(a Relatable, b Relatable, relativeTo int) {
	if relativeTo == SelfRelations {
		a.AddRelated(b)
		b.AddRelated(a)
		return
	}
	if a.Source() != b.Source() {
		if relativeTo == -1 {
			a.AddRelated(b)
			b.AddRelated(a)
		} else {
			if uint32(relativeTo) == a.Source() {
				a.AddRelated(b)
			}
			if uint32(relativeTo) == b.Source() {
				b.AddRelated(a)
			}
		}
	}
}

func Less(a Relatable, b Relatable) bool {
	if a.Chrom() != b.Chrom() {
		return a.Chrom() < b.Chrom()
	}
	return a.Start() < b.Start() // || (a.Start() == b.Start() && a.End() < b.End())
}

// 1, 2, 3 ... 9, 10, 11...
func NaturalLessPrefix(a Relatable, b Relatable) bool {
	if !SameChrom(a.Chrom(), b.Chrom()) {
		return NaturalLess(StripChr(a.Chrom()), StripChr(b.Chrom()))
	}
	return a.Start() < b.Start() || (a.Start() == b.Start() && a.End() < b.End())

}

// 1, 10, 11... 19, 2, 20, 21 ...
func LessPrefix(a Relatable, b Relatable) bool {
	if !SameChrom(a.Chrom(), b.Chrom()) {
		return StripChr(a.Chrom()) < StripChr(b.Chrom())
	}
	return a.Start() < b.Start() || (a.Start() == b.Start() && a.End() < b.End())
}

// CheckRelatedByOverlap returns true if Relatables overlap.
func CheckRelatedByOverlap(a Relatable, b Relatable) bool {
	return (b.Start() < a.End()) && (b.Chrom() == a.Chrom())
	// note with distance == 0 this just overlap.
	//distance := uint32(0)
	//return (b.Start()-distance < a.End()) && (b.Chrom() == a.Chrom())
}

// handles chromomomes like 'chr1' from one org and '1' from another.
func CheckOverlapPrefix(a Relatable, b Relatable) bool {
	if b.Start() < a.End() {
		return SameChrom(a.Chrom(), b.Chrom())
	}
	return false
}

// CheckKNN relates an interval to its k-nearest neighbors.
// The reporting function will have to do some filtering since this is only
// guaranteed to associate *at least* k neighbors, but it could be returning extra.
func CheckKNN(a Relatable, b Relatable) bool {
	// the first n checked would be the n_closest, but need to consider ties
	// the report function can decide what to do with them.
	k := 4
	r := a.Related()
	if len(r) >= k {
		// TODO: double-check this.
		return r[len(r)-1].Start()-a.End() < b.Start()-a.End()
	}
	return true
}

// filter rewrites the input-slice to remove nils.
func filter(s []Relatable, nils int) []Relatable {
	j := 0
	if len(s) != nils {

		for _, v := range s {
			if v != nil {
				s[j] = v
				j++
			}
		}
	}
	for k := j; k < len(s); k++ {
		s[k] = nil
	}
	return s[:j]
}

type irelate struct {
	checkRelated func(a, b Relatable) bool
	// relativeTo indicates which stream is the query stream. A value of -1 means
	// all vs all. A value of -2 reports overlaps even within the same stream.
	relativeTo int
	less       func(a, b Relatable) bool
	// cache holds the set of Relatables we must test for overlap. A Relatable
	// is ejected from the cache when it is not related to the interval that's
	// about to be added.
	cache []Relatable
	// an item eject from the cache gets put on the sendQ if it's from the query
	// stream.
	sendQ *relatableQueue
	// mergeStream creates a single (sorted) stream of all incoming intervals.
	mergeStream RelatableIterator
	//merger RelatableChannel
	nils int
}

// IRelate provides the basis for flexible overlap/proximity/k-nearest neighbor
// testing. IRelate receives merged, ordered Relatables via stream and takes
// function that checks if they are related (see CheckRelatedByOverlap).
// It is guaranteed that !Less(b, a) is true (we can't guarantee that Less(a, b)
// is true since they may have the same start). Once checkRelated returns false,
// it is assumed that no other `b` Relatables could possibly be related to `a`
// and so `a` is sent to the returnQ.
// streams are a variable number of iterators that send intervals.
func IRelate(checkRelated func(a, b Relatable) bool,
	relativeTo int,
	less func(a, b Relatable) bool,
	streams ...RelatableIterator) RelatableIterator {

	mergeStream := newMerger(less, relativeTo, streams...)

	ir := &irelate{checkRelated: checkRelated, relativeTo: relativeTo,
		mergeStream: mergeStream,
		cache:       make([]Relatable, 0, 1024), sendQ: &relatableQueue{make([]Relatable, 0, 1024), less},
		less: less}
	return ir
}

func (ir *irelate) Close() error {
	return nil
}

func (ir *irelate) Next() (Relatable, error) {

	for {
		interval, err := ir.mergeStream.Next()
		if err == io.EOF {
			break
		}
		// check the interval against everything in the cache.
		for i, c := range ir.cache {
			if c == nil {
				continue
			}
			if ir.checkRelated(c, interval) {
				relate(c, interval, ir.relativeTo)
			} else {
				// if it's not related, we remove it from the cache
				// if it's a query interval, we push it onto the sendQ.
				if ir.relativeTo == -1 || int(c.Source()) == ir.relativeTo {
					heap.Push(ir.sendQ, c)
				}
				ir.cache[i] = nil
				ir.nils++
			}
		}

		// only do this when we have a lot of nils as it's expensive to create a new slice.
		// nils are spaces that we've removed from the cache.
		if ir.nils < 2 {
			ir.cache = append(ir.cache, interval)
			continue
		}
		// remove nils from the cache (must do this before sending)
		ir.cache, ir.nils = filter(ir.cache, ir.nils), 0
		var o Relatable
		if len(ir.sendQ.rels) > 0 {
			o = ir.sendQ.rels[0]
		}
		// if the first thing in the sendQ is less than the first thing in the cache
		// then we can send Pop the lowest thing off the sendQ.
		// otherwise, we continue to read from the stream.
		if o != nil && (len(ir.cache) == 0 || ir.less(o, ir.cache[0])) {
			ir.cache = append(ir.cache, interval)
			return heap.Pop(ir.sendQ).(Relatable), nil
		}
		ir.cache = append(ir.cache, interval)
	}
	// stream is done so we empty the cache by pushing onto the sendQ
	if len(ir.cache) > 0 {
		ir.cache, ir.nils = filter(ir.cache, ir.nils), 0
		for _, c := range ir.cache {
			if ir.relativeTo == -1 || int(c.Source()) == ir.relativeTo {
				heap.Push(ir.sendQ, c)
			}
		}
		ir.cache = ir.cache[:0]
	}
	// ... then we clear the sendQ
	if len(ir.sendQ.rels) > 0 {
		return heap.Pop(ir.sendQ).(Relatable), nil
	}
	return nil, io.EOF
}

type merger struct {
	less       func(a, b Relatable) bool
	relativeTo int
	streams    []RelatableIterator
	q          relatableQueue
	seen       map[string]struct{}
	j          int
	lastChrom  string
	verbose    bool
}

func newMerger(less func(a, b Relatable) bool, relativeTo int, streams ...RelatableIterator) *merger {
	q := relatableQueue{make([]Relatable, 0, len(streams)), less}
	verbose := os.Getenv("IRELATE_VERBOSE") == "TRUE"

	for i, stream := range streams {
		interval, err := stream.Next()
		if err != nil && err != io.EOF {
			panic(err)
		}
		if interval != nil {
			interval.SetSource(uint32(i))
			heap.Push(&q, interval)
		}
		if err == io.EOF {
			stream.Close()
		}
	}
	m := &merger{less: less, relativeTo: relativeTo, streams: streams, q: q, seen: make(map[string]struct{}), j: -1000, lastChrom: "", verbose: verbose}

	return m
}

func (m *merger) Close() error {
	return nil
}

func (m *merger) Next() (Relatable, error) {
	if len(m.q.rels) == 0 {
		return nil, io.EOF
	}
	interval := heap.Pop(&m.q).(Relatable)
	source := interval.Source()
	if !SameChrom(interval.Chrom(), m.lastChrom) {
		if m.verbose && m.lastChrom != "" {
			log.Printf("on chromosome: %s\n", m.lastChrom)
		}
		m.lastChrom = StripChr(interval.Chrom())
		if _, ok := m.seen[m.lastChrom]; ok {
			log.Println("warning: chromosomes must be in different order between files or the chromosome sort order is not as expected.")
			log.Printf("warning: overlaps will likely be missed after this chrom: %s from source: %d\n", m.lastChrom, interval.Source())
		}
		m.seen[m.lastChrom] = struct{}{}
	}
	// pull the next interval from the same source.
	next_interval, err := m.streams[source].Next()
	if err == nil {
		if next_interval.Start() < interval.Start() {
			if SameChrom(next_interval.Chrom(), interval.Chrom()) {
				panic(fmt.Sprintf("intervals out of order within file: starts at: %d and %d from source: %d", interval.Start(), next_interval.Start(), source))
			}
		}
		next_interval.SetSource(source)
		heap.Push(&m.q, next_interval)
		m.j--
		if m.j == 0 {
			return nil, io.EOF
		}
	} else {
		if int(source) == m.relativeTo {
			// we pull in 200K more records and then stop. to make sure we get anything that might
			// relate to last query
			m.j = 200000
		}
	}
	if err == io.EOF {
		m.streams[source].Close()
	}
	return interval, nil
}
<|endoftext|>


<commit_before>package common

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

	"github.com/oursky/ourd/oddb"
	"github.com/oursky/ourd/oddb/oddbconv"
)

// ExecError is error resulted from application logic of plugin (e.g.
// an exception thrown within a lambda function)
type ExecError struct {
	Name        string `json:"name"`
	Description string `json:"desc"`
}

func (err *ExecError) Error() string {
	return err.Name + "\n" + err.Description
}

// JSONRecord defines a common serialization format for oddb.Record
type JSONRecord oddb.Record

// MarshalJSON implements json.Marshaler
func (record *JSONRecord) MarshalJSON() ([]byte, error) {
	data := map[string]interface{}{}
	for key, value := range record.Data {
		switch v := value.(type) {
		case time.Time:
			data[key] = (oddbconv.MapTime)(v)
		case oddb.Asset:
			data[key] = (oddbconv.MapAsset)(v)
		case oddb.Reference:
			data[key] = (oddbconv.MapReference)(v)
		default:
			data[key] = value
		}
	}

	m := map[string]interface{}{}
	oddbconv.MapData(data).ToMap(m)

	m["_id"] = record.ID
	m["_ownerID"] = record.OwnerID
	m["_access"] = record.ACL

	return json.Marshal(m)
}

// UnmarshalJSON implements json.Unmarshaler
func (record *JSONRecord) UnmarshalJSON(data []byte) (err error) {
	m := map[string]interface{}{}
	if err := json.Unmarshal(data, &m); err != nil {
		return err
	}

	var (
		id      oddb.RecordID
		acl     oddb.RecordACL
		dataMap map[string]interface{}
	)

	extractor := newMapExtractor(m)
	extractor.DoString("_id", func(s string) error {
		return id.UnmarshalText([]byte(s))
	})
	extractor.DoSlice("_access", func(slice []interface{}) error {
		return acl.InitFromJSON(slice)
	})
	if extractor.Err() != nil {
		return extractor.Err()
	}

	m = sanitizedDataMap(m)
	if err := (*oddbconv.MapData)(&dataMap).FromMap(m); err != nil {
		return err
	}

	record.ID = id
	record.ACL = acl
	record.Data = dataMap
	return nil
}

func sanitizedDataMap(m map[string]interface{}) map[string]interface{} {
	mm := map[string]interface{}{}
	for key, value := range m {
		if key[0] != '_' {
			mm[key] = value
		}
	}
	return mm
}

// mapExtractor helps to extract value of a key from a map
//
// potential candicate of a package
type mapExtractor struct {
	m   map[string]interface{}
	err error
}

func newMapExtractor(m map[string]interface{}) *mapExtractor {
	return &mapExtractor{m: m}
}

// Do execute doFunc if key exists in the map
// The key will always be removed no matter error occurred previously
func (e *mapExtractor) Do(key string, doFunc func(interface{}) error) {
	value, ok := e.m[key]
	delete(e.m, key)

	if e.err != nil {
		return
	}

	if ok {
		e.err = doFunc(value)
		delete(e.m, key)
	} else {
		e.err = fmt.Errorf(`no key "%s" in map`, key)
	}
}

func (e *mapExtractor) DoString(key string, doFunc func(string) error) {
	e.Do(key, func(i interface{}) error {
		if m, ok := i.(string); ok {
			return doFunc(m)
		}
		return fmt.Errorf("key %s is of type %T, not string", key, i)
	})
}

func (e *mapExtractor) DoMap(key string, doFunc func(map[string]interface{}) error) {
	e.Do(key, func(i interface{}) error {
		if m, ok := i.(map[string]interface{}); ok {
			return doFunc(m)
		}
		return fmt.Errorf("key %s is of type %T, not map[string]interface{}", key, i)
	})
}

func (e *mapExtractor) DoSlice(key string, doFunc func([]interface{}) error) {
	e.Do(key, func(i interface{}) error {
		switch slice := i.(type) {
		case []interface{}:
			return doFunc(slice)
		case nil:
			return doFunc(nil)
		default:
			return fmt.Errorf("key %s is of type %T, not []interface{}", key, i)
		}
	})
}

func (e *mapExtractor) Err() error {
	return e.err
}
<commit_msg>Serialize Location when calling plugin<commit_after>package common

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

	"github.com/oursky/ourd/oddb"
	"github.com/oursky/ourd/oddb/oddbconv"
)

// ExecError is error resulted from application logic of plugin (e.g.
// an exception thrown within a lambda function)
type ExecError struct {
	Name        string `json:"name"`
	Description string `json:"desc"`
}

func (err *ExecError) Error() string {
	return err.Name + "\n" + err.Description
}

// JSONRecord defines a common serialization format for oddb.Record
type JSONRecord oddb.Record

// MarshalJSON implements json.Marshaler
func (record *JSONRecord) MarshalJSON() ([]byte, error) {
	data := map[string]interface{}{}
	for key, value := range record.Data {
		switch v := value.(type) {
		case time.Time:
			data[key] = (oddbconv.MapTime)(v)
		case oddb.Asset:
			data[key] = (oddbconv.MapAsset)(v)
		case oddb.Reference:
			data[key] = (oddbconv.MapReference)(v)
		case *oddb.Location:
			data[key] = (*oddbconv.MapLocation)(v)
		default:
			data[key] = value
		}
	}

	m := map[string]interface{}{}
	oddbconv.MapData(data).ToMap(m)

	m["_id"] = record.ID
	m["_ownerID"] = record.OwnerID
	m["_access"] = record.ACL

	return json.Marshal(m)
}

// UnmarshalJSON implements json.Unmarshaler
func (record *JSONRecord) UnmarshalJSON(data []byte) (err error) {
	m := map[string]interface{}{}
	if err := json.Unmarshal(data, &m); err != nil {
		return err
	}

	var (
		id      oddb.RecordID
		acl     oddb.RecordACL
		dataMap map[string]interface{}
	)

	extractor := newMapExtractor(m)
	extractor.DoString("_id", func(s string) error {
		return id.UnmarshalText([]byte(s))
	})
	extractor.DoSlice("_access", func(slice []interface{}) error {
		return acl.InitFromJSON(slice)
	})
	if extractor.Err() != nil {
		return extractor.Err()
	}

	m = sanitizedDataMap(m)
	if err := (*oddbconv.MapData)(&dataMap).FromMap(m); err != nil {
		return err
	}

	record.ID = id
	record.ACL = acl
	record.Data = dataMap
	return nil
}

func sanitizedDataMap(m map[string]interface{}) map[string]interface{} {
	mm := map[string]interface{}{}
	for key, value := range m {
		if key[0] != '_' {
			mm[key] = value
		}
	}
	return mm
}

// mapExtractor helps to extract value of a key from a map
//
// potential candicate of a package
type mapExtractor struct {
	m   map[string]interface{}
	err error
}

func newMapExtractor(m map[string]interface{}) *mapExtractor {
	return &mapExtractor{m: m}
}

// Do execute doFunc if key exists in the map
// The key will always be removed no matter error occurred previously
func (e *mapExtractor) Do(key string, doFunc func(interface{}) error) {
	value, ok := e.m[key]
	delete(e.m, key)

	if e.err != nil {
		return
	}

	if ok {
		e.err = doFunc(value)
		delete(e.m, key)
	} else {
		e.err = fmt.Errorf(`no key "%s" in map`, key)
	}
}

func (e *mapExtractor) DoString(key string, doFunc func(string) error) {
	e.Do(key, func(i interface{}) error {
		if m, ok := i.(string); ok {
			return doFunc(m)
		}
		return fmt.Errorf("key %s is of type %T, not string", key, i)
	})
}

func (e *mapExtractor) DoMap(key string, doFunc func(map[string]interface{}) error) {
	e.Do(key, func(i interface{}) error {
		if m, ok := i.(map[string]interface{}); ok {
			return doFunc(m)
		}
		return fmt.Errorf("key %s is of type %T, not map[string]interface{}", key, i)
	})
}

func (e *mapExtractor) DoSlice(key string, doFunc func([]interface{}) error) {
	e.Do(key, func(i interface{}) error {
		switch slice := i.(type) {
		case []interface{}:
			return doFunc(slice)
		case nil:
			return doFunc(nil)
		default:
			return fmt.Errorf("key %s is of type %T, not []interface{}", key, i)
		}
	})
}

func (e *mapExtractor) Err() error {
	return e.err
}
<|endoftext|>


<commit_before>package tumblr

import "testing"

func TestInfo(t *testing.T) {
	// TODO
}
<commit_msg>Working test for blog info<commit_after>package tumblr

import (
	"testing"
)

func TestInfo(t *testing.T) {
	c := makeTumblr()
	b := c.NewBlog("lacecard.tumblr.com")
	i, err := b.Info()
	if err != nil {
		t.Error(err)
		return
	}
	if i.Updated < 1 {
		t.Errorf("Blog marked as never updated (updated=%d)", i.Updated)
		return
	}
	if i.Likes < 1 {
		t.Errorf("Blog marked as having no likes (likes=%d)", i.Updated)
		return
	}
	if i.Name != "lacecard" {
		t.Errorf("Blog information gives wrong name (name=%s)", i.Name)
		return
	}
}
<|endoftext|>


<commit_before>package database

import (
	"errors"
	"testing"
	"time"

	sqlmock "github.com/DATA-DOG/go-sqlmock"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/decoders"
)

func TestNewMock(t *testing.T) {
	db, mock, err := NewMock()
	mock.ExpectClose()
	if err != nil {
		t.Fatalf("got NewMock() = _, %v, want = _, nil", err)
	}
	if err := db.Close(); err != nil {
		t.Fatalf("got db.Close() = %v, want = nil", err)
	}
}

func TestNew(t *testing.T) {
	if _, err := New(); err != nil {
		t.Fatalf("got New() = _, %v, want = _, nil", err)
	}
}

func TestSetMaxOpenConns(t *testing.T) {
	conn, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("got sqlmock.New() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectClose()
	db := DB{conn}

	db.SetMaxOpenConns(5)
	if err := db.Close(); err != nil {
		t.Fatalf("got db.Close() = %v, want = nil", err)
	}
}

func TestInsert(t *testing.T) {
	oldVerbosity := constants.Verbose
	constants.Verbose = true
	defer func() { constants.Verbose = oldVerbosity }()

	closureIndex := 0
	var iter = func() (*decoders.DataPoint, error) {
		if closureIndex >= 3 {
			return nil, nil
		}
		point := &decoders.DataPoint{
			Serial: 64,
			Type:   'T',
			Data:   int64(closureIndex),
			Time:   time.Unix(int64(500+closureIndex), 0),
		}
		closureIndex++
		return point, nil
	}

	conn, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("got sqlmock.New() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	query := "COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN"
	stmt := mock.ExpectPrepare(query)
	stmt.ExpectExec().WithArgs(64, "T", 0, time.Unix(500, 0), nil).WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 1, time.Unix(501, 0), nil).WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 2, time.Unix(502, 0), nil).WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectCommit()
	db := DB{conn}

	if err := db.Insert(iter); err != nil {
		t.Errorf("got db.Insert(iter) = %v, want = nil", err)
	}
}

func TestInsertBeginErr(t *testing.T) {
	conn, _, err := sqlmock.New()
	if err != nil {
		t.Fatalf("got sqlmock.New() = _, _, %v, want = _, _, nil", err)
	}
	db := DB{conn}

	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != "all expectations were already fulfilled, call to database transaction Begin was not expected" {
		t.Errorf("got db.Insert() = %v, want = nil", err)
	}
}

func TestInsertPrepareErr(t *testing.T) {
	conn, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("got sqlmock.New() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	mock.ExpectRollback()
	db := DB{conn}

	want := `call to Prepare stetement with query 'COPY "data_raw" ("serial", "type", "data", "time", "device") FROM STDIN', was not expected, next expectation is: ExpectedRollback => expecting transaction Rollback`
	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != want {
		t.Errorf("got db.Insert() = %v, want = %s", err, want)
	}
}

func TestInsertFlushErr(t *testing.T) {
	conn, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("got sqlmock.New() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	mock.ExpectPrepare("COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN")
	mock.ExpectRollback()
	db := DB{conn}

	want := `call to exec query 'COPY "data_raw" ("serial", "type", "data", "time", "device") FROM STDIN' with args [], was not expected, next expectation is: ExpectedRollback => expecting transaction Rollback`
	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != want {
		t.Errorf("got db.Insert() = %v, want = %s", err, want)
	}
}

func TestInsertCloseErr(t *testing.T) {
	conn, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("got sqlmock.New() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	want := errors.New("STMT ERROR")
	stmt := mock.ExpectPrepare("COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN").WillReturnCloseError(want)
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectRollback()
	db := DB{conn}

	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != want.Error() {
		// TODO: Figure out why this test doesn't work.
		// Disabled until issue is fixed:
		// https://github.com/DATA-DOG/go-sqlmock/issues/25
		//t.Errorf("got db.Insert() = %v, want = %v", err, want)
	}
}

func TestInsertErr(t *testing.T) {
	conn, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("got sqlmock.New() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	query := "COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN"
	stmt := mock.ExpectPrepare(query)
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectRollback()
	db := DB{conn}

	want := "call to exec query 'COPY \"data_raw\" (\"serial\", \"type\", \"data\", \"time\", \"device\") FROM STDIN' with args [0 \x00 0 0001-01-01 00:00:00 +0000 UTC <nil>], was not expected, next expectation is: ExpectedRollback => expecting transaction Rollback"
	if err := db.Insert(func() (*decoders.DataPoint, error) { return &decoders.DataPoint{}, nil }); err == nil || err.Error() != want {
		t.Errorf("got db.Insert(iter) = %v, want = %s", err, want)
	}
}
<commit_msg>Modified database_test.go to use NewMock()<commit_after>package database

import (
	"errors"
	"testing"
	"time"

	sqlmock "github.com/DATA-DOG/go-sqlmock"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/decoders"
)

func TestNewMock(t *testing.T) {
	db, mock, err := NewMock()
	mock.ExpectClose()
	if err != nil {
		t.Fatalf("got NewMock() = _, %v, want = _, nil", err)
	}
	if err := db.Close(); err != nil {
		t.Fatalf("got db.Close() = %v, want = nil", err)
	}
}

func TestNew(t *testing.T) {
	if _, err := New(); err != nil {
		t.Fatalf("got New() = _, %v, want = _, nil", err)
	}
}

func TestSetMaxOpenConns(t *testing.T) {
	db, mock, err := NewMock()
	if err != nil {
		t.Fatalf("got NewMock() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectClose()

	db.SetMaxOpenConns(5)
	if err := db.Close(); err != nil {
		t.Fatalf("got db.Close() = %v, want = nil", err)
	}
}

func TestInsert(t *testing.T) {
	oldVerbosity := constants.Verbose
	constants.Verbose = true
	defer func() { constants.Verbose = oldVerbosity }()

	closureIndex := 0
	var iter = func() (*decoders.DataPoint, error) {
		if closureIndex >= 3 {
			return nil, nil
		}
		point := &decoders.DataPoint{
			Serial: 64,
			Type:   'T',
			Data:   int64(closureIndex),
			Time:   time.Unix(int64(500+closureIndex), 0),
		}
		closureIndex++
		return point, nil
	}

	db, mock, err := NewMock()
	if err != nil {
		t.Fatalf("got NewMock() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	query := "COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN"
	stmt := mock.ExpectPrepare(query)
	stmt.ExpectExec().WithArgs(64, "T", 0, time.Unix(500, 0), nil).WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 1, time.Unix(501, 0), nil).WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 2, time.Unix(502, 0), nil).WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectCommit()

	if err := db.Insert(iter); err != nil {
		t.Errorf("got db.Insert(iter) = %v, want = nil", err)
	}
}

func TestInsertBeginErr(t *testing.T) {
	db, _, err := NewMock()
	if err != nil {
		t.Fatalf("got NewMock() = _, _, %v, want = _, _, nil", err)
	}

	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != "all expectations were already fulfilled, call to database transaction Begin was not expected" {
		t.Errorf("got db.Insert() = %v, want = nil", err)
	}
}

func TestInsertPrepareErr(t *testing.T) {
	db, mock, err := NewMock()
	if err != nil {
		t.Fatalf("got NewMock() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	mock.ExpectRollback()

	want := `call to Prepare stetement with query 'COPY "data_raw" ("serial", "type", "data", "time", "device") FROM STDIN', was not expected, next expectation is: ExpectedRollback => expecting transaction Rollback`
	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != want {
		t.Errorf("got db.Insert() = %v, want = %s", err, want)
	}
}

func TestInsertFlushErr(t *testing.T) {
	db, mock, err := NewMock()
	if err != nil {
		t.Fatalf("got NewMock() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	mock.ExpectPrepare("COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN")
	mock.ExpectRollback()

	want := `call to exec query 'COPY "data_raw" ("serial", "type", "data", "time", "device") FROM STDIN' with args [], was not expected, next expectation is: ExpectedRollback => expecting transaction Rollback`
	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != want {
		t.Errorf("got db.Insert() = %v, want = %s", err, want)
	}
}

func TestInsertCloseErr(t *testing.T) {
	db, mock, err := NewMock()
	if err != nil {
		t.Fatalf("got NewMock() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	want := errors.New("STMT ERROR")
	stmt := mock.ExpectPrepare("COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN").WillReturnCloseError(want)
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectRollback()

	if err := db.Insert(func() (*decoders.DataPoint, error) { return nil, nil }); err == nil || err.Error() != want.Error() {
		// TODO: Figure out why this test doesn't work.
		// Disabled until issue is fixed:
		// https://github.com/DATA-DOG/go-sqlmock/issues/25
		//t.Errorf("got db.Insert() = %v, want = %v", err, want)
	}
}

func TestInsertErr(t *testing.T) {
	db, mock, err := NewMock()
	if err != nil {
		t.Fatalf("got NewMock() = _, _, %v, want = _, _, nil", err)
	}
	mock.ExpectBegin()
	query := "COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN"
	stmt := mock.ExpectPrepare(query)
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectRollback()

	want := "call to exec query 'COPY \"data_raw\" (\"serial\", \"type\", \"data\", \"time\", \"device\") FROM STDIN' with args [0 \x00 0 0001-01-01 00:00:00 +0000 UTC <nil>], was not expected, next expectation is: ExpectedRollback => expecting transaction Rollback"
	if err := db.Insert(func() (*decoders.DataPoint, error) { return &decoders.DataPoint{}, nil }); err == nil || err.Error() != want {
		t.Errorf("got db.Insert(iter) = %v, want = %s", err, want)
	}
}
<|endoftext|>


<commit_before>package is

import "bytes"
import "github.com/bmizerany/assert"
import "testing"
import "time"
import "regexp"
import "unsafe"

func TestArray(t *testing.T) {
	assert.Equal(t, Array([...]int{1, 2, 3}), true)
	assert.Equal(t, Array(false), false)
	assert.Equal(t, Array("string"), false)
}

func TestBool(t *testing.T) {
	assert.Equal(t, Bool(true), true)
	assert.Equal(t, Bool(false), true)
	assert.Equal(t, Bool([...]int{1, 2, 3}), false)
	assert.Equal(t, Bool("string"), false)
}

func TestBuffer(t *testing.T) {
	var b bytes.Buffer
	assert.Equal(t, Buffer(b), true)
	assert.Equal(t, Buffer(false), false)
	assert.Equal(t, Buffer([...]int{1, 2, 3}), false)
	assert.Equal(t, Buffer("string"), false)
}

func TestByte(t *testing.T) {
	assert.Equal(t, Byte(byte(1)), true)
	assert.Equal(t, Byte(byte(127)), true)
	assert.Equal(t, Byte(false), false)
	assert.Equal(t, Byte([...]int{1, 2, 3}), false)
	assert.Equal(t, Byte("string"), false)
}

func TestChan(t *testing.T) {
	ic := make(chan int)
	assert.Equal(t, Chan(ic), true)
	assert.Equal(t, Chan([...]int{1, 2, 3}), false)
	assert.Equal(t, Chan("string"), false)
}

func TestComplex64(t *testing.T) {
	assert.Equal(t, Complex64(complex64(0.1)), true)
	assert.Equal(t, Complex64(complex64(5.1)), true)
	assert.Equal(t, Complex64(false), false)
	assert.Equal(t, Complex64([...]int{1, 2, 3}), false)
	assert.Equal(t, Complex64("string"), false)
}

func TestComplex128(t *testing.T) {
	assert.Equal(t, Complex128(complex128(0.1)), true)
	assert.Equal(t, Complex128(complex128(5.1)), true)
	assert.Equal(t, Complex128(false), false)
	assert.Equal(t, Complex128([...]int{1, 2, 3}), false)
	assert.Equal(t, Complex128("string"), false)
}

func TestFloat32(t *testing.T) {
	assert.Equal(t, Float32(float32(0.1)), true)
	assert.Equal(t, Float32(float32(5.1)), true)
	assert.Equal(t, Float32(false), false)
	assert.Equal(t, Float32([...]int{1, 2, 3}), false)
	assert.Equal(t, Float32("string"), false)
}

func TestFloat64(t *testing.T) {
	assert.Equal(t, Float64(float64(0.1)), true)
	assert.Equal(t, Float64(float64(5.1)), true)
	assert.Equal(t, Float64(false), false)
	assert.Equal(t, Float64([...]int{1, 2, 3}), false)
	assert.Equal(t, Float64("string"), false)
}

func FuncTest() {}

func TestFunc(t *testing.T) {
	assert.Equal(t, Func(FuncTest), true)
	assert.Equal(t, Func(false), false)
	assert.Equal(t, Func([...]int{1, 2, 3}), false)
	assert.Equal(t, Func("string"), false)
}

func TestInt(t *testing.T) {
	assert.Equal(t, Int(1), true)
	assert.Equal(t, Int(100), true)
	assert.Equal(t, Int(false), false)
	assert.Equal(t, Int([...]int{1, 2, 3}), false)
	assert.Equal(t, Int("string"), false)
}

func TestInt8(t *testing.T) {
	assert.Equal(t, Int8(int8(1)), true)
	assert.Equal(t, Int8(int8(127)), true)
	assert.Equal(t, Int8(false), false)
	assert.Equal(t, Int8([...]int{1, 2, 3}), false)
	assert.Equal(t, Int8("string"), false)
}

func TestInt16(t *testing.T) {
	assert.Equal(t, Int16(int16(1)), true)
	assert.Equal(t, Int16(int16(32767)), true)
	assert.Equal(t, Int16(false), false)
	assert.Equal(t, Int16([...]int{1, 2, 3}), false)
	assert.Equal(t, Int16("string"), false)
}

func TestInt32(t *testing.T) {
	assert.Equal(t, Int32(int32(1)), true)
	assert.Equal(t, Int32(int32(1032767)), true)
	assert.Equal(t, Int32(1), false)
	assert.Equal(t, Int32(false), false)
	assert.Equal(t, Int32([...]int{1, 2, 3}), false)
	assert.Equal(t, Int32("string"), false)
}

func TestInt64(t *testing.T) {
	assert.Equal(t, Int64(int64(1)), true)
	assert.Equal(t, Int64(int64(1000032767)), true)
	assert.Equal(t, Int64(false), false)
	assert.Equal(t, Int64([...]int{1, 2, 3}), false)
	assert.Equal(t, Int64("string"), false)
}

func TestInterface(t *testing.T) {
	assert.Equal(t, Interface(false), false)
	assert.Equal(t, Interface([...]int{1, 2, 3}), false)
	assert.Equal(t, Interface("string"), false)
}

func TestMap(t *testing.T) {
	var names map[string]int = make(map[string]int)
	assert.Equal(t, Map(names), true)
	assert.Equal(t, Map(false), false)
	assert.Equal(t, Map([...]int{1, 2, 3}), false)
	assert.Equal(t, Map("string"), false)
}

func TestNil(t *testing.T) {
	assert.Equal(t, Nil(nil), true)
	assert.Equal(t, Nil(false), false)
	assert.Equal(t, Nil([...]int{1, 2, 3}), false)
	assert.Equal(t, Nil("string"), false)
}

func TestOfStructType(t *testing.T) {
	assert.Equal(t, OfStructType(time.Now(), "time.Time"), true)
	assert.Equal(t, OfStructType("string", "string"), true)
	assert.Equal(t, OfStructType(false, "bool"), true)
	assert.Equal(t, OfStructType(false, "false"), false)
	assert.Equal(t, OfStructType([...]int{1, 2, 3}, "array"), false)
}

func TestRune(t *testing.T) {
	assert.Equal(t, Rune(rune(1)), true)
	assert.Equal(t, Rune(rune(1032767)), true)
	assert.Equal(t, Rune(1), false)
	assert.Equal(t, Rune(false), false)
	assert.Equal(t, Rune([...]int{1, 2, 3}), false)
	assert.Equal(t, Rune("string"), false)
}

func TestPtr(t *testing.T) {
	i := 0
	assert.Equal(t, Ptr(&i), true)
	assert.Equal(t, Ptr(false), false)
	assert.Equal(t, Ptr([...]int{1, 2, 3}), false)
	assert.Equal(t, Ptr("string"), false)
}

func TestRegexp(t *testing.T) {
	r, _ := regexp.Compile("p([a-z]+)ch")
	assert.Equal(t, Regexp(r), true)
	assert.Equal(t, Regexp(false), false)
	assert.Equal(t, Regexp([...]int{1, 2, 3}), false)
	assert.Equal(t, Regexp("string"), false)
}

func TestSlice(t *testing.T) {
	s := make([]string, 3)
	assert.Equal(t, Slice(s), true)
	assert.Equal(t, Slice(false), false)
	assert.Equal(t, Slice([...]int{1, 2, 3}), false)
	assert.Equal(t, Slice("string"), false)
}

func TestString(t *testing.T) {
	s := make([]string, 3)
	assert.Equal(t, String("hello"), true)
	assert.Equal(t, String(false), false)
	assert.Equal(t, String([...]int{1, 2, 3}), false)
	assert.Equal(t, String(s), false)
}

type person struct {
	name string
	age  int
}

func TestStruct(t *testing.T) {
	assert.Equal(t, Struct(person{"Bob", 20}), true)
	assert.Equal(t, Struct(false), false)
	assert.Equal(t, Struct([...]int{1, 2, 3}), false)
	assert.Equal(t, Struct("string"), false)
}

func TestTime(t *testing.T) {
	assert.Equal(t, Time(time.Now()), true)
	assert.Equal(t, Time(time.Now().UTC()), true)
	assert.Equal(t, Time(false), false)
	assert.Equal(t, Time([...]int{1, 2, 3}), false)
	assert.Equal(t, Time("string"), false)
}

func TestUint(t *testing.T) {
	assert.Equal(t, Uint(uint(1)), true)
	assert.Equal(t, Uint(uint(100)), true)
	assert.Equal(t, Uint(false), false)
	assert.Equal(t, Uint([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint("string"), false)
}

func TestUint8(t *testing.T) {
	assert.Equal(t, Uint8(uint8(1)), true)
	assert.Equal(t, Uint8(uint8(127)), true)
	assert.Equal(t, Uint8(false), false)
	assert.Equal(t, Uint8([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint8("string"), false)
}

func TestUint16(t *testing.T) {
	assert.Equal(t, Uint16(uint16(1)), true)
	assert.Equal(t, Uint16(uint16(1000)), true)
	assert.Equal(t, Uint16(false), false)
	assert.Equal(t, Uint16([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint16("string"), false)
}

func TestUint32(t *testing.T) {
	assert.Equal(t, Uint32(uint32(1)), true)
	assert.Equal(t, Uint32(uint32(105000)), true)
	assert.Equal(t, Uint32(false), false)
	assert.Equal(t, Uint32([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint32("string"), false)
}

func TestUint64(t *testing.T) {
	assert.Equal(t, Uint64(uint64(1)), true)
	assert.Equal(t, Uint64(uint64(100000000)), true)
	assert.Equal(t, Uint64(false), false)
	assert.Equal(t, Uint64([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint64("string"), false)
}

func TestUintptr(t *testing.T) {
	assert.Equal(t, Uintptr(uintptr(1)), true)
	assert.Equal(t, Uintptr(uintptr(100000000)), true)
	assert.Equal(t, Uintptr(false), false)
	assert.Equal(t, Uintptr([...]int{1, 2, 3}), false)
	assert.Equal(t, Uintptr("string"), false)
}

func TestUnsafePointer(t *testing.T) {
	n := 4
	m := make([]int, n)
	assert.Equal(t, UnsafePointer(unsafe.Pointer(&m)), true)
	assert.Equal(t, UnsafePointer(false), false)
	assert.Equal(t, UnsafePointer([...]int{1, 2, 3}), false)
	assert.Equal(t, UnsafePointer("string"), false)
}
<commit_msg>Change to frozzare/go-assert<commit_after>package is

import (
	"bytes"
	"regexp"
	"testing"
	"time"
	"unsafe"

	"github.com/frozzare/go-assert"
)

func TestArray(t *testing.T) {
	assert.Equal(t, Array([...]int{1, 2, 3}), true)
	assert.Equal(t, Array(false), false)
	assert.Equal(t, Array("string"), false)
}

func TestBool(t *testing.T) {
	assert.Equal(t, Bool(true), true)
	assert.Equal(t, Bool(false), true)
	assert.Equal(t, Bool([...]int{1, 2, 3}), false)
	assert.Equal(t, Bool("string"), false)
}

func TestBuffer(t *testing.T) {
	var b bytes.Buffer
	assert.Equal(t, Buffer(b), true)
	assert.Equal(t, Buffer(false), false)
	assert.Equal(t, Buffer([...]int{1, 2, 3}), false)
	assert.Equal(t, Buffer("string"), false)
}

func TestByte(t *testing.T) {
	assert.Equal(t, Byte(byte(1)), true)
	assert.Equal(t, Byte(byte(127)), true)
	assert.Equal(t, Byte(false), false)
	assert.Equal(t, Byte([...]int{1, 2, 3}), false)
	assert.Equal(t, Byte("string"), false)
}

func TestChan(t *testing.T) {
	ic := make(chan int)
	assert.Equal(t, Chan(ic), true)
	assert.Equal(t, Chan([...]int{1, 2, 3}), false)
	assert.Equal(t, Chan("string"), false)
}

func TestComplex64(t *testing.T) {
	assert.Equal(t, Complex64(complex64(0.1)), true)
	assert.Equal(t, Complex64(complex64(5.1)), true)
	assert.Equal(t, Complex64(false), false)
	assert.Equal(t, Complex64([...]int{1, 2, 3}), false)
	assert.Equal(t, Complex64("string"), false)
}

func TestComplex128(t *testing.T) {
	assert.Equal(t, Complex128(complex128(0.1)), true)
	assert.Equal(t, Complex128(complex128(5.1)), true)
	assert.Equal(t, Complex128(false), false)
	assert.Equal(t, Complex128([...]int{1, 2, 3}), false)
	assert.Equal(t, Complex128("string"), false)
}

func TestFloat32(t *testing.T) {
	assert.Equal(t, Float32(float32(0.1)), true)
	assert.Equal(t, Float32(float32(5.1)), true)
	assert.Equal(t, Float32(false), false)
	assert.Equal(t, Float32([...]int{1, 2, 3}), false)
	assert.Equal(t, Float32("string"), false)
}

func TestFloat64(t *testing.T) {
	assert.Equal(t, Float64(float64(0.1)), true)
	assert.Equal(t, Float64(float64(5.1)), true)
	assert.Equal(t, Float64(false), false)
	assert.Equal(t, Float64([...]int{1, 2, 3}), false)
	assert.Equal(t, Float64("string"), false)
}

func FuncTest() {}

func TestFunc(t *testing.T) {
	assert.Equal(t, Func(FuncTest), true)
	assert.Equal(t, Func(false), false)
	assert.Equal(t, Func([...]int{1, 2, 3}), false)
	assert.Equal(t, Func("string"), false)
}

func TestInt(t *testing.T) {
	assert.Equal(t, Int(1), true)
	assert.Equal(t, Int(100), true)
	assert.Equal(t, Int(false), false)
	assert.Equal(t, Int([...]int{1, 2, 3}), false)
	assert.Equal(t, Int("string"), false)
}

func TestInt8(t *testing.T) {
	assert.Equal(t, Int8(int8(1)), true)
	assert.Equal(t, Int8(int8(127)), true)
	assert.Equal(t, Int8(false), false)
	assert.Equal(t, Int8([...]int{1, 2, 3}), false)
	assert.Equal(t, Int8("string"), false)
}

func TestInt16(t *testing.T) {
	assert.Equal(t, Int16(int16(1)), true)
	assert.Equal(t, Int16(int16(32767)), true)
	assert.Equal(t, Int16(false), false)
	assert.Equal(t, Int16([...]int{1, 2, 3}), false)
	assert.Equal(t, Int16("string"), false)
}

func TestInt32(t *testing.T) {
	assert.Equal(t, Int32(int32(1)), true)
	assert.Equal(t, Int32(int32(1032767)), true)
	assert.Equal(t, Int32(1), false)
	assert.Equal(t, Int32(false), false)
	assert.Equal(t, Int32([...]int{1, 2, 3}), false)
	assert.Equal(t, Int32("string"), false)
}

func TestInt64(t *testing.T) {
	assert.Equal(t, Int64(int64(1)), true)
	assert.Equal(t, Int64(int64(1000032767)), true)
	assert.Equal(t, Int64(false), false)
	assert.Equal(t, Int64([...]int{1, 2, 3}), false)
	assert.Equal(t, Int64("string"), false)
}

func TestInterface(t *testing.T) {
	assert.Equal(t, Interface(false), false)
	assert.Equal(t, Interface([...]int{1, 2, 3}), false)
	assert.Equal(t, Interface("string"), false)
}

func TestMap(t *testing.T) {
	names := map[string]int{}
	assert.Equal(t, Map(names), true)
	assert.Equal(t, Map(false), false)
	assert.Equal(t, Map([...]int{1, 2, 3}), false)
	assert.Equal(t, Map("string"), false)
}

func TestNil(t *testing.T) {
	assert.Equal(t, Nil(nil), true)
	assert.Equal(t, Nil(false), false)
	assert.Equal(t, Nil([...]int{1, 2, 3}), false)
	assert.Equal(t, Nil("string"), false)
}

func TestOfStructType(t *testing.T) {
	assert.Equal(t, OfStructType(time.Now(), "time.Time"), true)
	assert.Equal(t, OfStructType("string", "string"), true)
	assert.Equal(t, OfStructType(false, "bool"), true)
	assert.Equal(t, OfStructType(false, "false"), false)
	assert.Equal(t, OfStructType([...]int{1, 2, 3}, "array"), false)
}

func TestRune(t *testing.T) {
	assert.Equal(t, Rune(rune(1)), true)
	assert.Equal(t, Rune(rune(1032767)), true)
	assert.Equal(t, Rune(1), false)
	assert.Equal(t, Rune(false), false)
	assert.Equal(t, Rune([...]int{1, 2, 3}), false)
	assert.Equal(t, Rune("string"), false)
}

func TestPtr(t *testing.T) {
	i := 0
	assert.Equal(t, Ptr(&i), true)
	assert.Equal(t, Ptr(false), false)
	assert.Equal(t, Ptr([...]int{1, 2, 3}), false)
	assert.Equal(t, Ptr("string"), false)
}

func TestRegexp(t *testing.T) {
	r, _ := regexp.Compile("p([a-z]+)ch")
	assert.Equal(t, Regexp(r), true)
	assert.Equal(t, Regexp(false), false)
	assert.Equal(t, Regexp([...]int{1, 2, 3}), false)
	assert.Equal(t, Regexp("string"), false)
}

func TestSlice(t *testing.T) {
	s := make([]string, 3)
	assert.Equal(t, Slice(s), true)
	assert.Equal(t, Slice(false), false)
	assert.Equal(t, Slice([...]int{1, 2, 3}), false)
	assert.Equal(t, Slice("string"), false)
}

func TestString(t *testing.T) {
	s := make([]string, 3)
	assert.Equal(t, String("hello"), true)
	assert.Equal(t, String(false), false)
	assert.Equal(t, String([...]int{1, 2, 3}), false)
	assert.Equal(t, String(s), false)
}

type person struct {
	name string
	age  int
}

func TestStruct(t *testing.T) {
	assert.Equal(t, Struct(person{"Bob", 20}), true)
	assert.Equal(t, Struct(false), false)
	assert.Equal(t, Struct([...]int{1, 2, 3}), false)
	assert.Equal(t, Struct("string"), false)
}

func TestTime(t *testing.T) {
	assert.Equal(t, Time(time.Now()), true)
	assert.Equal(t, Time(time.Now().UTC()), true)
	assert.Equal(t, Time(false), false)
	assert.Equal(t, Time([...]int{1, 2, 3}), false)
	assert.Equal(t, Time("string"), false)
}

func TestUint(t *testing.T) {
	assert.Equal(t, Uint(uint(1)), true)
	assert.Equal(t, Uint(uint(100)), true)
	assert.Equal(t, Uint(false), false)
	assert.Equal(t, Uint([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint("string"), false)
}

func TestUint8(t *testing.T) {
	assert.Equal(t, Uint8(uint8(1)), true)
	assert.Equal(t, Uint8(uint8(127)), true)
	assert.Equal(t, Uint8(false), false)
	assert.Equal(t, Uint8([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint8("string"), false)
}

func TestUint16(t *testing.T) {
	assert.Equal(t, Uint16(uint16(1)), true)
	assert.Equal(t, Uint16(uint16(1000)), true)
	assert.Equal(t, Uint16(false), false)
	assert.Equal(t, Uint16([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint16("string"), false)
}

func TestUint32(t *testing.T) {
	assert.Equal(t, Uint32(uint32(1)), true)
	assert.Equal(t, Uint32(uint32(105000)), true)
	assert.Equal(t, Uint32(false), false)
	assert.Equal(t, Uint32([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint32("string"), false)
}

func TestUint64(t *testing.T) {
	assert.Equal(t, Uint64(uint64(1)), true)
	assert.Equal(t, Uint64(uint64(100000000)), true)
	assert.Equal(t, Uint64(false), false)
	assert.Equal(t, Uint64([...]int{1, 2, 3}), false)
	assert.Equal(t, Uint64("string"), false)
}

func TestUintptr(t *testing.T) {
	assert.Equal(t, Uintptr(uintptr(1)), true)
	assert.Equal(t, Uintptr(uintptr(100000000)), true)
	assert.Equal(t, Uintptr(false), false)
	assert.Equal(t, Uintptr([...]int{1, 2, 3}), false)
	assert.Equal(t, Uintptr("string"), false)
}

func TestUnsafePointer(t *testing.T) {
	n := 4
	m := make([]int, n)
	assert.Equal(t, UnsafePointer(unsafe.Pointer(&m)), true)
	assert.Equal(t, UnsafePointer(false), false)
	assert.Equal(t, UnsafePointer([...]int{1, 2, 3}), false)
	assert.Equal(t, UnsafePointer("string"), false)
}
<|endoftext|>


<commit_before>package couchbase

import (
	"bytes"
	"fmt"
	cb "github.com/couchbaselabs/go-couchbase"
	"github.com/couchbaselabs/indexing/api"
	"github.com/couchbaselabs/tuqtng/ast"
	"github.com/couchbaselabs/tuqtng/catalog"
	"hash/crc32"
	"strconv"
	"strings"
)

type ddocJSON struct {
	cb.DDocJSON
	IndexOn       string `json:"indexOn"`
	IndexChecksum int    `json:"indexChecksum"`
}

func newViewIndex(name string, on catalog.IndexKey, bkt *bucket) (*viewIndex, error) {

	doc, err := newDesignDoc(name, on)
	if err != nil {
		return nil, err
	}

	inst := viewIndex{
		name:   name,
		using:  catalog.VIEW,
		on:     on,
		ddoc:   doc,
		bucket: bkt,
	}

	err = inst.putDesignDoc()
	if err != nil {
		return nil, err
	}

	return &inst, nil
}

func newDesignDoc(idxname string, on catalog.IndexKey) (*designdoc, error) {
	var doc designdoc

	doc.name = "ddl_" + idxname
	doc.viewname = "autogen"

	err := generateMap(on, &doc)
	if err != nil {
		return nil, err
	}

	err = generateReduce(on, &doc)
	if err != nil {
		return nil, err
	}

	return &doc, nil
}

func newPrimaryIndex(b *bucket, ddname string, view string) (*primaryIndex, error) {
	meta := ast.NewFunctionCall("meta", ast.FunctionArgExpressionList{})
	mdid := ast.NewDotMemberOperator(meta, ast.NewProperty("id"))
	name := "#primary"
	ddoc := designdoc{name: ddname, viewname: view}
	idx := primaryIndex{
		viewIndex{
			name:   name,
			using:  catalog.PRIMARY,
			on:     catalog.IndexKey{mdid},
			ddoc:   &ddoc,
			bucket: b,
		},
	}
	return &idx, nil
}

func generateMap(on catalog.IndexKey, doc *designdoc) error {

	buf := new(bytes.Buffer)

	fmt.Fprintln(buf, templStart)
	fmt.Fprintln(buf, templFunctions)

	keylist := new(bytes.Buffer)
	for idx, expr := range on {

		walker := NewWalker()
		_, err := walker.Visit(expr)
		if err != nil {
			return err
		}

		jvar := fmt.Sprintf("key%v", idx+1)
		line := strings.Replace(templExpr, "$var", jvar, -1)
		line = strings.Replace(line, "$path", walker.JS(), -1)
		fmt.Fprint(buf, line)

		if idx > 0 {
			fmt.Fprint(keylist, ", ")
		}
		fmt.Fprint(keylist, jvar)
	}

	line := strings.Replace(templKey, "$keylist", keylist.String(), -1)
	line = strings.Replace(line, "$null", strconv.Itoa(TYPE_NULL), -1)
	line = strings.Replace(line, "boolean", strconv.Itoa(TYPE_BOOLEAN), -1)
	line = strings.Replace(line, "$number", strconv.Itoa(TYPE_NUMBER), -1)
	line = strings.Replace(line, "$string", strconv.Itoa(TYPE_STRING), -1)
	line = strings.Replace(line, "$array", strconv.Itoa(TYPE_ARRAY), -1)
	line = strings.Replace(line, "$object", strconv.Itoa(TYPE_OBJECT), -1)

	fmt.Fprint(buf, line)
	fmt.Fprint(buf, templEmit)
	fmt.Fprint(buf, templEnd)
	doc.mapfn = buf.String()

	return nil
}

func generateReduce(on catalog.IndexKey, doc *designdoc) error {
	doc.reducefn = ""
	return nil
}

func (idx *viewIndex) putDesignDoc() error {
	var view cb.ViewDefinition
	view.Map = idx.ddoc.mapfn

	var put ddocJSON
	put.Views = make(map[string]cb.ViewDefinition)
	put.Views[idx.name] = view
	put.IndexChecksum = checksum(idx.ddoc)

	if err := idx.bucket.cbbucket.PutDDoc(idx.DDocName(), &put); err != nil {
		return err
	}

	err := idx.checkDesignDoc()
	if err != nil {
		return api.DDocCreateFailed
	}

	return nil
}

func checksum(ddoc *designdoc) int {
	mapSum := crc32.ChecksumIEEE([]byte(ddoc.mapfn))
	reduceSum := crc32.ChecksumIEEE([]byte(ddoc.reducefn))
	return int(mapSum + reduceSum)
}

func (idx *viewIndex) checkDesignDoc() error {
	var ddoc ddocJSON

	if err := idx.bucket.cbbucket.GetDDoc(idx.DDocName(), &ddoc); err != nil {
		return err
	}

	if ddoc.IndexChecksum != checksum(idx.ddoc) {
		return api.DDocChanged
	}

	return nil
}

func (idx *viewIndex) DropViewIndex() error {
	if err := idx.bucket.cbbucket.DeleteDDoc(idx.DDocName()); err != nil {
		return err
	}
	return nil
}

// AST to JS conversion
type JsStatement struct {
	js bytes.Buffer
}

func NewWalker() *JsStatement {
	var js JsStatement
	return &js
}

func (this *JsStatement) JS() string {
	return this.js.String()
}

// inorder traversal of the AST to get JS expression out of it
func (this *JsStatement) Visit(e ast.Expression) (ast.Expression, error) {
	switch expr := e.(type) {

	case *ast.DotMemberOperator:
		if this.js.Len() == 0 {
			this.js.WriteString("doc.")
		}
		_, err := expr.Left.Accept(this)
		if err != nil {
			return nil, err
		}
		this.js.WriteString(".")
		_, err = expr.Right.Accept(this)
		if err != nil {
			return nil, err
		}

	case *ast.BracketMemberOperator:
		if this.js.Len() == 0 {
			this.js.WriteString("doc.")
		}
		_, err := expr.Left.Accept(this)
		if err != nil {
			return nil, err
		}
		this.js.WriteString("[")
		_, err = expr.Right.Accept(this)
		if err != nil {
			return nil, err
		}
		this.js.WriteString("]")

	case *ast.Property:
		if this.js.Len() == 0 {
			this.js.WriteString("doc.")
		}
		this.js.WriteString(expr.Path)

	case *ast.LiteralNumber:
		this.js.WriteString(fmt.Sprintf("%v", expr.Val))

	case *ast.LiteralString:
		this.js.WriteString(expr.Val)

	default:
		return e, api.ExprNotSupported

	}
	return e, nil
}
<commit_msg>fix some bugs in view building<commit_after>package couchbase

import (
	"bytes"
	"fmt"
	cb "github.com/couchbaselabs/go-couchbase"
	"github.com/couchbaselabs/indexing/api"
	"github.com/couchbaselabs/tuqtng/ast"
	"github.com/couchbaselabs/tuqtng/catalog"
	"hash/crc32"
	"strconv"
	"strings"
)

type ddocJSON struct {
	cb.DDocJSON
	IndexOn       string `json:"indexOn"`
	IndexChecksum int    `json:"indexChecksum"`
}

func newViewIndex(name string, on catalog.IndexKey, bkt *bucket) (*viewIndex, error) {

	doc, err := newDesignDoc(name, on)
	if err != nil {
		return nil, err
	}

	inst := viewIndex{
		name:   name,
		using:  catalog.VIEW,
		on:     on,
		ddoc:   doc,
		bucket: bkt,
	}

	err = inst.putDesignDoc()
	if err != nil {
		return nil, err
	}

	return &inst, nil
}

func newDesignDoc(idxname string, on catalog.IndexKey) (*designdoc, error) {
	var doc designdoc

	doc.name = "ddl_" + idxname
	doc.viewname = idxname

	err := generateMap(on, &doc)
	if err != nil {
		return nil, err
	}

	err = generateReduce(on, &doc)
	if err != nil {
		return nil, err
	}

	return &doc, nil
}

func newPrimaryIndex(b *bucket, ddname string, view string) (*primaryIndex, error) {
	meta := ast.NewFunctionCall("meta", ast.FunctionArgExpressionList{})
	mdid := ast.NewDotMemberOperator(meta, ast.NewProperty("id"))
	name := "#primary"
	ddoc := designdoc{name: ddname, viewname: view}
	idx := primaryIndex{
		viewIndex{
			name:   name,
			using:  catalog.PRIMARY,
			on:     catalog.IndexKey{mdid},
			ddoc:   &ddoc,
			bucket: b,
		},
	}
	return &idx, nil
}

func generateMap(on catalog.IndexKey, doc *designdoc) error {

	buf := new(bytes.Buffer)

	fmt.Fprintln(buf, templStart)
	line := strings.Replace(templFunctions, "$null", strconv.Itoa(TYPE_NULL), -1)
	line = strings.Replace(line, "$boolean", strconv.Itoa(TYPE_BOOLEAN), -1)
	line = strings.Replace(line, "$number", strconv.Itoa(TYPE_NUMBER), -1)
	line = strings.Replace(line, "$string", strconv.Itoa(TYPE_STRING), -1)
	line = strings.Replace(line, "$array", strconv.Itoa(TYPE_ARRAY), -1)
	line = strings.Replace(line, "$object", strconv.Itoa(TYPE_OBJECT), -1)
	fmt.Fprintln(buf, line)

	keylist := new(bytes.Buffer)
	for idx, expr := range on {

		walker := NewWalker()
		_, err := walker.Visit(expr)
		if err != nil {
			return err
		}

		jvar := fmt.Sprintf("key%v", idx+1)
		line := strings.Replace(templExpr, "$var", jvar, -1)
		line = strings.Replace(line, "$path", walker.JS(), -1)
		fmt.Fprint(buf, line)

		if idx > 0 {
			fmt.Fprint(keylist, ", ")
		}
		fmt.Fprint(keylist, jvar)
	}

	line = strings.Replace(templKey, "$keylist", keylist.String(), -1)

	fmt.Fprint(buf, line)
	fmt.Fprint(buf, templEmit)
	fmt.Fprint(buf, templEnd)
	doc.mapfn = buf.String()

	return nil
}

func generateReduce(on catalog.IndexKey, doc *designdoc) error {
	doc.reducefn = ""
	return nil
}

func (idx *viewIndex) putDesignDoc() error {
	var view cb.ViewDefinition
	view.Map = idx.ddoc.mapfn

	var put ddocJSON
	put.Views = make(map[string]cb.ViewDefinition)
	put.Views[idx.name] = view
	put.IndexChecksum = checksum(idx.ddoc)

	if err := idx.bucket.cbbucket.PutDDoc(idx.DDocName(), &put); err != nil {
		return err
	}

	err := idx.checkDesignDoc()
	if err != nil {
		return api.DDocCreateFailed
	}

	return nil
}

func checksum(ddoc *designdoc) int {
	mapSum := crc32.ChecksumIEEE([]byte(ddoc.mapfn))
	reduceSum := crc32.ChecksumIEEE([]byte(ddoc.reducefn))
	return int(mapSum + reduceSum)
}

func (idx *viewIndex) checkDesignDoc() error {
	var ddoc ddocJSON

	if err := idx.bucket.cbbucket.GetDDoc(idx.DDocName(), &ddoc); err != nil {
		return err
	}

	if ddoc.IndexChecksum != checksum(idx.ddoc) {
		return api.DDocChanged
	}

	return nil
}

func (idx *viewIndex) DropViewIndex() error {
	if err := idx.bucket.cbbucket.DeleteDDoc(idx.DDocName()); err != nil {
		return err
	}
	return nil
}

// AST to JS conversion
type JsStatement struct {
	js bytes.Buffer
}

func NewWalker() *JsStatement {
	var js JsStatement
	return &js
}

func (this *JsStatement) JS() string {
	return this.js.String()
}

// inorder traversal of the AST to get JS expression out of it
func (this *JsStatement) Visit(e ast.Expression) (ast.Expression, error) {
	switch expr := e.(type) {

	case *ast.DotMemberOperator:
		if this.js.Len() == 0 {
			this.js.WriteString("doc.")
		}
		_, err := expr.Left.Accept(this)
		if err != nil {
			return nil, err
		}
		this.js.WriteString(".")
		_, err = expr.Right.Accept(this)
		if err != nil {
			return nil, err
		}

	case *ast.BracketMemberOperator:
		if this.js.Len() == 0 {
			this.js.WriteString("doc.")
		}
		_, err := expr.Left.Accept(this)
		if err != nil {
			return nil, err
		}
		this.js.WriteString("[")
		_, err = expr.Right.Accept(this)
		if err != nil {
			return nil, err
		}
		this.js.WriteString("]")

	case *ast.Property:
		if this.js.Len() == 0 {
			this.js.WriteString("doc.")
		}
		this.js.WriteString(expr.Path)

	case *ast.LiteralNumber:
		this.js.WriteString(fmt.Sprintf("%v", expr.Val))

	case *ast.LiteralString:
		this.js.WriteString(expr.Val)

	default:
		return e, api.ExprNotSupported

	}
	return e, nil
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	pkgApi "k8s.io/apimachinery/pkg/types"
	"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
	kubernetes "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

func resourceKubernetesDeployment() *schema.Resource {
	return &schema.Resource{
		Create: resourceKubernetesDeploymentCreate,
		Read:   resourceKubernetesDeploymentRead,
		Exists: resourceKubernetesDeploymentExists,
		Update: resourceKubernetesDeploymentUpdate,
		Delete: resourceKubernetesDeploymentDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(10 * time.Minute),
			Update: schema.DefaultTimeout(10 * time.Minute),
			Delete: schema.DefaultTimeout(10 * time.Minute),
		},

		Schema: map[string]*schema.Schema{
			"metadata": namespacedMetadataSchema("deployment", true),
			"spec": {
				Type:        schema.TypeList,
				Description: "Spec defines the specification of the desired behavior of the deployment. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status",
				Required:    true,
				MaxItems:    1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"min_ready_seconds": {
							Type:        schema.TypeInt,
							Description: "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)",
							Optional:    true,
							Default:     0,
						},
						"replicas": {
							Type:        schema.TypeInt,
							Description: "The number of desired replicas. Defaults to 1. More info: http://kubernetes.io/docs/user-guide/replication-controller#what-is-a-replication-controller",
							Optional:    true,
							Default:     1,
						},
						"selector": {
							Type:        schema.TypeMap,
							Description: "A label query over pods that should match the Replicas count. If Selector is empty, it is defaulted to the labels present on the Pod template. Label keys and values that must match in order to be controlled by this deployment, if empty defaulted to labels on Pod template. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors",
							Required:    true,
						},
						//todo: strategy not working yet
						"strategy": {
							Type:        schema.TypeMap,
							Optional:    true,
							Computed:    true,
							Description: "Update strategy. One of RollingUpdate, Destroy. Defaults to RollingDate",
						},
						"template": {
							Type:        schema.TypeList,
							Description: "Describes the pod that will be created if insufficient replicas are detected. This takes precedence over a TemplateRef. More info: http://kubernetes.io/docs/user-guide/replication-controller#pod-template",
							Required:    true,
							MaxItems:    1,
							Elem: &schema.Resource{
								Schema: podSpecFields(),
							},
						},
					},
				},
			},
		},
	}
}

func resourceKubernetesDeploymentCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	metadata := expandMetadata(d.Get("metadata").([]interface{}))
	spec, err := expandDeploymentSpec(d.Get("spec").([]interface{}))
	if err != nil {
		return err
	}

	spec.Template.Spec.AutomountServiceAccountToken = ptrToBool(false)

	rc := v1beta1.Deployment{
		ObjectMeta: metadata,
		Spec:       spec,
	}

	log.Printf("[INFO] Creating new deployment: %#v", rc)
	out, err := conn.ExtensionsV1beta1().Deployments(metadata.Namespace).Create(&rc)
	if err != nil {
		return fmt.Errorf("Failed to create deployment: %s", err)
	}

	d.SetId(buildId(out.ObjectMeta))

	log.Printf("[DEBUG] Waiting for deployment %s to schedule %d replicas",
		d.Id(), *out.Spec.Replicas)
	// 10 mins should be sufficient for scheduling ~10k replicas
	err = resource.Retry(d.Timeout(schema.TimeoutCreate),
		waitForDeploymentReplicasFunc(conn, out.GetNamespace(), out.GetName()))
	if err != nil {
		return err
	}
	// We could wait for all pods to actually reach Ready state
	// but that means checking each pod status separately (which can be expensive at scale)
	// as there's no aggregate data available from the API

	log.Printf("[INFO] Submitted new deployment: %#v", out)

	return resourceKubernetesDeploymentRead(d, meta)
}

func resourceKubernetesDeploymentRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())
	log.Printf("[INFO] Reading deployment %s", name)
	rc, err := conn.ExtensionsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		log.Printf("[DEBUG] Received error: %#v", err)
		return err
	}
	log.Printf("[INFO] Received deployment: %#v", rc)

	err = d.Set("metadata", flattenMetadata(rc.ObjectMeta))
	if err != nil {
		return err
	}

	spec, err := flattenDeploymentSpec(rc.Spec)
	if err != nil {
		return err
	}

	err = d.Set("spec", spec)
	if err != nil {
		return err
	}

	return nil
}

func resourceKubernetesDeploymentUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())

	ops := patchMetadata("metadata.0.", "/metadata/", d)

	if d.HasChange("spec") {
		spec, err := expandDeploymentSpec(d.Get("spec").([]interface{}))
		if err != nil {
			return err
		}

		ops = append(ops, &ReplaceOperation{
			Path:  "/spec",
			Value: spec,
		})
	}
	data, err := ops.MarshalJSON()
	if err != nil {
		return fmt.Errorf("Failed to marshal update operations: %s", err)
	}
	log.Printf("[INFO] Updating deployment %q: %v", name, string(data))
	out, err := conn.ExtensionsV1beta1().Deployments(namespace).Patch(name, pkgApi.JSONPatchType, data)
	if err != nil {
		return fmt.Errorf("Failed to update deployment: %s", err)
	}
	log.Printf("[INFO] Submitted updated deployment: %#v", out)

	err = resource.Retry(d.Timeout(schema.TimeoutUpdate),
		waitForDeploymentReplicasFunc(conn, namespace, name))
	if err != nil {
		return err
	}

	return resourceKubernetesDeploymentRead(d, meta)
}

func resourceKubernetesDeploymentDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())
	log.Printf("[INFO] Deleting deployment: %#v", name)

	// Drain all replicas before deleting
	var ops PatchOperations
	ops = append(ops, &ReplaceOperation{
		Path:  "/spec/replicas",
		Value: 0,
	})
	data, err := ops.MarshalJSON()
	if err != nil {
		return err
	}
	_, err = conn.ExtensionsV1beta1().Deployments(namespace).Patch(name, pkgApi.JSONPatchType, data)
	if err != nil {
		return err
	}

	// Wait until all replicas are gone
	err = resource.Retry(d.Timeout(schema.TimeoutDelete),
		waitForDeploymentReplicasFunc(conn, namespace, name))
	if err != nil {
		return err
	}

	err = conn.ExtensionsV1beta1().Deployments(namespace).Delete(name, &metav1.DeleteOptions{})
	if err != nil {
		return err
	}

	log.Printf("[INFO] Replication controller %s deleted", name)

	d.SetId("")
	return nil
}

func resourceKubernetesDeploymentExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())
	log.Printf("[INFO] Checking deployment %s", name)
	_, err := conn.ExtensionsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 {
			return false, nil
		}
		log.Printf("[DEBUG] Received error: %#v", err)
	}
	return true, err
}

func waitForDeploymentReplicasFunc(conn *kubernetes.Clientset, ns, name string) resource.RetryFunc {
	return func() *resource.RetryError {
		rc, err := conn.ExtensionsV1beta1().Deployments(ns).Get(name, metav1.GetOptions{})
		if err != nil {
			return resource.NonRetryableError(err)
		}

		desiredReplicas := *rc.Spec.Replicas
		log.Printf("[DEBUG] Current number of labelled replicas of %q: %d (of %d)\n",
			rc.GetName(), rc.Status.Replicas, desiredReplicas)

		if rc.Status.Replicas == desiredReplicas {
			return nil
		}

		return resource.RetryableError(fmt.Errorf("Waiting for %d replicas of %q to be scheduled (%d)",
			desiredReplicas, rc.GetName(), rc.Status.Replicas))
	}
}
<commit_msg>rename variables to deployment<commit_after>package kubernetes

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	pkgApi "k8s.io/apimachinery/pkg/types"
	"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
	kubernetes "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

func resourceKubernetesDeployment() *schema.Resource {
	return &schema.Resource{
		Create: resourceKubernetesDeploymentCreate,
		Read:   resourceKubernetesDeploymentRead,
		Exists: resourceKubernetesDeploymentExists,
		Update: resourceKubernetesDeploymentUpdate,
		Delete: resourceKubernetesDeploymentDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(10 * time.Minute),
			Update: schema.DefaultTimeout(10 * time.Minute),
			Delete: schema.DefaultTimeout(10 * time.Minute),
		},

		Schema: map[string]*schema.Schema{
			"metadata": namespacedMetadataSchema("deployment", true),
			"spec": {
				Type:        schema.TypeList,
				Description: "Spec defines the specification of the desired behavior of the deployment. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status",
				Required:    true,
				MaxItems:    1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"min_ready_seconds": {
							Type:        schema.TypeInt,
							Description: "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)",
							Optional:    true,
							Default:     0,
						},
						"replicas": {
							Type:        schema.TypeInt,
							Description: "The number of desired replicas. Defaults to 1. More info: http://kubernetes.io/docs/user-guide/replication-controller#what-is-a-replication-controller",
							Optional:    true,
							Default:     1,
						},
						"selector": {
							Type:        schema.TypeMap,
							Description: "A label query over pods that should match the Replicas count. If Selector is empty, it is defaulted to the labels present on the Pod template. Label keys and values that must match in order to be controlled by this deployment, if empty defaulted to labels on Pod template. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors",
							Required:    true,
						},
						//todo: strategy not working yet
						"strategy": {
							Type:        schema.TypeMap,
							Optional:    true,
							Computed:    true,
							Description: "Update strategy. One of RollingUpdate, Destroy. Defaults to RollingDate",
						},
						"template": {
							Type:        schema.TypeList,
							Description: "Describes the pod that will be created if insufficient replicas are detected. This takes precedence over a TemplateRef. More info: http://kubernetes.io/docs/user-guide/replication-controller#pod-template",
							Required:    true,
							MaxItems:    1,
							Elem: &schema.Resource{
								Schema: podSpecFields(),
							},
						},
					},
				},
			},
		},
	}
}

func resourceKubernetesDeploymentCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	metadata := expandMetadata(d.Get("metadata").([]interface{}))
	spec, err := expandDeploymentSpec(d.Get("spec").([]interface{}))
	if err != nil {
		return err
	}

	spec.Template.Spec.AutomountServiceAccountToken = ptrToBool(false)

	deployment := v1beta1.Deployment{
		ObjectMeta: metadata,
		Spec:       spec,
	}

	log.Printf("[INFO] Creating new deployment: %#v", deployment)
	out, err := conn.ExtensionsV1beta1().Deployments(metadata.Namespace).Create(&deployment)
	if err != nil {
		return fmt.Errorf("Failed to create deployment: %s", err)
	}

	d.SetId(buildId(out.ObjectMeta))

	log.Printf("[DEBUG] Waiting for deployment %s to schedule %d replicas",
		d.Id(), *out.Spec.Replicas)
	// 10 mins should be sufficient for scheduling ~10k replicas
	err = resource.Retry(d.Timeout(schema.TimeoutCreate),
		waitForDeploymentReplicasFunc(conn, out.GetNamespace(), out.GetName()))
	if err != nil {
		return err
	}
	// We could wait for all pods to actually reach Ready state
	// but that means checking each pod status separately (which can be expensive at scale)
	// as there's no aggregate data available from the API

	log.Printf("[INFO] Submitted new deployment: %#v", out)

	return resourceKubernetesDeploymentRead(d, meta)
}

func resourceKubernetesDeploymentRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())
	log.Printf("[INFO] Reading deployment %s", name)
	deployment, err := conn.ExtensionsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		log.Printf("[DEBUG] Received error: %#v", err)
		return err
	}
	log.Printf("[INFO] Received deployment: %#v", deployment)

	err = d.Set("metadata", flattenMetadata(deployment.ObjectMeta))
	if err != nil {
		return err
	}

	spec, err := flattenDeploymentSpec(deployment.Spec)
	if err != nil {
		return err
	}

	err = d.Set("spec", spec)
	if err != nil {
		return err
	}

	return nil
}

func resourceKubernetesDeploymentUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())

	ops := patchMetadata("metadata.0.", "/metadata/", d)

	if d.HasChange("spec") {
		spec, err := expandDeploymentSpec(d.Get("spec").([]interface{}))
		if err != nil {
			return err
		}

		ops = append(ops, &ReplaceOperation{
			Path:  "/spec",
			Value: spec,
		})
	}
	data, err := ops.MarshalJSON()
	if err != nil {
		return fmt.Errorf("Failed to marshal update operations: %s", err)
	}
	log.Printf("[INFO] Updating deployment %q: %v", name, string(data))
	out, err := conn.ExtensionsV1beta1().Deployments(namespace).Patch(name, pkgApi.JSONPatchType, data)
	if err != nil {
		return fmt.Errorf("Failed to update deployment: %s", err)
	}
	log.Printf("[INFO] Submitted updated deployment: %#v", out)

	err = resource.Retry(d.Timeout(schema.TimeoutUpdate),
		waitForDeploymentReplicasFunc(conn, namespace, name))
	if err != nil {
		return err
	}

	return resourceKubernetesDeploymentRead(d, meta)
}

func resourceKubernetesDeploymentDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())
	log.Printf("[INFO] Deleting deployment: %#v", name)

	// Drain all replicas before deleting
	var ops PatchOperations
	ops = append(ops, &ReplaceOperation{
		Path:  "/spec/replicas",
		Value: 0,
	})
	data, err := ops.MarshalJSON()
	if err != nil {
		return err
	}
	_, err = conn.ExtensionsV1beta1().Deployments(namespace).Patch(name, pkgApi.JSONPatchType, data)
	if err != nil {
		return err
	}

	// Wait until all replicas are gone
	err = resource.Retry(d.Timeout(schema.TimeoutDelete),
		waitForDeploymentReplicasFunc(conn, namespace, name))
	if err != nil {
		return err
	}

	err = conn.ExtensionsV1beta1().Deployments(namespace).Delete(name, &metav1.DeleteOptions{})
	if err != nil {
		return err
	}

	log.Printf("[INFO] Replication controller %s deleted", name)

	d.SetId("")
	return nil
}

func resourceKubernetesDeploymentExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	conn := meta.(*kubernetes.Clientset)

	namespace, name := idParts(d.Id())
	log.Printf("[INFO] Checking deployment %s", name)
	_, err := conn.ExtensionsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 {
			return false, nil
		}
		log.Printf("[DEBUG] Received error: %#v", err)
	}
	return true, err
}

func waitForDeploymentReplicasFunc(conn *kubernetes.Clientset, ns, name string) resource.RetryFunc {
	return func() *resource.RetryError {
		deployment, err := conn.ExtensionsV1beta1().Deployments(ns).Get(name, metav1.GetOptions{})
		if err != nil {
			return resource.NonRetryableError(err)
		}

		desiredReplicas := *deployment.Spec.Replicas
		log.Printf("[DEBUG] Current number of labelled replicas of %q: %d (of %d)\n",
			deployment.GetName(), deployment.Status.Replicas, desiredReplicas)

		if deployment.Status.Replicas == desiredReplicas {
			return nil
		}

		return resource.RetryableError(fmt.Errorf("Waiting for %d replicas of %q to be scheduled (%d)",
			desiredReplicas, deployment.GetName(), deployment.Status.Replicas))
	}
}
<|endoftext|>


<commit_before>package onion

import (
	"os"
	"testing"

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

func TestEnvLayer(t *testing.T) {
	Convey("EnvLayer test ", t, func() {
		// Just for passing the errcheck errors :)
		So(os.Unsetenv("TEST1"), ShouldBeNil)
		So(os.Unsetenv("TEST2"), ShouldBeNil)
		So(os.Unsetenv("TEST3"), ShouldBeNil)
		So(os.Setenv("BLACK", "blacklisted"), ShouldBeNil)
		//o := New()

		Convey("Check if there is anything loaded", func() {
			el := NewEnvLayer("TEST1", "test2", "Test3")

			data, err := el.Load()
			So(err, ShouldBeNil)
			So(len(data), ShouldEqual, 0)
		})

		Convey("Check if the variable is loaded correctly", func() {
			el := NewEnvLayer("BLACK")

			data, err := el.Load()
			So(err, ShouldBeNil)
			So(len(data), ShouldEqual, 1)
			So(data["BLACK"], ShouldEqual, "blacklisted")

			Convey("Check if the onion handle it correctly", func() {
				o := New()
				err := o.AddLayer(el)
				So(err, ShouldBeNil)

				So(o.GetString("black", "no!"), ShouldEqual, "blacklisted")
			})
		})
	})

}
<commit_msg>fix the code for < 1.3<commit_after>package onion

import (
	"os"
	"testing"

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

func TestEnvLayer(t *testing.T) {
	Convey("EnvLayer test ", t, func() {
		// Just for passing the errcheck errors :)
		// Unsetenv is not available in < 1.3
		//So(os.Unsetenv("TEST1"), ShouldBeNil)
		//So(os.Unsetenv("TEST2"), ShouldBeNil)
		//So(os.Unsetenv("TEST3"), ShouldBeNil)
		So(os.Setenv("BLACK", "blacklisted"), ShouldBeNil)
		//o := New()

		Convey("Check if there is anything loaded", func() {
			el := NewEnvLayer("TEST1", "test2", "Test3")

			data, err := el.Load()
			So(err, ShouldBeNil)
			So(len(data), ShouldEqual, 0)
		})

		Convey("Check if the variable is loaded correctly", func() {
			el := NewEnvLayer("BLACK")

			data, err := el.Load()
			So(err, ShouldBeNil)
			So(len(data), ShouldEqual, 1)
			So(data["BLACK"], ShouldEqual, "blacklisted")

			Convey("Check if the onion handle it correctly", func() {
				o := New()
				err := o.AddLayer(el)
				So(err, ShouldBeNil)

				So(o.GetString("black", "no!"), ShouldEqual, "blacklisted")
			})
		})
	})

}
<|endoftext|>