func TestMarshal(t *testing.T) {
	SetDefault("port", 1313)
	Set("name", "Steve")

	type config struct {
		Port int
		Name string
	}

	var C config

	err := Marshal(&C)
	if err != nil {
		t.Fatalf("unable to decode into struct, %v", err)
	}

	assert.Equal(t, &C, &config{Name: "Steve", Port: 1313})

	Set("port", 1234)
	err = Marshal(&C)
	if err != nil {
		t.Fatalf("unable to decode into struct, %v", err)
	}
	assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
}
func TestRemoveSetting(t *testing.T) {
	r := createRouter()

	// It should return 400 if the id is invalid
	req := testRequest(r, "DELETE", "/account/settings/cake", nil)
	req.Header.Set("Authorization", "token")
	assert.Equal(t, 400, req.send().Code)

	// It should return 404 when the setting does not exist
	req.URL.Path = "/account/settings/1881"
	assert.Equal(t, 404, req.send().Code)

	// It should return 200 when removing a setting
	req.URL.Path = "/account/settings/1"
	assert.Equal(t, 200, req.send().Code)

	// It should have removed the setting
	req.Method = "GET"
	req.URL.Path = "/account/settings"
	res := req.send()
	assert.Equal(t, 200, res.Code)
	settings := []Setting{}
	err := json.Unmarshal(res.Body.Bytes(), &settings)
	assert.Nil(t, err)

	for _, setting := range settings {
		if setting.ID == 1 {
			t.Error("Setting with ID 1 did not get removed")
		}
	}
}
func TestGzip(t *testing.T) {
	req, _ := http.NewRequest(echo.GET, "/", nil)
	rec := httptest.NewRecorder()
	c := echo.NewContext(req, echo.NewResponse(rec), echo.New())
	h := func(c *echo.Context) error {
		return c.String(http.StatusOK, "test")
	}

	// Skip if no Accept-Encoding header
	Gzip()(h)(c)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "test", rec.Body.String())

	// Gzip
	req, _ = http.NewRequest(echo.GET, "/", nil)
	req.Header.Set(echo.AcceptEncoding, "gzip")
	rec = httptest.NewRecorder()
	c = echo.NewContext(req, echo.NewResponse(rec), echo.New())
	Gzip()(h)(c)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "gzip", rec.Header().Get(echo.ContentEncoding))
	r, err := gzip.NewReader(rec.Body)
	defer r.Close()
	if assert.NoError(t, err) {
		buf := new(bytes.Buffer)
		buf.ReadFrom(r)
		assert.Equal(t, "test", buf.String())
	}
}
func TestGetEpisodes(t *testing.T) {
	r := createRouter()

	expectedJSON := testJSON([]Episode{
		Episode{
			ID:     1,
			CastID: 1,
		},
	})

	// It should return 200 and a list of episodes
	req := testRequest(r, "GET", "/library/episodes/1", nil)
	req.Header.Set("Authorization", "token")
	res := req.send()
	assert.Equal(t, 200, res.Code)
	assert.Equal(t, expectedJSON, res.Body.String())

	// It should return 200 and an empty list if the cast is not found
	req.URL.Path = "/library/episodes/1337"
	res = req.send()
	assert.Equal(t, 200, res.Code)
	assert.Equal(t, testJSON([]Episode{}), res.Body.String())

	// It should return 400 if the ID is invalid
	req.URL.Path = "/library/episodes/datcast"
	assert.Equal(t, 400, req.send().Code)
}
func TestRouterMultiRoute(t *testing.T) {
	e := New()
	r := e.router

	// Routes
	r.Add(GET, "/users", func(c *Context) error {
		c.Set("path", "/users")
		return nil
	}, e)
	r.Add(GET, "/users/:id", func(c *Context) error {
		return nil
	}, e)
	c := NewContext(nil, nil, e)

	// Route > /users
	h, _ := r.Find(GET, "/users", c)
	if assert.NotNil(t, h) {
		h(c)
		assert.Equal(t, "/users", c.Get("path"))
	}

	// Route > /users/:id
	h, _ = r.Find(GET, "/users/1", c)
	if assert.NotNil(t, h) {
		assert.Equal(t, "1", c.P(0))
	}

	// Route > /user
	h, _ = r.Find(GET, "/user", c)
	assert.Nil(t, h)
}
func TestAddEvents(t *testing.T) {
	r := createRouter()

	// It should return 400 if json is not set
	req := testRequest(r, "POST", "/library/events", nil)
	req.Header.Set("Authorization", "evtest1")
	assert.Equal(t, 400, req.send().Code)

	// It should return 400 if the json is bad
	req.PostForm = url.Values{}
	req.PostForm.Set("json", "real_bad_json")
	assert.Equal(t, 400, req.send().Code)

	// It should return 200 when proper json is sent
	req.PostForm.Set("json", testJSON([]Event{
		Event{
			Type:              30,
			EpisodeID:         10,
			PositionTS:        481,
			ClientTS:          11,
			ConcurrentOrder:   0,
			ClientName:        "Castcloud",
			ClientDescription: "oink",
		},
	}))
	assert.Equal(t, 200, req.send().Code)

	// There should now be 2 events
	req.Method = "GET"
	res := checkEvents(t, req)
	assert.Len(t, res.Events, 2)
}
func TestStoreGetCasts(t *testing.T) {
	casts := store.GetCasts()
	assert.NotNil(t, casts)
	assert.True(t, len(casts) > 0)
	assert.Equal(t, uint64(1), casts[0].ID)
	assert.Equal(t, "test.go", casts[0].URL)
}
func TestEchoHandler(t *testing.T) {
	e := New()

	// HandlerFunc
	e.Get("/1", HandlerFunc(func(c *Context) error {
		return c.String(http.StatusOK, "1")
	}))

	// func(*echo.Context) error
	e.Get("/2", func(c *Context) error {
		return c.String(http.StatusOK, "2")
	})

	// http.Handler/http.HandlerFunc
	e.Get("/3", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("3"))
	}))

	// func(http.ResponseWriter, *http.Request)
	e.Get("/4", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("4"))
	})

	for _, p := range []string{"1", "2", "3", "4"} {
		c, b := request(GET, "/"+p, e)
		assert.Equal(t, http.StatusOK, c)
		assert.Equal(t, p, b)
	}

	// Unknown
	assert.Panics(t, func() {
		e.Get("/5", nil)
	})
}
func TestAliasInConfigFile(t *testing.T) {
	// the config file specifies "beard".  If we make this an alias for
	// "hasbeard", we still want the old config file to work with beard.
	RegisterAlias("beard", "hasbeard")
	assert.Equal(t, true, Get("hasbeard"))
	Set("hasbeard", false)
	assert.Equal(t, false, Get("beard"))
}
func TestRedirectToSlash(t *testing.T) {
	req, _ := http.NewRequest(echo.GET, "/users", nil)
	rec := httptest.NewRecorder()
	c := echo.NewContext(req, echo.NewResponse(rec), echo.New())
	RedirectToSlash(RedirectToSlashOptions{Code: http.StatusTemporaryRedirect})(c)
	assert.Equal(t, http.StatusTemporaryRedirect, rec.Code)
	assert.Equal(t, "/users/", c.Response().Header().Get("Location"))
}
func TestLevels(t *testing.T) {
	SetStdoutThreshold(LevelError)
	assert.Equal(t, StdoutThreshold(), LevelError)
	SetLogThreshold(LevelCritical)
	assert.Equal(t, LogThreshold(), LevelCritical)
	assert.NotEqual(t, StdoutThreshold(), LevelCritical)
	SetStdoutThreshold(LevelWarn)
	assert.Equal(t, StdoutThreshold(), LevelWarn)
}
func TestGetSettings(t *testing.T) {
	r := createRouter()

	// It should return 200 and a list of settings
	req := testRequest(r, "GET", "/account/settings", nil)
	req.Header.Set("Authorization", "token")
	res := req.send()
	assert.Equal(t, 200, res.Code)
	assert.Equal(t, testJSON([]Setting{}), res.Body.String())
}
func TestJWTAuth(t *testing.T) {
	req, _ := http.NewRequest(echo.GET, "/", nil)
	rec := httptest.NewRecorder()
	c := echo.NewContext(req, echo.NewResponse(rec), echo.New())
	key := []byte("key")
	fn := func(kid string, method jwt.SigningMethod) ([]byte, error) {
		return key, nil
	}
	ja := JWTAuth(fn)
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims["foo"] = "bar"
	token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
	ts, err := token.SignedString(key)
	assert.NoError(t, err)

	// Valid credentials
	auth := Bearer + " " + ts
	req.Header.Set(echo.Authorization, auth)
	assert.NoError(t, ja(c))

	//---------------------
	// Invalid credentials
	//---------------------

	// Expired token
	token.Claims["exp"] = time.Now().Add(-time.Second).Unix()
	ts, err = token.SignedString(key)
	assert.NoError(t, err)
	auth = Bearer + " " + ts
	req.Header.Set(echo.Authorization, auth)
	he := ja(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusUnauthorized, he.Code())

	// Empty Authorization header
	req.Header.Set(echo.Authorization, "")
	he = ja(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusBadRequest, he.Code())

	// Invalid Authorization header
	auth = "token"
	req.Header.Set(echo.Authorization, auth)
	he = ja(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusBadRequest, he.Code())

	// Invalid scheme
	auth = "Bear token"
	req.Header.Set(echo.Authorization, auth)
	he = ja(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusBadRequest, he.Code())

	// WebSocket
	c.Request().Header.Set(echo.Upgrade, echo.WebSocket)
	assert.NoError(t, ja(c))
}
func TestEchoGroup(t *testing.T) {
	e := New()
	buf := new(bytes.Buffer)
	e.Use(func(*Context) error {
		buf.WriteString("0")
		return nil
	})
	h := func(*Context) error { return nil }

	//--------
	// Routes
	//--------

	e.Get("/users", h)

	// Group
	g1 := e.Group("/group1")
	g1.Use(func(*Context) error {
		buf.WriteString("1")
		return nil
	})
	g1.Get("/", h)

	// Group with no parent middleware
	g2 := e.Group("/group2", func(*Context) error {
		buf.WriteString("2")
		return nil
	})
	g2.Get("/", h)

	// Nested groups
	g3 := e.Group("/group3")
	g4 := g3.Group("/group4")
	g4.Get("/", func(c *Context) error {
		return c.NoContent(http.StatusOK)
	})

	request(GET, "/users", e)
	// println(len(e.middleware))
	assert.Equal(t, "0", buf.String())

	buf.Reset()
	request(GET, "/group1/", e)
	// println(len(g1.echo.middleware))
	assert.Equal(t, "01", buf.String())

	buf.Reset()
	request(GET, "/group2/", e)
	assert.Equal(t, "2", buf.String())

	buf.Reset()
	c, _ := request(GET, "/group3/group4/", e)
	assert.Equal(t, http.StatusOK, c)
}
func TestMarshalling(t *testing.T) {
	SetConfigType("yaml")
	r := bytes.NewReader(yamlExample)

	marshalReader(r, v.config)
	assert.True(t, InConfig("name"))
	assert.False(t, InConfig("state"))
	assert.Equal(t, "steve", Get("name"))
	assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
	assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim"}, Get("clothing"))
	assert.Equal(t, 35, Get("age"))
}
func TestResponse(t *testing.T) {
	w := httptest.NewRecorder()
	r := NewResponse(w)

	// SetWriter
	r.SetWriter(w)

	// Writer
	assert.Equal(t, w, r.Writer())

	// Header
	assert.NotNil(t, r.Header())

	// WriteHeader
	r.WriteHeader(http.StatusOK)
	assert.Equal(t, http.StatusOK, r.status)

	// Committed
	assert.True(t, r.committed)

	// Already committed
	r.WriteHeader(http.StatusTeapot)
	assert.NotEqual(t, http.StatusTeapot, r.Status())

	// Status
	r.status = http.StatusOK
	assert.Equal(t, http.StatusOK, r.Status())

	// Write
	s := "echo"
	_, err := r.Write([]byte(s))
	assert.NoError(t, err)

	// Flush
	r.Flush()

	// Size
	assert.EqualValues(t, len(s), r.Size())

	// Hijack
	assert.Panics(t, func() {
		r.Hijack()
	})

	// CloseNotify
	assert.Panics(t, func() {
		r.CloseNotify()
	})

	// reset
	r.reset(httptest.NewRecorder())
}
func TestReadBufConfig(t *testing.T) {
	v := New()
	v.SetConfigType("yaml")
	v.ReadConfig(bytes.NewBuffer(yamlExample))
	t.Log(v.AllKeys())

	assert.True(t, v.InConfig("name"))
	assert.False(t, v.InConfig("state"))
	assert.Equal(t, "steve", v.Get("name"))
	assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, v.Get("hobbies"))
	assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim"}, v.Get("clothing"))
	assert.Equal(t, 35, v.Get("age"))
}
func TestRemoveCast(t *testing.T) {
	r := createRouter()

	req := testRequest(r, "DELETE", "/library/casts/1", nil)
	req.Header.Set("Authorization", "token")
	assert.Equal(t, 200, req.send().Code)
	user := store.GetUser("test")
	assert.NotContains(t, user.Subscriptions, uint64(1))

	// It should return 400 if the ID is invalid
	req.URL.Path = "/library/casts/nope"
	assert.Equal(t, 400, req.send().Code)
}
func TestRouterMicroParam(t *testing.T) {
	e := New()
	r := e.router
	r.Add(GET, "/:a/:b/:c", func(c *Context) error {
		return nil
	}, e)
	c := NewContext(nil, nil, e)
	h, _ := r.Find(GET, "/1/2/3", c)
	if assert.NotNil(t, h) {
		assert.Equal(t, "1", c.P(0))
		assert.Equal(t, "2", c.P(1))
		assert.Equal(t, "3", c.P(2))
	}
}
func TestRemotePrecedence(t *testing.T) {
	initJSON()

	remote := bytes.NewReader(remoteExample)
	assert.Equal(t, "0001", Get("id"))
	marshalReader(remote, v.kvstore)
	assert.Equal(t, "0001", Get("id"))
	assert.NotEqual(t, "cronut", Get("type"))
	assert.Equal(t, "remote", Get("newkey"))
	Set("newkey", "newvalue")
	assert.NotEqual(t, "remote", Get("newkey"))
	assert.Equal(t, "newvalue", Get("newkey"))
	Set("newkey", "remote")
}
func TestPing(t *testing.T) {
	r := createRouter()

	// It should return 401 if no token is set
	req := testRequest(r, "GET", "/account/ping", nil)
	assert.Equal(t, 401, req.send().Code)

	// It should return 401 if the token is invalid
	req.Header.Set("Authorization", "apples")
	assert.Equal(t, 401, req.send().Code)

	// It should return 200 if the token is valid
	req.Header.Set("Authorization", "token")
	assert.Equal(t, 200, req.send().Code)
}
func TestAddUser(t *testing.T) {
	err := store.AddUser(&User{
		Username: "******",
		Password: "******",
	})
	assert.Nil(t, err)

	user := store.GetUser("added")
	assert.NotNil(t, user)
	assert.Equal(t, "added", user.Username)
	assert.NotEmpty(t, user.Password)

	err = store.AddUser(&User{Username: "******"})
	assert.Equal(t, ErrUsernameUnavailable, err)
}
func TestAllKeys(t *testing.T) {
	initConfigs()

	ks := sort.StringSlice{"title", "newkey", "owner", "name", "beard", "ppu", "batters", "hobbies", "clothing", "age", "hacker", "id", "type", "eyes", "p_id", "p_ppu", "p_batters.batter.type", "p_type", "p_name"}
	dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
	all := map[string]interface{}{"owner": map[string]interface{}{"organization": "MongoDB", "Bio": "MongoDB Chief Developer Advocate & Hacker at Large", "dob": dob}, "title": "TOML Example", "ppu": 0.55, "eyes": "brown", "clothing": map[interface{}]interface{}{"trousers": "denim", "jacket": "leather"}, "id": "0001", "batters": map[string]interface{}{"batter": []interface{}{map[string]interface{}{"type": "Regular"}, map[string]interface{}{"type": "Chocolate"}, map[string]interface{}{"type": "Blueberry"}, map[string]interface{}{"type": "Devil's Food"}}}, "hacker": true, "beard": true, "hobbies": []interface{}{"skateboarding", "snowboarding", "go"}, "age": 35, "type": "donut", "newkey": "remote", "name": "Cake", "p_id": "0001", "p_ppu": "0.55", "p_name": "Cake", "p_batters.batter.type": "Regular", "p_type": "donut"}

	var allkeys sort.StringSlice
	allkeys = AllKeys()
	allkeys.Sort()
	ks.Sort()

	assert.Equal(t, ks, allkeys)
	assert.Equal(t, all, AllSettings())
}
func TestBasicAuth(t *testing.T) {
	req, _ := http.NewRequest(echo.GET, "/", nil)
	rec := httptest.NewRecorder()
	c := echo.NewContext(req, echo.NewResponse(rec), echo.New())
	fn := func(u, p string) bool {
		if u == "joe" && p == "secret" {
			return true
		}
		return false
	}
	ba := BasicAuth(fn)

	// Valid credentials
	auth := Basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret"))
	req.Header.Set(echo.Authorization, auth)
	assert.NoError(t, ba(c))

	//---------------------
	// Invalid credentials
	//---------------------

	// Incorrect password
	auth = Basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password"))
	req.Header.Set(echo.Authorization, auth)
	he := ba(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusUnauthorized, he.Code())

	// Empty Authorization header
	req.Header.Set(echo.Authorization, "")
	he = ba(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusBadRequest, he.Code())

	// Invalid Authorization header
	auth = base64.StdEncoding.EncodeToString([]byte(" :secret"))
	req.Header.Set(echo.Authorization, auth)
	he = ba(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusBadRequest, he.Code())

	// Invalid scheme
	auth = "Base " + base64.StdEncoding.EncodeToString([]byte(" :secret"))
	req.Header.Set(echo.Authorization, auth)
	he = ba(c).(*echo.HTTPError)
	assert.Equal(t, http.StatusBadRequest, he.Code())

	// WebSocket
	c.Request().Header.Set(echo.Upgrade, echo.WebSocket)
	assert.NoError(t, ba(c))
}
func TestStripTrailingSlash(t *testing.T) {
	req, _ := http.NewRequest(echo.GET, "/users/", nil)
	rec := httptest.NewRecorder()
	c := echo.NewContext(req, echo.NewResponse(rec), echo.New())
	StripTrailingSlash()(c)
	assert.Equal(t, "/users", c.Request().URL.Path)
}
func TestAutoEnv(t *testing.T) {
	Reset()

	AutomaticEnv()
	os.Setenv("FOO_BAR", "13")
	assert.Equal(t, "13", Get("foo_bar"))
}
func TestEchoFavicon(t *testing.T) {
	e := New()
	e.Favicon("examples/website/public/favicon.ico")
	c, b := request(GET, "/favicon.ico", e)
	assert.Equal(t, http.StatusOK, c)
	assert.NotEmpty(t, b)
}
func TestEchoIndex(t *testing.T) {
	e := New()
	e.Index("examples/website/public/index.html")
	c, b := request(GET, "/", e)
	assert.Equal(t, http.StatusOK, c)
	assert.NotEmpty(t, b)
}
func TestEchoNotFound(t *testing.T) {
	e := New()
	r, _ := http.NewRequest(GET, "/files", nil)
	w := httptest.NewRecorder()
	e.ServeHTTP(w, r)
	assert.Equal(t, http.StatusNotFound, w.Code)
}
func TestBindPFlags(t *testing.T) {
	flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)

	var testValues = map[string]*string{
		"host":     nil,
		"port":     nil,
		"endpoint": nil,
	}

	var mutatedTestValues = map[string]string{
		"host":     "localhost",
		"port":     "6060",
		"endpoint": "/public",
	}

	for name, _ := range testValues {
		testValues[name] = flagSet.String(name, "", "test")
	}

	err := BindPFlags(flagSet)
	if err != nil {
		t.Fatalf("error binding flag set, %v", err)
	}

	flagSet.VisitAll(func(flag *pflag.Flag) {
		flag.Value.Set(mutatedTestValues[flag.Name])
		flag.Changed = true
	})

	for name, expected := range mutatedTestValues {
		assert.Equal(t, Get(name), expected)
	}

}