options_parsing_test.go 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045
  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. "slices"
  6. "testing"
  7. )
  8. func TestBaseURLOptionParsing(t *testing.T) {
  9. configParser := NewConfigParser()
  10. if configParser.options.BaseURL() != "http://localhost" {
  11. t.Fatalf("Expected BASE_URL to be 'http://localhost' by default")
  12. }
  13. if configParser.options.RootURL() != "http://localhost" {
  14. t.Fatalf("Expected ROOT_URL to be 'http://localhost' by default")
  15. }
  16. if configParser.options.BasePath() != "" {
  17. t.Fatalf("Expected BASE_PATH to be empty by default")
  18. }
  19. if err := configParser.parseLines([]string{"BASE_URL=https://example.com/app"}); err != nil {
  20. t.Fatalf("Unexpected error: %v", err)
  21. }
  22. if configParser.options.BaseURL() != "https://example.com/app" {
  23. t.Fatalf("Expected BASE_URL to be 'https://example.com/app', got '%s'", configParser.options.BaseURL())
  24. }
  25. if configParser.options.RootURL() != "https://example.com" {
  26. t.Fatalf("Expected ROOT_URL to be 'https://example.com', got '%s'", configParser.options.RootURL())
  27. }
  28. if configParser.options.BasePath() != "/app" {
  29. t.Fatalf("Expected BASE_PATH to be '/app', got '%s'", configParser.options.BasePath())
  30. }
  31. if err := configParser.parseLines([]string{"BASE_URL=https://example.com/app/"}); err != nil {
  32. t.Fatalf("Unexpected error: %v", err)
  33. }
  34. if configParser.options.BaseURL() != "https://example.com/app" {
  35. t.Fatalf("Expected BASE_URL to be 'https://example.com/app', got '%s'", configParser.options.BaseURL())
  36. }
  37. if configParser.options.RootURL() != "https://example.com" {
  38. t.Fatalf("Expected ROOT_URL to be 'https://example.com', got '%s'", configParser.options.RootURL())
  39. }
  40. if configParser.options.BasePath() != "/app" {
  41. t.Fatalf("Expected BASE_PATH to be '/app', got '%s'", configParser.options.BasePath())
  42. }
  43. if err := configParser.parseLines([]string{"BASE_URL=example.com/app/"}); err == nil {
  44. t.Fatal("Expected an error due to missing scheme in BASE_URL")
  45. }
  46. }
  47. func TestWatchdogOptionParsing(t *testing.T) {
  48. configParser := NewConfigParser()
  49. if !configParser.options.Watchdog() {
  50. t.Fatal("Expected WATCHDOG to be enabled by default")
  51. }
  52. if !configParser.options.HasSchedulerService() {
  53. t.Fatal("Expected HAS_SCHEDULER_SERVICE to be enabled by default")
  54. }
  55. if err := configParser.parseLines([]string{"WATCHDOG=1"}); err != nil {
  56. t.Fatal("Unexpected error:", err)
  57. }
  58. if !configParser.options.Watchdog() {
  59. t.Fatal("Expected WATCHDOG to be enabled")
  60. }
  61. if !configParser.options.HasSchedulerService() {
  62. t.Fatal("Expected HAS_SCHEDULER_SERVICE to be enabled")
  63. }
  64. if err := configParser.parseLines([]string{"WATCHDOG=0"}); err != nil {
  65. t.Fatal("Unexpected error:", err)
  66. }
  67. if configParser.options.Watchdog() {
  68. t.Fatal("Expected WATCHDOG to be disabled")
  69. }
  70. if configParser.options.HasWatchdog() {
  71. t.Fatal("Expected HAS_WATCHDOG to be disabled")
  72. }
  73. }
  74. func TestWebAuthnOptionParsing(t *testing.T) {
  75. configParser := NewConfigParser()
  76. if configParser.options.WebAuthn() {
  77. t.Fatalf("Expected WEBAUTHN to be disabled by default")
  78. }
  79. if err := configParser.parseLines([]string{"WEBAUTHN=1"}); err != nil {
  80. t.Fatalf("Unexpected error: %v", err)
  81. }
  82. if !configParser.options.WebAuthn() {
  83. t.Fatalf("Expected WEBAUTHN to be enabled")
  84. }
  85. }
  86. func TestWorkerPoolSizeOptionParsing(t *testing.T) {
  87. configParser := NewConfigParser()
  88. if configParser.options.WorkerPoolSize() != 16 {
  89. t.Fatalf("Expected WORKER_POOL_SIZE to be 16 by default")
  90. }
  91. if err := configParser.parseLines([]string{"WORKER_POOL_SIZE=8"}); err != nil {
  92. t.Fatalf("Unexpected error: %v", err)
  93. }
  94. if configParser.options.WorkerPoolSize() != 8 {
  95. t.Fatalf("Expected WORKER_POOL_SIZE to be 8")
  96. }
  97. }
  98. func TestYouTubeAPIKeyOptionParsing(t *testing.T) {
  99. configParser := NewConfigParser()
  100. if configParser.options.YouTubeAPIKey() != "" {
  101. t.Fatalf("Expected YOUTUBE_API_KEY to be empty by default")
  102. }
  103. if err := configParser.parseLines([]string{"YOUTUBE_API_KEY=somekey"}); err != nil {
  104. t.Fatalf("Unexpected error: %v", err)
  105. }
  106. if configParser.options.YouTubeAPIKey() != "somekey" {
  107. t.Fatalf("Expected YOUTUBE_API_KEY to be 'somekey'")
  108. }
  109. }
  110. func TestAdminPasswordOptionParsing(t *testing.T) {
  111. configParser := NewConfigParser()
  112. if configParser.options.AdminPassword() != "" {
  113. t.Fatalf("Expected ADMIN_PASSWORD to be empty by default")
  114. }
  115. if err := configParser.parseLines([]string{"ADMIN_PASSWORD=secret123"}); err != nil {
  116. t.Fatalf("Unexpected error: %v", err)
  117. }
  118. if configParser.options.AdminPassword() != "secret123" {
  119. t.Fatalf("Expected ADMIN_PASSWORD to be 'secret123'")
  120. }
  121. }
  122. func TestAdminUsernameOptionParsing(t *testing.T) {
  123. configParser := NewConfigParser()
  124. if configParser.options.AdminUsername() != "" {
  125. t.Fatalf("Expected ADMIN_USERNAME to be empty by default")
  126. }
  127. if err := configParser.parseLines([]string{"ADMIN_USERNAME=admin"}); err != nil {
  128. t.Fatalf("Unexpected error: %v", err)
  129. }
  130. if configParser.options.AdminUsername() != "admin" {
  131. t.Fatalf("Expected ADMIN_USERNAME to be 'admin'")
  132. }
  133. }
  134. func TestAuthProxyHeaderOptionParsing(t *testing.T) {
  135. configParser := NewConfigParser()
  136. if configParser.options.AuthProxyHeader() != "" {
  137. t.Fatalf("Expected AUTH_PROXY_HEADER to be empty by default")
  138. }
  139. if err := configParser.parseLines([]string{"AUTH_PROXY_HEADER=X-Forwarded-User"}); err != nil {
  140. t.Fatalf("Unexpected error: %v", err)
  141. }
  142. if configParser.options.AuthProxyHeader() != "X-Forwarded-User" {
  143. t.Fatalf("Expected AUTH_PROXY_HEADER to be 'X-Forwarded-User'")
  144. }
  145. }
  146. func TestAuthProxyUserCreationOptionParsing(t *testing.T) {
  147. configParser := NewConfigParser()
  148. if configParser.options.AuthProxyUserCreation() {
  149. t.Fatal("Expected AUTH_PROXY_USER_CREATION to be disabled by default")
  150. }
  151. if configParser.options.IsAuthProxyUserCreationAllowed() {
  152. t.Fatal("Expected HAS_AUTH_PROXY_USER_CREATION to be disabled by default")
  153. }
  154. if err := configParser.parseLines([]string{"AUTH_PROXY_USER_CREATION=1"}); err != nil {
  155. t.Fatalf("Unexpected error: %v", err)
  156. }
  157. if !configParser.options.AuthProxyUserCreation() {
  158. t.Fatal("Expected AUTH_PROXY_USER_CREATION to be enabled")
  159. }
  160. if !configParser.options.IsAuthProxyUserCreationAllowed() {
  161. t.Fatal("Expected HAS_AUTH_PROXY_USER_CREATION to be enabled")
  162. }
  163. if err := configParser.parseLines([]string{"AUTH_PROXY_USER_CREATION=0"}); err != nil {
  164. t.Fatalf("Unexpected error: %v", err)
  165. }
  166. if configParser.options.AuthProxyUserCreation() {
  167. t.Fatal("Expected AUTH_PROXY_USER_CREATION to be disabled")
  168. }
  169. if configParser.options.IsAuthProxyUserCreationAllowed() {
  170. t.Fatal("Expected HAS_AUTH_PROXY_USER_CREATION to be disabled")
  171. }
  172. }
  173. func TestBatchSizeOptionParsing(t *testing.T) {
  174. configParser := NewConfigParser()
  175. if configParser.options.BatchSize() != 100 {
  176. t.Fatalf("Expected BATCH_SIZE to be 100 by default")
  177. }
  178. if err := configParser.parseLines([]string{"BATCH_SIZE=50"}); err != nil {
  179. t.Fatalf("Unexpected error: %v", err)
  180. }
  181. if configParser.options.BatchSize() != 50 {
  182. t.Fatalf("Expected BATCH_SIZE to be 50")
  183. }
  184. }
  185. func TestCertDomainOptionParsing(t *testing.T) {
  186. configParser := NewConfigParser()
  187. if configParser.options.CertDomain() != "" {
  188. t.Fatalf("Expected CERT_DOMAIN to be empty by default")
  189. }
  190. if err := configParser.parseLines([]string{"CERT_DOMAIN=example.com"}); err != nil {
  191. t.Fatalf("Unexpected error: %v", err)
  192. }
  193. if configParser.options.CertDomain() != "example.com" {
  194. t.Fatalf("Expected CERT_DOMAIN to be 'example.com'")
  195. }
  196. }
  197. func TestCertFileOptionParsing(t *testing.T) {
  198. configParser := NewConfigParser()
  199. if configParser.options.CertFile() != "" {
  200. t.Fatalf("Expected CERT_FILE to be empty by default")
  201. }
  202. if err := configParser.parseLines([]string{"CERT_FILE=/path/to/cert.pem"}); err != nil {
  203. t.Fatalf("Unexpected error: %v", err)
  204. }
  205. if configParser.options.CertFile() != "/path/to/cert.pem" {
  206. t.Fatalf("Expected CERT_FILE to be '/path/to/cert.pem'")
  207. }
  208. }
  209. func TestCleanupArchiveBatchSizeOptionParsing(t *testing.T) {
  210. configParser := NewConfigParser()
  211. if configParser.options.CleanupArchiveBatchSize() != 10000 {
  212. t.Fatalf("Expected CLEANUP_ARCHIVE_BATCH_SIZE to be 10000 by default")
  213. }
  214. if err := configParser.parseLines([]string{"CLEANUP_ARCHIVE_BATCH_SIZE=5000"}); err != nil {
  215. t.Fatalf("Unexpected error: %v", err)
  216. }
  217. if configParser.options.CleanupArchiveBatchSize() != 5000 {
  218. t.Fatalf("Expected CLEANUP_ARCHIVE_BATCH_SIZE to be 5000")
  219. }
  220. }
  221. func TestCreateAdminOptionParsing(t *testing.T) {
  222. configParser := NewConfigParser()
  223. if configParser.options.CreateAdmin() {
  224. t.Fatalf("Expected CREATE_ADMIN to be disabled by default")
  225. }
  226. if err := configParser.parseLines([]string{"CREATE_ADMIN=1"}); err != nil {
  227. t.Fatalf("Unexpected error: %v", err)
  228. }
  229. if !configParser.options.CreateAdmin() {
  230. t.Fatalf("Expected CREATE_ADMIN to be enabled")
  231. }
  232. if err := configParser.parseLines([]string{"CREATE_ADMIN=0"}); err != nil {
  233. t.Fatalf("Unexpected error: %v", err)
  234. }
  235. if configParser.options.CreateAdmin() {
  236. t.Fatalf("Expected CREATE_ADMIN to be disabled")
  237. }
  238. }
  239. func TestDatabaseMaxConnsOptionParsing(t *testing.T) {
  240. configParser := NewConfigParser()
  241. if configParser.options.DatabaseMaxConns() != 20 {
  242. t.Fatalf("Expected DATABASE_MAX_CONNS to be 20 by default")
  243. }
  244. if err := configParser.parseLines([]string{"DATABASE_MAX_CONNS=10"}); err != nil {
  245. t.Fatalf("Unexpected error: %v", err)
  246. }
  247. if configParser.options.DatabaseMaxConns() != 10 {
  248. t.Fatalf("Expected DATABASE_MAX_CONNS to be 10")
  249. }
  250. }
  251. func TestDatabaseMinConnsOptionParsing(t *testing.T) {
  252. configParser := NewConfigParser()
  253. if configParser.options.DatabaseMinConns() != 1 {
  254. t.Fatalf("Expected DATABASE_MIN_CONNS to be 1 by default")
  255. }
  256. if err := configParser.parseLines([]string{"DATABASE_MIN_CONNS=2"}); err != nil {
  257. t.Fatalf("Unexpected error: %v", err)
  258. }
  259. if configParser.options.DatabaseMinConns() != 2 {
  260. t.Fatalf("Expected DATABASE_MIN_CONNS to be 2")
  261. }
  262. }
  263. func TestDatabaseURLOptionParsing(t *testing.T) {
  264. configParser := NewConfigParser()
  265. if configParser.options.DatabaseURL() != "user=postgres password=postgres dbname=miniflux2 sslmode=disable" {
  266. t.Fatal("Expected DATABASE_URL to have default value")
  267. }
  268. if !configParser.options.IsDefaultDatabaseURL() {
  269. t.Fatal("Expected DATABASE_URL to be the default value")
  270. }
  271. if err := configParser.parseLines([]string{"DATABASE_URL=postgres://user:pass@localhost/db"}); err != nil {
  272. t.Fatalf("Unexpected error: %v", err)
  273. }
  274. if configParser.options.DatabaseURL() != "postgres://user:pass@localhost/db" {
  275. t.Fatal("Expected DATABASE_URL to be 'postgres://user:pass@localhost/db'")
  276. }
  277. if configParser.options.IsDefaultDatabaseURL() {
  278. t.Fatal("Expected DATABASE_URL to not be the default value")
  279. }
  280. }
  281. func TestDisableHSTSOptionParsing(t *testing.T) {
  282. configParser := NewConfigParser()
  283. if configParser.options.DisableHSTS() {
  284. t.Fatal("Expected DISABLE_HSTS to be disabled by default")
  285. }
  286. if !configParser.options.HasHSTS() {
  287. t.Fatal("Expected HAS_HSTS to be enabled by default")
  288. }
  289. if err := configParser.parseLines([]string{"DISABLE_HSTS=1"}); err != nil {
  290. t.Fatalf("Unexpected error: %v", err)
  291. }
  292. if !configParser.options.DisableHSTS() {
  293. t.Fatal("Expected DISABLE_HSTS to be enabled")
  294. }
  295. if configParser.options.HasHSTS() {
  296. t.Fatal("Expected HAS_HSTS to be disabled")
  297. }
  298. if err := configParser.parseLines([]string{"DISABLE_HSTS=0"}); err != nil {
  299. t.Fatalf("Unexpected error: %v", err)
  300. }
  301. if configParser.options.DisableHSTS() {
  302. t.Fatal("Expected DISABLE_HSTS to be disabled")
  303. }
  304. if !configParser.options.HasHSTS() {
  305. t.Fatal("Expected HAS_HSTS to be enabled")
  306. }
  307. }
  308. func TestDisableHTTPServiceOptionParsing(t *testing.T) {
  309. configParser := NewConfigParser()
  310. if configParser.options.DisableHTTPService() {
  311. t.Fatal("Expected DISABLE_HTTP_SERVICE to be disabled by default")
  312. }
  313. if !configParser.options.HasHTTPService() {
  314. t.Fatal("Expected HAS_HTTP_SERVICE to be enabled by default")
  315. }
  316. if err := configParser.parseLines([]string{"DISABLE_HTTP_SERVICE=1"}); err != nil {
  317. t.Fatalf("Unexpected error: %v", err)
  318. }
  319. if !configParser.options.DisableHTTPService() {
  320. t.Fatal("Expected DISABLE_HTTP_SERVICE to be enabled")
  321. }
  322. if configParser.options.HasHTTPService() {
  323. t.Fatal("Expected HAS_HTTP_SERVICE to be disabled")
  324. }
  325. if err := configParser.parseLines([]string{"DISABLE_HTTP_SERVICE=0"}); err != nil {
  326. t.Fatalf("Unexpected error: %v", err)
  327. }
  328. if configParser.options.DisableHTTPService() {
  329. t.Fatal("Expected DISABLE_HTTP_SERVICE to be disabled")
  330. }
  331. if !configParser.options.HasHTTPService() {
  332. t.Fatal("Expected HAS_HTTP_SERVICE to be disabled")
  333. }
  334. }
  335. func TestDisableLocalAuthOptionParsing(t *testing.T) {
  336. configParser := NewConfigParser()
  337. if configParser.options.DisableLocalAuth() {
  338. t.Fatalf("Expected DISABLE_LOCAL_AUTH to be disabled by default")
  339. }
  340. if err := configParser.parseLines([]string{"DISABLE_LOCAL_AUTH=1"}); err != nil {
  341. t.Fatalf("Unexpected error: %v", err)
  342. }
  343. if !configParser.options.DisableLocalAuth() {
  344. t.Fatalf("Expected DISABLE_LOCAL_AUTH to be enabled")
  345. }
  346. if err := configParser.parseLines([]string{"DISABLE_LOCAL_AUTH=0"}); err != nil {
  347. t.Fatalf("Unexpected error: %v", err)
  348. }
  349. if configParser.options.DisableLocalAuth() {
  350. t.Fatalf("Expected DISABLE_LOCAL_AUTH to be disabled")
  351. }
  352. }
  353. func TestDisableSchedulerServiceOptionParsing(t *testing.T) {
  354. configParser := NewConfigParser()
  355. if configParser.options.DisableSchedulerService() {
  356. t.Fatal("Expected DISABLE_SCHEDULER_SERVICE to be disabled by default")
  357. }
  358. if !configParser.options.HasSchedulerService() {
  359. t.Fatal("Expected HAS_SCHEDULER_SERVICE to be enabled by default")
  360. }
  361. if err := configParser.parseLines([]string{"DISABLE_SCHEDULER_SERVICE=1"}); err != nil {
  362. t.Fatalf("Unexpected error: %v", err)
  363. }
  364. if !configParser.options.DisableSchedulerService() {
  365. t.Fatal("Expected DISABLE_SCHEDULER_SERVICE to be enabled")
  366. }
  367. if configParser.options.HasSchedulerService() {
  368. t.Fatal("Expected HAS_SCHEDULER_SERVICE to be disabled")
  369. }
  370. if err := configParser.parseLines([]string{"DISABLE_SCHEDULER_SERVICE=0"}); err != nil {
  371. t.Fatalf("Unexpected error: %v", err)
  372. }
  373. if configParser.options.DisableSchedulerService() {
  374. t.Fatal("Expected DISABLE_SCHEDULER_SERVICE to be disabled")
  375. }
  376. if !configParser.options.HasSchedulerService() {
  377. t.Fatal("Expected HAS_SCHEDULER_SERVICE to be enabled")
  378. }
  379. }
  380. func TestFetchBilibiliWatchTimeOptionParsing(t *testing.T) {
  381. configParser := NewConfigParser()
  382. if configParser.options.FetchBilibiliWatchTime() {
  383. t.Fatalf("Expected FETCH_BILIBILI_WATCH_TIME to be disabled by default")
  384. }
  385. if err := configParser.parseLines([]string{"FETCH_BILIBILI_WATCH_TIME=1"}); err != nil {
  386. t.Fatalf("Unexpected error: %v", err)
  387. }
  388. if !configParser.options.FetchBilibiliWatchTime() {
  389. t.Fatalf("Expected FETCH_BILIBILI_WATCH_TIME to be enabled")
  390. }
  391. if err := configParser.parseLines([]string{"FETCH_BILIBILI_WATCH_TIME=0"}); err != nil {
  392. t.Fatalf("Unexpected error: %v", err)
  393. }
  394. if configParser.options.FetchBilibiliWatchTime() {
  395. t.Fatalf("Expected FETCH_BILIBILI_WATCH_TIME to be disabled")
  396. }
  397. }
  398. func TestFetchNebulaWatchTimeOptionParsing(t *testing.T) {
  399. configParser := NewConfigParser()
  400. if configParser.options.FetchNebulaWatchTime() {
  401. t.Fatalf("Expected FETCH_NEBULA_WATCH_TIME to be disabled by default")
  402. }
  403. if err := configParser.parseLines([]string{"FETCH_NEBULA_WATCH_TIME=1"}); err != nil {
  404. t.Fatalf("Unexpected error: %v", err)
  405. }
  406. if !configParser.options.FetchNebulaWatchTime() {
  407. t.Fatalf("Expected FETCH_NEBULA_WATCH_TIME to be enabled")
  408. }
  409. if err := configParser.parseLines([]string{"FETCH_NEBULA_WATCH_TIME=0"}); err != nil {
  410. t.Fatalf("Unexpected error: %v", err)
  411. }
  412. if configParser.options.FetchNebulaWatchTime() {
  413. t.Fatalf("Expected FETCH_NEBULA_WATCH_TIME to be disabled")
  414. }
  415. }
  416. func TestFetchOdyseeWatchTimeOptionParsing(t *testing.T) {
  417. configParser := NewConfigParser()
  418. if configParser.options.FetchOdyseeWatchTime() {
  419. t.Fatalf("Expected FETCH_ODYSEE_WATCH_TIME to be disabled by default")
  420. }
  421. if err := configParser.parseLines([]string{"FETCH_ODYSEE_WATCH_TIME=1"}); err != nil {
  422. t.Fatalf("Unexpected error: %v", err)
  423. }
  424. if !configParser.options.FetchOdyseeWatchTime() {
  425. t.Fatalf("Expected FETCH_ODYSEE_WATCH_TIME to be enabled")
  426. }
  427. if err := configParser.parseLines([]string{"FETCH_ODYSEE_WATCH_TIME=0"}); err != nil {
  428. t.Fatalf("Unexpected error: %v", err)
  429. }
  430. if configParser.options.FetchOdyseeWatchTime() {
  431. t.Fatalf("Expected FETCH_ODYSEE_WATCH_TIME to be disabled")
  432. }
  433. }
  434. func TestFetchYouTubeWatchTimeOptionParsing(t *testing.T) {
  435. configParser := NewConfigParser()
  436. if configParser.options.FetchYouTubeWatchTime() {
  437. t.Fatalf("Expected FETCH_YOUTUBE_WATCH_TIME to be disabled by default")
  438. }
  439. if err := configParser.parseLines([]string{"FETCH_YOUTUBE_WATCH_TIME=1"}); err != nil {
  440. t.Fatalf("Unexpected error: %v", err)
  441. }
  442. if !configParser.options.FetchYouTubeWatchTime() {
  443. t.Fatalf("Expected FETCH_YOUTUBE_WATCH_TIME to be enabled")
  444. }
  445. if err := configParser.parseLines([]string{"FETCH_YOUTUBE_WATCH_TIME=0"}); err != nil {
  446. t.Fatalf("Unexpected error: %v", err)
  447. }
  448. if configParser.options.FetchYouTubeWatchTime() {
  449. t.Fatalf("Expected FETCH_YOUTUBE_WATCH_TIME to be disabled")
  450. }
  451. }
  452. func TestHTTPClientMaxBodySizeOptionParsing(t *testing.T) {
  453. configParser := NewConfigParser()
  454. if configParser.options.HTTPClientMaxBodySize() != 15*1024*1024 {
  455. t.Fatalf("Expected HTTP_CLIENT_MAX_BODY_SIZE to be 15 by default, got %d", configParser.options.HTTPClientMaxBodySize())
  456. }
  457. if err := configParser.parseLines([]string{"HTTP_CLIENT_MAX_BODY_SIZE=25"}); err != nil {
  458. t.Fatalf("Unexpected error: %v", err)
  459. }
  460. expectedValue := 25 * 1024 * 1024
  461. currentValue := configParser.options.HTTPClientMaxBodySize()
  462. if currentValue != int64(expectedValue) {
  463. t.Fatalf("Expected HTTP_CLIENT_MAX_BODY_SIZE to be %d, got %d", expectedValue, currentValue)
  464. }
  465. }
  466. func TestHTTPClientUserAgentOptionParsing(t *testing.T) {
  467. configParser := NewConfigParser()
  468. if configParser.options.HTTPClientUserAgent() != defaultHTTPClientUserAgent {
  469. t.Fatalf("Expected HTTP_CLIENT_USER_AGENT to have default value")
  470. }
  471. if err := configParser.parseLines([]string{"HTTP_CLIENT_USER_AGENT=Custom User Agent"}); err != nil {
  472. t.Fatalf("Unexpected error: %v", err)
  473. }
  474. if configParser.options.HTTPClientUserAgent() != "Custom User Agent" {
  475. t.Fatalf("Expected HTTP_CLIENT_USER_AGENT to be 'Custom User Agent'")
  476. }
  477. }
  478. func TestHTTPSOptionParsing(t *testing.T) {
  479. configParser := NewConfigParser()
  480. if configParser.options.HTTPS() {
  481. t.Fatalf("Expected HTTPS to be disabled by default")
  482. }
  483. if err := configParser.parseLines([]string{"HTTPS=1"}); err != nil {
  484. t.Fatalf("Unexpected error: %v", err)
  485. }
  486. if !configParser.options.HTTPS() {
  487. t.Fatalf("Expected HTTPS to be enabled")
  488. }
  489. if err := configParser.parseLines([]string{"HTTPS=0"}); err != nil {
  490. t.Fatalf("Unexpected error: %v", err)
  491. }
  492. if configParser.options.HTTPS() {
  493. t.Fatalf("Expected HTTPS to be disabled")
  494. }
  495. }
  496. func TestInvidiousInstanceOptionParsing(t *testing.T) {
  497. configParser := NewConfigParser()
  498. if configParser.options.InvidiousInstance() != "yewtu.be" {
  499. t.Fatalf("Expected INVIDIOUS_INSTANCE to be 'yewtu.be' by default")
  500. }
  501. if err := configParser.parseLines([]string{"INVIDIOUS_INSTANCE=invidious.example.com"}); err != nil {
  502. t.Fatalf("Unexpected error: %v", err)
  503. }
  504. if configParser.options.InvidiousInstance() != "invidious.example.com" {
  505. t.Fatalf("Expected INVIDIOUS_INSTANCE to be 'invidious.example.com'")
  506. }
  507. }
  508. func TestCertKeyFileOptionParsing(t *testing.T) {
  509. configParser := NewConfigParser()
  510. if configParser.options.CertKeyFile() != "" {
  511. t.Fatalf("Expected KEY_FILE to be empty by default")
  512. }
  513. if err := configParser.parseLines([]string{"KEY_FILE=/path/to/key.pem"}); err != nil {
  514. t.Fatalf("Unexpected error: %v", err)
  515. }
  516. if configParser.options.CertKeyFile() != "/path/to/key.pem" {
  517. t.Fatalf("Expected KEY_FILE to be '/path/to/key.pem'")
  518. }
  519. }
  520. func TestLogDateTimeOptionParsing(t *testing.T) {
  521. configParser := NewConfigParser()
  522. if configParser.options.LogDateTime() {
  523. t.Fatalf("Expected LOG_DATE_TIME to be disabled by default")
  524. }
  525. if err := configParser.parseLines([]string{"LOG_DATE_TIME=1"}); err != nil {
  526. t.Fatalf("Unexpected error: %v", err)
  527. }
  528. if !configParser.options.LogDateTime() {
  529. t.Fatalf("Expected LOG_DATE_TIME to be enabled")
  530. }
  531. if err := configParser.parseLines([]string{"LOG_DATE_TIME=0"}); err != nil {
  532. t.Fatalf("Unexpected error: %v", err)
  533. }
  534. if configParser.options.LogDateTime() {
  535. t.Fatalf("Expected LOG_DATE_TIME to be disabled")
  536. }
  537. }
  538. func TestLogFileOptionParsing(t *testing.T) {
  539. configParser := NewConfigParser()
  540. if configParser.options.LogFile() != "stderr" {
  541. t.Fatalf("Expected LOG_FILE to be 'stderr' by default")
  542. }
  543. if err := configParser.parseLines([]string{"LOG_FILE=/var/log/miniflux.log"}); err != nil {
  544. t.Fatalf("Unexpected error: %v", err)
  545. }
  546. if configParser.options.LogFile() != "/var/log/miniflux.log" {
  547. t.Fatalf("Expected LOG_FILE to be '/var/log/miniflux.log'")
  548. }
  549. }
  550. func TestLogFormatOptionParsing(t *testing.T) {
  551. configParser := NewConfigParser()
  552. if configParser.options.LogFormat() != "text" {
  553. t.Fatalf("Expected LOG_FORMAT to be 'text' by default")
  554. }
  555. if err := configParser.parseLines([]string{"LOG_FORMAT=json"}); err != nil {
  556. t.Fatalf("Unexpected error: %v", err)
  557. }
  558. if configParser.options.LogFormat() != "json" {
  559. t.Fatalf("Expected LOG_FORMAT to be 'json'")
  560. }
  561. }
  562. func TestLogLevelOptionParsing(t *testing.T) {
  563. configParser := NewConfigParser()
  564. if configParser.options.LogLevel() != "info" {
  565. t.Fatalf("Expected LOG_LEVEL to be 'info' by default")
  566. }
  567. if err := configParser.parseLines([]string{"LOG_LEVEL=debug"}); err != nil {
  568. t.Fatalf("Unexpected error: %v", err)
  569. }
  570. if configParser.options.LogLevel() != "debug" {
  571. t.Fatalf("Expected LOG_LEVEL to be 'debug'")
  572. }
  573. }
  574. func TestMaintenanceMessageOptionParsing(t *testing.T) {
  575. configParser := NewConfigParser()
  576. if configParser.options.MaintenanceMessage() != "Miniflux is currently under maintenance" {
  577. t.Fatalf("Expected MAINTENANCE_MESSAGE to have default value")
  578. }
  579. if err := configParser.parseLines([]string{"MAINTENANCE_MESSAGE=System upgrade in progress"}); err != nil {
  580. t.Fatalf("Unexpected error: %v", err)
  581. }
  582. if configParser.options.MaintenanceMessage() != "System upgrade in progress" {
  583. t.Fatalf("Expected MAINTENANCE_MESSAGE to be 'System upgrade in progress'")
  584. }
  585. }
  586. func TestMaintenanceModeOptionParsing(t *testing.T) {
  587. configParser := NewConfigParser()
  588. if configParser.options.MaintenanceMode() {
  589. t.Fatal("Expected MAINTENANCE_MODE to be disabled by default")
  590. }
  591. if configParser.options.HasMaintenanceMode() {
  592. t.Fatal("Expected HAS_MAINTENANCE_MODE to be disabled by default")
  593. }
  594. if err := configParser.parseLines([]string{"MAINTENANCE_MODE=1"}); err != nil {
  595. t.Fatalf("Unexpected error: %v", err)
  596. }
  597. if !configParser.options.MaintenanceMode() {
  598. t.Fatal("Expected MAINTENANCE_MODE to be enabled")
  599. }
  600. if !configParser.options.HasMaintenanceMode() {
  601. t.Fatal("Expected HAS_MAINTENANCE_MODE to be enabled")
  602. }
  603. if err := configParser.parseLines([]string{"MAINTENANCE_MODE=0"}); err != nil {
  604. t.Fatalf("Unexpected error: %v", err)
  605. }
  606. if configParser.options.MaintenanceMode() {
  607. t.Fatal("Expected MAINTENANCE_MODE to be disabled")
  608. }
  609. if configParser.options.HasMaintenanceMode() {
  610. t.Fatal("Expected HAS_MAINTENANCE_MODE to be disabled")
  611. }
  612. }
  613. func TestMediaProxyModeOptionParsing(t *testing.T) {
  614. configParser := NewConfigParser()
  615. if configParser.options.MediaProxyMode() != "http-only" {
  616. t.Fatalf("Expected MEDIA_PROXY_MODE to be 'http-only' by default")
  617. }
  618. if err := configParser.parseLines([]string{"MEDIA_PROXY_MODE=all"}); err != nil {
  619. t.Fatalf("Unexpected error: %v", err)
  620. }
  621. if configParser.options.MediaProxyMode() != "all" {
  622. t.Fatalf("Expected MEDIA_PROXY_MODE to be 'all'")
  623. }
  624. }
  625. func TestMetricsCollectorOptionParsing(t *testing.T) {
  626. configParser := NewConfigParser()
  627. if configParser.options.MetricsCollector() {
  628. t.Fatal("Expected METRICS_COLLECTOR to be disabled by default")
  629. }
  630. if configParser.options.HasMetricsCollector() {
  631. t.Fatal("Expected HAS_METRICS_COLLECTOR to be disabled by default")
  632. }
  633. if err := configParser.parseLines([]string{"METRICS_COLLECTOR=1"}); err != nil {
  634. t.Fatalf("Unexpected error: %v", err)
  635. }
  636. if !configParser.options.MetricsCollector() {
  637. t.Fatal("Expected METRICS_COLLECTOR to be enabled")
  638. }
  639. if !configParser.options.HasMetricsCollector() {
  640. t.Fatal("Expected HAS_METRICS_COLLECTOR to be enabled")
  641. }
  642. if err := configParser.parseLines([]string{"METRICS_COLLECTOR=0"}); err != nil {
  643. t.Fatalf("Unexpected error: %v", err)
  644. }
  645. if configParser.options.MetricsCollector() {
  646. t.Fatal("Expected METRICS_COLLECTOR to be disabled")
  647. }
  648. if configParser.options.HasMetricsCollector() {
  649. t.Fatal("Expected HAS_METRICS_COLLECTOR to be disabled")
  650. }
  651. }
  652. func TestMetricsPasswordOptionParsing(t *testing.T) {
  653. configParser := NewConfigParser()
  654. if configParser.options.MetricsPassword() != "" {
  655. t.Fatalf("Expected METRICS_PASSWORD to be empty by default")
  656. }
  657. if err := configParser.parseLines([]string{"METRICS_PASSWORD=secret123"}); err != nil {
  658. t.Fatalf("Unexpected error: %v", err)
  659. }
  660. if configParser.options.MetricsPassword() != "secret123" {
  661. t.Fatalf("Expected METRICS_PASSWORD to be 'secret123'")
  662. }
  663. }
  664. func TestMetricsUsernameOptionParsing(t *testing.T) {
  665. configParser := NewConfigParser()
  666. if configParser.options.MetricsUsername() != "" {
  667. t.Fatalf("Expected METRICS_USERNAME to be empty by default")
  668. }
  669. if err := configParser.parseLines([]string{"METRICS_USERNAME=metrics_user"}); err != nil {
  670. t.Fatalf("Unexpected error: %v", err)
  671. }
  672. if configParser.options.MetricsUsername() != "metrics_user" {
  673. t.Fatalf("Expected METRICS_USERNAME to be 'metrics_user'")
  674. }
  675. }
  676. func TestOAuth2ClientIDOptionParsing(t *testing.T) {
  677. configParser := NewConfigParser()
  678. if configParser.options.OAuth2ClientID() != "" {
  679. t.Fatalf("Expected OAUTH2_CLIENT_ID to be empty by default")
  680. }
  681. if err := configParser.parseLines([]string{"OAUTH2_CLIENT_ID=client123"}); err != nil {
  682. t.Fatalf("Unexpected error: %v", err)
  683. }
  684. if configParser.options.OAuth2ClientID() != "client123" {
  685. t.Fatalf("Expected OAUTH2_CLIENT_ID to be 'client123'")
  686. }
  687. }
  688. func TestOAuth2ClientSecretOptionParsing(t *testing.T) {
  689. configParser := NewConfigParser()
  690. if configParser.options.OAuth2ClientSecret() != "" {
  691. t.Fatalf("Expected OAUTH2_CLIENT_SECRET to be empty by default")
  692. }
  693. if err := configParser.parseLines([]string{"OAUTH2_CLIENT_SECRET=secret456"}); err != nil {
  694. t.Fatalf("Unexpected error: %v", err)
  695. }
  696. if configParser.options.OAuth2ClientSecret() != "secret456" {
  697. t.Fatalf("Expected OAUTH2_CLIENT_SECRET to be 'secret456'")
  698. }
  699. }
  700. func TestOAuth2OIDCDiscoveryEndpointOptionParsing(t *testing.T) {
  701. configParser := NewConfigParser()
  702. if configParser.options.OAuth2OIDCDiscoveryEndpoint() != "" {
  703. t.Fatalf("Expected OAUTH2_OIDC_DISCOVERY_ENDPOINT to be empty by default")
  704. }
  705. if err := configParser.parseLines([]string{"OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://example.com/.well-known/openid_configuration"}); err != nil {
  706. t.Fatalf("Unexpected error: %v", err)
  707. }
  708. if configParser.options.OAuth2OIDCDiscoveryEndpoint() != "https://example.com/.well-known/openid_configuration" {
  709. t.Fatalf("Expected OAUTH2_OIDC_DISCOVERY_ENDPOINT to be 'https://example.com/.well-known/openid_configuration'")
  710. }
  711. }
  712. func TestOAuth2OIDCProviderNameOptionParsing(t *testing.T) {
  713. configParser := NewConfigParser()
  714. if configParser.options.OAuth2OIDCProviderName() != "OpenID Connect" {
  715. t.Fatalf("Expected OAUTH2_OIDC_PROVIDER_NAME to be 'OpenID Connect' by default")
  716. }
  717. if err := configParser.parseLines([]string{"OAUTH2_OIDC_PROVIDER_NAME=My Provider"}); err != nil {
  718. t.Fatalf("Unexpected error: %v", err)
  719. }
  720. if configParser.options.OAuth2OIDCProviderName() != "My Provider" {
  721. t.Fatalf("Expected OAUTH2_OIDC_PROVIDER_NAME to be 'My Provider'")
  722. }
  723. }
  724. func TestOAuth2ProviderOptionParsing(t *testing.T) {
  725. configParser := NewConfigParser()
  726. if configParser.options.OAuth2Provider() != "" {
  727. t.Fatal("Expected OAUTH2_PROVIDER to be empty by default")
  728. }
  729. if err := configParser.parseLines([]string{"OAUTH2_PROVIDER=google"}); err != nil {
  730. t.Fatalf("Unexpected error: %v", err)
  731. }
  732. if configParser.options.OAuth2Provider() != "google" {
  733. t.Fatal("Expected OAUTH2_PROVIDER to be 'google'")
  734. }
  735. if err := configParser.parseLines([]string{"OAUTH2_PROVIDER=oidc"}); err != nil {
  736. t.Fatalf("Unexpected error: %v", err)
  737. }
  738. if configParser.options.OAuth2Provider() != "oidc" {
  739. t.Fatal("Expected OAUTH2_PROVIDER to be 'oidc'")
  740. }
  741. if err := configParser.parseLines([]string{"OAUTH2_PROVIDER=invalid"}); err == nil {
  742. t.Fatal("Expected error for invalid OAUTH2_PROVIDER value")
  743. }
  744. }
  745. func TestOAuth2RedirectURLOptionParsing(t *testing.T) {
  746. configParser := NewConfigParser()
  747. if configParser.options.OAuth2RedirectURL() != "" {
  748. t.Fatalf("Expected OAUTH2_REDIRECT_URL to be empty by default")
  749. }
  750. if err := configParser.parseLines([]string{"OAUTH2_REDIRECT_URL=https://example.com/callback"}); err != nil {
  751. t.Fatalf("Unexpected error: %v", err)
  752. }
  753. if configParser.options.OAuth2RedirectURL() != "https://example.com/callback" {
  754. t.Fatalf("Expected OAUTH2_REDIRECT_URL to be 'https://example.com/callback'")
  755. }
  756. }
  757. func TestOAuth2UserCreationOptionParsing(t *testing.T) {
  758. configParser := NewConfigParser()
  759. if configParser.options.OAuth2UserCreation() {
  760. t.Fatal("Expected OAUTH2_USER_CREATION to be disabled by default")
  761. }
  762. if configParser.options.IsOAuth2UserCreationAllowed() {
  763. t.Fatal("Expected OAUTH2_USER_CREATION to be disabled by default")
  764. }
  765. if err := configParser.parseLines([]string{"OAUTH2_USER_CREATION=1"}); err != nil {
  766. t.Fatalf("Unexpected error: %v", err)
  767. }
  768. if !configParser.options.OAuth2UserCreation() {
  769. t.Fatal("Expected OAUTH2_USER_CREATION to be enabled")
  770. }
  771. if !configParser.options.IsOAuth2UserCreationAllowed() {
  772. t.Fatal("Expected OAUTH2_USER_CREATION to be enabled")
  773. }
  774. if err := configParser.parseLines([]string{"OAUTH2_USER_CREATION=0"}); err != nil {
  775. t.Fatalf("Unexpected error: %v", err)
  776. }
  777. if configParser.options.OAuth2UserCreation() {
  778. t.Fatal("Expected OAUTH2_USER_CREATION to be disabled")
  779. }
  780. if configParser.options.IsOAuth2UserCreationAllowed() {
  781. t.Fatal("Expected OAUTH2_USER_CREATION to be disabled")
  782. }
  783. }
  784. func TestPollingLimitPerHostOptionParsing(t *testing.T) {
  785. configParser := NewConfigParser()
  786. if configParser.options.PollingLimitPerHost() != 0 {
  787. t.Fatalf("Expected POLLING_LIMIT_PER_HOST to be 0 by default")
  788. }
  789. if err := configParser.parseLines([]string{"POLLING_LIMIT_PER_HOST=5"}); err != nil {
  790. t.Fatalf("Unexpected error: %v", err)
  791. }
  792. if configParser.options.PollingLimitPerHost() != 5 {
  793. t.Fatalf("Expected POLLING_LIMIT_PER_HOST to be 5")
  794. }
  795. }
  796. func TestPollingParsingErrorLimitOptionParsing(t *testing.T) {
  797. configParser := NewConfigParser()
  798. if configParser.options.PollingParsingErrorLimit() != 3 {
  799. t.Fatalf("Expected POLLING_PARSING_ERROR_LIMIT to be 3 by default")
  800. }
  801. if err := configParser.parseLines([]string{"POLLING_PARSING_ERROR_LIMIT=5"}); err != nil {
  802. t.Fatalf("Unexpected error: %v", err)
  803. }
  804. if configParser.options.PollingParsingErrorLimit() != 5 {
  805. t.Fatalf("Expected POLLING_PARSING_ERROR_LIMIT to be 5")
  806. }
  807. }
  808. func TestPollingSchedulerOptionParsing(t *testing.T) {
  809. configParser := NewConfigParser()
  810. if configParser.options.PollingScheduler() != "round_robin" {
  811. t.Fatalf("Expected POLLING_SCHEDULER to be 'round_robin' by default")
  812. }
  813. if err := configParser.parseLines([]string{"POLLING_SCHEDULER=entry_frequency"}); err != nil {
  814. t.Fatalf("Unexpected error: %v", err)
  815. }
  816. if configParser.options.PollingScheduler() != "entry_frequency" {
  817. t.Fatalf("Expected POLLING_SCHEDULER to be 'entry_frequency'")
  818. }
  819. }
  820. func TestPortOptionParsing(t *testing.T) {
  821. configParser := NewConfigParser()
  822. if configParser.options.Port() != "" {
  823. t.Fatalf("Expected PORT to be empty by default")
  824. }
  825. if err := configParser.parseLines([]string{"PORT=1234"}); err != nil {
  826. t.Fatalf("Unexpected error: %v", err)
  827. }
  828. if configParser.options.Port() != "1234" {
  829. t.Fatalf("Expected PORT to be '1234'")
  830. }
  831. addresses := configParser.options.ListenAddr()
  832. if len(addresses) != 1 || addresses[0] != ":1234" {
  833. t.Fatalf("Expected LISTEN_ADDR to be ':1234'")
  834. }
  835. }
  836. func TestRunMigrationsOptionParsing(t *testing.T) {
  837. configParser := NewConfigParser()
  838. if configParser.options.RunMigrations() {
  839. t.Fatalf("Expected RUN_MIGRATIONS to be disabled by default")
  840. }
  841. if err := configParser.parseLines([]string{"RUN_MIGRATIONS=1"}); err != nil {
  842. t.Fatalf("Unexpected error: %v", err)
  843. }
  844. if !configParser.options.RunMigrations() {
  845. t.Fatalf("Expected RUN_MIGRATIONS to be enabled")
  846. }
  847. if err := configParser.parseLines([]string{"RUN_MIGRATIONS=0"}); err != nil {
  848. t.Fatalf("Unexpected error: %v", err)
  849. }
  850. if configParser.options.RunMigrations() {
  851. t.Fatalf("Expected RUN_MIGRATIONS to be disabled")
  852. }
  853. }
  854. func TestSchedulerEntryFrequencyFactorOptionParsing(t *testing.T) {
  855. configParser := NewConfigParser()
  856. if configParser.options.SchedulerEntryFrequencyFactor() != 1 {
  857. t.Fatalf("Expected SCHEDULER_ENTRY_FREQUENCY_FACTOR to be 1 by default")
  858. }
  859. if err := configParser.parseLines([]string{"SCHEDULER_ENTRY_FREQUENCY_FACTOR=2"}); err != nil {
  860. t.Fatalf("Unexpected error: %v", err)
  861. }
  862. if configParser.options.SchedulerEntryFrequencyFactor() != 2 {
  863. t.Fatalf("Expected SCHEDULER_ENTRY_FREQUENCY_FACTOR to be 2")
  864. }
  865. }
  866. func TestYouTubeEmbedUrlOverrideOptionParsing(t *testing.T) {
  867. configParser := NewConfigParser()
  868. // Test default value
  869. if configParser.options.YouTubeEmbedUrlOverride() != "https://www.youtube-nocookie.com/embed/" {
  870. t.Fatal("Expected YOUTUBE_EMBED_URL_OVERRIDE to have default value")
  871. }
  872. if configParser.options.YouTubeEmbedDomain() != "www.youtube-nocookie.com" {
  873. t.Fatal("Expected YOUTUBE_EMBED_DOMAIN to be 'www.youtube-nocookie.com' by default")
  874. }
  875. // Test custom value
  876. if err := configParser.parseLines([]string{"YOUTUBE_EMBED_URL_OVERRIDE=https://custom.youtube.com/embed/"}); err != nil {
  877. t.Fatalf("Unexpected error: %v", err)
  878. }
  879. if configParser.options.YouTubeEmbedUrlOverride() != "https://custom.youtube.com/embed/" {
  880. t.Fatal("Expected YOUTUBE_EMBED_URL_OVERRIDE to be 'https://custom.youtube.com/embed/'")
  881. }
  882. if configParser.options.YouTubeEmbedDomain() != "custom.youtube.com" {
  883. t.Fatal("Expected YOUTUBE_EMBED_DOMAIN to be 'custom.youtube.com'")
  884. }
  885. // Test empty value resets to default
  886. configParser = NewConfigParser()
  887. if err := configParser.parseLines([]string{"YOUTUBE_EMBED_URL_OVERRIDE="}); err != nil {
  888. t.Fatalf("Unexpected error: %v", err)
  889. }
  890. if configParser.options.YouTubeEmbedUrlOverride() != "https://www.youtube-nocookie.com/embed/" {
  891. t.Fatal("Expected YOUTUBE_EMBED_URL_OVERRIDE to have default value")
  892. }
  893. // Test invalid value
  894. configParser = NewConfigParser()
  895. if err := configParser.parseLines([]string{"YOUTUBE_EMBED_URL_OVERRIDE=http://example.com/%"}); err == nil {
  896. t.Fatal("Expected error for invalid YOUTUBE_EMBED_URL_OVERRIDE")
  897. }
  898. }
  899. func TestCleanupArchiveReadIntervalOptionParsing(t *testing.T) {
  900. configParser := NewConfigParser()
  901. if configParser.options.CleanupArchiveReadInterval().Hours() != 24*60 {
  902. t.Fatalf("Expected CLEANUP_ARCHIVE_READ_DAYS to be 60 days by default")
  903. }
  904. if err := configParser.parseLines([]string{"CLEANUP_ARCHIVE_READ_DAYS=30"}); err != nil {
  905. t.Fatalf("Unexpected error: %v", err)
  906. }
  907. if configParser.options.CleanupArchiveReadInterval().Hours() != 24*30 {
  908. t.Fatalf("Expected CLEANUP_ARCHIVE_READ_DAYS to be 30 days")
  909. }
  910. }
  911. func TestCleanupArchiveUnreadIntervalOptionParsing(t *testing.T) {
  912. configParser := NewConfigParser()
  913. if configParser.options.CleanupArchiveUnreadInterval().Hours() != 24*180 {
  914. t.Fatalf("Expected CLEANUP_ARCHIVE_UNREAD_DAYS to be 180 days by default")
  915. }
  916. if err := configParser.parseLines([]string{"CLEANUP_ARCHIVE_UNREAD_DAYS=90"}); err != nil {
  917. t.Fatalf("Unexpected error: %v", err)
  918. }
  919. if configParser.options.CleanupArchiveUnreadInterval().Hours() != 24*90 {
  920. t.Fatalf("Expected CLEANUP_ARCHIVE_UNREAD_DAYS to be 90 days")
  921. }
  922. }
  923. func TestCleanupFrequencyOptionParsing(t *testing.T) {
  924. configParser := NewConfigParser()
  925. if configParser.options.CleanupFrequency().Hours() != 24 {
  926. t.Fatalf("Expected CLEANUP_FREQUENCY_HOURS to be 24 hours by default")
  927. }
  928. if err := configParser.parseLines([]string{"CLEANUP_FREQUENCY_HOURS=12"}); err != nil {
  929. t.Fatalf("Unexpected error: %v", err)
  930. }
  931. if configParser.options.CleanupFrequency().Hours() != 12 {
  932. t.Fatalf("Expected CLEANUP_FREQUENCY_HOURS to be 12 hours")
  933. }
  934. }
  935. func TestCleanupRemoveSessionsIntervalOptionParsing(t *testing.T) {
  936. configParser := NewConfigParser()
  937. if configParser.options.CleanupRemoveSessionsInterval().Hours() != 24*30 {
  938. t.Fatalf("Expected CLEANUP_REMOVE_SESSIONS_DAYS to be 30 days by default")
  939. }
  940. if err := configParser.parseLines([]string{"CLEANUP_REMOVE_SESSIONS_DAYS=14"}); err != nil {
  941. t.Fatalf("Unexpected error: %v", err)
  942. }
  943. if configParser.options.CleanupRemoveSessionsInterval().Hours() != 24*14 {
  944. t.Fatalf("Expected CLEANUP_REMOVE_SESSIONS_DAYS to be 14 days")
  945. }
  946. }
  947. func TestDatabaseConnectionLifetimeOptionParsing(t *testing.T) {
  948. configParser := NewConfigParser()
  949. if configParser.options.DatabaseConnectionLifetime().Minutes() != 5 {
  950. t.Fatalf("Expected DATABASE_CONNECTION_LIFETIME to be 5 minutes by default")
  951. }
  952. if err := configParser.parseLines([]string{"DATABASE_CONNECTION_LIFETIME=10"}); err != nil {
  953. t.Fatalf("Unexpected error: %v", err)
  954. }
  955. if configParser.options.DatabaseConnectionLifetime().Minutes() != 10 {
  956. t.Fatalf("Expected DATABASE_CONNECTION_LIFETIME to be 10 minutes")
  957. }
  958. }
  959. func TestForceRefreshIntervalOptionParsing(t *testing.T) {
  960. configParser := NewConfigParser()
  961. if configParser.options.ForceRefreshInterval().Minutes() != 30 {
  962. t.Fatalf("Expected FORCE_REFRESH_INTERVAL to be 30 minutes by default")
  963. }
  964. if err := configParser.parseLines([]string{"FORCE_REFRESH_INTERVAL=15"}); err != nil {
  965. t.Fatalf("Unexpected error: %v", err)
  966. }
  967. if configParser.options.ForceRefreshInterval().Minutes() != 15 {
  968. t.Fatalf("Expected FORCE_REFRESH_INTERVAL to be 15 minutes")
  969. }
  970. }
  971. func TestHTTPClientProxiesOptionParsing(t *testing.T) {
  972. configParser := NewConfigParser()
  973. if configParser.options.HasHTTPClientProxiesConfigured() {
  974. t.Fatalf("Expected HTTP_CLIENT_PROXIES to be empty by default")
  975. }
  976. if err := configParser.parseLines([]string{"HTTP_CLIENT_PROXIES=proxy1.example.com:8080,proxy2.example.com:8080"}); err != nil {
  977. t.Fatalf("Unexpected error: %v", err)
  978. }
  979. if !configParser.options.HasHTTPClientProxiesConfigured() {
  980. t.Fatalf("Expected HTTP_CLIENT_PROXIES to be configured")
  981. }
  982. proxies := configParser.options.HTTPClientProxies()
  983. if len(proxies) != 2 || proxies[0] != "proxy1.example.com:8080" || proxies[1] != "proxy2.example.com:8080" {
  984. t.Fatalf("Expected HTTP_CLIENT_PROXIES to contain two proxies")
  985. }
  986. }
  987. func TestHTTPClientProxyOptionParsing(t *testing.T) {
  988. configParser := NewConfigParser()
  989. if configParser.options.HTTPClientProxyURL() != nil {
  990. t.Fatal("Expected HTTP_CLIENT_PROXY to be nil by default")
  991. }
  992. if configParser.options.HasHTTPClientProxyURLConfigured() {
  993. t.Fatal("Expected HAS_HTTP_CLIENT_PROXY to be disabled by default")
  994. }
  995. if err := configParser.parseLines([]string{"HTTP_CLIENT_PROXY=http://proxy.example.com:8080"}); err != nil {
  996. t.Fatalf("Unexpected error: %v", err)
  997. }
  998. proxyURL := configParser.options.HTTPClientProxyURL()
  999. if proxyURL == nil || proxyURL.String() != "http://proxy.example.com:8080" {
  1000. t.Fatal("Expected HTTP_CLIENT_PROXY to be 'http://proxy.example.com:8080'")
  1001. }
  1002. if !configParser.options.HasHTTPClientProxyURLConfigured() {
  1003. t.Fatal("Expected HAS_HTTP_CLIENT_PROXY to be enabled")
  1004. }
  1005. }
  1006. func TestHTTPClientTimeoutOptionParsing(t *testing.T) {
  1007. configParser := NewConfigParser()
  1008. if configParser.options.HTTPClientTimeout().Seconds() != 20 {
  1009. t.Fatalf("Expected HTTP_CLIENT_TIMEOUT to be 20 seconds by default")
  1010. }
  1011. if err := configParser.parseLines([]string{"HTTP_CLIENT_TIMEOUT=30"}); err != nil {
  1012. t.Fatalf("Unexpected error: %v", err)
  1013. }
  1014. if configParser.options.HTTPClientTimeout().Seconds() != 30 {
  1015. t.Fatalf("Expected HTTP_CLIENT_TIMEOUT to be 30 seconds")
  1016. }
  1017. }
  1018. func TestFetcherAllowPrivateNetworksOptionParsing(t *testing.T) {
  1019. configParser := NewConfigParser()
  1020. if configParser.options.FetcherAllowPrivateNetworks() {
  1021. t.Fatalf("Expected FETCHER_ALLOW_PRIVATE_NETWORKS to be disabled by default")
  1022. }
  1023. if err := configParser.parseLines([]string{"FETCHER_ALLOW_PRIVATE_NETWORKS=1"}); err != nil {
  1024. t.Fatalf("Unexpected error: %v", err)
  1025. }
  1026. if !configParser.options.FetcherAllowPrivateNetworks() {
  1027. t.Fatalf("Expected FETCHER_ALLOW_PRIVATE_NETWORKS to be enabled")
  1028. }
  1029. if err := configParser.parseLines([]string{"FETCHER_ALLOW_PRIVATE_NETWORKS=0"}); err != nil {
  1030. t.Fatalf("Unexpected error: %v", err)
  1031. }
  1032. if configParser.options.FetcherAllowPrivateNetworks() {
  1033. t.Fatalf("Expected FETCHER_ALLOW_PRIVATE_NETWORKS to be disabled")
  1034. }
  1035. }
  1036. func TestIntegrationAllowPrivateNetworksOptionParsing(t *testing.T) {
  1037. configParser := NewConfigParser()
  1038. if configParser.options.IntegrationAllowPrivateNetworks() {
  1039. t.Fatalf("Expected INTEGRATION_ALLOW_PRIVATE_NETWORKS to be disabled by default")
  1040. }
  1041. if err := configParser.parseLines([]string{"INTEGRATION_ALLOW_PRIVATE_NETWORKS=1"}); err != nil {
  1042. t.Fatalf("Unexpected error: %v", err)
  1043. }
  1044. if !configParser.options.IntegrationAllowPrivateNetworks() {
  1045. t.Fatalf("Expected INTEGRATION_ALLOW_PRIVATE_NETWORKS to be enabled")
  1046. }
  1047. if err := configParser.parseLines([]string{"INTEGRATION_ALLOW_PRIVATE_NETWORKS=0"}); err != nil {
  1048. t.Fatalf("Unexpected error: %v", err)
  1049. }
  1050. if configParser.options.IntegrationAllowPrivateNetworks() {
  1051. t.Fatalf("Expected INTEGRATION_ALLOW_PRIVATE_NETWORKS to be disabled")
  1052. }
  1053. }
  1054. func TestHTTPServerTimeoutOptionParsing(t *testing.T) {
  1055. configParser := NewConfigParser()
  1056. if configParser.options.HTTPServerTimeout().Seconds() != 300 {
  1057. t.Fatal("Expected HTTP_SERVER_TIMEOUT to be 300 seconds by default")
  1058. }
  1059. if err := configParser.parseLines([]string{"HTTP_SERVER_TIMEOUT=60"}); err != nil {
  1060. t.Fatalf("Unexpected error: %v", err)
  1061. }
  1062. if configParser.options.HTTPServerTimeout().Seconds() != 60 {
  1063. t.Fatal("Expected HTTP_SERVER_TIMEOUT to be 60 seconds")
  1064. }
  1065. }
  1066. func TestListenAddrOptionParsing(t *testing.T) {
  1067. configParser := NewConfigParser()
  1068. addrs := configParser.options.ListenAddr()
  1069. if len(addrs) != 1 || addrs[0] != "127.0.0.1:8080" {
  1070. t.Fatalf("Expected LISTEN_ADDR to be '127.0.0.1:8080' by default")
  1071. }
  1072. if err := configParser.parseLines([]string{"LISTEN_ADDR=0.0.0.0:8080,127.0.0.1:8081,/unix.socket"}); err != nil {
  1073. t.Fatalf("Unexpected error: %v", err)
  1074. }
  1075. addrs = configParser.options.ListenAddr()
  1076. if len(addrs) != 3 || addrs[0] != "0.0.0.0:8080" || addrs[1] != "127.0.0.1:8081" || addrs[2] != "/unix.socket" {
  1077. t.Fatalf("Expected LISTEN_ADDR to contain two addresses")
  1078. }
  1079. }
  1080. func TestMediaCustomProxyURLOptionParsing(t *testing.T) {
  1081. configParser := NewConfigParser()
  1082. if configParser.options.MediaCustomProxyURL() != nil {
  1083. t.Fatalf("Expected MEDIA_PROXY_CUSTOM_URL to be nil by default")
  1084. }
  1085. if err := configParser.parseLines([]string{"MEDIA_PROXY_CUSTOM_URL=https://proxy.example.com"}); err != nil {
  1086. t.Fatalf("Unexpected error: %v", err)
  1087. }
  1088. proxyURL := configParser.options.MediaCustomProxyURL()
  1089. if proxyURL == nil || proxyURL.String() != "https://proxy.example.com" {
  1090. t.Fatalf("Expected MEDIA_PROXY_CUSTOM_URL to be 'https://proxy.example.com'")
  1091. }
  1092. }
  1093. func TestMediaProxyHTTPClientTimeoutOptionParsing(t *testing.T) {
  1094. configParser := NewConfigParser()
  1095. if configParser.options.MediaProxyHTTPClientTimeout().Seconds() != 120 {
  1096. t.Fatalf("Expected MEDIA_PROXY_HTTP_CLIENT_TIMEOUT to be 120 seconds by default")
  1097. }
  1098. if err := configParser.parseLines([]string{"MEDIA_PROXY_HTTP_CLIENT_TIMEOUT=60"}); err != nil {
  1099. t.Fatalf("Unexpected error: %v", err)
  1100. }
  1101. if configParser.options.MediaProxyHTTPClientTimeout().Seconds() != 60 {
  1102. t.Fatalf("Expected MEDIA_PROXY_HTTP_CLIENT_TIMEOUT to be 60 seconds")
  1103. }
  1104. }
  1105. func TestMediaProxyPrivateKeyOptionParsing(t *testing.T) {
  1106. configParser := NewConfigParser()
  1107. if len(configParser.options.MediaProxyPrivateKey()) != 0 {
  1108. t.Fatalf("Expected MEDIA_PROXY_PRIVATE_KEY to be empty by default")
  1109. }
  1110. if err := configParser.parseLines([]string{"MEDIA_PROXY_PRIVATE_KEY=secret123"}); err != nil {
  1111. t.Fatalf("Unexpected error: %v", err)
  1112. }
  1113. privateKey := configParser.options.MediaProxyPrivateKey()
  1114. if string(privateKey) != "secret123" {
  1115. t.Fatalf("Expected MEDIA_PROXY_PRIVATE_KEY to be 'secret123'")
  1116. }
  1117. }
  1118. func TestMediaProxyResourceTypesOptionParsing(t *testing.T) {
  1119. configParser := NewConfigParser()
  1120. resourceTypes := configParser.options.MediaProxyResourceTypes()
  1121. if len(resourceTypes) != 1 || resourceTypes[0] != "image" {
  1122. t.Fatalf("Expected MEDIA_PROXY_RESOURCE_TYPES to have default values")
  1123. }
  1124. if err := configParser.parseLines([]string{"MEDIA_PROXY_RESOURCE_TYPES=image,video"}); err != nil {
  1125. t.Fatalf("Unexpected error: %v", err)
  1126. }
  1127. resourceTypes = configParser.options.MediaProxyResourceTypes()
  1128. if len(resourceTypes) != 2 || resourceTypes[0] != "image" || resourceTypes[1] != "video" {
  1129. t.Fatalf("Expected MEDIA_PROXY_RESOURCE_TYPES to contain image and video")
  1130. }
  1131. if err := configParser.parseLines([]string{"MEDIA_PROXY_RESOURCE_TYPES=image,invalid,video"}); err == nil {
  1132. t.Fatal("Expected error due to invalid resource type")
  1133. }
  1134. }
  1135. func TestMetricsAllowedNetworksOptionParsing(t *testing.T) {
  1136. configParser := NewConfigParser()
  1137. networks := configParser.options.MetricsAllowedNetworks()
  1138. if len(networks) != 1 || networks[0] != "127.0.0.1/8" {
  1139. t.Fatalf("Expected METRICS_ALLOWED_NETWORKS to have default values")
  1140. }
  1141. if err := configParser.parseLines([]string{"METRICS_ALLOWED_NETWORKS=10.0.0.0/8,192.168.0.0/16"}); err != nil {
  1142. t.Fatalf("Unexpected error: %v", err)
  1143. }
  1144. networks = configParser.options.MetricsAllowedNetworks()
  1145. if len(networks) != 2 || networks[0] != "10.0.0.0/8" || networks[1] != "192.168.0.0/16" {
  1146. t.Fatalf("Expected METRICS_ALLOWED_NETWORKS to contain specified networks")
  1147. }
  1148. }
  1149. func TestMetricsRefreshIntervalOptionParsing(t *testing.T) {
  1150. configParser := NewConfigParser()
  1151. if configParser.options.MetricsRefreshInterval().Seconds() != 60 {
  1152. t.Fatalf("Expected METRICS_REFRESH_INTERVAL to be 60 seconds by default")
  1153. }
  1154. if err := configParser.parseLines([]string{"METRICS_REFRESH_INTERVAL=120"}); err != nil {
  1155. t.Fatalf("Unexpected error: %v", err)
  1156. }
  1157. if configParser.options.MetricsRefreshInterval().Seconds() != 120 {
  1158. t.Fatalf("Expected METRICS_REFRESH_INTERVAL to be 120 seconds")
  1159. }
  1160. }
  1161. func TestPollingFrequencyOptionParsing(t *testing.T) {
  1162. configParser := NewConfigParser()
  1163. if configParser.options.PollingFrequency().Minutes() != 60 {
  1164. t.Fatalf("Expected POLLING_FREQUENCY to be 60 minutes by default")
  1165. }
  1166. if err := configParser.parseLines([]string{"POLLING_FREQUENCY=30"}); err != nil {
  1167. t.Fatalf("Unexpected error: %v", err)
  1168. }
  1169. if configParser.options.PollingFrequency().Minutes() != 30 {
  1170. t.Fatalf("Expected POLLING_FREQUENCY to be 30 minutes")
  1171. }
  1172. }
  1173. func TestSchedulerEntryFrequencyMaxIntervalOptionParsing(t *testing.T) {
  1174. configParser := NewConfigParser()
  1175. if configParser.options.SchedulerEntryFrequencyMaxInterval().Hours() != 24 {
  1176. t.Fatalf("Expected SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL to be 24 hours by default")
  1177. }
  1178. if err := configParser.parseLines([]string{"SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL=720"}); err != nil {
  1179. t.Fatalf("Unexpected error: %v", err)
  1180. }
  1181. if configParser.options.SchedulerEntryFrequencyMaxInterval().Hours() != 12 {
  1182. t.Fatalf("Expected SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL to be 12 hours")
  1183. }
  1184. }
  1185. func TestSchedulerEntryFrequencyMinIntervalOptionParsing(t *testing.T) {
  1186. configParser := NewConfigParser()
  1187. if configParser.options.SchedulerEntryFrequencyMinInterval().Minutes() != 5 {
  1188. t.Fatalf("Expected SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL to be 5 minutes by default")
  1189. }
  1190. if err := configParser.parseLines([]string{"SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL=10"}); err != nil {
  1191. t.Fatalf("Unexpected error: %v", err)
  1192. }
  1193. if configParser.options.SchedulerEntryFrequencyMinInterval().Minutes() != 10 {
  1194. t.Fatalf("Expected SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL to be 10 minutes")
  1195. }
  1196. }
  1197. func TestSchedulerRoundRobinMaxIntervalOptionParsing(t *testing.T) {
  1198. configParser := NewConfigParser()
  1199. if configParser.options.SchedulerRoundRobinMaxInterval().Hours() != 24 {
  1200. t.Fatalf("Expected SCHEDULER_ROUND_ROBIN_MAX_INTERVAL to be 24 hours by default")
  1201. }
  1202. if err := configParser.parseLines([]string{"SCHEDULER_ROUND_ROBIN_MAX_INTERVAL=60"}); err != nil {
  1203. t.Fatalf("Unexpected error: %v", err)
  1204. }
  1205. if configParser.options.SchedulerRoundRobinMaxInterval().Hours() != 1 {
  1206. t.Fatalf("Expected SCHEDULER_ROUND_ROBIN_MAX_INTERVAL to be 1 hour")
  1207. }
  1208. }
  1209. func TestSchedulerRoundRobinMinIntervalOptionParsing(t *testing.T) {
  1210. configParser := NewConfigParser()
  1211. if configParser.options.SchedulerRoundRobinMinInterval().Minutes() != 60 {
  1212. t.Fatalf("Expected SCHEDULER_ROUND_ROBIN_MIN_INTERVAL to be 60 minutes by default")
  1213. }
  1214. if err := configParser.parseLines([]string{"SCHEDULER_ROUND_ROBIN_MIN_INTERVAL=30"}); err != nil {
  1215. t.Fatalf("Unexpected error: %v", err)
  1216. }
  1217. if configParser.options.SchedulerRoundRobinMinInterval().Minutes() != 30 {
  1218. t.Fatalf("Expected SCHEDULER_ROUND_ROBIN_MIN_INTERVAL to be 30 minutes")
  1219. }
  1220. }
  1221. func TestTrustedReverseProxyNetworksOptionParsing(t *testing.T) {
  1222. configParser := NewConfigParser()
  1223. // Test default value
  1224. defaultNetworks := configParser.options.TrustedReverseProxyNetworks()
  1225. if len(defaultNetworks) != 0 {
  1226. t.Fatalf("Expected 0 allowed networks by default, got %d", len(defaultNetworks))
  1227. }
  1228. // Test valid value
  1229. if err := configParser.parseLines([]string{"TRUSTED_REVERSE_PROXY_NETWORKS=10.0.0.0/8,192.168.1.0/24"}); err != nil {
  1230. t.Fatalf("Unexpected error: %v", err)
  1231. }
  1232. allowedNetworks := configParser.options.TrustedReverseProxyNetworks()
  1233. if len(allowedNetworks) != 2 {
  1234. t.Fatalf("Expected 2 allowed networks, got %d", len(allowedNetworks))
  1235. }
  1236. if !slices.Contains(allowedNetworks, "10.0.0.0/8") {
  1237. t.Errorf("Expected 10.0.0.0/8 in allowed networks")
  1238. }
  1239. if !slices.Contains(allowedNetworks, "192.168.1.0/24") {
  1240. t.Errorf("Expected 192.168.1.0/24 in allowed networks")
  1241. }
  1242. // Test invalid value
  1243. if err := configParser.parseLines([]string{"TRUSTED_REVERSE_PROXY_NETWORKS=127.0.0.1"}); err == nil {
  1244. t.Fatal("Expected error when parsing invalid CIDR notation IP 127.0.0.1, got nil")
  1245. }
  1246. }
  1247. func TestYouTubeEmbedDomainOptionParsing(t *testing.T) {
  1248. configParser := NewConfigParser()
  1249. if configParser.options.YouTubeEmbedDomain() != "www.youtube-nocookie.com" {
  1250. t.Fatalf("Expected YouTubeEmbedDomain to be 'www.youtube-nocookie.com' by default")
  1251. }
  1252. // YouTube embed domain is derived from YOUTUBE_EMBED_URL_OVERRIDE
  1253. if err := configParser.parseLines([]string{"YOUTUBE_EMBED_URL_OVERRIDE=https://custom.youtube.com/embed/"}); err != nil {
  1254. t.Fatalf("Unexpected error: %v", err)
  1255. }
  1256. if configParser.options.YouTubeEmbedDomain() != "custom.youtube.com" {
  1257. t.Fatalf("Expected YouTubeEmbedDomain to be 'custom.youtube.com'")
  1258. }
  1259. }
  1260. func TestSetLogLevelFunction(t *testing.T) {
  1261. configParser := NewConfigParser()
  1262. // Test default log level
  1263. if configParser.options.LogLevel() != "info" {
  1264. t.Fatalf("Expected LOG_LEVEL to be 'info' by default, got '%s'", configParser.options.LogLevel())
  1265. }
  1266. // Test setting log level to debug
  1267. configParser.options.SetLogLevel("debug")
  1268. if configParser.options.LogLevel() != "debug" {
  1269. t.Fatalf("Expected LOG_LEVEL to be 'debug' after SetLogLevel('debug'), got '%s'", configParser.options.LogLevel())
  1270. }
  1271. if configParser.options.options["LOG_LEVEL"].rawValue != "debug" {
  1272. t.Fatalf("Expected LOG_LEVEL RawValue to be 'debug', got '%s'", configParser.options.options["LOG_LEVEL"].rawValue)
  1273. }
  1274. // Test setting log level to warning
  1275. configParser.options.SetLogLevel("warning")
  1276. if configParser.options.LogLevel() != "warning" {
  1277. t.Fatalf("Expected LOG_LEVEL to be 'warning' after SetLogLevel('warning'), got '%s'", configParser.options.LogLevel())
  1278. }
  1279. if configParser.options.options["LOG_LEVEL"].rawValue != "warning" {
  1280. t.Fatalf("Expected LOG_LEVEL RawValue to be 'warning', got '%s'", configParser.options.options["LOG_LEVEL"].rawValue)
  1281. }
  1282. }
  1283. func TestSetHTTPSValueFunction(t *testing.T) {
  1284. configParser := NewConfigParser()
  1285. // Test setting HTTPS to true
  1286. configParser.options.SetHTTPSValue(true)
  1287. if !configParser.options.HTTPS() {
  1288. t.Fatalf("Expected HTTPS to be true after SetHTTPSValue(true)")
  1289. }
  1290. // Test setting HTTPS to false
  1291. configParser.options.SetHTTPSValue(false)
  1292. if configParser.options.HTTPS() {
  1293. t.Fatalf("Expected HTTPS to be false after SetHTTPSValue(false)")
  1294. }
  1295. // Test setting HTTPS to true again
  1296. configParser.options.SetHTTPSValue(true)
  1297. if !configParser.options.HTTPS() {
  1298. t.Fatalf("Expected HTTPS to be true after second SetHTTPSValue(true)")
  1299. }
  1300. }
  1301. func TestConfigMap(t *testing.T) {
  1302. configMap := NewConfigOptions().ConfigMap(false)
  1303. if len(configMap) == 0 {
  1304. t.Fatal("Expected ConfigMap to contain configuration options")
  1305. }
  1306. // The first option should be "ADMIN_PASSWORD"
  1307. if configMap[0].Key != "ADMIN_PASSWORD" {
  1308. t.Fatalf("Expected first config option to be 'ADMIN_PASSWORD', got '%s'", configMap[0].Key)
  1309. }
  1310. }
  1311. func TestConfigMapWithRedactedSecrets(t *testing.T) {
  1312. configParser := NewConfigParser()
  1313. if err := configParser.parseLines([]string{"ADMIN_PASSWORD=secret123"}); err != nil {
  1314. t.Fatalf("Unexpected error: %v", err)
  1315. }
  1316. configMap := configParser.options.ConfigMap(true)
  1317. if len(configMap) == 0 {
  1318. t.Fatal("Expected ConfigMap to contain configuration options")
  1319. }
  1320. // The first option should be "ADMIN_PASSWORD"
  1321. if configMap[0].Key != "ADMIN_PASSWORD" {
  1322. t.Fatalf("Expected first config option to be 'ADMIN_PASSWORD', got '%s'", configMap[0].Key)
  1323. }
  1324. // The value should be redacted
  1325. if configMap[0].Value != "<redacted>" {
  1326. t.Fatalf("Expected ADMIN_PASSWORD value to be redacted, got '%s'", configMap[0].Value)
  1327. }
  1328. }
  1329. func TestValidateOIDCProviderRequiresDiscoveryEndpoint(t *testing.T) {
  1330. configParser := NewConfigParser()
  1331. if err := configParser.parseLines([]string{"OAUTH2_PROVIDER=oidc"}); err != nil {
  1332. t.Fatalf("Unexpected parse error: %v", err)
  1333. }
  1334. err := configParser.options.Validate()
  1335. if err == nil {
  1336. t.Fatal("Expected error when OIDC provider is set without discovery endpoint")
  1337. }
  1338. if err.Error() != "OAUTH2_OIDC_DISCOVERY_ENDPOINT must be configured when using the OIDC provider" {
  1339. t.Fatalf("Unexpected error message: %v", err)
  1340. }
  1341. }
  1342. func TestValidateOIDCProviderWithDiscoveryEndpoint(t *testing.T) {
  1343. configParser := NewConfigParser()
  1344. if err := configParser.parseLines([]string{
  1345. "OAUTH2_PROVIDER=oidc",
  1346. "OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://example.com/.well-known/openid-configuration",
  1347. }); err != nil {
  1348. t.Fatalf("Unexpected parse error: %v", err)
  1349. }
  1350. if err := configParser.options.Validate(); err != nil {
  1351. t.Fatalf("Unexpected error: %v", err)
  1352. }
  1353. }
  1354. func TestValidateDisableLocalAuthWithoutAlternative(t *testing.T) {
  1355. configParser := NewConfigParser()
  1356. if err := configParser.parseLines([]string{"DISABLE_LOCAL_AUTH=1"}); err != nil {
  1357. t.Fatalf("Unexpected parse error: %v", err)
  1358. }
  1359. if err := configParser.options.Validate(); err == nil {
  1360. t.Fatal("Expected error when local auth is disabled without alternative")
  1361. }
  1362. }
  1363. func TestValidateDisableLocalAuthWithOAuth2ButNoUserCreation(t *testing.T) {
  1364. configParser := NewConfigParser()
  1365. if err := configParser.parseLines([]string{
  1366. "DISABLE_LOCAL_AUTH=1",
  1367. "OAUTH2_PROVIDER=oidc",
  1368. "OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://example.com/.well-known/openid-configuration",
  1369. }); err != nil {
  1370. t.Fatalf("Unexpected parse error: %v", err)
  1371. }
  1372. if err := configParser.options.Validate(); err == nil {
  1373. t.Fatal("Expected error when local auth is disabled with OAuth2 but without user creation")
  1374. }
  1375. }
  1376. func TestValidateDisableLocalAuthWithOAuth2AndUserCreation(t *testing.T) {
  1377. configParser := NewConfigParser()
  1378. if err := configParser.parseLines([]string{
  1379. "DISABLE_LOCAL_AUTH=1",
  1380. "OAUTH2_PROVIDER=oidc",
  1381. "OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://example.com/.well-known/openid-configuration",
  1382. "OAUTH2_USER_CREATION=1",
  1383. }); err != nil {
  1384. t.Fatalf("Unexpected parse error: %v", err)
  1385. }
  1386. if err := configParser.options.Validate(); err != nil {
  1387. t.Fatalf("Unexpected error: %v", err)
  1388. }
  1389. }
  1390. func TestValidateDisableLocalAuthWithAuthProxyButNoUserCreation(t *testing.T) {
  1391. configParser := NewConfigParser()
  1392. if err := configParser.parseLines([]string{
  1393. "DISABLE_LOCAL_AUTH=1",
  1394. "AUTH_PROXY_HEADER=X-Forwarded-User",
  1395. "AUTH_PROXY_USER_CREATION=0",
  1396. "TRUSTED_REVERSE_PROXY_NETWORKS=10.0.0.0/8",
  1397. }); err != nil {
  1398. t.Fatalf("Unexpected parse error: %v", err)
  1399. }
  1400. if err := configParser.options.Validate(); err == nil {
  1401. t.Fatal("Expected error when local auth is disabled with auth proxy but without user creation")
  1402. }
  1403. }
  1404. func TestValidateDisableLocalAuthWithAuthProxyAndUserCreation(t *testing.T) {
  1405. configParser := NewConfigParser()
  1406. if err := configParser.parseLines([]string{
  1407. "DISABLE_LOCAL_AUTH=1",
  1408. "AUTH_PROXY_HEADER=X-Forwarded-User",
  1409. "AUTH_PROXY_USER_CREATION=1",
  1410. "TRUSTED_REVERSE_PROXY_NETWORKS=10.0.0.0/8",
  1411. }); err != nil {
  1412. t.Fatalf("Unexpected parse error: %v", err)
  1413. }
  1414. if err := configParser.options.Validate(); err != nil {
  1415. t.Fatalf("Unexpected error: %v", err)
  1416. }
  1417. }
  1418. func TestValidateAuthProxyRequiresTrustedNetworks(t *testing.T) {
  1419. configParser := NewConfigParser()
  1420. if err := configParser.parseLines([]string{"AUTH_PROXY_HEADER=X-Forwarded-User"}); err != nil {
  1421. t.Fatalf("Unexpected parse error: %v", err)
  1422. }
  1423. err := configParser.options.Validate()
  1424. if err == nil {
  1425. t.Fatal("Expected error when auth proxy header is set without trusted networks")
  1426. }
  1427. if err.Error() != "TRUSTED_REVERSE_PROXY_NETWORKS must be configured when AUTH_PROXY_HEADER is used" {
  1428. t.Fatalf("Unexpected error message: %v", err)
  1429. }
  1430. }
  1431. func TestValidateAuthProxyWithTrustedNetworks(t *testing.T) {
  1432. configParser := NewConfigParser()
  1433. if err := configParser.parseLines([]string{
  1434. "AUTH_PROXY_HEADER=X-Forwarded-User",
  1435. "TRUSTED_REVERSE_PROXY_NETWORKS=10.0.0.0/8",
  1436. }); err != nil {
  1437. t.Fatalf("Unexpected parse error: %v", err)
  1438. }
  1439. if err := configParser.options.Validate(); err != nil {
  1440. t.Fatalf("Unexpected error: %v", err)
  1441. }
  1442. }
  1443. func TestValidateCertFileMissingKeyFile(t *testing.T) {
  1444. configParser := NewConfigParser()
  1445. if err := configParser.parseLines([]string{"CERT_FILE=/path/to/cert.pem"}); err != nil {
  1446. t.Fatalf("Unexpected parse error: %v", err)
  1447. }
  1448. if err := configParser.options.Validate(); err == nil {
  1449. t.Fatal("Expected error when CERT_FILE is set without KEY_FILE")
  1450. }
  1451. }
  1452. func TestValidateKeyFileMissingCertFile(t *testing.T) {
  1453. configParser := NewConfigParser()
  1454. if err := configParser.parseLines([]string{"KEY_FILE=/path/to/key.pem"}); err != nil {
  1455. t.Fatalf("Unexpected parse error: %v", err)
  1456. }
  1457. if err := configParser.options.Validate(); err == nil {
  1458. t.Fatal("Expected error when KEY_FILE is set without CERT_FILE")
  1459. }
  1460. }
  1461. func TestValidateCertFileAndKeyFile(t *testing.T) {
  1462. configParser := NewConfigParser()
  1463. if err := configParser.parseLines([]string{
  1464. "CERT_FILE=/path/to/cert.pem",
  1465. "KEY_FILE=/path/to/key.pem",
  1466. }); err != nil {
  1467. t.Fatalf("Unexpected parse error: %v", err)
  1468. }
  1469. if err := configParser.options.Validate(); err != nil {
  1470. t.Fatalf("Unexpected error: %v", err)
  1471. }
  1472. }
  1473. func TestValidateCertDomainAndCertFileMutuallyExclusive(t *testing.T) {
  1474. configParser := NewConfigParser()
  1475. if err := configParser.parseLines([]string{
  1476. "CERT_DOMAIN=example.com",
  1477. "CERT_FILE=/path/to/cert.pem",
  1478. "KEY_FILE=/path/to/key.pem",
  1479. }); err != nil {
  1480. t.Fatalf("Unexpected parse error: %v", err)
  1481. }
  1482. if err := configParser.options.Validate(); err == nil {
  1483. t.Fatal("Expected error when both CERT_DOMAIN and CERT_FILE are set")
  1484. }
  1485. }
  1486. func TestValidateCertDomainAlone(t *testing.T) {
  1487. configParser := NewConfigParser()
  1488. if err := configParser.parseLines([]string{"CERT_DOMAIN=example.com"}); err != nil {
  1489. t.Fatalf("Unexpected parse error: %v", err)
  1490. }
  1491. if err := configParser.options.Validate(); err != nil {
  1492. t.Fatalf("Unexpected error: %v", err)
  1493. }
  1494. }
  1495. func TestValidateMetricsUsernameWithoutPassword(t *testing.T) {
  1496. configParser := NewConfigParser()
  1497. if err := configParser.parseLines([]string{"METRICS_USERNAME=admin"}); err != nil {
  1498. t.Fatalf("Unexpected parse error: %v", err)
  1499. }
  1500. if err := configParser.options.Validate(); err == nil {
  1501. t.Fatal("Expected error when METRICS_USERNAME is set without METRICS_PASSWORD")
  1502. }
  1503. }
  1504. func TestValidateMetricsPasswordWithoutUsername(t *testing.T) {
  1505. configParser := NewConfigParser()
  1506. if err := configParser.parseLines([]string{"METRICS_PASSWORD=secret"}); err != nil {
  1507. t.Fatalf("Unexpected parse error: %v", err)
  1508. }
  1509. if err := configParser.options.Validate(); err == nil {
  1510. t.Fatal("Expected error when METRICS_PASSWORD is set without METRICS_USERNAME")
  1511. }
  1512. }
  1513. func TestValidateMetricsUsernameAndPassword(t *testing.T) {
  1514. configParser := NewConfigParser()
  1515. if err := configParser.parseLines([]string{
  1516. "METRICS_USERNAME=admin",
  1517. "METRICS_PASSWORD=secret",
  1518. }); err != nil {
  1519. t.Fatalf("Unexpected parse error: %v", err)
  1520. }
  1521. if err := configParser.options.Validate(); err != nil {
  1522. t.Fatalf("Unexpected error: %v", err)
  1523. }
  1524. }
  1525. func TestValidateDatabaseMinConnsGreaterThanMaxConns(t *testing.T) {
  1526. configParser := NewConfigParser()
  1527. if err := configParser.parseLines([]string{
  1528. "DATABASE_MIN_CONNS=25",
  1529. "DATABASE_MAX_CONNS=10",
  1530. }); err != nil {
  1531. t.Fatalf("Unexpected parse error: %v", err)
  1532. }
  1533. if err := configParser.options.Validate(); err == nil {
  1534. t.Fatal("Expected error when DATABASE_MIN_CONNS > DATABASE_MAX_CONNS")
  1535. }
  1536. }
  1537. func TestValidateDatabaseMinConnsEqualToMaxConns(t *testing.T) {
  1538. configParser := NewConfigParser()
  1539. if err := configParser.parseLines([]string{
  1540. "DATABASE_MIN_CONNS=10",
  1541. "DATABASE_MAX_CONNS=10",
  1542. }); err != nil {
  1543. t.Fatalf("Unexpected parse error: %v", err)
  1544. }
  1545. if err := configParser.options.Validate(); err != nil {
  1546. t.Fatalf("Unexpected error: %v", err)
  1547. }
  1548. }
  1549. func TestValidateSchedulerRoundRobinMinGreaterThanMax(t *testing.T) {
  1550. configParser := NewConfigParser()
  1551. if err := configParser.parseLines([]string{
  1552. "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL=1440",
  1553. "SCHEDULER_ROUND_ROBIN_MAX_INTERVAL=60",
  1554. }); err != nil {
  1555. t.Fatalf("Unexpected parse error: %v", err)
  1556. }
  1557. if err := configParser.options.Validate(); err == nil {
  1558. t.Fatal("Expected error when SCHEDULER_ROUND_ROBIN_MIN_INTERVAL > SCHEDULER_ROUND_ROBIN_MAX_INTERVAL")
  1559. }
  1560. }
  1561. func TestValidateSchedulerRoundRobinMinLessThanMax(t *testing.T) {
  1562. configParser := NewConfigParser()
  1563. if err := configParser.parseLines([]string{
  1564. "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL=60",
  1565. "SCHEDULER_ROUND_ROBIN_MAX_INTERVAL=1440",
  1566. }); err != nil {
  1567. t.Fatalf("Unexpected parse error: %v", err)
  1568. }
  1569. if err := configParser.options.Validate(); err != nil {
  1570. t.Fatalf("Unexpected error: %v", err)
  1571. }
  1572. }
  1573. func TestValidateSchedulerEntryFrequencyMinGreaterThanMax(t *testing.T) {
  1574. configParser := NewConfigParser()
  1575. if err := configParser.parseLines([]string{
  1576. "SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL=1440",
  1577. "SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL=5",
  1578. }); err != nil {
  1579. t.Fatalf("Unexpected parse error: %v", err)
  1580. }
  1581. if err := configParser.options.Validate(); err == nil {
  1582. t.Fatal("Expected error when SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL > SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL")
  1583. }
  1584. }
  1585. func TestValidateSchedulerEntryFrequencyMinLessThanMax(t *testing.T) {
  1586. configParser := NewConfigParser()
  1587. if err := configParser.parseLines([]string{
  1588. "SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL=5",
  1589. "SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL=1440",
  1590. }); err != nil {
  1591. t.Fatalf("Unexpected parse error: %v", err)
  1592. }
  1593. if err := configParser.options.Validate(); err != nil {
  1594. t.Fatalf("Unexpected error: %v", err)
  1595. }
  1596. }