package contenttype import ( "bytes" "fmt" "testing" ) type ParseContentTypeTestCase struct { Input string ExpectedOutput *ContentType /* or nil if an error is expected */ ExpectedString *string /* or nil if equals to Input */ } var parseContentTypeTestCases []ParseContentTypeTestCase = []ParseContentTypeTestCase{ ParseContentTypeTestCase{ "text/html", &ContentType{"text", "html", "", map[string]string{}}, nil, }, ParseContentTypeTestCase{ "text/svg+xml; charset=UTF-8", &ContentType{"text", "svg", "xml", map[string]string{"charset": "UTF-8"}}, nil, }, ParseContentTypeTestCase{ "text/", nil, nil, }, ParseContentTypeTestCase{ "text; charset=UTF-8", &ContentType{"text", "", "", map[string]string{"charset": "UTF-8"}}, nil, }, ParseContentTypeTestCase{ "text/+xml; charset=UTF-8", &ContentType{"text", "", "xml", map[string]string{"charset": "UTF-8"}}, nil, }, } type ContentTypeEqualsTestCase struct { A, B ContentType Equals bool } var Map_Empty map[string]string = map[string]string{} var Map_A map[string]string = map[string]string{"a": "value_a"} var Map_B map[string]string = map[string]string{"b": "value_b"} var Map_AB map[string]string = map[string]string{"a": "value_a", "b": "value_b"} var ContentType_E ContentType = ContentType{"a", "b", "c", Map_Empty} var ContentType_A ContentType = ContentType{"a", "b", "c", Map_A} var ContentType_B ContentType = ContentType{"a", "b", "c", Map_B} var ContentType_AB ContentType = ContentType{"a", "b", "c", Map_AB} var contentTypeEqualsTestCases []ContentTypeEqualsTestCase = []ContentTypeEqualsTestCase{ // TopLevelType, SubType, Suffix ContentTypeEqualsTestCase{ContentType_E, ContentType{"a", "b", "c", Map_Empty}, true}, ContentTypeEqualsTestCase{ContentType_E, ContentType{"o", "b", "c", Map_Empty}, false}, ContentTypeEqualsTestCase{ContentType_E, ContentType{"a", "o", "c", Map_Empty}, false}, ContentTypeEqualsTestCase{ContentType_E, ContentType{"a", "b", "o", Map_Empty}, false}, // Parameters ContentTypeEqualsTestCase{ContentType_A, ContentType_A, true}, ContentTypeEqualsTestCase{ContentType_B, ContentType_B, true}, ContentTypeEqualsTestCase{ContentType_AB, ContentType_AB, true}, ContentTypeEqualsTestCase{ContentType_A, ContentType_E, false}, ContentTypeEqualsTestCase{ContentType_A, ContentType_B, false}, ContentTypeEqualsTestCase{ContentType_B, ContentType_A, false}, ContentTypeEqualsTestCase{ContentType_AB, ContentType_A, false}, ContentTypeEqualsTestCase{ContentType_AB, ContentType_E, false}, ContentTypeEqualsTestCase{ContentType_A, ContentType_AB, false}, } type FilterTestCase struct { Description string Input Filter TrueValues []ContentType FalseValues []ContentType } var filterTestCases []FilterTestCase = []FilterTestCase{ FilterTestCase{ "contains xml", NewFilterContains("xml"), []ContentType{ ContentType{"xml", "", "", Map_Empty}, ContentType{"text", "xml", "", Map_Empty}, ContentType{"text", "html", "xml", Map_Empty}, }, []ContentType{ ContentType{"text", "svg", "", map[string]string{"script": "javascript"}}, ContentType{"java", "script", "", Map_Empty}, }, }, FilterTestCase{ "equals applications/xhtml", NewFilterEquals("application", "xhtml", "*"), []ContentType{ ContentType{"application", "xhtml", "xml", Map_Empty}, ContentType{"application", "xhtml", "", Map_Empty}, ContentType{"application", "xhtml", "zip", Map_Empty}, ContentType{"application", "xhtml", "zip", Map_AB}, }, []ContentType{ ContentType{"application", "javascript", "", Map_Empty}, ContentType{"text", "xhtml", "", Map_Empty}, }, }, FilterTestCase{ "equals application/*", NewFilterEquals("application", "*", ""), []ContentType{ ContentType{"application", "xhtml", "", Map_Empty}, ContentType{"application", "javascript", "", Map_Empty}, }, []ContentType{ ContentType{"text", "xhtml", "", Map_Empty}, ContentType{"text", "xhtml", "xml", Map_Empty}, }, }, FilterTestCase{ "equals applications */javascript", NewFilterEquals("*", "javascript", ""), []ContentType{ ContentType{"application", "javascript", "", Map_Empty}, ContentType{"text", "javascript", "", Map_Empty}, }, []ContentType{ ContentType{"text", "html", "", Map_Empty}, ContentType{"text", "javascript", "zip", Map_Empty}, }, }, FilterTestCase{ "equals applications/* or */javascript", NewFilterOr([]Filter{ NewFilterEquals("application", "*", ""), NewFilterEquals("*", "javascript", ""), }), []ContentType{ ContentType{"application", "javascript", "", Map_Empty}, ContentType{"text", "javascript", "", Map_Empty}, ContentType{"application", "xhtml", "", Map_Empty}, }, []ContentType{ ContentType{"text", "html", "", Map_Empty}, ContentType{"application", "xhtml", "xml", Map_Empty}, }, }, } type FilterParametersTestCase struct { Input map[string]string Filter map[string]bool Output map[string]string } var filterParametersTestCases []FilterParametersTestCase = []FilterParametersTestCase{ FilterParametersTestCase{ map[string]string{}, map[string]bool{"A": true, "B": true}, map[string]string{}, }, FilterParametersTestCase{ map[string]string{"A": "value_A", "B": "value_B"}, map[string]bool{}, map[string]string{}, }, FilterParametersTestCase{ map[string]string{"A": "value_A", "B": "value_B"}, map[string]bool{"A": true}, map[string]string{"A": "value_A"}, }, FilterParametersTestCase{ map[string]string{"A": "value_A", "B": "value_B"}, map[string]bool{"A": true, "B": true}, map[string]string{"A": "value_A", "B": "value_B"}, }, } func TestContentTypeEquals(t *testing.T) { for _, testCase := range contentTypeEqualsTestCases { if !testCase.A.Equals(testCase.B) && testCase.Equals { t.Errorf(`Must be equals "%s"="%s"`, testCase.A, testCase.B) } else if testCase.A.Equals(testCase.B) && !testCase.Equals { t.Errorf(`Mustn't be equals "%s"!="%s"`, testCase.A, testCase.B) } } } func TestParseContentType(t *testing.T) { for _, testCase := range parseContentTypeTestCases { // test ParseContentType contentType, err := ParseContentType(testCase.Input) if testCase.ExpectedOutput == nil { // error expected if err == nil { // but there is no error t.Errorf(`Expecting error for "%s"`, testCase.Input) } } else { // no expected error if err != nil { t.Errorf(`Unexpecting error for "%s" : %s`, testCase.Input, err) } else if !contentType.Equals(*testCase.ExpectedOutput) { // the parsed contentType doesn't matched t.Errorf(`Unexpecting result for "%s", instead got "%s"`, testCase.ExpectedOutput.String(), contentType.String()) } else { // ParseContentType is fine, checking String() contentTypeString := contentType.String() expectedString := testCase.Input if testCase.ExpectedString != nil { expectedString = *testCase.ExpectedString } if contentTypeString != expectedString { t.Errorf(`Error with String() output of "%s", got "%s", ContentType{"%s", "%s", "%s", "%s"}`, expectedString, contentTypeString, contentType.TopLevelType, contentType.SubType, contentType.Suffix, contentType.Parameters) } } } } } func FilterToString(m map[string]bool) string { b := new(bytes.Buffer) for key, value := range m { if value { fmt.Fprintf(b, "'%s'=true;", key) } else { fmt.Fprintf(b, "'%s'=false;", key) } } return b.String() } func TestFilters(t *testing.T) { for _, testCase := range filterTestCases { for _, contentType := range testCase.TrueValues { if !testCase.Input(contentType) { t.Errorf(`Filter "%s" must accept the value "%s"`, testCase.Description, contentType) } } for _, contentType := range testCase.FalseValues { if testCase.Input(contentType) { t.Errorf(`Filter "%s" mustn't accept the value "%s"`, testCase.Description, contentType) } } } } func TestFilterParameters(t *testing.T) { for _, testCase := range filterParametersTestCases { // copy Input since the map will be modified InputCopy := make(map[string]string) for k, v := range testCase.Input { InputCopy[k] = v } // apply filter contentType := ContentType{"", "", "", InputCopy} contentType.FilterParameters(testCase.Filter) // test contentTypeOutput := ContentType{"", "", "", testCase.Output} if !contentTypeOutput.Equals(contentType) { t.Errorf(`FilterParameters error : %s becomes %s with this filter %s`, testCase.Input, contentType.Parameters, FilterToString(testCase.Filter)) } } }