2017-11-21 02:25:45 +01:00
|
|
|
// Copyright 2017 Frédéric Guillot. All rights reserved.
|
|
|
|
// Use of this source code is governed by the Apache 2.0
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2018-08-25 06:51:50 +02:00
|
|
|
package client // import "miniflux.app/http/client"
|
2017-11-21 02:25:45 +01:00
|
|
|
|
2018-10-30 07:00:03 +01:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"io/ioutil"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"unicode/utf8"
|
|
|
|
)
|
2017-11-21 02:25:45 +01:00
|
|
|
|
2018-10-30 07:00:03 +01:00
|
|
|
func TestIsNotFound(t *testing.T) {
|
|
|
|
scenarios := map[int]bool{
|
|
|
|
200: false,
|
|
|
|
404: true,
|
|
|
|
410: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
for input, expected := range scenarios {
|
|
|
|
r := &Response{StatusCode: input}
|
|
|
|
actual := r.IsNotFound()
|
|
|
|
|
|
|
|
if actual != expected {
|
|
|
|
t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input)
|
|
|
|
}
|
2017-11-21 02:25:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-30 07:00:03 +01:00
|
|
|
func TestIsNotAuthorized(t *testing.T) {
|
|
|
|
scenarios := map[int]bool{
|
|
|
|
200: false,
|
|
|
|
401: true,
|
|
|
|
403: false,
|
|
|
|
}
|
|
|
|
|
|
|
|
for input, expected := range scenarios {
|
|
|
|
r := &Response{StatusCode: input}
|
|
|
|
actual := r.IsNotAuthorized()
|
|
|
|
|
|
|
|
if actual != expected {
|
|
|
|
t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input)
|
|
|
|
}
|
2017-11-21 02:25:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-30 07:00:03 +01:00
|
|
|
func TestHasServerFailure(t *testing.T) {
|
|
|
|
scenarios := map[int]bool{
|
|
|
|
200: false,
|
|
|
|
404: true,
|
|
|
|
500: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
for input, expected := range scenarios {
|
|
|
|
r := &Response{StatusCode: input}
|
|
|
|
actual := r.HasServerFailure()
|
|
|
|
|
|
|
|
if actual != expected {
|
|
|
|
t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input)
|
|
|
|
}
|
2017-11-21 02:25:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIsModifiedWith304Status(t *testing.T) {
|
|
|
|
r := &Response{StatusCode: 304}
|
|
|
|
if r.IsModified("etag", "lastModified") {
|
|
|
|
t.Error("The resource should not be considered modified")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIsModifiedWithIdenticalEtag(t *testing.T) {
|
|
|
|
r := &Response{StatusCode: 200, ETag: "etag"}
|
|
|
|
if r.IsModified("etag", "lastModified") {
|
|
|
|
t.Error("The resource should not be considered modified")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIsModifiedWithIdenticalLastModified(t *testing.T) {
|
|
|
|
r := &Response{StatusCode: 200, LastModified: "lastModified"}
|
|
|
|
if r.IsModified("etag", "lastModified") {
|
|
|
|
t.Error("The resource should not be considered modified")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIsModifiedWithDifferentHeaders(t *testing.T) {
|
|
|
|
r := &Response{StatusCode: 200, ETag: "some etag", LastModified: "some date"}
|
|
|
|
if !r.IsModified("etag", "lastModified") {
|
|
|
|
t.Error("The resource should be considered modified")
|
|
|
|
}
|
|
|
|
}
|
2018-10-30 07:00:03 +01:00
|
|
|
|
|
|
|
func TestToString(t *testing.T) {
|
|
|
|
input := `test`
|
|
|
|
r := &Response{Body: strings.NewReader(input)}
|
|
|
|
|
2019-12-27 00:26:23 +01:00
|
|
|
if r.BodyAsString() != input {
|
2018-10-30 07:00:03 +01:00
|
|
|
t.Error(`Unexpected ouput`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnsureUnicodeWithHTMLDocuments(t *testing.T) {
|
|
|
|
var unicodeTestCases = []struct {
|
|
|
|
filename, contentType string
|
|
|
|
convertedToUnicode bool
|
|
|
|
}{
|
|
|
|
{"HTTP-charset.html", "text/html; charset=iso-8859-15", true},
|
|
|
|
{"UTF-16LE-BOM.html", "", true},
|
|
|
|
{"UTF-16BE-BOM.html", "", true},
|
|
|
|
{"meta-content-attribute.html", "text/html", true},
|
|
|
|
{"meta-charset-attribute.html", "text/html", true},
|
|
|
|
{"No-encoding-declaration.html", "text/html", true},
|
|
|
|
{"HTTP-vs-UTF-8-BOM.html", "text/html; charset=iso-8859-15", true},
|
|
|
|
{"HTTP-vs-meta-content.html", "text/html; charset=iso-8859-15", true},
|
|
|
|
{"HTTP-vs-meta-charset.html", "text/html; charset=iso-8859-15", true},
|
|
|
|
{"UTF-8-BOM-vs-meta-content.html", "text/html", true},
|
|
|
|
{"UTF-8-BOM-vs-meta-charset.html", "text/html", true},
|
|
|
|
{"windows_1251.html", "text/html; charset=windows-1251", true},
|
|
|
|
{"gb2312.html", "text/html", true},
|
|
|
|
{"urdu.xml", "text/xml; charset=utf-8", true},
|
|
|
|
{"content-type-only-win-8859-1.xml", "application/xml; charset=ISO-8859-1", true},
|
|
|
|
{"rdf_utf8.xml", "application/rss+xml; charset=utf-8", true},
|
2019-09-19 07:12:15 +02:00
|
|
|
{"rdf_utf8.xml", "application/rss+xml; charset: utf-8", true}, // Invalid Content-Type
|
2018-10-30 07:00:03 +01:00
|
|
|
{"charset-content-type-xml-iso88591.xml", "application/rss+xml; charset=ISO-8859-1", false},
|
|
|
|
{"windows_1251.xml", "text/xml", false},
|
2018-11-24 21:17:00 +01:00
|
|
|
{"smallfile.xml", "text/xml; charset=utf-8", true},
|
2018-12-13 06:13:06 +01:00
|
|
|
{"single_quote_xml_encoding.xml", "text/xml; charset=utf-8", true},
|
2018-10-30 07:00:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range unicodeTestCases {
|
|
|
|
content, err := ioutil.ReadFile("testdata/" + tc.filename)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf(`Unable to read file %q: %v`, tc.filename, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
r := &Response{Body: bytes.NewReader(content), ContentType: tc.contentType}
|
|
|
|
parseErr := r.EnsureUnicodeBody()
|
|
|
|
if parseErr != nil {
|
2019-09-19 07:12:15 +02:00
|
|
|
t.Fatalf(`Unicode conversion error for %q - %q: %v`, tc.filename, tc.contentType, parseErr)
|
2018-10-30 07:00:03 +01:00
|
|
|
}
|
|
|
|
|
2019-12-27 00:26:23 +01:00
|
|
|
isUnicode := utf8.ValidString(r.BodyAsString())
|
2018-10-30 07:00:03 +01:00
|
|
|
if isUnicode != tc.convertedToUnicode {
|
|
|
|
t.Errorf(`Unicode conversion %q - %q, got: %v, expected: %v`,
|
|
|
|
tc.filename, tc.contentType, isUnicode, tc.convertedToUnicode)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|