Exemple #1
0
func TestDecode_NilInterfaceHook(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"w": "",
	}

	decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
		if t.String() == "io.Writer" {
			return nil, nil
		}

		return v, nil
	}

	var result NilInterface
	config := &DecoderConfig{
		DecodeHook: decodeHook,
		Result:     &result,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = decoder.Decode(input)
	if err != nil {
		t.Fatalf("got an err: %s", err)
	}

	if result.W != nil {
		t.Errorf("W should be nil: %#v", result.W)
	}
}
Exemple #2
0
func TestSerialDeserialization(t *testing.T) {
	f1 := &FileId{VolumeId: 345, Key: 8698, Hashcode: 23849095}
	log.Println("vid", f1.VolumeId, "key", f1.Key, "hash", f1.Hashcode)

	f2 := ParseFileId(t.String())

	log.Println("vvid", f2.VolumeId, "vkey", f2.Key, "vhash", f2.Hashcode)
}
Exemple #3
0
func TestNNF(t *testing.T) {
	// Build a simple BNF aGrammar description aGrammar.
	gb := parser.OpenGrammarBuilder()

	gb.Name("a4").
		Terminals("a").
		Nonterminals("S", "A", "E").
		Rule().Lhs("`*").Rhs("S", "`.").
		Rule().Lhs("S").Rhs("A", "A", "A", "A").
		Rule().Lhs("A").Rhs("a").
		Rule().Lhs("A").Rhs("E").
		Rule().Lhs("E").Rhs("`e")

	g, err := gb.Build()
	if err != nil {
		t.Error(err)
		return
	}

	var aGrammar parser.Grammar
	var rTransform parser.SyntaxTreeTransform

	nnf, err := IsNihilisticNormalForm(g)
	if err != nil {
		t.Error()
		return
	}
	if !nnf {
		fmt.Println("Grammar is not NNF, transforming.")
		aGrammar, rTransform, err = GetNihilisticAugmentGrammar(g)
		if err != nil {
			t.Error(err)
			return
		}
	} else {
		t.Error("Grammar returned NNF.")
		return
	}

	fmt.Println("Name: " + aGrammar.Name())
	terms := make([]string, aGrammar.NumTerminals())
	for i, t := range aGrammar.Terminals() {
		terms[i] = t.String()
	}
	nterms := make([]string, aGrammar.NumNonterminals())
	for i, t := range aGrammar.Nonterminals() {
		nterms[i] = t.String()
	}
	fmt.Println("Terminals: " + strings.Join(terms, ", "))
	fmt.Println("Nonterminals: " + strings.Join(nterms, ", "))
	fmt.Println("Productions:")
	for _, p := range aGrammar.Productions() {
		fmt.Println("   " + p.String())
	}
	rTransform = rTransform
}
Exemple #4
0
func TestGraphGenerator(t *testing.T) {
	testData := []struct {
		size int
		n    int
		want []string
	}{
		{
			size: 1,
			n:    0,
			want: nil,
		},
		{
			size: 1,
			n:    1,
			want: []string{
				"/gn<0>\t\"follow\"@[]\t/gn<0>",
			},
		},
		{
			size: 2,
			n:    4,
			want: []string{
				"/gn<0>\t\"follow\"@[]\t/gn<0>",
				"/gn<0>\t\"follow\"@[]\t/gn<1>",
				"/gn<1>\t\"follow\"@[]\t/gn<0>",
				"/gn<1>\t\"follow\"@[]\t/gn<1>",
			},
		},
	}
	for _, entry := range testData {
		g, err := NewRandomGraph(entry.size)
		if err != nil {
			t.Fatalf("graph.NewRandomGraph(%d) should have never failed, %v.", entry.size, err)
		}
		trpls, err := g.Generate(entry.n)
		if err != nil {
			t.Fatalf("graph.NewRandomGraph(%d) should have never failed, %v.", entry.size, err)
		}
		if got, want := len(trpls), len(entry.want); got != want {
			t.Fatalf("g.Generate(%d) returned the wrong number of triples; got %d, want %d.", entry.n, got, want)
		}
		var tts []string
		for _, t := range trpls {
			tts = append(tts, t.String())
		}
		sort.Strings(tts)
		if got, want := tts, entry.want; !reflect.DeepEqual(got, want) {
			t.Fatalf("g.Generate(%d) returned the wrong number of triples; got %v, want %v.", entry.n, got, want)
		}
	}
}
Exemple #5
0
func TestDo(t *testing.T) {

	// For now, we just pile stuff into this one function.
	// ToDo: Don't do that.

	g, _ := GetGraph("config.test")

	g.WriteIndexedTriple(TripleFromStrings("aaa", "p1", "bbb", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("aaa", "p1", "fff", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("aaa", "p5", "jjj", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("bbb", "p2", "ccc", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("ccc", "p3", "ddd", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("ccc", "p3", "eee", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("ggg", "p4", "ccc", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("ggg", "p1", "hhh", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("ggg", "p1", "iii", "today"), nil)

	g.DoAll(nil, 100, func(t *Triple) bool {
		fmt.Printf("triple %v\n", t.String())
		return true
	})

	fmt.Println("DoS")

	g.DoVertexes(nil, 30, func(s []byte) bool {
		Out([]byte("p1")).Walk(g, s).Print()
		return true
	})

	i := g.NewVertexIterator()
	for {
		v, ok := i.Next()
		if !ok {
			break
		}
		fmt.Printf("v %s\n", v)
	}

	i = g.NewVertexIterator()
	for {
		v := i.NextVertex()
		if v == "" {
			break
		}
		fmt.Printf("nv %s\n", v)
	}

	g.Close()
}
Exemple #6
0
func TestID(t *testing.T) {
	ts := []T{
		Make("test").T(),
		Int(7),
		Str("hello"),
	}
	for _, t := range ts {
		it := IDT(t).T()
		if it.String() != t.String() {
			fmt.Println("%v != %v", t, it)
		}
		s := ConstC{t}
		is := IDC(s).C()
		if s.String() != is.String() {
			fmt.Println("%v != %v", s, is)
		}
	}
}
func TestTokenized(t *testing.T) {
	Convey("Tokenizing data from a request works as expected", t, func() {
		// Let's setup a test server.
		var ts *httptest.Server
		ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Method == "GET" && r.URL.Path == "/test" {
				defer r.Body.Close()
				w.Header().Add("X-Custom-Hdr", "Custom Header")
				w.Header().Add("Set-Cookie", "session_id=42 ; Path=/")
				w.WriteHeader(200)
				fmt.Fprint(w, fmt.Sprintf(`{"URL": "%s", "json": true, "foolMeOnce": "shame on you"}`, r.URL))
			}
		}))
		Convey("Given a Tokenized objects, confirm that it formats the right information if does not format anything.", func() {
			t := Tokenized{Data: "test"}
			So(t.Format(nil), ShouldEqual, "test")
			So(t.String(), ShouldEqual, "{Tokenized with data}")
		})
		Convey("Given a Tokenized objects, confirm that it formats the right information if response is nil.", func() {
			t := Tokenized{Data: "test", Cookie: "ChocChip"}
			So(t.Format(nil), ShouldEqual, "test")
			So(t.String(), ShouldEqual, "{Tokenized with cookie with data}")
		})
		Convey("Given a Tokenized objects, confirm that it formats the right information.", func() {
			example := `<headers responseToken="resp" headerToken="hdr" cookieToken="cke">
							X-Fool:NotAMonkey resp/foolMeOnce
							Cookie:test=true;session_id=cke/session_id
							Some-Header:hdr/X-Custom-Hdr
							X-Cannot-Decode: resp/json
						</headers>`
			out := Tokenized{}
			xml.Unmarshal([]byte(example), &out)
			gresp, _ := goreq.Request{Uri: ts.URL + "/test"}.Do()
			resp := Response{}
			resp.FromGoResp(gresp, nil, time.Now())
			expectations := []string{"", "X-Fool:NotAMonkey shame on you", "Cookie:test=true;session_id=42", "Some-Header:Custom Header", "X-Cannot-Decode:", ""}
			for pos, line := range strings.Split(out.Format(&resp), "\n") {
				So(strings.TrimSpace(line), ShouldEqual, expectations[pos])
			}
			So(out.String(), ShouldEqual, "{Tokenized with cookie with header with data}")
		})
	})
}
Exemple #8
0
/*

First:

bnf:	ntdecl, NONTERM
ntdecl:	ntdecl, NONTERM
def: ntort, IDENTIFIER, NONTERM
ntort: IDENTIFIER, NONTERM


<bnf>		`.
<ntdecl>	<bnf>. <bnf> PIPE
NONTERM		COLEQ <ntort>.
COLEQ		<def>
<def>		<ntdecl>.
PIPE		<def>
<ntort>		<def>. <def>
IDENTIFIER	<ntort>.


<bnf>		`.
<ntdecl>	<bnf>. <bnf> PIPE `.
NONTERM		COLEQ <ntort>. <def>. <def> <ntdecl>. <bnf>. <bnf> PIPE `.
COLEQ		<def>
<def>		<ntdecl>. <bnf>. <bnf> PIPE `.
PIPE		<def>
<ntort>		<def>. <def> <ntdecl>. <bnf>. <bnf> PIPE `.
IDENTIFIER	<ntort>. <def>. <def> <ntdecl>. <bnf>. <bnf> PIPE `.

<bnf>		`.
<ntdecl>	<bnf> PIPE `.
<def>		<bnf> PIPE `.
<ntort>		<def> <bnf> PIPE `.
NONTERM		<def> <bnf> COLEQ PIPE `.
COLEQ		<def>
PIPE		<def>
IDENTIFIER	<def> <bnf> PIPE `.


0	`* := <bnf> `.

1	<bnf> := <ntdecl>
2		   | <ntdecl> <bnf>

3	<ntdecl> := NONTERM COLEQ <def>
4			  | <ntdecl> PIPE <def>

5	<def> := <ntort>
6	       | <ntort> <def>

7	<ntort> := IDENTIFIER
	         | NONTERM

Reading <ntdecl> ...

    .NT
		3,ntdecl: . NT C <def>
		4,ntdecl: . <ntdecl> P <def>
		3,ntdecl: NT C . <def>
		4,ntdecl: <ntdecl> P . <def>
	.ID
		3,ntdecl: NT C . <def>
		4,ntdecl: <ntdecl> P . <def>
	.C
		3,ntdecl: NT . C <def>
	.P
		4,ntdecl: <ntdecl> . P <def>


*/
func TestGrammarBuilder(t *testing.T) {
	// Build a simple BNF grammar description grammar.
	gb := OpenGrammarBuilder()

	gb.Terminals("NONTERM", "COLEQ", "PIPE", "IDENTIFIER").
		Nonterminals("bnf", "ntdecl", "def", "ntort").
		Rule().Lhs("bnf").Rhs("ntdecl").
		Rule().Lhs("bnf").Rhs("ntdecl", "bnf").
		Rule().Lhs("ntdecl").Rhs("NONTERM", "COLEQ", "def").
		Rule().Lhs("ntdecl").Rhs("ntdecl", "PIPE", "def").
		Rule().Lhs("def").Rhs("ntort").
		Rule().Lhs("def").Rhs("ntort", "def").
		Rule().Lhs("ntort").Rhs("IDENTIFIER").
		Rule().Lhs("ntort").Rhs("NONTERM").
		Rule().Lhs("`*").Rhs("bnf", "`.").
		Name("simple-bnf")

	grammar, err := gb.Build()
	if err != nil {
		t.Error(err)
	}
	fmt.Println("Name: " + grammar.Name())
	terms := make([]string, grammar.NumTerminals())
	for i, t := range grammar.Terminals() {
		terms[i] = t.String()
	}
	nterms := make([]string, grammar.NumNonterminals())
	for i, t := range grammar.Nonterminals() {
		nterms[i] = t.String()
	}
	fmt.Println("Terminals: " + strings.Join(terms, ", "))
	fmt.Println("Nonterminals: " + strings.Join(nterms, ", "))
	fmt.Println("Productions:")
	for _, p := range grammar.Productions() {
		fmt.Println("   " + p.String())
	}
}
Exemple #9
0
func TestLexer(t *testing.T) {
	Convey("basic lexer testing", t, func() {
		for _, c := range []Case{
			{`"`, `ILLEGAL "unterminated string: ''"`, ""},
			{"", `EOF ""`, ""},
			{"\n  ", `EOF ""`, ""},
			{"; asdf", `COMMENT "; asdf"`, ""},
			{"; asdf\n", `COMMENT "; asdf\n"`, ""},
			{"(", `LEFT_PAREN "("`, ""},
			{")", `RIGHT_PAREN ")"`, ""},
			{" . ", `DOT "."`, ""},
			{"'", `QUOTE "'"`, ""},
			{"-", `SYMBOL "-"`, ""},
			{"-1", `NUMBER "-1"`, ""},
			{".", `NUMBER "."`, ""},
			{"123", `NUMBER "123"`, ""},
			{"-abc", `SYMBOL "-abc"`, ""},
			{"abc", `SYMBOL "abc"`, ""},
			{`"abc"`, `STRING "abc"`, ""},
			{`"abc\`, `ILLEGAL "unterminated string: \"abc\""`, ""},
			{"#t", `TRUE "t"`, ""},
			{"#f", `FALSE "f"`, ""},
			{"#n", `ILLEGAL "unsupported hash code #n"`, ""},
			{"a(", `SYMBOL "a"`, ""},
			{"12(", `NUMBER "12"`, ""},
		} {
			doLex(c.value, c.expected, c.err)
		}

		Convey("Unknown tokeen", func() {
			t := Token(500)
			So(t.String(), ShouldEqual, "Unknown token: 500")
		})

	})
}
Exemple #10
0
func TestIterator(t *testing.T) {
	tmpDir, err := ioutil.TempDir(os.TempDir(), "cayley_test")
	if err != nil {
		t.Fatalf("Could not create working directory: %v", err)
	}
	defer os.RemoveAll(tmpDir)
	t.Log(tmpDir)

	err = createNewLevelDB(tmpDir, nil)
	if err != nil {
		t.Fatal("Failed to create LevelDB database.")
	}

	qs, err := newQuadStore(tmpDir, nil)
	if qs == nil || err != nil {
		t.Error("Failed to create leveldb QuadStore.")
	}

	w, _ := writer.NewSingleReplication(qs, nil)
	w.AddQuadSet(makeQuadSet())
	var it graph.Iterator

	it = qs.NodesAllIterator()
	if it == nil {
		t.Fatal("Got nil iterator.")
	}

	size, exact := it.Size()
	if size <= 0 || size >= 20 {
		t.Errorf("Unexpected size, got:%d expect:(0, 20)", size)
	}
	if exact {
		t.Errorf("Got unexpected exact result.")
	}
	if typ := it.Type(); typ != graph.All {
		t.Errorf("Unexpected iterator type, got:%v expect:%v", typ, graph.All)
	}
	optIt, changed := it.Optimize()
	if changed || optIt != it {
		t.Errorf("Optimize unexpectedly changed iterator.")
	}

	expect := []string{
		"A",
		"B",
		"C",
		"D",
		"E",
		"F",
		"G",
		"follows",
		"status",
		"cool",
		"status_graph",
	}
	sort.Strings(expect)
	for i := 0; i < 2; i++ {
		got := iteratedNames(qs, it)
		sort.Strings(got)
		if !reflect.DeepEqual(got, expect) {
			t.Errorf("Unexpected iterated result on repeat %d, got:%v expect:%v", i, got, expect)
		}
		it.Reset()
	}

	for _, pq := range expect {
		if !it.Contains(qs.ValueOf(pq)) {
			t.Errorf("Failed to find and check %q correctly", pq)
		}
	}
	// FIXME(kortschak) Why does this fail?
	/*
		for _, pq := range []string{"baller"} {
			if it.Contains(qs.ValueOf(pq)) {
				t.Errorf("Failed to check %q correctly", pq)
			}
		}
	*/
	it.Reset()

	it = qs.QuadsAllIterator()
	graph.Next(it)
	q := qs.Quad(it.Result())
	set := makeQuadSet()
	var ok bool
	for _, t := range set {
		if t.String() == q.String() {
			ok = true
			break
		}
	}
	if !ok {
		t.Errorf("Failed to find %q during iteration, got:%q", q, set)
	}

	qs.Close()
}
Exemple #11
0
func Test_Values(t *testing.T) {
	Convey("Test getting and setting values", t, func() {
		cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
		So(err, ShouldBeNil)
		So(cfg, ShouldNotBeNil)

		Convey("Get values in default section", func() {
			sec := cfg.Section("")
			So(sec, ShouldNotBeNil)
			So(sec.Key("NAME").Value(), ShouldEqual, "ini")
			So(sec.Key("NAME").String(), ShouldEqual, "ini")
			So(sec.Key("NAME").Comment, ShouldEqual, "; Package name")
			So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
		})

		Convey("Get values in non-default section", func() {
			sec := cfg.Section("author")
			So(sec, ShouldNotBeNil)
			So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
			So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon")

			sec = cfg.Section("package")
			So(sec, ShouldNotBeNil)
			So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
		})

		Convey("Get auto-increment key names", func() {
			keys := cfg.Section("features").Keys()
			for i, k := range keys {
				So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1))
			}
		})

		Convey("Get overwrite value", func() {
			So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "*****@*****.**")
		})

		Convey("Get sections", func() {
			sections := cfg.Sections()
			for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "advance"} {
				So(sections[i].Name(), ShouldEqual, name)
			}
		})

		Convey("Get parent section value", func() {
			So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
		})

		Convey("Get multiple line value", func() {
			So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
		})

		Convey("Get values with type", func() {
			sec := cfg.Section("types")
			v1, err := sec.Key("BOOL").Bool()
			So(err, ShouldBeNil)
			So(v1, ShouldBeTrue)

			v1, err = sec.Key("BOOL_FALSE").Bool()
			So(err, ShouldBeNil)
			So(v1, ShouldBeFalse)

			v2, err := sec.Key("FLOAT64").Float64()
			So(err, ShouldBeNil)
			So(v2, ShouldEqual, 1.25)

			v3, err := sec.Key("INT").Int()
			So(err, ShouldBeNil)
			So(v3, ShouldEqual, 10)

			v4, err := sec.Key("INT").Int64()
			So(err, ShouldBeNil)
			So(v4, ShouldEqual, 10)

			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			v5, err := sec.Key("TIME").Time()
			So(err, ShouldBeNil)
			So(v5.String(), ShouldEqual, t.String())

			Convey("Must get values with type", func() {
				So(sec.Key("STRING").MustString("404"), ShouldEqual, "str")
				So(sec.Key("BOOL").MustBool(), ShouldBeTrue)
				So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25)
				So(sec.Key("INT").MustInt(), ShouldEqual, 10)
				So(sec.Key("INT").MustInt64(), ShouldEqual, 10)
				So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String())

				Convey("Must get values with default value", func() {
					So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404")
					So(sec.Key("BOOL_404").MustBool(true), ShouldBeTrue)
					So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5)
					So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15)
					So(sec.Key("INT_404").MustInt64(15), ShouldEqual, 15)

					t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
					So(err, ShouldBeNil)
					So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String())
				})
			})
		})

		Convey("Get value with candidates", func() {
			sec := cfg.Section("types")
			So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str")
			So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
			So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
			So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10)

			zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())

			Convey("Get value with candidates and default value", func() {
				So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str")
				So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
				So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10)
				So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10)
				So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
			})
		})

		Convey("Get values in range", func() {
			sec := cfg.Section("types")
			So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25)
			So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10)
			So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10)

			minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			So(sec.Key("TIME").RangeTime(t, minT, maxT).String(), ShouldEqual, t.String())

			Convey("Get value in range with default value", func() {
				So(sec.Key("FLOAT64").RangeFloat64(5, 0, 1), ShouldEqual, 5)
				So(sec.Key("INT").RangeInt(7, 0, 5), ShouldEqual, 7)
				So(sec.Key("INT").RangeInt64(7, 0, 5), ShouldEqual, 7)
				So(sec.Key("TIME").RangeTime(t, minT, midT).String(), ShouldEqual, t.String())
			})
		})

		Convey("Get values into slice", func() {
			sec := cfg.Section("array")
			So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de")
			So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0)

			vals1 := sec.Key("FLOAT64S").Float64s(",")
			for i, v := range []float64{1.1, 2.2, 3.3} {
				So(vals1[i], ShouldEqual, v)
			}

			vals2 := sec.Key("INTS").Ints(",")
			for i, v := range []int{1, 2, 3} {
				So(vals2[i], ShouldEqual, v)
			}

			vals3 := sec.Key("INTS").Int64s(",")
			for i, v := range []int64{1, 2, 3} {
				So(vals3[i], ShouldEqual, v)
			}

			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			vals4 := sec.Key("TIMES").Times(",")
			for i, v := range []time.Time{t, t, t} {
				So(vals4[i].String(), ShouldEqual, v.String())
			}
		})

		Convey("Get key hash", func() {
			cfg.Section("").KeysHash()
		})

		Convey("Set key value", func() {
			k := cfg.Section("author").Key("NAME")
			k.SetValue("无闻")
			So(k.String(), ShouldEqual, "无闻")
		})

		Convey("Get key strings", func() {
			So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME")
		})

		Convey("Delete a key", func() {
			cfg.Section("package.sub").DeleteKey("UNUSED_KEY")
			_, err := cfg.Section("package.sub").GetKey("UNUSED_KEY")
			So(err, ShouldNotBeNil)
		})

		Convey("Get section strings", func() {
			So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,advance")
		})

		Convey("Delete a section", func() {
			cfg.DeleteSection("")
			So(cfg.SectionStrings()[0], ShouldNotEqual, DEFAULT_SECTION)
		})

		Convey("Create new sections", func() {
			cfg.NewSections("test", "test2")
			_, err := cfg.GetSection("test")
			So(err, ShouldBeNil)
			_, err = cfg.GetSection("test2")
			So(err, ShouldBeNil)
		})
	})

	Convey("Test getting and setting bad values", t, func() {
		cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
		So(err, ShouldBeNil)
		So(cfg, ShouldNotBeNil)

		Convey("Create new key with empty name", func() {
			k, err := cfg.Section("").NewKey("", "")
			So(err, ShouldNotBeNil)
			So(k, ShouldBeNil)
		})

		Convey("Create new section with empty name", func() {
			s, err := cfg.NewSection("")
			So(err, ShouldNotBeNil)
			So(s, ShouldBeNil)
		})

		Convey("Create new sections with empty name", func() {
			So(cfg.NewSections(""), ShouldNotBeNil)
		})

		Convey("Get section that not exists", func() {
			s, err := cfg.GetSection("404")
			So(err, ShouldNotBeNil)
			So(s, ShouldBeNil)

			s = cfg.Section("404")
			So(s, ShouldNotBeNil)
		})
	})
}
func Test_Struct(t *testing.T) {
	Convey("Map to struct", t, func() {
		Convey("Map file to struct", func() {
			ts := new(testStruct)
			So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)

			So(ts.Name, ShouldEqual, "Unknwon")
			So(ts.Age, ShouldEqual, 21)
			So(ts.Male, ShouldBeTrue)
			So(ts.Money, ShouldEqual, 1.25)
			So(ts.Unsigned, ShouldEqual, 3)

			t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
			So(err, ShouldBeNil)
			So(ts.Born.String(), ShouldEqual, t.String())

			dur, err := time.ParseDuration("2h45m")
			So(err, ShouldBeNil)
			So(ts.Time.Seconds(), ShouldEqual, dur.Seconds())

			So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston")
			So(ts.Others.Visits[0].String(), ShouldEqual, t.String())
			So(ts.Others.Note, ShouldEqual, "Hello world!")
			So(ts.testEmbeded.GPA, ShouldEqual, 2.8)
		})

		Convey("Map section to struct", func() {
			foobar := new(fooBar)
			f, err := Load([]byte(_CONF_DATA_STRUCT))
			So(err, ShouldBeNil)

			So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil)
			So(foobar.Here, ShouldEqual, "there")
			So(foobar.When, ShouldEqual, "then")
		})

		Convey("Map to non-pointer struct", func() {
			cfg, err := Load([]byte(_CONF_DATA_STRUCT))
			So(err, ShouldBeNil)
			So(cfg, ShouldNotBeNil)

			So(cfg.MapTo(testStruct{}), ShouldNotBeNil)
		})

		Convey("Map to unsupported type", func() {
			cfg, err := Load([]byte(_CONF_DATA_STRUCT))
			So(err, ShouldBeNil)
			So(cfg, ShouldNotBeNil)

			cfg.NameMapper = func(raw string) string {
				if raw == "Byte" {
					return "NAME"
				}
				return raw
			}
			So(cfg.MapTo(&unsupport{}), ShouldNotBeNil)
			So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil)
			So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil)
		})

		Convey("Map from invalid data source", func() {
			So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
		})

		Convey("Map to wrong types and gain default values", func() {
			cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT))
			So(err, ShouldBeNil)

			t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
			So(err, ShouldBeNil)
			dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}}
			So(cfg.MapTo(dv), ShouldBeNil)
			So(dv.Name, ShouldEqual, "Joe")
			So(dv.Age, ShouldEqual, 10)
			So(dv.Male, ShouldBeTrue)
			So(dv.Money, ShouldEqual, 1.25)
			So(dv.Born.String(), ShouldEqual, t.String())
			So(strings.Join(dv.Cities, ","), ShouldEqual, "HangZhou,Boston")
		})
	})

	Convey("Reflect from struct", t, func() {
		type Embeded struct {
			Dates  []time.Time `delim:"|"`
			Places []string
			None   []int
		}
		type Author struct {
			Name      string `ini:"NAME"`
			Male      bool
			Age       int
			GPA       float64
			NeverMind string `ini:"-"`
			*Embeded  `ini:"infos"`
		}
		a := &Author{"Unknwon", true, 21, 2.8, "",
			&Embeded{
				[]time.Time{time.Now(), time.Now()},
				[]string{"HangZhou", "Boston"},
				[]int{},
			}}
		cfg := Empty()
		So(ReflectFrom(cfg, a), ShouldBeNil)
		cfg.SaveTo("testdata/conf_reflect.ini")

		Convey("Reflect from non-point struct", func() {
			So(ReflectFrom(cfg, Author{}), ShouldNotBeNil)
		})
	})
}
func Test_Values(t *testing.T) {
	Convey("Test getting and setting values", t, func() {
		cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
		So(err, ShouldBeNil)
		So(cfg, ShouldNotBeNil)

		Convey("Get values in default section", func() {
			sec := cfg.Section("")
			So(sec, ShouldNotBeNil)
			So(sec.Key("NAME").Value(), ShouldEqual, "ini")
			So(sec.Key("NAME").String(), ShouldEqual, "ini")
			So(sec.Key("NAME").Validate(func(in string) string {
				return in
			}), ShouldEqual, "ini")
			So(sec.Key("NAME").Comment, ShouldEqual, "; Package name")
			So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
		})

		Convey("Get values in non-default section", func() {
			sec := cfg.Section("author")
			So(sec, ShouldNotBeNil)
			So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
			So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon")

			sec = cfg.Section("package")
			So(sec, ShouldNotBeNil)
			So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
		})

		Convey("Get auto-increment key names", func() {
			keys := cfg.Section("features").Keys()
			for i, k := range keys {
				So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1))
			}
		})

		Convey("Get overwrite value", func() {
			So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "*****@*****.**")
		})

		Convey("Get sections", func() {
			sections := cfg.Sections()
			for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "advance"} {
				So(sections[i].Name(), ShouldEqual, name)
			}
		})

		Convey("Get parent section value", func() {
			So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
			So(cfg.Section("package.fake.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
		})

		Convey("Get multiple line value", func() {
			So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
		})

		Convey("Get values with type", func() {
			sec := cfg.Section("types")
			v1, err := sec.Key("BOOL").Bool()
			So(err, ShouldBeNil)
			So(v1, ShouldBeTrue)

			v1, err = sec.Key("BOOL_FALSE").Bool()
			So(err, ShouldBeNil)
			So(v1, ShouldBeFalse)

			v2, err := sec.Key("FLOAT64").Float64()
			So(err, ShouldBeNil)
			So(v2, ShouldEqual, 1.25)

			v3, err := sec.Key("INT").Int()
			So(err, ShouldBeNil)
			So(v3, ShouldEqual, 10)

			v4, err := sec.Key("INT").Int64()
			So(err, ShouldBeNil)
			So(v4, ShouldEqual, 10)

			v5, err := sec.Key("UINT").Uint()
			So(err, ShouldBeNil)
			So(v5, ShouldEqual, 3)

			v6, err := sec.Key("UINT").Uint64()
			So(err, ShouldBeNil)
			So(v6, ShouldEqual, 3)

			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			v7, err := sec.Key("TIME").Time()
			So(err, ShouldBeNil)
			So(v7.String(), ShouldEqual, t.String())

			Convey("Must get values with type", func() {
				So(sec.Key("STRING").MustString("404"), ShouldEqual, "str")
				So(sec.Key("BOOL").MustBool(), ShouldBeTrue)
				So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25)
				So(sec.Key("INT").MustInt(), ShouldEqual, 10)
				So(sec.Key("INT").MustInt64(), ShouldEqual, 10)
				So(sec.Key("UINT").MustUint(), ShouldEqual, 3)
				So(sec.Key("UINT").MustUint64(), ShouldEqual, 3)
				So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String())

				dur, err := time.ParseDuration("2h45m")
				So(err, ShouldBeNil)
				So(sec.Key("DURATION").MustDuration().Seconds(), ShouldEqual, dur.Seconds())

				Convey("Must get values with default value", func() {
					So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404")
					So(sec.Key("BOOL_404").MustBool(true), ShouldBeTrue)
					So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5)
					So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15)
					So(sec.Key("INT_404").MustInt64(15), ShouldEqual, 15)
					So(sec.Key("UINT_404").MustUint(6), ShouldEqual, 6)
					So(sec.Key("UINT_404").MustUint64(6), ShouldEqual, 6)

					t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
					So(err, ShouldBeNil)
					So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String())

					So(sec.Key("DURATION_404").MustDuration(dur).Seconds(), ShouldEqual, dur.Seconds())
				})
			})
		})

		Convey("Get value with candidates", func() {
			sec := cfg.Section("types")
			So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str")
			So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
			So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
			So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10)
			So(sec.Key("UINT").InUint(0, []uint{3, 6, 9}), ShouldEqual, 3)
			So(sec.Key("UINT").InUint64(0, []uint64{3, 6, 9}), ShouldEqual, 3)

			zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())

			Convey("Get value with candidates and default value", func() {
				So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str")
				So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
				So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10)
				So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10)
				So(sec.Key("UINT_404").InUint(3, []uint{3, 6, 9}), ShouldEqual, 3)
				So(sec.Key("UINT_404").InUint64(3, []uint64{3, 6, 9}), ShouldEqual, 3)
				So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
			})
		})

		Convey("Get values in range", func() {
			sec := cfg.Section("types")
			So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25)
			So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10)
			So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10)

			minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z")
			So(err, ShouldBeNil)
			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			So(sec.Key("TIME").RangeTime(t, minT, maxT).String(), ShouldEqual, t.String())

			Convey("Get value in range with default value", func() {
				So(sec.Key("FLOAT64").RangeFloat64(5, 0, 1), ShouldEqual, 5)
				So(sec.Key("INT").RangeInt(7, 0, 5), ShouldEqual, 7)
				So(sec.Key("INT").RangeInt64(7, 0, 5), ShouldEqual, 7)
				So(sec.Key("TIME").RangeTime(t, minT, midT).String(), ShouldEqual, t.String())
			})
		})

		Convey("Get values into slice", func() {
			sec := cfg.Section("array")
			So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de")
			So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0)

			vals1 := sec.Key("FLOAT64S").Float64s(",")
			float64sEqual(vals1, 1.1, 2.2, 3.3)

			vals2 := sec.Key("INTS").Ints(",")
			intsEqual(vals2, 1, 2, 3)

			vals3 := sec.Key("INTS").Int64s(",")
			int64sEqual(vals3, 1, 2, 3)

			vals4 := sec.Key("UINTS").Uints(",")
			uintsEqual(vals4, 1, 2, 3)

			vals5 := sec.Key("UINTS").Uint64s(",")
			uint64sEqual(vals5, 1, 2, 3)

			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			vals6 := sec.Key("TIMES").Times(",")
			timesEqual(vals6, t, t, t)
		})

		Convey("Get valid values into slice", func() {
			sec := cfg.Section("array")
			vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
			float64sEqual(vals1, 1.1, 2.2, 3.3)

			vals2 := sec.Key("INTS").ValidInts(",")
			intsEqual(vals2, 1, 2, 3)

			vals3 := sec.Key("INTS").ValidInt64s(",")
			int64sEqual(vals3, 1, 2, 3)

			vals4 := sec.Key("UINTS").ValidUints(",")
			uintsEqual(vals4, 1, 2, 3)

			vals5 := sec.Key("UINTS").ValidUint64s(",")
			uint64sEqual(vals5, 1, 2, 3)

			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			vals6 := sec.Key("TIMES").ValidTimes(",")
			timesEqual(vals6, t, t, t)
		})

		Convey("Get values one type into slice of another type", func() {
			sec := cfg.Section("array")
			vals1 := sec.Key("STRINGS").ValidFloat64s(",")
			So(vals1, ShouldBeEmpty)

			vals2 := sec.Key("STRINGS").ValidInts(",")
			So(vals2, ShouldBeEmpty)

			vals3 := sec.Key("STRINGS").ValidInt64s(",")
			So(vals3, ShouldBeEmpty)

			vals4 := sec.Key("STRINGS").ValidUints(",")
			So(vals4, ShouldBeEmpty)

			vals5 := sec.Key("STRINGS").ValidUint64s(",")
			So(vals5, ShouldBeEmpty)

			vals6 := sec.Key("STRINGS").ValidTimes(",")
			So(vals6, ShouldBeEmpty)
		})

		Convey("Get valid values into slice without errors", func() {
			sec := cfg.Section("array")
			vals1, err := sec.Key("FLOAT64S").StrictFloat64s(",")
			So(err, ShouldBeNil)
			float64sEqual(vals1, 1.1, 2.2, 3.3)

			vals2, err := sec.Key("INTS").StrictInts(",")
			So(err, ShouldBeNil)
			intsEqual(vals2, 1, 2, 3)

			vals3, err := sec.Key("INTS").StrictInt64s(",")
			So(err, ShouldBeNil)
			int64sEqual(vals3, 1, 2, 3)

			vals4, err := sec.Key("UINTS").StrictUints(",")
			So(err, ShouldBeNil)
			uintsEqual(vals4, 1, 2, 3)

			vals5, err := sec.Key("UINTS").StrictUint64s(",")
			So(err, ShouldBeNil)
			uint64sEqual(vals5, 1, 2, 3)

			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
			So(err, ShouldBeNil)
			vals6, err := sec.Key("TIMES").StrictTimes(",")
			So(err, ShouldBeNil)
			timesEqual(vals6, t, t, t)
		})

		Convey("Get invalid values into slice", func() {
			sec := cfg.Section("array")
			vals1, err := sec.Key("STRINGS").StrictFloat64s(",")
			So(vals1, ShouldBeEmpty)
			So(err, ShouldNotBeNil)

			vals2, err := sec.Key("STRINGS").StrictInts(",")
			So(vals2, ShouldBeEmpty)
			So(err, ShouldNotBeNil)

			vals3, err := sec.Key("STRINGS").StrictInt64s(",")
			So(vals3, ShouldBeEmpty)
			So(err, ShouldNotBeNil)

			vals4, err := sec.Key("STRINGS").StrictUints(",")
			So(vals4, ShouldBeEmpty)
			So(err, ShouldNotBeNil)

			vals5, err := sec.Key("STRINGS").StrictUint64s(",")
			So(vals5, ShouldBeEmpty)
			So(err, ShouldNotBeNil)

			vals6, err := sec.Key("STRINGS").StrictTimes(",")
			So(vals6, ShouldBeEmpty)
			So(err, ShouldNotBeNil)
		})

		Convey("Get key hash", func() {
			cfg.Section("").KeysHash()
		})

		Convey("Set key value", func() {
			k := cfg.Section("author").Key("NAME")
			k.SetValue("无闻")
			So(k.String(), ShouldEqual, "无闻")
		})

		Convey("Get key strings", func() {
			So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME,DURATION,UINT")
		})

		Convey("Delete a key", func() {
			cfg.Section("package.sub").DeleteKey("UNUSED_KEY")
			_, err := cfg.Section("package.sub").GetKey("UNUSED_KEY")
			So(err, ShouldNotBeNil)
		})

		Convey("Has Key (backwards compatible)", func() {
			sec := cfg.Section("package.sub")
			haskey1 := sec.Haskey("UNUSED_KEY")
			haskey2 := sec.Haskey("CLONE_URL")
			haskey3 := sec.Haskey("CLONE_URL_NO")
			So(haskey1, ShouldBeTrue)
			So(haskey2, ShouldBeTrue)
			So(haskey3, ShouldBeFalse)
		})

		Convey("Has Key", func() {
			sec := cfg.Section("package.sub")
			haskey1 := sec.HasKey("UNUSED_KEY")
			haskey2 := sec.HasKey("CLONE_URL")
			haskey3 := sec.HasKey("CLONE_URL_NO")
			So(haskey1, ShouldBeTrue)
			So(haskey2, ShouldBeTrue)
			So(haskey3, ShouldBeFalse)
		})

		Convey("Has Value", func() {
			sec := cfg.Section("author")
			hasvalue1 := sec.HasValue("Unknwon")
			hasvalue2 := sec.HasValue("doc")
			So(hasvalue1, ShouldBeTrue)
			So(hasvalue2, ShouldBeFalse)
		})

		Convey("Get section strings", func() {
			So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,comments,advance")
		})

		Convey("Delete a section", func() {
			cfg.DeleteSection("")
			So(cfg.SectionStrings()[0], ShouldNotEqual, DEFAULT_SECTION)
		})

		Convey("Create new sections", func() {
			cfg.NewSections("test", "test2")
			_, err := cfg.GetSection("test")
			So(err, ShouldBeNil)
			_, err = cfg.GetSection("test2")
			So(err, ShouldBeNil)
		})
	})

	Convey("Test getting and setting bad values", t, func() {
		cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
		So(err, ShouldBeNil)
		So(cfg, ShouldNotBeNil)

		Convey("Create new key with empty name", func() {
			k, err := cfg.Section("").NewKey("", "")
			So(err, ShouldNotBeNil)
			So(k, ShouldBeNil)
		})

		Convey("Create new section with empty name", func() {
			s, err := cfg.NewSection("")
			So(err, ShouldNotBeNil)
			So(s, ShouldBeNil)
		})

		Convey("Create new sections with empty name", func() {
			So(cfg.NewSections(""), ShouldNotBeNil)
		})

		Convey("Get section that not exists", func() {
			s, err := cfg.GetSection("404")
			So(err, ShouldNotBeNil)
			So(s, ShouldBeNil)

			s = cfg.Section("404")
			So(s, ShouldNotBeNil)
		})
	})

	Convey("Test key hash clone", t, func() {
		cfg, err := Load([]byte(strings.Replace("network=tcp,addr=127.0.0.1:6379,db=4,pool_size=100,idle_timeout=180", ",", "\n", -1)))
		So(err, ShouldBeNil)
		for _, v := range cfg.Section("").KeysHash() {
			So(len(v), ShouldBeGreaterThan, 0)
		}
	})

	Convey("Key has empty value", t, func() {
		_conf := `key1=
key2= ; comment`
		cfg, err := Load([]byte(_conf))
		So(err, ShouldBeNil)
		So(cfg.Section("").Key("key1").Value(), ShouldBeEmpty)
	})
}
Exemple #14
0
func Test_Struct(t *testing.T) {
	Convey("Map to struct", t, func() {
		Convey("Map file to struct", func() {
			ts := new(testStruct)
			So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)

			So(ts.Name, ShouldEqual, "Unknwon")
			So(ts.Age, ShouldEqual, 21)
			So(ts.Male, ShouldBeTrue)
			So(ts.Money, ShouldEqual, 1.25)
			So(ts.Unsigned, ShouldEqual, 3)

			t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
			So(err, ShouldBeNil)
			So(ts.Born.String(), ShouldEqual, t.String())

			dur, err := time.ParseDuration("2h45m")
			So(err, ShouldBeNil)
			So(ts.Time.Seconds(), ShouldEqual, dur.Seconds())

			So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston")
			So(ts.Others.Visits[0].String(), ShouldEqual, t.String())
			So(fmt.Sprint(ts.Others.Years), ShouldEqual, "[1993 1994]")
			So(fmt.Sprint(ts.Others.Numbers), ShouldEqual, "[10010 10086]")
			So(fmt.Sprint(ts.Others.Ages), ShouldEqual, "[18 19]")
			So(fmt.Sprint(ts.Others.Populations), ShouldEqual, "[12345678 98765432]")
			So(fmt.Sprint(ts.Others.Coordinates), ShouldEqual, "[192.168 10.11]")
			So(ts.Others.Note, ShouldEqual, "Hello world!")
			So(ts.testEmbeded.GPA, ShouldEqual, 2.8)
		})

		Convey("Map section to struct", func() {
			foobar := new(fooBar)
			f, err := Load([]byte(_CONF_DATA_STRUCT))
			So(err, ShouldBeNil)

			So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil)
			So(foobar.Here, ShouldEqual, "there")
			So(foobar.When, ShouldEqual, "then")
		})

		Convey("Map to non-pointer struct", func() {
			cfg, err := Load([]byte(_CONF_DATA_STRUCT))
			So(err, ShouldBeNil)
			So(cfg, ShouldNotBeNil)

			So(cfg.MapTo(testStruct{}), ShouldNotBeNil)
		})

		Convey("Map to unsupported type", func() {
			cfg, err := Load([]byte(_CONF_DATA_STRUCT))
			So(err, ShouldBeNil)
			So(cfg, ShouldNotBeNil)

			cfg.NameMapper = func(raw string) string {
				if raw == "Byte" {
					return "NAME"
				}
				return raw
			}
			So(cfg.MapTo(&unsupport{}), ShouldNotBeNil)
			So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil)
			So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil)
		})

		Convey("Map from invalid data source", func() {
			So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
		})

		Convey("Map to wrong types and gain default values", func() {
			cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT))
			So(err, ShouldBeNil)

			t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
			So(err, ShouldBeNil)
			dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}}
			So(cfg.MapTo(dv), ShouldBeNil)
			So(dv.Name, ShouldEqual, "Joe")
			So(dv.Age, ShouldEqual, 10)
			So(dv.Male, ShouldBeTrue)
			So(dv.Money, ShouldEqual, 1.25)
			So(dv.Born.String(), ShouldEqual, t.String())
			So(strings.Join(dv.Cities, ","), ShouldEqual, "HangZhou,Boston")
		})
	})

	Convey("Reflect from struct", t, func() {
		type Embeded struct {
			Dates       []time.Time `delim:"|"`
			Places      []string
			Years       []int
			Numbers     []int64
			Ages        []uint
			Populations []uint64
			Coordinates []float64
			None        []int
		}
		type Author struct {
			Name      string `ini:"NAME"`
			Male      bool
			Age       int
			Height    uint
			GPA       float64
			Date      time.Time
			NeverMind string `ini:"-"`
			*Embeded  `ini:"infos"`
		}

		t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
		So(err, ShouldBeNil)
		a := &Author{"Unknwon", true, 21, 100, 2.8, t, "",
			&Embeded{
				[]time.Time{t, t},
				[]string{"HangZhou", "Boston"},
				[]int{1993, 1994},
				[]int64{10010, 10086},
				[]uint{18, 19},
				[]uint64{12345678, 98765432},
				[]float64{192.168, 10.11},
				[]int{},
			}}
		cfg := Empty()
		So(ReflectFrom(cfg, a), ShouldBeNil)

		var buf bytes.Buffer
		_, err = cfg.WriteTo(&buf)
		So(err, ShouldBeNil)
		So(buf.String(), ShouldEqual, `NAME   = Unknwon
Male   = true
Age    = 21
Height = 100
GPA    = 2.8
Date   = 1993-10-07T20:17:05Z

[infos]
Dates       = 1993-10-07T20:17:05Z|1993-10-07T20:17:05Z
Places      = HangZhou,Boston
Years       = 1993,1994
Numbers     = 10010,10086
Ages        = 18,19
Populations = 12345678,98765432
Coordinates = 192.168,10.11
None        = 

`)

		Convey("Reflect from non-point struct", func() {
			So(ReflectFrom(cfg, Author{}), ShouldNotBeNil)
		})
	})
}
Exemple #15
0
func TestGrammarIndex(t *testing.T) {
	// Build a simple BNF grammar description grammar.
	gb := parser.OpenGrammarBuilder()

	gb.Terminals("NONTERM", "COLEQ", "PIPE", "IDENTIFIER").
		Nonterminals("bnf", "ntdecl", "def", "ntort").
		Rule().Lhs("bnf").Rhs("ntdecl").
		Rule().Lhs("bnf").Rhs("ntdecl", "bnf").
		Rule().Lhs("ntdecl").Rhs("NONTERM", "COLEQ", "def").
		Rule().Lhs("ntdecl").Rhs("ntdecl", "PIPE", "def").
		Rule().Lhs("def").Rhs("ntort").
		Rule().Lhs("def").Rhs("ntort", "def").
		Rule().Lhs("ntort").Rhs("IDENTIFIER").
		Rule().Lhs("ntort").Rhs("NONTERM").
		Rule().Lhs("`*").Rhs("bnf", "`.").
		Name("simple-bnf")

	g, err := gb.Build()
	if err != nil {
		t.Error(err)
	}
	grammar := parser.GetIndexedGrammar(g)

	fmt.Println("Name: " + grammar.Name())
	terms := make([]string, grammar.NumTerminals())
	for i, t := range grammar.Terminals() {
		terms[i] = t.String()
	}
	nterms := make([]string, grammar.NumNonterminals())
	for i, t := range grammar.Nonterminals() {
		nterms[i] = t.String()
	}
	fmt.Println("Terminals: " + strings.Join(terms, ", "))
	fmt.Println("Nonterminals: " + strings.Join(nterms, ", "))
	fmt.Println("Productions:")
	for _, p := range grammar.Productions() {
		fmt.Println("   " + p.String())
	}

	idx, err := grammar.GetIndex("basic")
	if err != nil {
		t.Error()
		return
	}
	basicIndex := idx.(*BasicGrammarIndex)
	fmt.Println("Basic index type: '" + basicIndex.IndexName() + "'")
	fmt.Println("Production RHS starts: ")
	for idx := 0; idx < grammar.NumTerminals(); idx++ {
		term := grammar.Terminal(idx)
		starts := basicIndex.RhsStarts(term)
		if len(starts) == 0 {
			continue
		}
		fmt.Println("  " + term.String() + ":")
		for _, p := range starts {
			fmt.Println("   " + p.String())
		}
	}
	fmt.Println("\nProduction RHS ends: ")
	for idx := 0; idx < grammar.NumTerminals(); idx++ {
		term := grammar.Terminal(idx)
		starts := basicIndex.RhsEnds(term)
		if len(starts) == 0 {
			continue
		}
		fmt.Println("  " + term.String() + ":")
		for _, p := range starts {
			fmt.Println("   " + p.String())
		}
	}
	fmt.Println("\nProduction RHS contains: ")
	for idx := 0; idx < grammar.NumTerminals(); idx++ {
		term := grammar.Terminal(idx)
		starts := basicIndex.RhsContains(term)
		if len(starts) == 0 {
			continue
		}
		fmt.Println("  " + term.String() + ":")
		for _, p := range starts {
			fmt.Println("   " + p.String())
		}
	}
	fmt.Println("Grammar class:")
	idx, err = grammar.GetIndex(GRAMMAR_CLASS_INDEX)
	if err != nil {
		t.Error(err)
		return
	}
	gcidx := idx.(*GrammarClassIndex)
	fmt.Println("       type: " + gcidx.Class().String())
	fmt.Println(" regularity: " + gcidx.Regularity().String())
	idx, err = grammar.GetIndex(FIRST_FOLLOW_INDEX)
	if err != nil {
		t.Error(err)
		return
	}
	ffidx := idx.(*FFIndex)
	fmt.Println("FIRST(x): ")
	for _, p := range g.Nonterminals() {
		fmt.Println("  " + p.String())
		for _, k := range ffidx.Firsts(p) {
			fmt.Println("    " + k.String())
		}
	}
	fmt.Println("FOLLOW(x): ")
	for _, p := range g.Nonterminals() {
		fmt.Println("  " + p.String())
		for _, k := range ffidx.Follows(p) {
			fmt.Println("    " + k.String())
		}
	}
	for _, p := range g.Terminals() {
		fmt.Println("  " + p.String())
		for _, k := range ffidx.Firsts(p) {
			fmt.Println("    " + k.String())
		}
	}
}
Exemple #16
0
func TestIterator(t *testing.T) {
	var ts *TripleStore

	Convey("Given a prepared database", t, func() {
		tmpDir, _ := ioutil.TempDir(os.TempDir(), "cayley_test")
		t.Log(tmpDir)
		defer os.RemoveAll(tmpDir)
		ok := CreateNewLevelDB(tmpDir)
		So(ok, ShouldBeTrue)
		ts = NewTripleStore(tmpDir, nil)
		ts.AddTripleSet(makeTripleSet())
		var it graph.Iterator

		Convey("Can create an all iterator for nodes", func() {
			it = ts.GetNodesAllIterator()
			So(it, ShouldNotBeNil)

			Convey("Has basics", func() {
				size, accurate := it.Size()
				So(size, ShouldBeBetween, 0, 20)
				So(accurate, ShouldBeFalse)
				So(it.Type(), ShouldEqual, "all")
				re_it, ok := it.Optimize()
				So(ok, ShouldBeFalse)
				So(re_it, ShouldPointTo, it)
			})

			Convey("Iterates all nodes", func() {
				expected := []string{
					"A",
					"B",
					"C",
					"D",
					"E",
					"F",
					"G",
					"follows",
					"status",
					"cool",
					"status_graph",
				}
				sort.Strings(expected)
				actual := extractValuesFromIterator(ts, it)
				sort.Strings(actual)
				So(actual, ShouldResemble, expected)
				it.Reset()
				actual = extractValuesFromIterator(ts, it)
				sort.Strings(actual)
				So(actual, ShouldResemble, expected)

			})

			Convey("Contains a couple nodes", func() {
				So(it.Check(ts.GetIdFor("A")), ShouldBeTrue)
				So(it.Check(ts.GetIdFor("cool")), ShouldBeTrue)
				//So(it.Check(ts.GetIdFor("baller")), ShouldBeFalse)
			})

			Reset(func() {
				it.Reset()
			})
		})

		Convey("Can create an all iterator for edges", func() {
			it := ts.GetTriplesAllIterator()
			So(it, ShouldNotBeNil)
			Convey("Has basics", func() {
				size, accurate := it.Size()
				So(size, ShouldBeBetween, 0, 20)
				So(accurate, ShouldBeFalse)
				So(it.Type(), ShouldEqual, "all")
				re_it, ok := it.Optimize()
				So(ok, ShouldBeFalse)
				So(re_it, ShouldPointTo, it)
			})

			Convey("Iterates an edge", func() {
				edge_val, _ := it.Next()
				triple := ts.GetTriple(edge_val)
				set := makeTripleSet()
				var string_set []string
				for _, t := range set {
					string_set = append(string_set, t.String())
				}
				So(triple.String(), ShouldBeIn, string_set)
			})

			Reset(func() {
				ts.Close()
			})
		})
	})

}
Exemple #17
0
func Test_Struct(t *testing.T) {
	Convey("Map file to struct", t, func() {
		ts := new(testStruct)
		So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)

		So(ts.Name, ShouldEqual, "Unknwon")
		So(ts.Age, ShouldEqual, 21)
		So(ts.Male, ShouldBeTrue)
		So(ts.Money, ShouldEqual, 1.25)

		t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
		So(err, ShouldBeNil)
		So(ts.Born.String(), ShouldEqual, t.String())

		So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston")
		So(ts.Others.Visits[0].String(), ShouldEqual, t.String())
		So(ts.Others.Note, ShouldEqual, "Hello world!")
		So(ts.testEmbeded.GPA, ShouldEqual, 2.8)
	})

	Convey("Map to non-pointer struct", t, func() {
		cfg, err := Load([]byte(_CONF_DATA_STRUCT))
		So(err, ShouldBeNil)
		So(cfg, ShouldNotBeNil)

		So(cfg.MapTo(testStruct{}), ShouldNotBeNil)
	})

	Convey("Map to unsupported type", t, func() {
		cfg, err := Load([]byte(_CONF_DATA_STRUCT))
		So(err, ShouldBeNil)
		So(cfg, ShouldNotBeNil)

		cfg.NameMapper = func(raw string) string {
			if raw == "Byte" {
				return "NAME"
			}
			return raw
		}
		So(cfg.MapTo(&unsupport{}), ShouldNotBeNil)
		So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil)
		So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil)
	})

	Convey("Map from invalid data source", t, func() {
		So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
	})

	Convey("Map to wrong types and gain default values", t, func() {
		cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT))
		So(err, ShouldBeNil)

		t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
		So(err, ShouldBeNil)
		dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}}
		So(cfg.MapTo(dv), ShouldBeNil)
		So(dv.Name, ShouldEqual, "Joe")
		So(dv.Age, ShouldEqual, 10)
		So(dv.Male, ShouldBeTrue)
		So(dv.Money, ShouldEqual, 1.25)
		So(dv.Born.String(), ShouldEqual, t.String())
		So(strings.Join(dv.Cities, ","), ShouldEqual, "HangZhou,Boston")
	})
}
func TestTimeCapture(t *testing.T) {

	Convey("String output should windup in file (instead of os.Stdout) ", t, func() {
		stdout := os.Stdout
		defer func() { os.Stdout = stdout }()

		f, _ := ioutil.TempFile("/tmp", "tc-tests-")
		fmt.Println(f.Name())

		os.Stdout = f
		t := TimeCapture{}
		t.Dump()
		f.Sync()
		os.Stdout = stdout
		f.Close()

		bytes, _ := ioutil.ReadFile(f.Name())
		content := string(bytes)
		str := t.String()

		So(content, ShouldNotEqual, "")
		So(content, ShouldEqual, str)
	})

	Convey("Capture time should out a non-zero string", t, func() {
		delay := 100 * time.Millisecond
		tc := Capture(func() {
			<-time.After(delay)
		})
		buf := bytes.NewBufferString("")
		tc.Out(buf)
		s := buf.String()
		So(s, ShouldNotEqual, "")
	})

	Convey("Capture time of function should take >= delayed time", t, func() {
		delay := 200 * time.Millisecond
		tc := Capture(func() {
			<-time.After(delay)
		})
		So(tc.Elapsed(), ShouldBeGreaterThanOrEqualTo, delay)
	})

	Convey("A started delta should have a start >= to now", t, func() {
		d := &Delta{}
		t := time.Now().UnixNano()
		d.Start()

		So(d.start, ShouldBeGreaterThanOrEqualTo, t)
		So(d.end, ShouldEqual, 0)
		So(d.Elapsed(), ShouldBeGreaterThanOrEqualTo, 0)
	})

	Convey("Should only be able to call Stop() once and capture that timestamp", t, func() {
		d := &Delta{}
		d.Start()
		<-time.NewTimer(50 * time.Millisecond).C
		d.Stop()
		originalStop := d.end
		<-time.NewTimer(50 * time.Millisecond).C
		d.Stop()

		So(d.isStarted, ShouldBeTrue)
		So(d.isStopped, ShouldBeTrue)
		So(d.end, ShouldEqual, originalStop)
	})

	Convey("Should only be able to call Start() once and capture that timestamp", t, func() {
		d := &Delta{}
		d.Start()
		originalStart := d.start
		<-time.NewTimer(50 * time.Millisecond).C
		d.Start()

		So(d.isStopped, ShouldBeFalse)
		So(d.isStarted, ShouldBeTrue)
		So(d.start, ShouldEqual, originalStart)
	})

	Convey("Calling Elapsed() should stop the timer", t, func() {
		d := &Delta{}
		d.Elapsed()
		So(d.isStopped, ShouldBeTrue)
	})

	Convey("New Delta should have ellapsed time of 0", t, func() {
		d := &Delta{}
		So(d.start, ShouldEqual, 0)
		So(d.end, ShouldEqual, 0)
		So(d.isStarted, ShouldBeFalse)
		So(d.isStopped, ShouldBeFalse)
		So(d.Diff(), ShouldEqual, 0)
		So(int64(d.Elapsed()), ShouldBeGreaterThan, 0)
	})
}