2015-06-15 10:02:10 +08:00
package browse
import (
2015-08-29 10:34:01 +08:00
"encoding/json"
"github.com/mholt/caddy/middleware"
2015-07-18 17:37:05 +08:00
"net/http"
"net/http/httptest"
2015-08-29 10:34:01 +08:00
"net/url"
"os"
2015-06-15 10:02:10 +08:00
"sort"
"testing"
2015-07-18 17:37:05 +08:00
"text/template"
2015-06-15 10:02:10 +08:00
"time"
)
// "sort" package has "IsSorted" function, but no "IsReversed";
func isReversed ( data sort . Interface ) bool {
n := data . Len ( )
for i := n - 1 ; i > 0 ; i -- {
if ! data . Less ( i , i - 1 ) {
return false
}
}
return true
}
func TestSort ( t * testing . T ) {
// making up []fileInfo with bogus values;
// to be used to make up our "listing"
fileInfos := [ ] FileInfo {
{
Name : "fizz" ,
Size : 4 ,
ModTime : time . Now ( ) . AddDate ( - 1 , 1 , 0 ) ,
} ,
{
Name : "buzz" ,
Size : 2 ,
ModTime : time . Now ( ) . AddDate ( 0 , - 3 , 3 ) ,
} ,
{
Name : "bazz" ,
Size : 1 ,
ModTime : time . Now ( ) . AddDate ( 0 , - 2 , - 23 ) ,
} ,
{
Name : "jazz" ,
Size : 3 ,
ModTime : time . Now ( ) ,
} ,
}
listing := Listing {
Name : "foobar" ,
Path : "/fizz/buzz" ,
CanGoUp : false ,
Items : fileInfos ,
}
// sort by name
listing . Sort = "name"
listing . applySort ( )
if ! sort . IsSorted ( byName ( listing ) ) {
t . Errorf ( "The listing isn't name sorted: %v" , listing . Items )
}
// sort by size
listing . Sort = "size"
listing . applySort ( )
if ! sort . IsSorted ( bySize ( listing ) ) {
t . Errorf ( "The listing isn't size sorted: %v" , listing . Items )
}
// sort by Time
listing . Sort = "time"
listing . applySort ( )
if ! sort . IsSorted ( byTime ( listing ) ) {
t . Errorf ( "The listing isn't time sorted: %v" , listing . Items )
}
// reverse by name
listing . Sort = "name"
listing . Order = "desc"
listing . applySort ( )
if ! isReversed ( byName ( listing ) ) {
t . Errorf ( "The listing isn't reversed by name: %v" , listing . Items )
}
// reverse by size
listing . Sort = "size"
listing . Order = "desc"
listing . applySort ( )
if ! isReversed ( bySize ( listing ) ) {
t . Errorf ( "The listing isn't reversed by size: %v" , listing . Items )
}
// reverse by time
listing . Sort = "time"
listing . Order = "desc"
listing . applySort ( )
if ! isReversed ( byTime ( listing ) ) {
t . Errorf ( "The listing isn't reversed by time: %v" , listing . Items )
}
}
2015-07-18 17:37:05 +08:00
func TestBrowseTemplate ( t * testing . T ) {
2015-07-23 15:35:46 +08:00
tmpl , err := template . ParseFiles ( "testdata/photos.tpl" )
2015-07-18 17:37:05 +08:00
if err != nil {
t . Fatalf ( "An error occured while parsing the template: %v" , err )
}
b := Browse {
Next : middleware . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) ( int , error ) {
t . Fatalf ( "Next shouldn't be called" )
return 0 , nil
} ) ,
2015-07-23 15:35:46 +08:00
Root : "./testdata" ,
2015-07-18 17:37:05 +08:00
Configs : [ ] Config {
Config {
PathScope : "/photos" ,
Template : tmpl ,
} ,
} ,
}
req , err := http . NewRequest ( "GET" , "/photos/" , nil )
if err != nil {
t . Fatalf ( "Test: Could not create HTTP request: %v" , err )
}
rec := httptest . NewRecorder ( )
2015-10-09 13:58:11 +08:00
code , err := b . ServeHTTP ( rec , req )
if code != http . StatusOK {
t . Fatalf ( "Wrong status, expected %d, got %d" , http . StatusOK , code )
2015-07-18 17:37:05 +08:00
}
respBody := rec . Body . String ( )
expectedBody := ` < ! DOCTYPE html >
< html >
< head >
< title > Template < / title >
< / head >
< body >
< h1 > Header < / h1 >
< h1 > / photos / < / h1 >
< a href = "test.html" > test . html < / a > < br >
< a href = "test2.html" > test2 . html < / a > < br >
2015-10-09 13:58:11 +08:00
< a href = "test3.html" > test3 . html < / a > < br >
2015-07-18 17:37:05 +08:00
< / body >
< / html >
`
if respBody != expectedBody {
t . Fatalf ( "Expected body: %v got: %v" , expectedBody , respBody )
}
2015-08-29 10:34:01 +08:00
}
func TestBrowseJson ( t * testing . T ) {
b := Browse {
Next : middleware . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) ( int , error ) {
t . Fatalf ( "Next shouldn't be called" )
return 0 , nil
} ) ,
Root : "./testdata" ,
Configs : [ ] Config {
Config {
2015-10-09 13:58:11 +08:00
PathScope : "/photos/" ,
2015-08-29 10:34:01 +08:00
} ,
} ,
}
2015-10-09 13:58:11 +08:00
//Getting the listing from the ./testdata/photos, the listing returned will be used to validate test results
file , err := os . Open ( b . Root + "/photos" )
2015-08-29 10:34:01 +08:00
if err != nil {
if os . IsPermission ( err ) {
t . Fatalf ( "Os Permission Error" )
}
}
defer file . Close ( )
files , err := file . Readdir ( - 1 )
if err != nil {
t . Fatalf ( "Unable to Read Contents of the directory" )
}
var fileinfos [ ] FileInfo
2015-10-09 13:58:11 +08:00
2015-08-29 10:34:01 +08:00
for _ , f := range files {
name := f . Name ( )
if f . IsDir ( ) {
name += "/"
}
url := url . URL { Path : name }
fileinfos = append ( fileinfos , FileInfo {
IsDir : f . IsDir ( ) ,
Name : f . Name ( ) ,
Size : f . Size ( ) ,
URL : url . String ( ) ,
ModTime : f . ModTime ( ) ,
Mode : f . Mode ( ) ,
} )
}
listing := Listing {
Items : fileinfos ,
}
2015-10-09 13:58:11 +08:00
//listing obtained above and will be used for validation inside the tests
tests := [ ] struct {
QueryUrl string
SortBy string
OrderBy string
Limit int
shouldErr bool
expectedResult [ ] FileInfo
} {
//test case 1: testing for default sort and order and without the limit parameter, default sort is by name and the default order is ascending
//without the limit query entire listing will be produced
{ "/" , "" , "" , - 1 , false , listing . Items } ,
//test case 2: limit is set to 1, orderBy and sortBy is default
{ "/?limit=1" , "" , "" , 1 , false , listing . Items [ : 1 ] } ,
//test case 3 : if the listing request is bigger than total size of listing then it should return everything
{ "/?limit=100000000" , "" , "" , 100000000 , false , listing . Items } ,
//testing for negative limit
{ "/?limit=-1" , "" , "" , - 1 , false , listing . Items } ,
//testing with limit set to -1 and order set to descending
{ "/?limit=-1&order=desc" , "" , "desc" , - 1 , false , listing . Items } ,
//testing with limit set to 2 and order set to descending
{ "/?limit=2&order=desc" , "" , "desc" , 2 , false , listing . Items } ,
//testing with limit set to 3 and order set to descending
{ "/?limit=3&order=desc" , "" , "desc" , 3 , false , listing . Items } ,
//testing with limit set to 3 and order set to ascending
{ "/?limit=3&order=asc" , "" , "asc" , 3 , false , listing . Items } ,
//testing with limit set to 1111111 and order set to ascending
{ "/?limit=1111111&order=asc" , "" , "asc" , 1111111 , false , listing . Items } ,
//testing with limit set to default and order set to ascending and sorting by size
{ "/?order=asc&sort=size" , "size" , "asc" , - 1 , false , listing . Items } ,
//testing with limit set to default and order set to ascending and sorting by last modified
{ "/?order=asc&sort=time" , "time" , "asc" , - 1 , false , listing . Items } ,
//testing with limit set to 1 and order set to ascending and sorting by last modified
{ "/?order=asc&sort=time&limit=1" , "time" , "asc" , 1 , false , listing . Items } ,
//testing with limit set to -100 and order set to ascending and sorting by last modified
{ "/?order=asc&sort=time&limit=-100" , "time" , "asc" , - 100 , false , listing . Items } ,
//testing with limit set to -100 and order set to ascending and sorting by size
{ "/?order=asc&sort=size&limit=-100" , "size" , "asc" , - 100 , false , listing . Items } ,
2015-08-29 10:34:01 +08:00
}
2015-10-09 13:58:11 +08:00
for i , test := range tests {
var marsh [ ] byte
req , err := http . NewRequest ( "GET" , "/photos" + test . QueryUrl , nil )
if err == nil && test . shouldErr {
t . Errorf ( "Test %d didn't error, but it should have" , i )
} else if err != nil && ! test . shouldErr {
t . Errorf ( "Test %d errored, but it shouldn't have; got '%v'" , i , err )
}
req . Header . Set ( "Accept" , "application/json" )
rec := httptest . NewRecorder ( )
code , err := b . ServeHTTP ( rec , req )
if code != http . StatusOK {
t . Fatalf ( "Wrong status, expected %d, got %d" , http . StatusOK , code )
}
if rec . HeaderMap . Get ( "Content-Type" ) != "application/json; charset=utf-8" {
t . Fatalf ( "Expected Content type to be application/json; charset=utf-8, but got %s " , rec . HeaderMap . Get ( "Content-Type" ) )
}
actualJsonResponseString := rec . Body . String ( )
copyOflisting := listing
if test . SortBy == "" {
copyOflisting . Sort = "name"
} else {
copyOflisting . Sort = test . SortBy
}
if test . OrderBy == "" {
copyOflisting . Order = "asc"
} else {
copyOflisting . Order = test . OrderBy
}
copyOflisting . applySort ( )
limit := test . Limit
if limit <= len ( copyOflisting . Items ) && limit > 0 {
marsh , err = json . Marshal ( copyOflisting . Items [ : limit ] )
} else { // if the 'limit' query is empty, or has the wrong value, list everything
marsh , err = json . Marshal ( copyOflisting . Items )
}
if err != nil {
t . Fatalf ( "Unable to Marshal the listing " )
}
expectedJsonString := string ( marsh )
if actualJsonResponseString != expectedJsonString {
t . Errorf ( "Json response string doesnt match the expected Json response for test number %d with sort = %s , order = %s,\nExpected response %s\nActual response = %s\n " , i + 1 , test . SortBy , test . OrderBy , expectedJsonString , actualJsonResponseString )
}
2015-08-29 10:34:01 +08:00
}
2015-07-18 17:37:05 +08:00
}