func GetConfig(rootDir string) cfg.Config {
	rootDir = getTMRoot(rootDir)
	initTMRoot(rootDir)

	var mapConfig = cfg.MapConfig(make(map[string]interface{}))
	configFilePath := path.Join(rootDir, "config.toml")
	configFileBytes := MustReadFile(configFilePath)
	err := toml.Unmarshal(configFileBytes, mapConfig)
	if err != nil {
		Exit(Fmt("Could not read config: %v", err))
	}

	// Set defaults or panic
	if mapConfig.IsSet("chain_id") {
		Exit("Cannot set 'chain_id' via config.toml")
	}
	if mapConfig.IsSet("version") {
		Exit("Cannot set 'version' via config.toml")
	}
	mapConfig.SetDefault("chain_id", "tendermint_test")
	mapConfig.SetDefault("version", "0.5.0")
	mapConfig.SetDefault("genesis_file", rootDir+"/genesis.json")
	mapConfig.SetDefault("moniker", "anonymous")
	mapConfig.SetDefault("node_laddr", "0.0.0.0:36656")
	mapConfig.SetDefault("fast_sync", false)
	mapConfig.SetDefault("skip_upnp", true)
	mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
	mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
	mapConfig.SetDefault("db_backend", "memdb")
	mapConfig.SetDefault("db_dir", rootDir+"/data")
	mapConfig.SetDefault("log_level", "debug")
	mapConfig.SetDefault("rpc_laddr", "0.0.0.0:36657")
	mapConfig.SetDefault("revisions_file", rootDir+"/revisions")
	return mapConfig
}
func testUnmarshal(t *testing.T, testcases []testcase) {
	for _, v := range testcases {
		var actual error = toml.Unmarshal([]byte(v.data), v.actual)
		var expect error = v.err
		if !reflect.DeepEqual(actual, expect) {
			t.Errorf(`toml.Unmarshal([]byte(%#v), %#v) => %#v; want %#v`, v.data, nil, actual, expect)
		}
		if !reflect.DeepEqual(v.actual, v.expect) {
			t.Errorf(`toml.Unmarshal([]byte(%#v), v); v => %#v; want %#v`, v.data, v.actual, v.expect)
		}
	}
}
func TestUnmarshal_WithUnmarshaler(t *testing.T) {
	type testStruct struct {
		Title         UnmarshalString
		MaxConn       UnmarshalString
		Ports         UnmarshalString
		Servers       UnmarshalString
		Table         UnmarshalString
		Arraytable    UnmarshalString
		ArrayOfStruct []testUnmarshalStruct
	}
	data := `title = "testtitle"
max_conn = 777
ports = [8080, 8081, 8082]
servers = [1, 2, 3]
[table]
name = "alice"
[[arraytable]]
name = "alice"
[[arraytable]]
name = "bob"
[[array_of_struct]]
title = "Alice's Adventures in Wonderland"
author = "Lewis Carroll"
`
	var v testStruct
	if err := toml.Unmarshal([]byte(data), &v); err != nil {
		t.Fatal(err)
	}
	actual := v
	expect := testStruct{
		Title:      `UnmarshalString: "testtitle"`,
		MaxConn:    `UnmarshalString: 777`,
		Ports:      `UnmarshalString: [8080, 8081, 8082]`,
		Servers:    `UnmarshalString: [1, 2, 3]`,
		Table:      "UnmarshalString: [table]\nname = \"alice\"",
		Arraytable: "UnmarshalString: [[arraytable]]\nname = \"alice\"\n[[arraytable]]\nname = \"bob\"",
		ArrayOfStruct: []testUnmarshalStruct{
			{
				Title:  "Unmarshaled: [[array_of_struct]]\ntitle = \"Alice's Adventures in Wonderland\"\nauthor = \"Lewis Carroll\"",
				Author: "",
			},
		},
	}
	if !reflect.DeepEqual(actual, expect) {
		t.Errorf(`toml.Unmarshal(data, &v); v => %#v; want %#v`, actual, expect)
	}
}
func TestUnmarshal_WithUnmarshalerForTopLevelStruct(t *testing.T) {
	data := `title = "Alice's Adventures in Wonderland"
author = "Lewis Carroll"
`
	var v testUnmarshalStruct
	if err := toml.Unmarshal([]byte(data), &v); err != nil {
		t.Fatal(err)
	}
	actual := v
	expect := testUnmarshalStruct{
		Title: `Unmarshaled: title = "Alice's Adventures in Wonderland"
author = "Lewis Carroll"
`,
		Author: "",
	}
	if !reflect.DeepEqual(actual, expect) {
		t.Errorf(`toml.Unmarshal(data, &v); v => %#v; want %#v`, actual, expect)
	}
}
func TestUnmarshal_WithMultibyteString(t *testing.T) {
	type testStruct struct {
		Name    string
		Numbers []string
	}
	v := testStruct{}
	data := `name = "七一〇七"
numbers = ["壱", "弐", "参"]
`
	if err := toml.Unmarshal([]byte(data), &v); err != nil {
		t.Fatal(err)
	}
	actual := v
	expect := testStruct{
		Name:    "七一〇七",
		Numbers: []string{"壱", "弐", "参"},
	}
	if !reflect.DeepEqual(actual, expect) {
		t.Errorf(`toml.Unmarshal([]byte(data), &v); v => %#v; want %#v`, actual, expect)
	}
}
func BenchmarkUnmarshal(b *testing.B) {
	var v struct {
		Title string
		Owner struct {
			Name         string
			Organization string
			Bio          string
			Dob          time.Time
		}
		Database struct {
			Server        string
			Ports         []int
			ConnectionMax int
			Enabled       bool
		}
		Servers struct {
			Alpha struct {
				IP string
				DC string
			}
			Beta struct {
				IP string
				DC string
			}
		}
		Clients struct {
			Data  []interface{}
			Hosts []string
		}
	}
	data, err := loadTestData()
	if err != nil {
		b.Fatal(err)
	}
	for i := 0; i < b.N; i++ {
		if err := toml.Unmarshal(data, &v); err != nil {
			b.Fatal(err)
		}
	}
}
func GetConfig(rootDir string) cfg.Config {
	rootDir = getTMRoot(rootDir)
	initTMRoot(rootDir)

	var mapConfig = cfg.MapConfig(make(map[string]interface{}))
	configFilePath := path.Join(rootDir, "config.toml")
	configFileBytes := MustReadFile(configFilePath)
	err := toml.Unmarshal(configFileBytes, mapConfig)
	if err != nil {
		Exit(Fmt("Could not read config: %v", err))
	}

	// Set defaults or panic
	if mapConfig.IsSet("chain_id") {
		Exit("Cannot set 'chain_id' via config.toml")
	}
	if mapConfig.IsSet("version") {
		Exit("Cannot set 'version' via config.toml")
	}
	mapConfig.SetDefault("chain_id", "tendermint_testnet_10")
	// Major: alpha
	// Minor: encrypted p2p!
	// Revision: ripemd for NewContractAddress
	mapConfig.SetDefault("version", "0.5.1")
	mapConfig.SetDefault("genesis_file", rootDir+"/genesis.json")
	mapConfig.SetDefault("moniker", "anonymous")
	mapConfig.SetDefault("node_laddr", "0.0.0.0:46656")
	// mapConfig.SetDefault("seeds", "goldenalchemist.chaintest.net:46656")
	mapConfig.SetDefault("fast_sync", true)
	mapConfig.SetDefault("skip_upnp", false)
	mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
	mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
	mapConfig.SetDefault("db_backend", "leveldb")
	mapConfig.SetDefault("db_dir", rootDir+"/data")
	mapConfig.SetDefault("log_level", "info")
	mapConfig.SetDefault("rpc_laddr", "0.0.0.0:46657")
	mapConfig.SetDefault("revisions_file", rootDir+"/revisions")
	return mapConfig
}
func TestUnmarshal(t *testing.T) {
	data, err := loadTestData()
	if err != nil {
		t.Fatal(err)
	}
	var v testStruct
	var actual interface{} = toml.Unmarshal(data, &v)
	var expect interface{} = nil
	if !reflect.DeepEqual(actual, expect) {
		t.Errorf(`toml.Unmarshal(data, &testStruct{}) => %#v; want %#v`, actual, expect)
	}

	actual = v
	expect = testStruct{
		Table: Table{
			Key: "value",
			Subtable: Subtable{
				Key: "another value",
			},
			Inline: Inline{
				Name: Name{
					First: "Tom",
					Last:  "Preston-Werner",
				},
				Point: Point{
					X: 1,
					Y: 2,
				},
			},
		},
		X: X{},
		String: String{
			Basic: Basic{
				Basic: "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF.",
			},
			Multiline: Multiline{
				Key1: "One\nTwo",
				Key2: "One\nTwo",
				Key3: "One\nTwo",
				Continued: Continued{
					Key1: "The quick brown fox jumps over the lazy dog.",
					Key2: "The quick brown fox jumps over the lazy dog.",
					Key3: "The quick brown fox jumps over the lazy dog.",
				},
			},
			Literal: Literal{
				Winpath:  `C:\Users\nodejs\templates`,
				Winpath2: `\\ServerX\admin$\system32\`,
				Quoted:   `Tom "Dubs" Preston-Werner`,
				Regex:    `<\i\c*\s*>`,
				Multiline: LiteralMultiline{
					Regex2: `I [dw]on't need \d{2} apples`,
					Lines:  "The first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n",
				},
			},
		},
		Integer: Integer{
			Key1: 99,
			Key2: 42,
			Key3: 0,
			Key4: -17,
			Underscores: IntegerUnderscores{
				Key1: 1000,
				Key2: 5349221,
				Key3: 12345,
			},
		},
		Float: Float{
			Fractional: Fractional{
				Key1: 1.0,
				Key2: 3.1415,
				Key3: -0.01,
			},
			Exponent: Exponent{
				Key1: 5e22,
				Key2: 1e6,
				Key3: -2e-2,
			},
			Both: Both{
				Key: 6.626e-34,
			},
			Underscores: FloatUnderscores{
				Key1: 9224617.445991228313,
				Key2: 1e100,
			},
		},
		Boolean: Boolean{
			True:  true,
			False: false,
		},
		Datetime: Datetime{
			Key1: mustTime(time.Parse(time.RFC3339Nano, "1979-05-27T07:32:00Z")),
			Key2: mustTime(time.Parse(time.RFC3339Nano, "1979-05-27T00:32:00-07:00")),
			Key3: mustTime(time.Parse(time.RFC3339Nano, "1979-05-27T00:32:00.999999-07:00")),
		},
		Array: Array{
			Key1: []int{1, 2, 3},
			Key2: []string{"red", "yellow", "green"},
			Key3: [][]int{{1, 2}, {3, 4, 5}},
			Key4: [][]interface{}{{int64(1), int64(2)}, {"a", "b", "c"}},
			Key5: []int{1, 2, 3},
			Key6: []int{1, 2},
		},
		Products: []Product{
			{Name: "Hammer", Sku: 738594937},
			{},
			{Name: "Nail", Sku: 284758393, Color: "gray"},
		},
		Fruit: []Fruit{
			{
				Name: "apple",
				Physical: Physical{
					Color: "red",
					Shape: "round",
				},
				Variety: []Variety{
					{Name: "red delicious"},
					{Name: "granny smith"},
				},
			},
			{
				Name: "banana",
				Variety: []Variety{
					{Name: "plantain"},
				},
			},
		},
	}
	if !reflect.DeepEqual(actual, expect) {
		t.Errorf(`toml.Unmarshal(data, v); v => %#v; want %#v`, actual, expect)
	}
}