validators_test.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package config // import "miniflux.app/v2/internal/config"
  4. import (
  5. "strings"
  6. "testing"
  7. )
  8. func TestValidateChoices(t *testing.T) {
  9. tests := []struct {
  10. name string
  11. rawValue string
  12. choices []string
  13. expectError bool
  14. }{
  15. {
  16. name: "valid choice",
  17. rawValue: "option1",
  18. choices: []string{"option1", "option2", "option3"},
  19. expectError: false,
  20. },
  21. {
  22. name: "valid choice from middle",
  23. rawValue: "option2",
  24. choices: []string{"option1", "option2", "option3"},
  25. expectError: false,
  26. },
  27. {
  28. name: "valid choice from end",
  29. rawValue: "option3",
  30. choices: []string{"option1", "option2", "option3"},
  31. expectError: false,
  32. },
  33. {
  34. name: "invalid choice",
  35. rawValue: "invalid",
  36. choices: []string{"option1", "option2", "option3"},
  37. expectError: true,
  38. },
  39. {
  40. name: "empty value with non-empty choices",
  41. rawValue: "",
  42. choices: []string{"option1", "option2"},
  43. expectError: true,
  44. },
  45. {
  46. name: "case sensitive - different case",
  47. rawValue: "OPTION1",
  48. choices: []string{"option1", "option2"},
  49. expectError: true,
  50. },
  51. {
  52. name: "single choice valid",
  53. rawValue: "only",
  54. choices: []string{"only"},
  55. expectError: false,
  56. },
  57. {
  58. name: "empty choices list",
  59. rawValue: "anything",
  60. choices: []string{},
  61. expectError: true,
  62. },
  63. }
  64. for _, tt := range tests {
  65. t.Run(tt.name, func(t *testing.T) {
  66. err := validateChoices(tt.rawValue, tt.choices)
  67. if tt.expectError {
  68. if err == nil {
  69. t.Errorf("expected error but got none")
  70. } else {
  71. // Verify error message format
  72. expectedPrefix := "value must be one of:"
  73. if !strings.Contains(err.Error(), expectedPrefix) {
  74. t.Errorf("error message should contain '%s', got: %s", expectedPrefix, err.Error())
  75. }
  76. }
  77. } else {
  78. if err != nil {
  79. t.Errorf("expected no error but got: %v", err)
  80. }
  81. }
  82. })
  83. }
  84. }
  85. func TestValidateListChoices(t *testing.T) {
  86. tests := []struct {
  87. name string
  88. inputValues []string
  89. choices []string
  90. expectError bool
  91. }{
  92. {
  93. name: "all valid choices",
  94. inputValues: []string{"option1", "option2"},
  95. choices: []string{"option1", "option2", "option3"},
  96. expectError: false,
  97. },
  98. {
  99. name: "single valid choice",
  100. inputValues: []string{"option1"},
  101. choices: []string{"option1", "option2", "option3"},
  102. expectError: false,
  103. },
  104. {
  105. name: "empty input list",
  106. inputValues: []string{},
  107. choices: []string{"option1", "option2", "option3"},
  108. expectError: false,
  109. },
  110. {
  111. name: "all choices from available list",
  112. inputValues: []string{"option1", "option2", "option3"},
  113. choices: []string{"option1", "option2", "option3"},
  114. expectError: false,
  115. },
  116. {
  117. name: "duplicate valid choices",
  118. inputValues: []string{"option1", "option1", "option2"},
  119. choices: []string{"option1", "option2", "option3"},
  120. expectError: false,
  121. },
  122. {
  123. name: "one invalid choice",
  124. inputValues: []string{"option1", "invalid"},
  125. choices: []string{"option1", "option2", "option3"},
  126. expectError: true,
  127. },
  128. {
  129. name: "all invalid choices",
  130. inputValues: []string{"invalid1", "invalid2"},
  131. choices: []string{"option1", "option2", "option3"},
  132. expectError: true,
  133. },
  134. {
  135. name: "case sensitive - different case",
  136. inputValues: []string{"OPTION1"},
  137. choices: []string{"option1", "option2"},
  138. expectError: true,
  139. },
  140. {
  141. name: "empty string in input",
  142. inputValues: []string{""},
  143. choices: []string{"option1", "option2"},
  144. expectError: true,
  145. },
  146. {
  147. name: "empty choices list with non-empty input",
  148. inputValues: []string{"anything"},
  149. choices: []string{},
  150. expectError: true,
  151. },
  152. {
  153. name: "mixed valid and invalid choices",
  154. inputValues: []string{"option1", "invalid", "option2"},
  155. choices: []string{"option1", "option2", "option3"},
  156. expectError: true,
  157. },
  158. }
  159. for _, tt := range tests {
  160. t.Run(tt.name, func(t *testing.T) {
  161. err := validateListChoices(tt.inputValues, tt.choices)
  162. if tt.expectError {
  163. if err == nil {
  164. t.Errorf("expected error but got none")
  165. } else {
  166. // Verify error message format
  167. expectedPrefix := "value must be one of:"
  168. if !strings.Contains(err.Error(), expectedPrefix) {
  169. t.Errorf("error message should contain '%s', got: %s", expectedPrefix, err.Error())
  170. }
  171. }
  172. } else {
  173. if err != nil {
  174. t.Errorf("expected no error but got: %v", err)
  175. }
  176. }
  177. })
  178. }
  179. }
  180. func TestValidateGreaterThan(t *testing.T) {
  181. if err := validateGreaterThan("10", 5); err != nil {
  182. t.Errorf("expected no error, got: %v", err)
  183. }
  184. if err := validateGreaterThan("5", 5); err == nil {
  185. t.Errorf("expected error, got none")
  186. }
  187. if err := validateGreaterThan("abc", 5); err == nil {
  188. t.Errorf("expected error for non-integer input, got none")
  189. }
  190. if err := validateGreaterThan("-1", 0); err == nil {
  191. t.Errorf("expected error for value below minimum, got none")
  192. }
  193. }
  194. func TestValidateGreaterOrEqualThan(t *testing.T) {
  195. if err := validateGreaterOrEqualThan("10", 5); err != nil {
  196. t.Errorf("expected no error, got: %v", err)
  197. }
  198. if err := validateGreaterOrEqualThan("5", 5); err != nil {
  199. t.Errorf("expected no error for equal value, got: %v", err)
  200. }
  201. if err := validateGreaterOrEqualThan("abc", 5); err == nil {
  202. t.Errorf("expected error for non-integer input, got none")
  203. }
  204. if err := validateGreaterOrEqualThan("-1", 0); err == nil {
  205. t.Errorf("expected error for value below minimum, got none")
  206. }
  207. }
  208. func TestValidateRange(t *testing.T) {
  209. tests := []struct {
  210. name string
  211. rawValue string
  212. min int
  213. max int
  214. expectError bool
  215. errorMsg string
  216. }{
  217. {
  218. name: "valid integer within range",
  219. rawValue: "5",
  220. min: 1,
  221. max: 10,
  222. expectError: false,
  223. },
  224. {
  225. name: "valid integer at minimum",
  226. rawValue: "1",
  227. min: 1,
  228. max: 10,
  229. expectError: false,
  230. },
  231. {
  232. name: "valid integer at maximum",
  233. rawValue: "10",
  234. min: 1,
  235. max: 10,
  236. expectError: false,
  237. },
  238. {
  239. name: "valid zero in range",
  240. rawValue: "0",
  241. min: -5,
  242. max: 5,
  243. expectError: false,
  244. },
  245. {
  246. name: "valid negative in range",
  247. rawValue: "-3",
  248. min: -5,
  249. max: 5,
  250. expectError: false,
  251. },
  252. {
  253. name: "integer below minimum",
  254. rawValue: "0",
  255. min: 1,
  256. max: 10,
  257. expectError: true,
  258. errorMsg: "value must be between 1 and 10",
  259. },
  260. {
  261. name: "integer above maximum",
  262. rawValue: "11",
  263. min: 1,
  264. max: 10,
  265. expectError: true,
  266. errorMsg: "value must be between 1 and 10",
  267. },
  268. {
  269. name: "integer far below minimum",
  270. rawValue: "-100",
  271. min: 1,
  272. max: 10,
  273. expectError: true,
  274. errorMsg: "value must be between 1 and 10",
  275. },
  276. {
  277. name: "integer far above maximum",
  278. rawValue: "100",
  279. min: 1,
  280. max: 10,
  281. expectError: true,
  282. errorMsg: "value must be between 1 and 10",
  283. },
  284. {
  285. name: "non-integer string",
  286. rawValue: "abc",
  287. min: 1,
  288. max: 10,
  289. expectError: true,
  290. errorMsg: "value must be an integer",
  291. },
  292. {
  293. name: "empty string",
  294. rawValue: "",
  295. min: 1,
  296. max: 10,
  297. expectError: true,
  298. errorMsg: "value must be an integer",
  299. },
  300. {
  301. name: "float string",
  302. rawValue: "5.5",
  303. min: 1,
  304. max: 10,
  305. expectError: true,
  306. errorMsg: "value must be an integer",
  307. },
  308. {
  309. name: "string with spaces",
  310. rawValue: " 5 ",
  311. min: 1,
  312. max: 10,
  313. expectError: true,
  314. errorMsg: "value must be an integer",
  315. },
  316. {
  317. name: "single value range",
  318. rawValue: "5",
  319. min: 5,
  320. max: 5,
  321. expectError: false,
  322. },
  323. {
  324. name: "single value range - below",
  325. rawValue: "4",
  326. min: 5,
  327. max: 5,
  328. expectError: true,
  329. errorMsg: "value must be between 5 and 5",
  330. },
  331. {
  332. name: "single value range - above",
  333. rawValue: "6",
  334. min: 5,
  335. max: 5,
  336. expectError: true,
  337. errorMsg: "value must be between 5 and 5",
  338. },
  339. }
  340. for _, tt := range tests {
  341. t.Run(tt.name, func(t *testing.T) {
  342. err := validateRange(tt.rawValue, tt.min, tt.max)
  343. if tt.expectError {
  344. if err == nil {
  345. t.Errorf("expected error but got none")
  346. } else if tt.errorMsg != "" && err.Error() != tt.errorMsg {
  347. t.Errorf("expected error message '%s', got '%s'", tt.errorMsg, err.Error())
  348. }
  349. } else {
  350. if err != nil {
  351. t.Errorf("expected no error but got: %v", err)
  352. }
  353. }
  354. })
  355. }
  356. }