Пример #1
0
func TestWriteSuccessMessage(t *testing.T) {
	h := testhelper.New(t)

	tests := []struct {
		ecode int
		ebody string
	}{
		// Test A success message. The rest are tested above.
		{
			ecode: http.StatusOK,
			ebody: `{"Type":"success","Message":"Success."}`,
		},
	}

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating context", err)
	defer c.Close()

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest("GET", "/", nil)
		h.FatalNotNil("creating request", err)

		// Call the test function
		WriteSuccessMessage(c, w, r)

		// Check the values.
		h.ErrorNotEqual("response code", w.Code, test.ecode)
		h.ErrorNotEqual("response body", w.Body.String(), test.ebody)
	}
}
Пример #2
0
func TestUnmarshalOrFail(t *testing.T) {
	h := testhelper.New(t)

	tests := []struct {
		result bool
		ecode  int
		ebody  string
		bytes  []byte
		where  interface{}
	}{
		// Test a good unmarshal.
		{
			result: true,
			ecode:  0,
			ebody:  "",
			bytes:  []byte(`{"C":123}`),
			where:  &struct{ C int64 }{},
		},

		// Test a bad unmarshal.
		{
			result: false,
			ecode:  http.StatusBadRequest,
			ebody:  `{"Type":"error","Message":"Failed."}`,
			bytes:  []byte(`{"C":12`),
			where:  &struct{ C int64 }{},
		},
	}

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating context", err)
	defer c.Close()

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest("GET", "/", nil)
		h.FatalNotNil("creating request", err)

		// Call the test function
		results := UnmarshalOrFail(c, w, r, test.bytes, test.where)

		h.SetFunc("UnmarshalOrFail(c, w, r, test.bytes, test.where)")

		h.FatalNotEqual("umarshal results", results, test.result)

		// We don't get anything back on the wire if it succeeded.
		if test.result == true {
			continue
		}

		// Check the values.
		h.ErrorNotEqual("response code", w.Code, test.ecode)
		h.ErrorNotEqual("response body", w.Body.String(), test.ebody)
	}
}
Пример #3
0
func TestWriteJSON(t *testing.T) {
	h := testhelper.New(t)

	tests := []struct {
		data     interface{}
		code     int
		response string
	}{
		// Test the error case.
		{
			data: struct {
				C complex128
			}{
				C: complex(1, 1),
			},
			code:     http.StatusInternalServerError,
			response: `{"Type":"error","Message":"Something unexpected happened."}`,
		},

		// Test a normal case.
		{
			data: struct {
				C int64
			}{
				C: 123,
			},
			code:     http.StatusOK,
			response: `{"C":123}`,
		},
	}

	// We can use the same context for all tests.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating context", err)
	defer c.Close()

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest("GET", "/", nil)
		h.FatalNotNil("creating request", err)

		WriteJSON(c, w, r, test.data)

		// Check the values.
		h.ErrorNotEqual("response code", w.Code, test.code)
		h.ErrorNotEqual("response body", w.Body.String(), test.response)
	}
}
Пример #4
0
func TestLogAndMessage(t *testing.T) {
	h := testhelper.New(t)

	tests := []struct {
		method string
		url    string
		err    error
		ecode  int
		ebody  string
		mtype  string
		msg    string
	}{
		// Test A success message. The rest are tested above.
		{
			method: "GET",
			url:    "/",
			err:    nil,
			ecode:  http.StatusOK,
			ebody:  `{"Type":"success","Message":"Success."}`,
			mtype:  "success",
			msg:    "Success.",
		},
	}

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating context", err)
	defer c.Close()

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest(test.method, test.url, nil)
		h.FatalNotNil("creating request", err)

		h.SetFunc(`LogAndMessage(c, w, r, err("%v"), "%s, "%s", %d)`,
			test.err, test.mtype, test.msg, test.ecode)

		// Call the test function
		LogAndMessage(c, w, r, test.err, test.mtype, test.msg, test.ecode)

		// Check the values.
		h.ErrorNotEqual("response code", w.Code, test.ecode)
		h.ErrorNotEqual("response body", w.Body.String(), test.ebody)
	}
}
Пример #5
0
func TestNewKey(t *testing.T) {
	h := testhelper.New(t)

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating contxt", err)
	defer c.Close()

	// Make the request and writer.
	w := httptest.NewRecorder()
	r, err := http.NewRequest("GET", "/newkey", nil)
	h.FatalNotNil("creating request", err)

	skey, key, ok := NewKey(c, w, r, "Item", nil)

	h.ErrorNotEqual("new key", ok, true)
	h.ErrorNotEqual("keys", skey, key.Encode())
}
Пример #6
0
func TestGetUserLogoutURL(t *testing.T) {
	h := testhelper.New(t)

	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating context", err)
	defer c.Close()

	// Make the request and writer.
	w := httptest.NewRecorder()
	r, err := http.NewRequest("GET", "/", nil)
	h.FatalNotNil("creating request", err)

	url, ok := GetUserLogoutURL(c, w, r, "/")
	h.FatalNotEqual("getting url", ok, true)

	surl := "/_ah/login?continue=http%3A//127.0.0.1%3A"
	eurl := "/&action=Logout"
	if !strings.HasPrefix(url, surl) || !strings.HasSuffix(url, eurl) {
		t.Errorf("Expecting '%v' for url, but got: %v",
			surl+"[PORT]"+eurl, url)
	}
}
Пример #7
0
func TestDeleteStringKeyAndAncestors(t *testing.T) {
	// This also tests DeleteKeys.

	h := testhelper.New(t)

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating contxt", err)
	defer c.Close()

	// Make the request and writer.
	w := httptest.NewRecorder()
	r, err := http.NewRequest("GET", "/datastore", nil)
	h.FatalNotNil("creating request", err)

	// Make the parent
	parent := makeKey(c, nil)
	ok := PutStringKeys(c, w, r, []string{parent.Encode()}, []stringer{stringer{"parent"}})
	h.FatalNotEqual("put parent", ok, true)

	// Make the child
	child := makeKey(c, parent)
	ok = PutStringKeys(c, w, r, []string{child.Encode()}, []stringer{stringer{"child"}})
	h.FatalNotEqual("put child", ok, true)

	// Call the delete
	ok = DeleteStringKeyAndAncestors(c, w, r, "Item", parent.Encode())
	h.FatalNotEqual("delete ancestors", ok, true)

	// Check the parent
	var value stringer
	err = datastore.Get(c, parent, &value)
	h.ErrorNil("deleted parent", err)

	// Check the child
	err = datastore.Get(c, child, &value)
	h.ErrorNil("deleted child", err)
}
Пример #8
0
func TestGetUserOrUnexpected(t *testing.T) {
	h := testhelper.New(t)

	// We are going to reuse the context here.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating context", err)
	defer c.Close()

	tests := []struct {
		f       func()
		success bool
		email   string
		admin   bool
		ecode   int
		ebody   string
	}{
		// Test login for an admin user.
		{
			f: func() {
				c.Login("*****@*****.**", true)
			},
			success: true,
			email:   "*****@*****.**",
			admin:   true,
			ecode:   0,
			ebody:   "",
		},

		// Test login for a non admin user.
		{
			f: func() {
				c.Logout()
				c.Login("*****@*****.**", false)
			},
			success: true,
			email:   "*****@*****.**",
			admin:   false,
			ecode:   0,
			ebody:   "",
		},

		// Test being logged out.
		{
			f: func() {
				c.Logout()
			},
			success: false,
			email:   "",
			admin:   false,
			ecode:   http.StatusInternalServerError,
			ebody:   `{"Type":"error","Message":"Something unexpected happened."}`,
		},
	}

	for i, test := range tests {
		h.SetIndex(i)

		// Prep the test.
		test.f()

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest("GET", "/", nil)
		h.FatalNotNil("creating request", err)

		// Call the normal function
		u, ok := GetUserOrUnexpected(c, w, r)
		h.FatalNotEqual("success", ok, test.success)

		if test.success {
			// Check the user credentials
			h.ErrorNotEqual("email", u.Email, test.email)
			h.ErrorNotEqual("admin", u.Admin, test.admin)
		} else {
			// Check the values.
			h.ErrorNotEqual("response code", w.Code, test.ecode)
			h.ErrorNotEqual("response body", w.Body.String(), test.ebody)
		}
	}
}
Пример #9
0
func TestLogAnds(t *testing.T) {
	h := testhelper.New(t)

	// These are our test cases.
	tests := []struct {
		f      LogAndFunc
		fn     string
		method string
		url    string
		err    error
		ecode  int
		ebody  string
	}{
		// LogAndNotFound
		{
			f:      LogAndNotFound,
			fn:     "LogAndNotFound",
			method: "GET",
			url:    "/",
			err:    fmt.Errorf("no such file or directory"),
			ecode:  http.StatusNotFound,
			ebody:  `{"Type":"error","Message":"Not found."}`,
		},

		// LogAndFailed
		{
			f:      LogAndFailed,
			fn:     "LogAndFailed",
			method: "GET",
			url:    "/",
			err:    fmt.Errorf("oopsie, you failed"),
			ecode:  http.StatusBadRequest,
			ebody:  `{"Type":"error","Message":"Failed."}`,
		},

		// LogAndUnexpected
		{
			f:      LogAndUnexpected,
			fn:     "LogAndUnexpected",
			method: "GET",
			url:    "/",
			err:    fmt.Errorf("oopsie, i failed"),
			ecode:  http.StatusInternalServerError,
			ebody:  `{"Type":"error","Message":"Something unexpected happened."}`,
		},
	}

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating contxt", err)
	defer c.Close()

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest(test.method, test.url, nil)
		h.FatalNotNil("creating request", err)

		h.SetFunc(`%s(c, w, r, err("%v"))`, test.fn, test.err)

		// Call the test function
		test.f(c, w, r, test.err)

		// Check the values.
		h.ErrorNotEqual("response code", w.Code, test.ecode)
		h.ErrorNotEqual("response body", w.Body.String(), test.ebody)
	}
}
Пример #10
0
func TestUnmarshalFromBodyOrFail(t *testing.T) {
	h := testhelper.New(t)

	tests := []struct {
		body    string
		result  bool
		ecode   int
		ebody   string
		request *http.Request
		where   interface{}
	}{
		// Test a nil body.
		{
			result:  false,
			ecode:   http.StatusBadRequest,
			ebody:   `{"Type":"error","Message":"Failed."}`,
			request: newRequest("GET", "/", nil),
			where:   nil,
		},

		// Test a body that will fail reading.
		{
			result:  false,
			ecode:   http.StatusInternalServerError,
			ebody:   `{"Type":"error","Message":"Something unexpected happened."}`,
			request: newRequest("GET", "/", ErrorReader{}),
			where:   nil,
		},

		// Test a normal body.
		{
			result:  true,
			ecode:   0,
			ebody:   "",
			request: newRequest("GET", "/", strings.NewReader(`{"C":123}`)),
			where:   &struct{ C int64 }{},
		},

		// Test a JSON decoding error.
		{
			result:  false,
			ecode:   http.StatusBadRequest,
			ebody:   `{"Type":"error","Message":"Failed."}`,
			request: newRequest("GET", "/", strings.NewReader(`{"C":12`)),
			where:   &struct{ C int64 }{},
		},
	}

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating context", err)
	defer c.Close()

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()

		// Call the test function
		results := UnmarshalFromBodyOrFail(c, w, test.request, test.where)

		h.SetFunc("UnmarshalFromBodyOrFail(c, w, test.request, test.where)")

		h.FatalNotEqual("umarshal results", results, test.result)

		// If we failed, we should test the wire.
		if test.result == false {
			// Check the values.
			h.ErrorNotEqual("response code", w.Code, test.ecode)
			h.ErrorNotEqual("response body", w.Body.String(), test.ebody)
		}
	}
}
Пример #11
0
func TestPutStringKeys(t *testing.T) {
	// This also tests PutKeys.

	h := testhelper.New(t)

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating contxt", err)
	defer c.Close()

	// These are the tests
	tests := []struct {
		keys   []string
		values []stringer
		expect bool
	}{
		// An empty list.
		{
			keys:   []string{},
			values: []stringer{},
			expect: true,
		},

		// A normal list.
		{
			keys:   []string{makeKey(c, nil).Encode(), makeKey(c, nil).Encode()},
			values: []stringer{stringer{"one"}, stringer{"two"}},
			expect: true,
		},

		// More keys than values.
		{
			keys:   []string{makeKey(c, nil).Encode(), makeKey(c, nil).Encode()},
			values: []stringer{stringer{"one"}},
			expect: false,
		},

		// More values than keys.
		{
			keys:   []string{makeKey(c, nil).Encode(), makeKey(c, nil).Encode()},
			values: []stringer{stringer{"one"}, stringer{"two"}, stringer{"three"}},
			expect: false,
		},

		// Invalid key.
		{
			keys:   []string{makeKey(c, nil).Encode(), makeKey(c, nil).Encode(), "hahaha"},
			values: []stringer{stringer{"one"}, stringer{"two"}, stringer{"three"}},
			expect: false,
		},
	}

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest("GET", "/datastore", nil)
		h.FatalNotNil("creating request", err)

		result := PutStringKeys(c, w, r, test.keys, test.values)
		h.FatalNotEqual("put keys", result, test.expect)

		if test.expect == false {
			// Test the output.
			h.ErrorNotEqual("response code", w.Code, http.StatusInternalServerError)
			h.ErrorNotEqual("response body", w.Body.String(),
				`{"Type":"error","Message":"Something unexpected happened."}`)
		} else {
			for _, key := range test.keys {
				// Make sure each of the keys persisted.
				var value stringer
				k, err := datastore.DecodeKey(key)
				h.FatalNotNil("decoding key", err)

				err = datastore.Get(c, k, &value)
				h.FatalNotNil("datastore get", err)

				// High replication seems to make this impossible.
				// h.ErrorNotEqual("datastore value", test.values[j].s, value.s)
			}
		}
	}
}
Пример #12
0
func TestDeleteStringKeys(t *testing.T) {
	// This also tests DeleteKeys.

	h := testhelper.New(t)

	// We are going to reuse the context.
	c, err := appenginetesting.NewContext(nil)
	h.FatalNotNil("creating contxt", err)
	defer c.Close()

	// These are the tests
	tests := []struct {
		keys    []string
		values  []stringer
		inserts []bool
		deletes []bool
		expects []bool
	}{
		// A normal list.
		{
			keys: []string{
				makeKey(c, nil).Encode(),
				makeKey(c, nil).Encode(),
				makeKey(c, nil).Encode(),
				makeKey(c, nil).Encode(),
				makeKey(c, nil).Encode(),
				makeKey(c, nil).Encode(),
			},
			values: []stringer{
				stringer{"one"},
				stringer{"two"},
				stringer{"three"},
				stringer{"four"},
				stringer{"five"},
				stringer{"six"},
			},
			deletes: []bool{false, false, true, false, true, false},
		},
	}

	for i, test := range tests {
		h.SetIndex(i)

		// Make the request and writer.
		w := httptest.NewRecorder()
		r, err := http.NewRequest("GET", "/datastore", nil)
		h.FatalNotNil("creating request", err)

		// insert the items.
		ok := PutStringKeys(c, w, r, test.keys, test.values)
		h.FatalNotEqual("put keys", ok, true)

		// make the items to delete
		dkeys := make([]string, 0, 0)
		for j, key := range test.keys {
			if test.deletes[j] {
				dkeys = append(dkeys, key)
			}
		}

		h.SetFunc("DeleteStringKeys(c, w, r, %v)", dkeys)

		// delete the items
		ok = DeleteStringKeys(c, w, r, dkeys)

		// Check each of the items.
		for j, key := range test.keys {
			var value stringer
			k, err := datastore.DecodeKey(key)
			h.FatalNotNil("decoding key", err)

			err = datastore.Get(c, k, &value)
			if test.deletes[j] {
				h.ErrorNil("deleted item", err)
			} else {
				h.ErrorNotNil("deleted item", err)
			}
		}
	}
}