github.com/woremacx/kocha@v0.7.1-0.20150731103243-a5889322afc9/kocha_test.go (about) 1 package kocha_test 2 3 import ( 4 "bytes" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "net/url" 9 "os" 10 "reflect" 11 "testing" 12 13 "github.com/woremacx/kocha" 14 "github.com/woremacx/kocha/log" 15 ) 16 17 type testLogFormatter struct { 18 } 19 20 func (f *testLogFormatter) Format(w io.Writer, entry *log.Entry) error { 21 return nil 22 } 23 24 func newConfig() *kocha.Config { 25 return &kocha.Config{ 26 AppPath: "testpath", 27 AppName: "testappname", 28 DefaultLayout: "testapp", 29 Template: &kocha.Template{}, 30 RouteTable: kocha.RouteTable{ 31 { 32 Name: "route1", 33 Path: "route_path1", 34 Controller: &kocha.FixtureRootTestCtrl{}, 35 }, 36 { 37 Name: "route2", 38 Path: "route_path2", 39 Controller: &kocha.FixtureRootTestCtrl{}, 40 }, 41 }, 42 Logger: &kocha.LoggerConfig{}, 43 } 44 } 45 46 func TestConst(t *testing.T) { 47 for _, v := range []struct { 48 name string 49 actual, expected interface{} 50 }{ 51 {"DefaultHttpAddr", kocha.DefaultHttpAddr, "127.0.0.1:9100"}, 52 {"DefaultMaxClientBodySize", kocha.DefaultMaxClientBodySize, 1024 * 1024 * 10}, 53 {"StaticDir", kocha.StaticDir, "public"}, 54 } { 55 actual := v.actual 56 expected := v.expected 57 if !reflect.DeepEqual(actual, expected) { 58 t.Errorf(`%#v => %#v; want %#v`, v.name, actual, expected) 59 } 60 } 61 } 62 63 func TestNew(t *testing.T) { 64 func() { 65 config := newConfig() 66 app, err := kocha.New(config) 67 if err != nil { 68 t.Fatal(err) 69 } 70 actual := app.Config 71 expected := config 72 if !reflect.DeepEqual(actual, expected) { 73 t.Errorf("Expect %v, but %v", expected, actual) 74 } 75 if config.MaxClientBodySize != kocha.DefaultMaxClientBodySize { 76 t.Errorf("Expect %v, but %v", kocha.DefaultMaxClientBodySize, config.MaxClientBodySize) 77 } 78 }() 79 80 func() { 81 config := newConfig() 82 config.MaxClientBodySize = -1 83 app, err := kocha.New(config) 84 if err != nil { 85 t.Fatal(err) 86 } 87 actual := app.Config 88 expected := config 89 if !reflect.DeepEqual(actual, expected) { 90 t.Errorf("Expect %v, but %v", expected, actual) 91 } 92 if config.MaxClientBodySize != kocha.DefaultMaxClientBodySize { 93 t.Errorf("Expect %v, but %v", kocha.DefaultMaxClientBodySize, config.MaxClientBodySize) 94 } 95 }() 96 97 func() { 98 config := newConfig() 99 config.MaxClientBodySize = 20131108 100 app, err := kocha.New(config) 101 if err != nil { 102 t.Fatal(err) 103 } 104 actual := app.Config 105 expected := config 106 if !reflect.DeepEqual(actual, expected) { 107 t.Errorf("Expect %v, but %v", expected, actual) 108 } 109 if config.MaxClientBodySize != 20131108 { 110 t.Errorf("Expect %v, but %v", 20131108, config.MaxClientBodySize) 111 } 112 }() 113 114 // test for event. 115 func() { 116 config := newConfig() 117 app, err := kocha.New(config) 118 if err != nil { 119 t.Fatal(err) 120 } 121 var actual interface{} = app.Event.WorkersPerQueue 122 if actual == nil { 123 t.Errorf(`New(config).Event => %#v; want not nil`, actual) 124 } 125 126 config.Event = &kocha.Event{ 127 WorkersPerQueue: 100, 128 } 129 app, err = kocha.New(config) 130 if err != nil { 131 t.Fatal(err) 132 } 133 actual = app.Event 134 var expect interface{} = config.Event 135 if !reflect.DeepEqual(actual, expect) { 136 t.Errorf(`New(config).Event => %#v; want %#v`, actual, expect) 137 } 138 }() 139 } 140 141 func TestNew_buildLogger(t *testing.T) { 142 func() { 143 config := newConfig() 144 config.Logger = nil 145 app, err := kocha.New(config) 146 if err != nil { 147 t.Fatal(err) 148 } 149 actual := app.Config.Logger 150 expected := &kocha.LoggerConfig{ 151 Writer: os.Stdout, 152 Formatter: &log.LTSVFormatter{}, 153 } 154 if !reflect.DeepEqual(actual, expected) { 155 t.Errorf(`New(...).Config.Logger => %#v; want %#v`, actual, expected) 156 } 157 }() 158 159 func() { 160 var buf bytes.Buffer 161 formatter := &testLogFormatter{} 162 level := log.PANIC 163 config := newConfig() 164 config.Logger.Writer = &buf 165 config.Logger.Formatter = formatter 166 config.Logger.Level = level 167 app, err := kocha.New(config) 168 if err != nil { 169 t.Fatal(err) 170 } 171 actual := app.Config.Logger 172 expected := &kocha.LoggerConfig{ 173 Writer: &buf, 174 Formatter: formatter, 175 Level: level, 176 } 177 if !reflect.DeepEqual(actual, expected) { 178 t.Errorf(`New(...).Config.Logger => %#v; want %#v`, actual, expected) 179 } 180 }() 181 } 182 183 func TestApplication_ServeHTTP(t *testing.T) { 184 for _, v := range []struct { 185 uri string 186 status int 187 body string 188 contentType string 189 }{ 190 {"/", http.StatusOK, "This is layout\nThis is root\n\n", "text/html"}, 191 {"/user/7", http.StatusOK, "This is layout\nThis is user 7\n\n", "text/html"}, 192 {"/2013/07/19/user/naoina", http.StatusOK, "This is layout\nThis is date naoina: 2013-07-19\n\n", "text/html"}, 193 {"/missing", http.StatusNotFound, "This is layout\n404 template not found\n\n", "text/html"}, 194 {"/json", http.StatusOK, "{\n \"layout\": \"application\",\n {\"tmpl5\":\"json\"}\n\n}\n", "application/json"}, 195 {"/teapot", http.StatusTeapot, "This is layout\nI'm a tea pot\n\n", "text/html"}, 196 {"/panic_in_render", http.StatusInternalServerError, "Internal Server Error\n", "text/plain; charset=utf-8"}, 197 {"/static/robots.txt", http.StatusOK, "# User-Agent: *\n# Disallow: /\n", "text/plain; charset=utf-8"}, 198 // This returns 500 Internal Server Error (not 502 BadGateway) because the file 'error/502.html' not found. 199 {"/error_controller_test", http.StatusInternalServerError, "Internal Server Error\n", "text/plain; charset=utf-8"}, 200 } { 201 func() { 202 defer func() { 203 if err := recover(); err != nil { 204 t.Errorf(`GET %#v is panicked; want no panic; %v`, v.uri, err) 205 } 206 }() 207 w := httptest.NewRecorder() 208 req, err := http.NewRequest("GET", v.uri, nil) 209 if err != nil { 210 t.Fatal(err) 211 } 212 app := kocha.NewTestApp() 213 app.ServeHTTP(w, req) 214 215 var actual interface{} = w.Code 216 var expected interface{} = v.status 217 if !reflect.DeepEqual(actual, expected) { 218 t.Errorf(`GET %#v status => %#v; want %#v`, v.uri, actual, expected) 219 } 220 221 actual = w.Body.String() 222 expected = v.body 223 if !reflect.DeepEqual(actual, expected) { 224 t.Errorf(`GET %#v => %#v; want %#v`, v.uri, actual, expected) 225 } 226 227 actual = w.Header().Get("Content-Type") 228 expected = v.contentType 229 if !reflect.DeepEqual(actual, expected) { 230 t.Errorf(`GET %#v Content-Type => %#v; want %#v`, v.uri, actual, expected) 231 } 232 }() 233 } 234 235 // test for panic in handler 236 func() { 237 defer func() { 238 actual := recover() 239 expect := "panic test" 240 if !reflect.DeepEqual(actual, expect) { 241 t.Errorf(`GET /error; recover() => %#v; want %#v`, actual, expect) 242 } 243 }() 244 w := httptest.NewRecorder() 245 req, err := http.NewRequest("GET", "/error", nil) 246 if err != nil { 247 t.Fatal(err) 248 } 249 app := kocha.NewTestApp() 250 app.ServeHTTP(w, req) 251 }() 252 253 // middleware tests 254 func() { 255 req, err := http.NewRequest("GET", "/", nil) 256 if err != nil { 257 t.Fatal(err) 258 } 259 app := kocha.NewTestApp() 260 var called []string 261 m1 := &TestMiddleware{t: t, id: "A", called: &called} 262 m2 := &TestMiddleware{t: t, id: "B", called: &called} 263 app.Config.Middlewares = []kocha.Middleware{m1, m2, &kocha.DispatchMiddleware{}} // all default middlewares are override 264 w := httptest.NewRecorder() 265 app.ServeHTTP(w, req) 266 267 var actual interface{} = called 268 var expected interface{} = []string{"beforeA", "beforeB", "afterB", "afterA"} 269 if !reflect.DeepEqual(actual, expected) { 270 t.Errorf(`GET "/" with middlewares calls => %#v; want %#v`, actual, expected) 271 } 272 273 actual = w.Code 274 expected = http.StatusOK 275 if !reflect.DeepEqual(actual, expected) { 276 t.Errorf(`GET "/" with middlewares status => %#v; want %#v`, actual, expected) 277 } 278 279 actual = w.Body.String() 280 expected = "This is layout\nThis is root\n\n" 281 if !reflect.DeepEqual(actual, expected) { 282 t.Errorf(`GET "/" with middlewares => %#v; want %#v`, actual, expected) 283 } 284 285 actual = w.Header().Get("Content-Type") 286 expected = "text/html" 287 if !reflect.DeepEqual(actual, expected) { 288 t.Errorf(`GET "/" with middlewares Context-Type => %#v; want %#v`, actual, expected) 289 } 290 }() 291 292 func() { 293 defer func() { 294 actual := recover() 295 expect := "before" 296 if !reflect.DeepEqual(actual, expect) { 297 t.Errorf(`GET /; recover() => %#v; want %#v`, actual, expect) 298 } 299 }() 300 req, err := http.NewRequest("GET", "/", nil) 301 if err != nil { 302 t.Fatal(err) 303 } 304 app := kocha.NewTestApp() 305 m := &TestPanicInBeforeMiddleware{} 306 app.Config.Middlewares = []kocha.Middleware{m, &kocha.DispatchMiddleware{}} // all default middlewares are override 307 w := httptest.NewRecorder() 308 app.ServeHTTP(w, req) 309 }() 310 311 func() { 312 defer func() { 313 actual := recover() 314 expect := "after" 315 if !reflect.DeepEqual(actual, expect) { 316 t.Errorf(`GET /; recover() => %#v; want %#v`, actual, expect) 317 } 318 }() 319 w := httptest.NewRecorder() 320 req, err := http.NewRequest("GET", "/", nil) 321 if err != nil { 322 t.Fatal(err) 323 } 324 app := kocha.NewTestApp() 325 m := &TestPanicInAfterMiddleware{} 326 app.Config.Middlewares = []kocha.Middleware{m, &kocha.DispatchMiddleware{}} // all default middlewares are override 327 app.ServeHTTP(w, req) 328 }() 329 330 // test for rewrite request url by middleware. 331 func() { 332 defer func() { 333 if err := recover(); err != nil { 334 t.Errorf("GET / with TestRewriteURLPathMiddleware has been panicked => %#v; want no panic", err) 335 } 336 }() 337 w := httptest.NewRecorder() 338 req, err := http.NewRequest("GET", "/error", nil) 339 if err != nil { 340 t.Fatal(err) 341 } 342 app := kocha.NewTestApp() 343 m := &TestRewriteURLPathMiddleware{rewritePath: "/"} 344 app.Config.Middlewares = []kocha.Middleware{m, &kocha.DispatchMiddleware{}} 345 app.ServeHTTP(w, req) 346 var actual interface{} = w.Code 347 var expect interface{} = http.StatusOK 348 if !reflect.DeepEqual(actual, expect) { 349 t.Errorf(`GET "/" with TestRewriteURLPathMiddleware status => %#v; want %#v`, actual, expect) 350 } 351 352 actual = w.Body.String() 353 expect = "This is layout\nThis is root\n\n" 354 if !reflect.DeepEqual(actual, expect) { 355 t.Errorf(`GET "/" with TestRewriteURLPathMiddleware => %#v; want %#v`, actual, expect) 356 } 357 358 actual = w.Header().Get("Content-Type") 359 expect = "text/html" 360 if !reflect.DeepEqual(actual, expect) { 361 t.Errorf(`GET "/" with TestRewriteURLPathMiddleware Context-Type => %#v; want %#v`, actual, expect) 362 } 363 }() 364 } 365 366 func TestApplication_ServeHTTP_withPOST(t *testing.T) { 367 // plain. 368 func() { 369 values := url.Values{} 370 values.Set("name", "naoina") 371 values.Add("type", "human") 372 req, err := http.NewRequest("POST", "/post_test", bytes.NewBufferString(values.Encode())) 373 if err != nil { 374 t.Fatal(err) 375 } 376 req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 377 app := kocha.NewTestApp() 378 w := httptest.NewRecorder() 379 app.ServeHTTP(w, req) 380 var actual interface{} = w.Code 381 var expected interface{} = http.StatusOK 382 if !reflect.DeepEqual(actual, expected) { 383 t.Errorf("POST /post_test status => %#v, want %#v", actual, expected) 384 } 385 386 actual = w.Body.String() 387 expected = "This is layout\nmap[params:map[]]\n\n" 388 if !reflect.DeepEqual(actual, expected) { 389 t.Errorf("POST /post_test body => %#v, want %#v", actual, expected) 390 } 391 }() 392 393 // with FormMiddleware. 394 func() { 395 values := url.Values{} 396 values.Set("name", "naoina") 397 values.Add("type", "human") 398 req, err := http.NewRequest("POST", "/post_test", bytes.NewBufferString(values.Encode())) 399 if err != nil { 400 t.Fatal(err) 401 } 402 req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 403 app := kocha.NewTestApp() 404 app.Config.Middlewares = []kocha.Middleware{&kocha.FormMiddleware{}, &kocha.DispatchMiddleware{}} 405 w := httptest.NewRecorder() 406 app.ServeHTTP(w, req) 407 var actual interface{} = w.Code 408 var expect interface{} = http.StatusOK 409 if !reflect.DeepEqual(actual, expect) { 410 t.Errorf("POST /post_test status => %#v, want %#v", actual, expect) 411 } 412 413 actual = w.Body.String() 414 expect = "This is layout\nmap[params:map[name:[naoina] type:[human]]]\n\n" 415 if !reflect.DeepEqual(actual, expect) { 416 t.Errorf("POST /post_test body => %#v, want %#v", actual, expect) 417 } 418 }() 419 } 420 421 type TestMiddleware struct { 422 t *testing.T 423 id string 424 called *[]string 425 } 426 427 func (m *TestMiddleware) Process(app *kocha.Application, c *kocha.Context, next func() error) error { 428 *m.called = append(*m.called, "before"+m.id) 429 if err := next(); err != nil { 430 return err 431 } 432 *m.called = append(*m.called, "after"+m.id) 433 return nil 434 } 435 436 type TestPanicInBeforeMiddleware struct{} 437 438 func (m *TestPanicInBeforeMiddleware) Process(app *kocha.Application, c *kocha.Context, next func() error) error { 439 panic("before") 440 if err := next(); err != nil { 441 return err 442 } 443 return nil 444 } 445 446 type TestPanicInAfterMiddleware struct{} 447 448 func (m *TestPanicInAfterMiddleware) Process(app *kocha.Application, c *kocha.Context, next func() error) error { 449 if err := next(); err != nil { 450 return err 451 } 452 panic("after") 453 return nil 454 } 455 456 type TestRewriteURLPathMiddleware struct { 457 rewritePath string 458 } 459 460 func (m *TestRewriteURLPathMiddleware) Process(app *kocha.Application, c *kocha.Context, next func() error) error { 461 c.Request.URL.Path = m.rewritePath 462 return next() 463 } 464 465 type testUnit struct { 466 name string 467 active bool 468 callCount int 469 } 470 471 func (u *testUnit) ActiveIf() bool { 472 u.callCount++ 473 return u.active 474 } 475 476 type testUnit2 struct{} 477 478 func (u *testUnit2) ActiveIf() bool { 479 return true 480 } 481 482 func TestApplication_Invoke(t *testing.T) { 483 // test that it invokes newFunc when ActiveIf returns true. 484 func() { 485 app := kocha.NewTestApp() 486 unit := &testUnit{"test1", true, 0} 487 called := false 488 app.Invoke(unit, func() { 489 called = true 490 }, func() { 491 t.Errorf("defaultFunc has been called") 492 }) 493 actual := called 494 expected := true 495 if !reflect.DeepEqual(actual, expected) { 496 t.Errorf("Expect %q, but %q", expected, actual) 497 } 498 }() 499 500 // test that it invokes defaultFunc when ActiveIf returns false. 501 func() { 502 app := kocha.NewTestApp() 503 unit := &testUnit{"test2", false, 0} 504 called := false 505 app.Invoke(unit, func() { 506 t.Errorf("newFunc has been called") 507 }, func() { 508 called = true 509 }) 510 actual := called 511 expected := true 512 if !reflect.DeepEqual(actual, expected) { 513 t.Errorf("Expect %q, but %q", expected, actual) 514 } 515 }() 516 517 // test that it invokes defaultFunc when any errors occurred in newFunc. 518 func() { 519 app := kocha.NewTestApp() 520 unit := &testUnit{"test3", true, 0} 521 called := false 522 app.Invoke(unit, func() { 523 panic("expected error") 524 }, func() { 525 called = true 526 }) 527 actual := called 528 expected := true 529 if !reflect.DeepEqual(actual, expected) { 530 t.Errorf("Expect %q, but %q", expected, actual) 531 } 532 }() 533 534 // test that it will be panic when panic occurred in defaultFunc. 535 func() { 536 defer func() { 537 if err := recover(); err == nil { 538 t.Errorf("panic doesn't occurred") 539 } else if err != "expected error in defaultFunc" { 540 t.Errorf("panic doesn't occurred in defaultFunc: %v", err) 541 } 542 }() 543 app := kocha.NewTestApp() 544 unit := &testUnit{"test4", false, 0} 545 app.Invoke(unit, func() { 546 t.Errorf("newFunc has been called") 547 }, func() { 548 panic("expected error in defaultFunc") 549 }) 550 }() 551 552 // test that it panic when panic occurred in both newFunc and defaultFunc. 553 func() { 554 defer func() { 555 if err := recover(); err == nil { 556 t.Errorf("panic doesn't occurred") 557 } else if err != "expected error in defaultFunc" { 558 t.Errorf("panic doesn't occurred in defaultFunc: %v", err) 559 } 560 }() 561 app := kocha.NewTestApp() 562 unit := &testUnit{"test5", true, 0} 563 called := false 564 app.Invoke(unit, func() { 565 called = true 566 panic("expected error") 567 }, func() { 568 panic("expected error in defaultFunc") 569 }) 570 actual := called 571 expected := true 572 if !reflect.DeepEqual(actual, expected) { 573 t.Errorf("Expect %q, but %q", expected, actual) 574 } 575 }() 576 577 func() { 578 app := kocha.NewTestApp() 579 unit := &testUnit{"test6", true, 0} 580 app.Invoke(unit, func() { 581 panic("expected error") 582 }, func() { 583 // do nothing. 584 }) 585 var actual interface{} = unit.callCount 586 var expected interface{} = 1 587 if !reflect.DeepEqual(actual, expected) { 588 t.Errorf("Expect %q, but %q", expected, actual) 589 } 590 591 // again. 592 app.Invoke(unit, func() { 593 t.Errorf("newFunc has been called") 594 }, func() { 595 // do nothing. 596 }) 597 actual = unit.callCount 598 expected = 1 599 if !reflect.DeepEqual(actual, expected) { 600 t.Errorf("Expect %q, but %q", expected, actual) 601 } 602 603 // same unit type. 604 unit = &testUnit{"test7", true, 0} 605 called := false 606 app.Invoke(unit, func() { 607 t.Errorf("newFunc has been called") 608 }, func() { 609 called = true 610 }) 611 actual = called 612 expected = true 613 if !reflect.DeepEqual(actual, expected) { 614 t.Errorf("Expect %q, but %q", expected, actual) 615 } 616 617 // different unit type. 618 unit2 := &testUnit2{} 619 called = false 620 app.Invoke(unit2, func() { 621 called = true 622 }, func() { 623 t.Errorf("defaultFunc has been called") 624 }) 625 actual = called 626 expected = true 627 if !reflect.DeepEqual(actual, expected) { 628 t.Errorf("Expect %q, but %q", expected, actual) 629 } 630 }() 631 } 632 633 func TestGetenv(t *testing.T) { 634 func() { 635 actual := kocha.Getenv("TEST_KOCHA_ENV", "default value") 636 expected := "default value" 637 if !reflect.DeepEqual(actual, expected) { 638 t.Errorf("Getenv(%q, %q) => %q, want %q", "TEST_KOCHA_ENV", "default value", actual, expected) 639 } 640 641 actual = os.Getenv("TEST_KOCHA_ENV") 642 expected = "default value" 643 if !reflect.DeepEqual(actual, expected) { 644 t.Errorf("os.Getenv(%q) => %q, want %q", "TEST_KOCHA_ENV", actual, expected) 645 } 646 }() 647 648 func() { 649 os.Setenv("TEST_KOCHA_ENV", "set kocha env") 650 defer os.Clearenv() 651 actual := kocha.Getenv("TEST_KOCHA_ENV", "default value") 652 expected := "set kocha env" 653 if !reflect.DeepEqual(actual, expected) { 654 t.Errorf("Getenv(%q, %q) => %q, want %q", "TEST_KOCHA_ENV", "default value", actual, expected) 655 } 656 657 actual = os.Getenv("TEST_KOCHA_ENV") 658 expected = "set kocha env" 659 if !reflect.DeepEqual(actual, expected) { 660 t.Errorf("os.Getenv(%q) => %q, want %q", "TEST_KOCHA_ENV", actual, expected) 661 } 662 }() 663 }