4
0

response_test.go 4.3 KB

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