示例#1
0
func Test_Render_NoRace(t *testing.T) {
	// This test used to fail if run with -race
	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory: "fixtures/basic",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "hello", "world")
	})

	done := make(chan bool)
	doreq := func() {
		res := httptest.NewRecorder()
		req, _ := http.NewRequest("GET", "/foobar", nil)

		m.ServeHTTP(res, req)

		expect(t, res.Code, 200)
		expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
		// ContentLength should be deferred to the ResponseWriter and not Render
		expect(t, res.Header().Get(ContentLength), "")
		expect(t, res.Body.String(), "<h1>Hello world</h1>\n")
		done <- true
	}
	// Run two requests to check there is no race condition
	go doreq()
	go doreq()
	<-done
	<-done
}
示例#2
0
func performFileTest(t *testing.T, binder handlerFunc, testCase fileTestCase) {
	httpRecorder := httptest.NewRecorder()
	m := martini.Classic()

	fileTestHandler := func(actual BlogPost, errs Errors) {
		assertFileAsExpected(t, testCase, actual.HeaderImage, testCase.singleFile)

		if len(testCase.multipleFiles) != len(actual.Pictures) {
			t.Errorf("For '%s': Expected %d multiple files, but actually had %d instead",
				testCase.description, len(testCase.multipleFiles), len(actual.Pictures))
		}

		for i, expectedFile := range testCase.multipleFiles {
			if i >= len(actual.Pictures) {
				break
			}
			assertFileAsExpected(t, testCase, actual.Pictures[i], expectedFile)
		}
	}

	m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) {
		fileTestHandler(actual, errs)
	})

	m.ServeHTTP(httpRecorder, buildRequestWithFile(testCase))

	switch httpRecorder.Code {
	case http.StatusNotFound:
		panic("Routing is messed up in test fixture (got 404): check methods and paths")
	case http.StatusInternalServerError:
		panic("Something bad happened on '" + testCase.description + "'")
	}
}
示例#3
0
func Test_Render_Funcs(t *testing.T) {

	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory: "fixtures/custom_funcs",
		Funcs: []template.FuncMap{
			{
				"myCustomFunc": func() string {
					return "My custom function"
				},
			},
		},
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "index", "jeremy")
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Body.String(), "My custom function\n")
}
func performMultipartFormTest(t *testing.T, binder handlerFunc, testCase multipartFormTestCase) {
	httpRecorder := httptest.NewRecorder()
	m := martini.Classic()

	m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) {
		if testCase.shouldSucceed && len(errs) > 0 {
			t.Errorf("'%s' should have succeeded, but there were errors (%d):\n%+v",
				testCase.description, len(errs), errs)
		} else if !testCase.shouldSucceed && len(errs) == 0 {
			t.Errorf("'%s' should not have succeeded, but it did (there were no errors)", testCase.description)
		}
		expString := fmt.Sprintf("%+v", testCase.inputAndExpected)
		actString := fmt.Sprintf("%+v", actual)
		if actString != expString {
			t.Errorf("'%s': expected\n'%s'\nbut got\n'%s'",
				testCase.description, expString, actString)
		}
	})

	multipartPayload, mpWriter := makeMultipartPayload(testCase)

	req, err := http.NewRequest("POST", testRoute, multipartPayload)
	if err != nil {
		panic(err)
	}

	req.Header.Add("Content-Type", mpWriter.FormDataContentType())

	err = mpWriter.Close()
	if err != nil {
		panic(err)
	}

	if testCase.callFormValueBefore {
		req.FormValue("foo")
	}

	m.ServeHTTP(httpRecorder, req)

	switch httpRecorder.Code {
	case http.StatusNotFound:
		panic("Routing is messed up in test fixture (got 404): check methods and paths")
	case http.StatusInternalServerError:
		panic("Something bad happened on '" + testCase.description + "'")
	}
}
示例#5
0
// When binding from Form data, testing the type of data to bind
// and converting a string into that type is tedious, so these tests
// cover all those cases.
func TestSetWithProperType(t *testing.T) {
	testInputs := map[string]string{
		"successful": `integer=-1&integer8=-8&integer16=-16&integer32=-32&integer64=-64&uinteger=1&uinteger8=8&uinteger16=16&uinteger32=32&uinteger64=64&boolean_1=true&fl32_1=32.3232&fl64_1=-64.6464646464&str=string`,
		"errorful":   `integer=&integer8=asdf&integer16=--&integer32=&integer64=dsf&uinteger=&uinteger8=asdf&uinteger16=+&uinteger32= 32 &uinteger64=+%20+&boolean_1=&boolean_2=asdf&fl32_1=asdf&fl32_2=&fl64_1=&fl64_2=asdfstr`,
	}

	expectedOutputs := map[string]Everything{
		"successful": Everything{
			Integer:    -1,
			Integer8:   -8,
			Integer16:  -16,
			Integer32:  -32,
			Integer64:  -64,
			Uinteger:   1,
			Uinteger8:  8,
			Uinteger16: 16,
			Uinteger32: 32,
			Uinteger64: 64,
			Boolean_1:  true,
			Fl32_1:     32.3232,
			Fl64_1:     -64.6464646464,
			Str:        "string",
		},
		"errorful": Everything{},
	}

	for key, testCase := range testInputs {
		httpRecorder := httptest.NewRecorder()
		m := martini.Classic()

		m.Post(testRoute, Form(Everything{}), func(actual Everything, errs Errors) {
			actualStr := fmt.Sprintf("%+v", actual)
			expectedStr := fmt.Sprintf("%+v", expectedOutputs[key])
			if actualStr != expectedStr {
				t.Errorf("For '%s' expected\n%s but got\n%s", key, expectedStr, actualStr)
			}
		})
		req, err := http.NewRequest("POST", testRoute, strings.NewReader(testCase))
		if err != nil {
			panic(err)
		}
		req.Header.Set("Content-Type", formContentType)
		m.ServeHTTP(httpRecorder, req)
	}
}
示例#6
0
func Test_Render_Bad_HTML(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory: "fixtures/basic",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "nope", nil)
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 500)
	expect(t, res.Body.String(), "html/template: \"nope\" is undefined\n")
}
示例#7
0
func Test_Render_Layout_Current(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory: "fixtures/basic",
		Layout:    "current_layout",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "content", "jeremy")
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Body.String(), "content head\n<h1>jeremy</h1>\n\ncontent foot\n")
}
示例#8
0
func main() {

	// Initialize
	m := martini.Classic()

	// Connect to mongo
	m.Use(middlewares.Connect())

	// Templating support
	m.Use(middlewares.Templates())

	// Routes
	m.Get("/", articles.List)
	m.Get("/new", articles.AddEdit)
	m.Post("/articles", binding.Form(models.Article{}), articles.Add)
	m.Get("/articles/:_id", articles.Show)

	// Start listening
	m.Run()
}
示例#9
0
func Test_Render_XML(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
	// nothing here to configure
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.XML(300, GreetingXML{One: "hello", Two: "world"})
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 300)
	expect(t, res.Header().Get(ContentType), ContentXML+"; charset=UTF-8")
	expect(t, res.Body.String(), `<greeting one="hello" two="world"></greeting>`)
}
示例#10
0
func Test_Render_Charset_JSON(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Charset: "foobar",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.JSON(300, Greeting{"hello", "world"})
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 300)
	expect(t, res.Header().Get(ContentType), ContentJSON+"; charset=foobar")
	expect(t, res.Body.String(), `{"one":"hello","two":"world"}`)
}
示例#11
0
func Test_Render_BinaryData(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
	// nothing here to configure
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.Data(200, []byte("hello there"))
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 200)
	expect(t, res.Header().Get(ContentType), ContentBinary)
	expect(t, res.Body.String(), "hello there")
}
示例#12
0
func Test_Render_Nested_HTML(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory: "fixtures/basic",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "admin/index", "jeremy")
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 200)
	expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
	expect(t, res.Body.String(), "<h1>Admin jeremy</h1>\n")
}
示例#13
0
func Test_Render_JSON_Prefix(t *testing.T) {
	m := martini.Classic()
	prefix := ")]}',\n"
	m.Use(Renderer(Options{
		PrefixJSON: []byte(prefix),
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.JSON(300, Greeting{"hello", "world"})
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 300)
	expect(t, res.Header().Get(ContentType), ContentJSON+"; charset=UTF-8")
	expect(t, res.Body.String(), prefix+`{"one":"hello","two":"world"}`)
}
示例#14
0
func Test_Render_Delimiters(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Delims:    Delims{"{[{", "}]}"},
		Directory: "fixtures/basic",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "delims", "jeremy")
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 200)
	expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
	expect(t, res.Body.String(), "<h1>Hello jeremy</h1>")
}
示例#15
0
func Test_Render_Extensions(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory:  "fixtures/basic",
		Extensions: []string{".tmpl", ".html"},
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "hypertext", nil)
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 200)
	expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
	expect(t, res.Body.String(), "Hypertext!\n")
}
示例#16
0
func Test_Render_Default_Charset_HTML(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory: "fixtures/basic",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "hello", "jeremy")
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 200)
	expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
	// ContentLength should be deferred to the ResponseWriter and not Render
	expect(t, res.Header().Get(ContentLength), "")
	expect(t, res.Body.String(), "<h1>Hello jeremy</h1>\n")
}
示例#17
0
func Test_Render_Override_Layout(t *testing.T) {
	m := martini.Classic()
	m.Use(Renderer(Options{
		Directory: "fixtures/basic",
		Layout:    "layout",
	}))

	// routing
	m.Get("/foobar", func(r Render) {
		r.HTML(200, "content", "jeremy", HTMLOptions{
			Layout: "another_layout",
		})
	})

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/foobar", nil)

	m.ServeHTTP(res, req)

	expect(t, res.Code, 200)
	expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
	expect(t, res.Body.String(), "another head\n<h1>jeremy</h1>\n\nanother foot\n")
}
示例#18
0
func performFormTest(t *testing.T, binder handlerFunc, testCase formTestCase) {
	httpRecorder := httptest.NewRecorder()
	m := martini.Classic()

	formTestHandler := func(actual interface{}, errs Errors) {
		if testCase.shouldSucceed && len(errs) > 0 {
			t.Errorf("'%s' should have succeeded, but there were errors (%d):\n%+v",
				testCase.description, len(errs), errs)
		} else if !testCase.shouldSucceed && len(errs) == 0 {
			t.Errorf("'%s' should have had errors, but there were none", testCase.description)
		}
		expString := fmt.Sprintf("%+v", testCase.expected)
		actString := fmt.Sprintf("%+v", actual)
		if actString != expString && !(testCase.deepEqual && reflect.DeepEqual(testCase.expected, actual)) {
			t.Errorf("'%s': expected\n'%s'\nbut got\n'%s'",
				testCase.description, expString, actString)
		}
	}

	switch testCase.expected.(type) {
	case Post:
		if testCase.withInterface {
			m.Post(testRoute, binder(Post{}, (*modeler)(nil)), func(actual Post, iface modeler, errs Errors) {
				if actual.Title != iface.Model() {
					t.Errorf("For '%s': expected the struct to be mapped to the context as an interface",
						testCase.description)
				}
				formTestHandler(actual, errs)
			})
		} else {
			m.Post(testRoute, binder(Post{}), func(actual Post, errs Errors) {
				formTestHandler(actual, errs)
			})
			m.Get(testRoute, binder(Post{}), func(actual Post, errs Errors) {
				formTestHandler(actual, errs)
			})
		}

	case BlogPost:
		if testCase.withInterface {
			m.Post(testRoute, binder(BlogPost{}, (*modeler)(nil)), func(actual BlogPost, iface modeler, errs Errors) {
				if actual.Title != iface.Model() {
					t.Errorf("For '%s': expected the struct to be mapped to the context as an interface",
						testCase.description)
				}
				formTestHandler(actual, errs)
			})
		} else {
			m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) {
				formTestHandler(actual, errs)
			})
		}

	case EmbedPerson:
		m.Post(testRoute, binder(EmbedPerson{}), func(actual EmbedPerson, errs Errors) {
			formTestHandler(actual, errs)
		})
		m.Get(testRoute, binder(EmbedPerson{}), func(actual EmbedPerson, errs Errors) {
			formTestHandler(actual, errs)
		})
	}

	if testCase.method == "" {
		testCase.method = "POST"
	}

	req, err := http.NewRequest(testCase.method, testRoute+testCase.queryString, strings.NewReader(testCase.payload))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", testCase.contentType)

	m.ServeHTTP(httpRecorder, req)

	switch httpRecorder.Code {
	case http.StatusNotFound:
		panic("Routing is messed up in test fixture (got 404): check methods and paths")
	case http.StatusInternalServerError:
		panic("Something bad happened on '" + testCase.description + "'")
	}
}
示例#19
0
func performJsonTest(t *testing.T, binder handlerFunc, testCase jsonTestCase) {
	var payload io.Reader
	httpRecorder := httptest.NewRecorder()
	m := martini.Classic()

	jsonTestHandler := func(actual interface{}, errs Errors) {
		if testCase.shouldSucceedOnJson && len(errs) > 0 {
			t.Errorf("'%s' should have succeeded, but there were errors (%d):\n%+v",
				testCase.description, len(errs), errs)
		} else if !testCase.shouldSucceedOnJson && len(errs) == 0 {
			t.Errorf("'%s' should NOT have succeeded, but there were NO errors", testCase.description)
		}
		expString := fmt.Sprintf("%+v", testCase.expected)
		actString := fmt.Sprintf("%+v", actual)
		if actString != expString {
			t.Errorf("'%s': expected\n'%s'\nbut got\n'%s'",
				testCase.description, expString, actString)
		}
	}

	switch testCase.expected.(type) {
	case []Post:
		if testCase.withInterface {
			m.Post(testRoute, binder([]Post{}, (*modeler)(nil)), func(actual []Post, iface modeler, errs Errors) {

				for _, a := range actual {
					if a.Title != iface.Model() {
						t.Errorf("For '%s': expected the struct to be mapped to the context as an interface",
							testCase.description)
					}
					jsonTestHandler(a, errs)
				}
			})
		} else {
			m.Post(testRoute, binder([]Post{}), func(actual []Post, errs Errors) {
				jsonTestHandler(actual, errs)
			})
		}

	case Post:
		if testCase.withInterface {
			m.Post(testRoute, binder(Post{}, (*modeler)(nil)), func(actual Post, iface modeler, errs Errors) {
				if actual.Title != iface.Model() {
					t.Errorf("For '%s': expected the struct to be mapped to the context as an interface",
						testCase.description)
				}
				jsonTestHandler(actual, errs)
			})
		} else {
			m.Post(testRoute, binder(Post{}), func(actual Post, errs Errors) {
				jsonTestHandler(actual, errs)
			})
		}

	case BlogPost:
		if testCase.withInterface {
			m.Post(testRoute, binder(BlogPost{}, (*modeler)(nil)), func(actual BlogPost, iface modeler, errs Errors) {
				if actual.Title != iface.Model() {
					t.Errorf("For '%s': expected the struct to be mapped to the context as an interface",
						testCase.description)
				}
				jsonTestHandler(actual, errs)
			})
		} else {
			m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) {
				jsonTestHandler(actual, errs)
			})
		}
	}

	if testCase.payload == "-nil-" {
		payload = nil
	} else {
		payload = strings.NewReader(testCase.payload)
	}

	req, err := http.NewRequest("POST", testRoute, payload)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", testCase.contentType)

	m.ServeHTTP(httpRecorder, req)

	switch httpRecorder.Code {
	case http.StatusNotFound:
		panic("Routing is messed up in test fixture (got 404): check method and path")
	case http.StatusInternalServerError:
		panic("Something bad happened on '" + testCase.description + "'")
	default:
		if testCase.shouldSucceedOnJson &&
			httpRecorder.Code != http.StatusOK &&
			!testCase.shouldFailOnBind {
			t.Errorf("'%s' should have succeeded (except when using Bind, where it should fail), but returned HTTP status %d with body '%s'",
				testCase.description, httpRecorder.Code, httpRecorder.Body.String())
		}
	}
}