// Copyright 2015 Light Code Labs, LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package limits import ( "reflect" "testing" "github.com/mholt/caddy" "github.com/mholt/caddy/caddyhttp/httpserver" ) const ( KB = 1024 MB = 1024 * 1024 GB = 1024 * 1024 * 1024 ) func TestParseLimits(t *testing.T) { for name, c := range map[string]struct { input string shouldErr bool expect httpserver.Limits }{ "catchAll": { input: `limits 2kb`, expect: httpserver.Limits{ MaxRequestHeaderSize: 2 * KB, MaxRequestBodySizes: []httpserver.PathLimit{{Path: "/", Limit: 2 * KB}}, }, }, "onlyHeader": { input: `limits { header 2kb }`, expect: httpserver.Limits{ MaxRequestHeaderSize: 2 * KB, }, }, "onlyBody": { input: `limits { body 2kb }`, expect: httpserver.Limits{ MaxRequestBodySizes: []httpserver.PathLimit{{Path: "/", Limit: 2 * KB}}, }, }, "onlyBodyWithPath": { input: `limits { body /test 2kb }`, expect: httpserver.Limits{ MaxRequestBodySizes: []httpserver.PathLimit{{Path: "/test", Limit: 2 * KB}}, }, }, "mixture": { input: `limits { header 1kb body 2kb body /bar 3kb }`, expect: httpserver.Limits{ MaxRequestHeaderSize: 1 * KB, MaxRequestBodySizes: []httpserver.PathLimit{ {Path: "/bar", Limit: 3 * KB}, {Path: "/", Limit: 2 * KB}, }, }, }, "invalidFormat": { input: `limits a b`, shouldErr: true, }, "invalidHeaderFormat": { input: `limits { header / 100 }`, shouldErr: true, }, "invalidBodyFormat": { input: `limits { body / 100 200 }`, shouldErr: true, }, "invalidKind": { input: `limits { head 100 }`, shouldErr: true, }, "invalidLimitSize": { input: `limits 10bk`, shouldErr: true, }, } { c := c t.Run(name, func(t *testing.T) { controller := caddy.NewTestController("", c.input) _, err := parseLimits(controller) if c.shouldErr && err == nil { t.Error("failed to get expected error") } if !c.shouldErr && err != nil { t.Errorf("got unexpected error: %v", err) } if got := httpserver.GetConfig(controller).Limits; !reflect.DeepEqual(got, c.expect) { t.Errorf("expect %#v, but got %#v", c.expect, got) } }) } } func TestParseArguments(t *testing.T) { cases := []struct { arguments []pathLimitUnparsed expected []httpserver.PathLimit hasError bool }{ // Parse errors {arguments: []pathLimitUnparsed{{"/", "123.5"}}, expected: []httpserver.PathLimit{}, hasError: true}, {arguments: []pathLimitUnparsed{{"/", "200LB"}}, expected: []httpserver.PathLimit{}, hasError: true}, {arguments: []pathLimitUnparsed{{"/", "path:999MB"}}, expected: []httpserver.PathLimit{}, hasError: true}, {arguments: []pathLimitUnparsed{{"/", "1_234_567"}}, expected: []httpserver.PathLimit{}, hasError: true}, {arguments: []pathLimitUnparsed{{"/", "0MB"}}, expected: []httpserver.PathLimit{}, hasError: true}, // Valid results {arguments: []pathLimitUnparsed{}, expected: []httpserver.PathLimit{}, hasError: false}, { arguments: []pathLimitUnparsed{{"/", "100"}}, expected: []httpserver.PathLimit{{Path: "/", Limit: 100}}, hasError: false, }, { arguments: []pathLimitUnparsed{{"/", "100KB"}}, expected: []httpserver.PathLimit{{Path: "/", Limit: 100 * KB}}, hasError: false, }, { arguments: []pathLimitUnparsed{{"/", "100MB"}}, expected: []httpserver.PathLimit{{Path: "/", Limit: 100 * MB}}, hasError: false, }, { arguments: []pathLimitUnparsed{{"/", "100GB"}}, expected: []httpserver.PathLimit{{Path: "/", Limit: 100 * GB}}, hasError: false, }, { arguments: []pathLimitUnparsed{{"index", "100"}}, expected: []httpserver.PathLimit{{Path: "/index", Limit: 100}}, hasError: false, }, { arguments: []pathLimitUnparsed{{"/home", "100MB"}, {"/upload/images", "500GB"}}, expected: []httpserver.PathLimit{ {Path: "/home", Limit: 100 * MB}, {Path: "/upload/images", Limit: 500 * GB}, }, hasError: false}, { arguments: []pathLimitUnparsed{{"/", "999"}, {"/home", "12345MB"}}, expected: []httpserver.PathLimit{ {Path: "/", Limit: 999}, {Path: "/home", Limit: 12345 * MB}, }, hasError: false, }, // Duplicates { arguments: []pathLimitUnparsed{{"/home", "999"}, {"/home", "12345MB"}}, expected: []httpserver.PathLimit{ {Path: "/home", Limit: 12345 * MB}, }, hasError: false, }, } for caseNum, c := range cases { output, err := parseArguments(c.arguments) if c.hasError && (err == nil) { t.Errorf("Expecting error for case %v but none encountered", caseNum) } if !c.hasError && (err != nil) { t.Errorf("Expecting no error for case %v but encountered %v", caseNum, err) } if !reflect.DeepEqual(c.expected, output) { t.Errorf("Case %v is expecting: %v, actual %v", caseNum, c.expected, output) } } } func TestSortPathLimits(t *testing.T) { cases := []struct { arguments []httpserver.PathLimit expected []httpserver.PathLimit }{ // Parse errors {arguments: []httpserver.PathLimit{}, expected: []httpserver.PathLimit{}}, { arguments: []httpserver.PathLimit{{Path: "/index", Limit: 100}}, expected: []httpserver.PathLimit{{Path: "/index", Limit: 100}}, }, { arguments: []httpserver.PathLimit{ {Path: "/static", Limit: 1}, {Path: "/static/images", Limit: 100}, {Path: "/index", Limit: 200}, }, expected: []httpserver.PathLimit{ {Path: "/static/images", Limit: 100}, {Path: "/static", Limit: 1}, {Path: "/index", Limit: 200}}, }, } for caseNum, c := range cases { output := append([]httpserver.PathLimit{}, c.arguments...) SortPathLimits(output) if !reflect.DeepEqual(c.expected, output) { t.Errorf("Case %v is expecting: %v, actual %v", caseNum, c.expected, output) } } }