response_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright 2017 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package client // import "miniflux.app/http/client"
  5. import (
  6. "bytes"
  7. "os"
  8. "strings"
  9. "testing"
  10. "unicode/utf8"
  11. )
  12. func TestIsNotFound(t *testing.T) {
  13. scenarios := map[int]bool{
  14. 200: false,
  15. 404: true,
  16. 410: true,
  17. }
  18. for input, expected := range scenarios {
  19. r := &Response{StatusCode: input}
  20. actual := r.IsNotFound()
  21. if actual != expected {
  22. t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input)
  23. }
  24. }
  25. }
  26. func TestIsNotAuthorized(t *testing.T) {
  27. scenarios := map[int]bool{
  28. 200: false,
  29. 401: true,
  30. 403: false,
  31. }
  32. for input, expected := range scenarios {
  33. r := &Response{StatusCode: input}
  34. actual := r.IsNotAuthorized()
  35. if actual != expected {
  36. t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input)
  37. }
  38. }
  39. }
  40. func TestHasServerFailure(t *testing.T) {
  41. scenarios := map[int]bool{
  42. 200: false,
  43. 404: true,
  44. 500: true,
  45. }
  46. for input, expected := range scenarios {
  47. r := &Response{StatusCode: input}
  48. actual := r.HasServerFailure()
  49. if actual != expected {
  50. t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input)
  51. }
  52. }
  53. }
  54. func TestIsModifiedWith304Status(t *testing.T) {
  55. r := &Response{StatusCode: 304}
  56. if r.IsModified("etag", "lastModified") {
  57. t.Error("The resource should not be considered modified")
  58. }
  59. }
  60. func TestIsModifiedWithIdenticalEtag(t *testing.T) {
  61. r := &Response{StatusCode: 200, ETag: "etag"}
  62. if r.IsModified("etag", "lastModified") {
  63. t.Error("The resource should not be considered modified")
  64. }
  65. }
  66. func TestIsModifiedWithIdenticalLastModified(t *testing.T) {
  67. r := &Response{StatusCode: 200, LastModified: "lastModified"}
  68. if r.IsModified("etag", "lastModified") {
  69. t.Error("The resource should not be considered modified")
  70. }
  71. }
  72. func TestIsModifiedWithDifferentHeaders(t *testing.T) {
  73. r := &Response{StatusCode: 200, ETag: "some etag", LastModified: "some date"}
  74. if !r.IsModified("etag", "lastModified") {
  75. t.Error("The resource should be considered modified")
  76. }
  77. }
  78. func TestToString(t *testing.T) {
  79. input := `test`
  80. r := &Response{Body: strings.NewReader(input)}
  81. if r.BodyAsString() != input {
  82. t.Error(`Unexpected output`)
  83. }
  84. }
  85. func TestEnsureUnicodeWithHTMLDocuments(t *testing.T) {
  86. var unicodeTestCases = []struct {
  87. filename, contentType string
  88. convertedToUnicode bool
  89. }{
  90. {"HTTP-charset.html", "text/html; charset=iso-8859-15", true},
  91. {"UTF-16LE-BOM.html", "", true},
  92. {"UTF-16BE-BOM.html", "", true},
  93. {"meta-content-attribute.html", "text/html", true},
  94. {"meta-charset-attribute.html", "text/html", true},
  95. {"No-encoding-declaration.html", "text/html", true},
  96. {"HTTP-vs-UTF-8-BOM.html", "text/html; charset=iso-8859-15", true},
  97. {"HTTP-vs-meta-content.html", "text/html; charset=iso-8859-15", true},
  98. {"HTTP-vs-meta-charset.html", "text/html; charset=iso-8859-15", true},
  99. {"UTF-8-BOM-vs-meta-content.html", "text/html", true},
  100. {"UTF-8-BOM-vs-meta-charset.html", "text/html", true},
  101. {"windows_1251.html", "text/html; charset=windows-1251", true},
  102. {"gb2312.html", "text/html", true},
  103. {"urdu.xml", "text/xml; charset=utf-8", true},
  104. {"content-type-only-win-8859-1.xml", "application/xml; charset=ISO-8859-1", true},
  105. {"rdf_utf8.xml", "application/rss+xml; charset=utf-8", true},
  106. {"rdf_utf8.xml", "application/rss+xml; charset: utf-8", true}, // Invalid Content-Type
  107. {"charset-content-type-xml-iso88591.xml", "application/rss+xml; charset=ISO-8859-1", false},
  108. {"windows_1251.xml", "text/xml", false},
  109. {"smallfile.xml", "text/xml; charset=utf-8", true},
  110. {"single_quote_xml_encoding.xml", "text/xml; charset=utf-8", true},
  111. }
  112. for _, tc := range unicodeTestCases {
  113. content, err := os.ReadFile("testdata/" + tc.filename)
  114. if err != nil {
  115. t.Fatalf(`Unable to read file %q: %v`, tc.filename, err)
  116. }
  117. r := &Response{Body: bytes.NewReader(content), ContentType: tc.contentType}
  118. parseErr := r.EnsureUnicodeBody()
  119. if parseErr != nil {
  120. t.Fatalf(`Unicode conversion error for %q - %q: %v`, tc.filename, tc.contentType, parseErr)
  121. }
  122. isUnicode := utf8.ValidString(r.BodyAsString())
  123. if isUnicode != tc.convertedToUnicode {
  124. t.Errorf(`Unicode conversion %q - %q, got: %v, expected: %v`,
  125. tc.filename, tc.contentType, isUnicode, tc.convertedToUnicode)
  126. }
  127. }
  128. }