1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-05 13:21:25 -05:00

Compare commits

...

54 Commits

Author SHA1 Message Date
ta264
354d247314 Try disabling response compression 2022-05-25 21:51:13 +01:00
ta264
c032f3fa7a try to fix build 2022-05-16 21:51:56 +01:00
ta264
1de454de17 New: Support older ARMv7 CPUs
Eg armada370 ad armadaxp
2022-05-16 21:21:48 +01:00
ta264
879668eb61 New: .NET 6.0.5 2022-05-15 21:48:23 +01:00
bakerboy448
097b46c49f New: Parse QxR Group r00t
Fixes #7290
2022-05-15 12:45:31 -05:00
Servarr
ddeb3a7840 Automated API Docs update 2022-05-13 17:45:11 -05:00
Qstick
50018d0325 New: Instance name in System/Status API endpoint 2022-05-13 23:37:53 +01:00
Qstick
a37fc0dc1f New: Instance name for Page Title 2022-05-13 23:37:53 +01:00
Robin Dadswell
39ad315e73 New: Instance Name used for Syslog 2022-05-13 23:37:53 +01:00
Robin Dadswell
0559996566 New: Set Instance Name 2022-05-13 23:37:53 +01:00
Stevie Robinson
e7d4429fe4 New: Add optional Source Title column to history
(cherry picked from commit 581fb2cb3d47d62fe16b840081647056ec77043d)
Fixes #7159
2022-05-12 21:48:22 -05:00
bakerboy448
6c494e9a92 New: Support for new Nyaa RSS Feed format
(cherry picked from commit 40ecdbc12de8b320a4d650aea65a36e8edea77d8)
2022-05-12 19:16:46 -05:00
Qstick
62faa1aad8 Fixed: Don't try to add MovieMeta if mapping fails for list items 2022-05-11 19:46:41 -05:00
Mark McDowall
907950e309 Fixed: Importing file from UNC shared folder without job folder
(cherry picked from commit 9183c6b84638e3654c3f90a80e560a06575606bb)
2022-05-08 19:05:31 -05:00
Qstick
1caced614e Fixed: No restart requirement for Refresh Monitored interval change 2022-05-08 16:11:53 -05:00
Qstick
5824ba963b Fixed: Correct User-Agent api logging 2022-05-06 08:25:34 -05:00
Qstick
7f2d5d8d10 Delete nan.json 2022-05-01 22:30:00 -05:00
Qstick
81bffe243a Delete zh_Hans.json 2022-05-01 22:29:50 -05:00
Weblate
2d6fde282a Translated using Weblate (Chinese (Simplified)) [skip ci]
Currently translated at 28.6% (320 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 28.6% (320 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 4.6% (52 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 97.2% (1086 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.1% (214 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 4.5% (51 of 1117 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 95.9% (1072 of 1117 strings)

Update translation files  [skip ci]

Updated by "Remove blank strings" hook in Weblate.

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 3.5% (40 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 2.0% (23 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 99.5% (1112 of 1117 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 97.9% (1094 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.0% (213 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.0% (213 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 1.1% (13 of 1117 strings)

Translated using Weblate (Arabic) [skip ci]

Currently translated at 93.9% (1049 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Thai) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Bulgarian) [skip ci]

Currently translated at 91.3% (1020 of 1117 strings)

Translated using Weblate (Hindi) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Romanian) [skip ci]

Currently translated at 93.0% (1039 of 1117 strings)

Translated using Weblate (Vietnamese) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Turkish) [skip ci]

Currently translated at 93.2% (1042 of 1117 strings)

Translated using Weblate (Swedish) [skip ci]

Currently translated at 93.8% (1048 of 1117 strings)

Translated using Weblate (Russian) [skip ci]

Currently translated at 98.8% (1104 of 1117 strings)

Translated using Weblate (Portuguese) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Polish) [skip ci]

Currently translated at 93.3% (1043 of 1117 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 95.7% (1070 of 1117 strings)

Translated using Weblate (Korean) [skip ci]

Currently translated at 22.2% (248 of 1117 strings)

Translated using Weblate (Japanese) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Icelandic) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Hebrew) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Greek) [skip ci]

Currently translated at 93.3% (1043 of 1117 strings)

Translated using Weblate (Danish) [skip ci]

Currently translated at 93.1% (1041 of 1117 strings)

Translated using Weblate (Czech) [skip ci]

Currently translated at 94.1% (1052 of 1117 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 96.5% (1078 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 97.9% (1094 of 1117 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.8% (1115 of 1117 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.8% (1115 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 15.7% (176 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 15.7% (176 of 1117 strings)

Co-authored-by: AnlakHui <AnlakHui@gmail.com>
Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: EldestBard <449734150@qq.com>
Co-authored-by: Florian <sephrat.flo@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: M1C <webnar@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Zalhera <tobias.bechen@gmail.com>
Co-authored-by: andrey4korop <andrey999@i.ua>
Co-authored-by: jianjam <jianjam@qq.com>
Co-authored-by: killsover <w904202822@163.com>
Co-authored-by: lhquark <lhquark@gmail.com>
Co-authored-by: marcosteam <wdy71608161@gmail.com>
Co-authored-by: minermartijn <minermartijn@gmail.com>
Co-authored-by: neoestremi <remidu34070@hotmail.fr>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_Hans/
Translation: Servarr/Radarr
2022-04-29 10:59:36 -05:00
Qstick
3125b038d5 Fixed: Wrong translation mapping can be used for file naming and metadata
Fixes #7243
2022-04-26 19:27:07 -05:00
Qstick
89e25a6241 Fixed: Translated fields are mapped incorrectly for existing search results 2022-04-26 18:29:15 -05:00
Qstick
4db6688fe0 Fixed: UI hiding search results with duplicate GUIDs
Closes #7241

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2022-04-24 13:16:20 -05:00
Qstick
4ac1aeaf06 Fixed: QBittorrent unknown download state: forcedMetaDL
Closes #7242

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2022-04-24 13:14:58 -05:00
Qstick
e2ae743ee1 Fix migration 207 distinct on tmdbid only for list movie insert 2022-04-24 13:13:05 -05:00
Robin Dadswell
9ad316a6f5 Fix metadata migration 2022-04-23 16:41:43 -05:00
Servarr
b643d2e23d Automated API Docs update 2022-04-23 20:35:25 +01:00
Qstick
6a03eddda9 Rework Movie Metadata data model 2022-04-23 13:14:03 -05:00
ta264
1576bf1f17 Temporarily ignore update tests until linux-x86 released 2022-04-23 02:25:39 -05:00
ta264
6325b70e27 New: Add linux-x86 builds
[common]
2022-04-23 02:25:39 -05:00
Qstick
24206ad0a3 New: Support Plex API Path Scan (Similar to autoscan)
Closes #4640
Closes #5527
2022-04-21 22:49:09 -05:00
Mark McDowall
2fc7cbff89 Fixed: Interactive Search Filter not filtering multiple qualities in the same filter row
(cherry picked from commit c93f63cd204bf62dab3dffef6e29c8dd4c408cab)
2022-04-18 21:07:50 -05:00
Tristan Kennedy
55ef505d74 Added padding to search tab to maintain visual consistancy 2022-04-15 23:58:45 -05:00
Qstick
cabdad6306 Fixed: Update ScheduledTask cache LastStartTime on command execution 2022-04-15 18:16:01 -05:00
Qstick
8d4b2dd21b Bump Version to 4.2 2022-04-15 16:47:28 -05:00
Qstick
ad04031c99 Bump webpack packages 2022-04-14 21:08:10 -05:00
Qstick
e9a5f87e45 Remove old DotNetVersion method and dep 2022-04-14 21:06:29 -05:00
Qstick
bc6ac0cd4b Bump Monotorrent to 2.0.5
Fixes #7206
2022-04-11 19:18:01 -05:00
Qstick
c2328e4b79 Fixed: Don't die if Plex watchlist guid node is missing or null
Fixes #7213
2022-04-11 08:30:39 -05:00
Servarr
36119facf0 Automated API Docs update 2022-04-10 22:10:41 -05:00
Justin Vanderhooft
a1fa1ddf5d New: Add support for Plex Watchlist importing (#5707)
* New: Add support for Plex Watchlists

* Fixed: Error when trying to import an empty Plex Watchlist

* cleanups

Co-authored-by: Mark McDowall <mark@mcdowall.ca>
Co-authored-by: Qstick <qstick@gmail.com>
2022-04-10 17:52:10 -05:00
Douglas R Andreani
ba770dce73 New: Add date picker for custom filter dates
(cherry picked from commit 5a08d5dc248bf1dbaa43264a2a470149cf716a3c)
2022-04-10 12:18:41 -05:00
ta264
d58f0806f6 Make postgres integration tests actually use postgres 2022-04-08 15:10:13 -07:00
bakerboy448
a95f8fa873 Fixed: Clarify Qbit Content Path Error
(cherry picked from commit bba4a5636ed07277d82531c35cfc996bd17870eb)
2022-04-06 22:09:13 -05:00
François-Xavier Payet
d1a9cf98cc Fixed: Use Movie Original Language for Custom Format Original Language (#6882) 2022-04-06 15:32:49 -05:00
ta264
be29fc6adb Fix .editorconfig to disallow this
[common]
2022-04-06 20:09:12 +01:00
ta264
c1085e965b FFMpeg 5.0.1 2022-04-06 13:57:32 +01:00
Marcelo Castagna
dc5c997e9b Fixed: Properly handle 119 error code from Synology Download Station
(cherry picked from commit 3be5d6c258bd947ae4c4d895b2f54faa5a7a222b)
2022-04-05 21:37:39 -05:00
Weblate
040acbf65a Translated using Weblate (Hungarian) [skip ci]
Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 97.9% (1094 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.0% (213 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.0% (213 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 1.1% (13 of 1117 strings)

Translated using Weblate (Arabic) [skip ci]

Currently translated at 93.9% (1049 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Thai) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Bulgarian) [skip ci]

Currently translated at 91.3% (1020 of 1117 strings)

Translated using Weblate (Hindi) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Romanian) [skip ci]

Currently translated at 93.0% (1039 of 1117 strings)

Translated using Weblate (Vietnamese) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Turkish) [skip ci]

Currently translated at 93.2% (1042 of 1117 strings)

Translated using Weblate (Swedish) [skip ci]

Currently translated at 93.8% (1048 of 1117 strings)

Translated using Weblate (Russian) [skip ci]

Currently translated at 98.8% (1104 of 1117 strings)

Translated using Weblate (Portuguese) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Polish) [skip ci]

Currently translated at 93.3% (1043 of 1117 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 95.7% (1070 of 1117 strings)

Translated using Weblate (Korean) [skip ci]

Currently translated at 22.2% (248 of 1117 strings)

Translated using Weblate (Japanese) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Icelandic) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Hebrew) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Greek) [skip ci]

Currently translated at 93.3% (1043 of 1117 strings)

Translated using Weblate (Danish) [skip ci]

Currently translated at 93.1% (1041 of 1117 strings)

Translated using Weblate (Czech) [skip ci]

Currently translated at 94.1% (1052 of 1117 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 96.5% (1078 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 97.9% (1094 of 1117 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.8% (1115 of 1117 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.8% (1115 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 15.7% (176 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 15.7% (176 of 1117 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Florian <sephrat.flo@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Zalhera <tobias.bechen@gmail.com>
Co-authored-by: andrey4korop <andrey999@i.ua>
Co-authored-by: jianjam <jianjam@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_Hans/
Translation: Servarr/Radarr
2022-04-05 19:30:50 -05:00
ta264
d089d036e6 Fixed: FFprobe failing on MacOS and AV1 streams 2022-04-05 19:24:22 +01:00
bakerboy448
46732c7d73 add 576 resolution back to simple title regex 2022-04-03 17:08:53 -05:00
Weblate
8fd3254745 Translated using Weblate (Ukrainian) [skip ci]
Currently translated at 1.6% (18 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Spanish) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 1.0% (12 of 1116 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 0.8% (10 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 97.7% (1091 of 1116 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Spanish) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 97.7% (1091 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 97.5% (1089 of 1116 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 100.0% (1116 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 96.7% (1080 of 1116 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 96.7% (1080 of 1116 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 97.8% (1092 of 1116 strings)

Co-authored-by: Ana <phampyk@gmail.com>
Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: EthanChoy <ethanchoy@163.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Kakise <sam.taa@icloud.com>
Co-authored-by: Kevin Ho <309446119@qq.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: Vincent <intelligentvincent@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: andrey4korop <andrey999@i.ua>
Co-authored-by: killsover <w904202822@163.com>
Co-authored-by: lhquark <lhquark@gmail.com>
Co-authored-by: libsu <libsu@qq.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Co-authored-by: westay1984 <westjay@qq.com>
Co-authored-by: 無情天 <kofzhanganguo@126.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_Hans/
Translation: Servarr/Radarr
2022-04-02 18:23:41 -05:00
ta264
9b21408a03 Set up tests on postgres 2022-04-03 00:06:30 +01:00
ta264
bd53092f0c Allow configuring postgres with environment variables 2022-04-03 00:06:30 +01:00
Robin Dadswell
80b1aa9a2c New: Postgres Support
Co-Authored-By: Qstick <376117+Qstick@users.noreply.github.com>
2022-04-03 00:06:30 +01:00
348 changed files with 6862 additions and 3643 deletions

View File

@@ -19,10 +19,10 @@ indent_size = 4
dotnet_sort_system_directives_first = true
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:refactoring
dotnet_style_qualification_for_property = false:refactoring
dotnet_style_qualification_for_method = false:refactoring
dotnet_style_qualification_for_event = false:refactoring
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_event = false:warning
# Indentation preferences
csharp_indent_block_contents = true
@@ -32,10 +32,6 @@ csharp_indent_case_contents_when_block = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _

View File

@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.1.0'
majorVersion: '4.2.0'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.201'
dotnetVersion: '6.0.300'
nodeVersion: '16.X'
innoVersion: '6.2.0'
windowsImage: 'windows-2022'
@@ -95,17 +95,25 @@ stages:
inputs:
version: $(dotnetVersion)
- bash: |
BUNDLEDVERSIONS=${AGENT_TOOLSDIRECTORY}/dotnet/sdk/${DOTNETVERSION}/Microsoft.NETCoreSdk.BundledVersions.props
echo $BUNDLEDVERSIONS
grep osx-x64 $BUNDLEDVERSIONS
if grep -q freebsd-x64 $BUNDLEDVERSIONS; then
echo "BSD already enabled"
else
echo "Enabling BSD support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64/' $BUNDLEDVERSIONS
SDK_PATH="${AGENT_TOOLSDIRECTORY}/dotnet/sdk/${DOTNETVERSION}"
BUNDLEDVERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
if ! grep -q freebsd-x64 $BUNDLEDVERSIONS; then
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86;linux-arm-vfpv3d16/' $BUNDLEDVERSIONS
fi
displayName: Enable FreeBSD Support
- bash: ./build.sh --backend --enable-bsd
grep freebsd-x64 $BUNDLEDVERSIONS
displayName: Extra Platform Support - Generic
- bash: |
SDK_PATH="${AGENT_TOOLSDIRECTORY}/dotnet/sdk/${DOTNETVERSION}"
RUNTIMEIDENTIFIERGRAPH="${SDK_PATH}/RuntimeIdentifierGraph.json"
if ! grep -q linux-arm-vfpv3d16 "${RUNTIMEIDENTIFIERGRAPH}"; then
sed -i.ORI '/"runtimes":/a \ \ \ \ "linux-arm-vfpv3d16": {"#import": ["linux-arm"]},' "${RUNTIMEIDENTIFIERGRAPH}"
fi
grep -A5 -B5 linux-arm-vfpv3d16 $RUNTIMEIDENTIFIERGRAPH
displayName: Enable Extra Platform Support - Windows
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- bash: ./build.sh --backend --enable-extra-platforms
displayName: Build Radarr Backend
- bash: |
find ${OUTPUTFOLDER} -type f ! -path "*/publish/*" -exec rm -rf {} \;
@@ -119,24 +127,28 @@ stages:
displayName: Publish Backend
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/win-x64/publish'
artifact: WindowsCoreTests
displayName: Publish Windows Test Package
artifact: win-x64-tests
displayName: Publish win-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x64/publish'
artifact: LinuxCoreTests
displayName: Publish Linux Test Package
artifact: linux-x64-tests
displayName: Publish linux-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x86/publish'
artifact: linux-x86-tests
displayName: Publish linux-x86 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-musl-x64/publish'
artifact: LinuxMuslCoreTests
displayName: Publish Linux Musl Test Package
artifact: linux-musl-x64-tests
displayName: Publish linux-musl-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/freebsd-x64/publish'
artifact: FreebsdCoreTests
displayName: Publish FreeBSD Test Package
artifact: freebsd-x64-tests
displayName: Publish freebsd-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/osx-x64/publish'
artifact: MacCoreTests
displayName: Publish MacOS Test Package
artifact: osx-x64-tests
displayName: Publish osx-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- stage: Build_Frontend
@@ -240,7 +252,7 @@ stages:
artifactName: WindowsFrontend
targetPath: _output
displayName: Fetch Frontend
- bash: ./build.sh --packages --enable-bsd
- bash: ./build.sh --packages --enable-extra-platforms
displayName: Create Packages
- bash: |
find . -name "ffprobe" -exec chmod a+x {} \;
@@ -248,28 +260,28 @@ stages:
find . -name "Radarr.Update" -exec chmod a+x {} \;
displayName: Set executable bits
- task: ArchiveFiles@2
displayName: Create Windows Core zip
displayName: Create win-x64 zip
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).windows-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x64/net6.0
- task: ArchiveFiles@2
displayName: Create Windows x86 Core zip
displayName: Create win-x86 zip
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).windows-core-x86.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x86/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS x64 Core app
displayName: Create osx-x64 app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-app-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64-app/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS x64 Core tar
displayName: Create osx-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-core-x64.tar.gz'
archiveType: 'tar'
@@ -277,14 +289,14 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS arm64 Core app
displayName: Create osx-arm64 app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-app-core-arm64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64-app/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS arm64 Core tar
displayName: Create osx-arm64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-core-arm64.tar.gz'
archiveType: 'tar'
@@ -292,7 +304,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create Linux Core tar
displayName: Create linux-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-x64.tar.gz'
archiveType: 'tar'
@@ -300,7 +312,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x64/net6.0
- task: ArchiveFiles@2
displayName: Create Linux Musl Core tar
displayName: Create linux-musl-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-x64.tar.gz'
archiveType: 'tar'
@@ -308,7 +320,15 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/net6.0
- task: ArchiveFiles@2
displayName: Create ARM32 Linux Core tar
displayName: Create linux-x86 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-x86.tar.gz'
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x86/net6.0
- task: ArchiveFiles@2
displayName: Create linux-arm tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm.tar.gz'
archiveType: 'tar'
@@ -316,7 +336,15 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm/net6.0
- task: ArchiveFiles@2
displayName: Create ARM32 Linux Musl Core tar
displayName: Create linux-arm-vfpv3d16 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm-vfpv3d16.tar.gz'
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm-vfpv3d16/net6.0
- task: ArchiveFiles@2
displayName: Create linux-musl-arm tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm.tar.gz'
archiveType: 'tar'
@@ -324,7 +352,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm/net6.0
- task: ArchiveFiles@2
displayName: Create ARM64 Linux Core tar
displayName: Create linux-arm64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm64.tar.gz'
archiveType: 'tar'
@@ -332,7 +360,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create ARM64 Linux Musl Core tar
displayName: Create linux-musl-arm64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm64.tar.gz'
archiveType: 'tar'
@@ -340,7 +368,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create FreeBSD Core Core tar
displayName: Create freebsd-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).freebsd-core-x64.tar.gz'
archiveType: 'tar'
@@ -407,22 +435,22 @@ stages:
matrix:
MacCore:
osName: 'Mac'
testName: 'MacCore'
testName: 'osx-x64'
poolName: 'Azure Pipelines'
imageName: ${{ variables.macImage }}
WindowsCore:
osName: 'Windows'
testName: 'WindowsCore'
testName: 'win-x64'
poolName: 'Azure Pipelines'
imageName: ${{ variables.windowsImage }}
LinuxCore:
osName: 'Linux'
testName: 'LinuxCore'
testName: 'linux-x64'
poolName: 'Azure Pipelines'
imageName: ${{ variables.linuxImage }}
FreebsdCore:
osName: 'Linux'
testName: 'FreebsdCore'
testName: 'freebsd-x64'
poolName: 'FreeBSD'
imageName:
@@ -441,7 +469,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(testName)Tests'
artifactName: '$(testName)-tests'
targetPath: $(testsFolder)
- powershell: Set-Service SCardSvr -StartupType Manual
displayName: Enable Windows Test Service
@@ -475,8 +503,12 @@ stages:
matrix:
alpine:
testName: 'Musl Net Core'
artifactName: LinuxMuslCoreTests
artifactName: linux-musl-x64-tests
containerImage: ghcr.io/servarr/testimages:alpine
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pool:
vmImage: ${{ variables.linuxImage }}
@@ -487,9 +519,15 @@ stages:
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
displayName: 'Install .NET'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -515,6 +553,61 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(testName) Unit Tests'
failTaskOnFailedTests: true
- job: Unit_LinuxCore_Postgres
displayName: Unit Native LinuxCore with Postgres Database
dependsOn: Prepare
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
pattern: 'Radarr.*.linux-core-x64.tar.gz'
artifactName: linux-x64-tests
Radarr__Postgres__Host: 'localhost'
Radarr__Postgres__Port: '5432'
Radarr__Postgres__User: 'radarr'
Radarr__Postgres__Password: 'radarr'
pool:
vmImage: 'ubuntu-18.04'
timeoutInMinutes: 10
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
inputs:
version: $(dotnetVersion)
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: $(artifactName)
targetPath: $(testsFolder)
- bash: |
chmod a+x _tests/ffprobe
displayName: Make ffprobe Executable
- bash: find ${TESTSFOLDER} -name "Radarr.Test.Dummy" -exec chmod a+x {} \;
displayName: Make Test Dummy Executable
condition: and(succeeded(), ne(variables['osName'], 'Windows'))
- bash: |
docker run -d --name=postgres14 \
-e POSTGRES_PASSWORD=radarr \
-e POSTGRES_USER=radarr \
-p 5432:5432/tcp \
postgres:14
displayName: Start postgres
- bash: |
chmod a+x ${TESTSFOLDER}/test.sh
ls -lR ${TESTSFOLDER}
${TESTSFOLDER}/test.sh Linux Unit Test
displayName: Run Tests
- task: PublishTestResults@2
displayName: Publish Test Results
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'LinuxCore Postgres Unit Tests'
failTaskOnFailedTests: true
- stage: Integration
displayName: Integration
@@ -542,17 +635,17 @@ stages:
matrix:
MacCore:
osName: 'Mac'
testName: 'MacCore'
testName: 'osx-x64'
imageName: ${{ variables.macImage }}
pattern: 'Radarr.*.osx-core-x64.tar.gz'
WindowsCore:
osName: 'Windows'
testName: 'WindowsCore'
testName: 'win-x64'
imageName: ${{ variables.windowsImage }}
pattern: 'Radarr.*.windows-core-x64.zip'
LinuxCore:
osName: 'Linux'
testName: 'LinuxCore'
testName: 'linux-x64'
imageName: ${{ variables.linuxImage }}
pattern: 'Radarr.*.linux-core-x64.tar.gz'
@@ -569,7 +662,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(testName)Tests'
artifactName: '$(testName)-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -599,6 +692,67 @@ stages:
failTaskOnFailedTests: true
displayName: Publish Test Results
- job: Integration_LinuxCore_Postgres
displayName: Integration Native LinuxCore with Postgres Database
dependsOn: Prepare
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
pattern: 'Radarr.*.linux-core-x64.tar.gz'
Radarr__Postgres__Host: 'localhost'
Radarr__Postgres__Port: '5432'
Radarr__Postgres__User: 'radarr'
Radarr__Postgres__Password: 'radarr'
pool:
vmImage: 'ubuntu-18.04'
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
inputs:
version: $(dotnetVersion)
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: 'linux-x64-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
inputs:
buildType: 'current'
artifactName: Packages
itemPattern: '**/$(pattern)'
targetPath: $(Build.ArtifactStagingDirectory)
- task: ExtractFiles@1
inputs:
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
displayName: Extract Package
- bash: |
mkdir -p ./bin/
cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Radarr/. ./bin/
displayName: Move Package Contents
- bash: |
docker run -d --name=postgres14 \
-e POSTGRES_PASSWORD=radarr \
-e POSTGRES_USER=radarr \
-p 5432:5432/tcp \
postgres:14
displayName: Start postgres
- bash: |
chmod a+x ${TESTSFOLDER}/test.sh
${TESTSFOLDER}/test.sh Linux Integration Test
displayName: Run Integration Tests
- task: PublishTestResults@2
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'Integration LinuxCore Postgres Database Integration Tests'
failTaskOnFailedTests: true
displayName: Publish Test Results
- job: Integration_FreeBSD
displayName: Integration Native FreeBSD
dependsOn: Prepare
@@ -616,7 +770,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: 'FreebsdCoreTests'
artifactName: 'freebsd-x64-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -652,10 +806,15 @@ stages:
strategy:
matrix:
alpine:
testName: 'Musl Net Core'
artifactName: LinuxMuslCoreTests
testName: 'linux-musl-x64'
artifactName: linux-musl-x64-tests
containerImage: ghcr.io/servarr/testimages:alpine
pattern: 'Radarr.*.linux-musl-core-x64.tar.gz'
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pattern: 'Radarr.*.linux-core-x86.tar.gz'
pool:
vmImage: ${{ variables.linuxImage }}
@@ -665,9 +824,15 @@ stages:
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
displayName: 'Install .NET'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -713,16 +878,19 @@ stages:
matrix:
Linux:
osName: 'Linux'
artifactName: 'linux-x64'
imageName: ${{ variables.linuxImage }}
pattern: 'Radarr.*.linux-core-x64.tar.gz'
failBuild: true
Mac:
osName: 'Mac'
artifactName: 'osx-x64'
imageName: ${{ variables.macImage }}
pattern: 'Radarr.*.osx-core-x64.tar.gz'
failBuild: true
Windows:
osName: 'Windows'
artifactName: 'win-x64'
imageName: ${{ variables.windowsImage }}
pattern: 'Radarr.*.windows-core-x64.zip'
failBuild: true
@@ -740,7 +908,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(osName)CoreTests'
artifactName: '$(artifactName)-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact

View File

@@ -25,14 +25,26 @@ UpdateVersionNumber()
fi
}
EnableBsdSupport()
EnableExtraPlatformsInSDK()
{
#todo enable sdk with
#SDK_PATH=$(dotnet --list-sdks | grep -P '5\.\d\.\d+' | head -1 | sed 's/\(5\.[0-9]*\.[0-9]*\).*\[\(.*\)\]/\2\/\1/g')
# BUNDLED_VERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
SDK_PATH=$(dotnet --list-sdks | grep '6\.[0-9]\.[0-9]\{3\}' | tail -1 | sed 's/\(6\.[0-9]*\.[0-9]*\).*\[\(.*\)\]/\2\/\1/g')
BUNDLEDVERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
if ! grep -q freebsd-x64 "${BUNDLEDVERSIONS}"; then
echo "Enabling extra platform support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86;linux-arm-vfpv3d16/' "${BUNDLEDVERSIONS}"
fi
RUNTIMEIDENTIFIERGRAPH="${SDK_PATH}/RuntimeIdentifierGraph.json"
if ! grep -q linux-arm-vfpv3d16 "${RUNTIMEIDENTIFIERGRAPH}"; then
sed -i.ORI '/"runtimes":/a \ \ \ \ "linux-arm-vfpv3d16": {"#import": ["linux-arm"]},' "${RUNTIMEIDENTIFIERGRAPH}"
fi
}
if grep -qv freebsd-x64 src/Directory.Build.props; then
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64</RuntimeIdentifiers>^g" src/Directory.Build.props
EnableExtraPlatforms()
{
if ! grep -q freebsd-x64 src/Directory.Build.props; then
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64;linux-x86;linux-arm-vfpv3d16</RuntimeIdentifiers>^g" src/Directory.Build.props
fi
}
@@ -66,8 +78,8 @@ Build()
platform=Posix
fi
dotnet clean $slnFile -c Debug
dotnet clean $slnFile -c Release
#dotnet clean $slnFile -c Debug
#dotnet clean $slnFile -c Release
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
then
@@ -292,7 +304,8 @@ if [ $# -eq 0 ]; then
PACKAGES=YES
INSTALLER=NO
LINT=YES
ENABLE_BSD=NO
ENABLE_EXTRA_PLATFORMS=NO
ENABLE_EXTRA_PLATFORMS_IN_SDK=NO
fi
while [[ $# -gt 0 ]]
@@ -304,8 +317,12 @@ case $key in
BACKEND=YES
shift # past argument
;;
--enable-bsd)
ENABLE_BSD=YES
--enable-bsd|--enable-extra-platforms)
ENABLE_EXTRA_PLATFORMS=YES
shift # past argument
;;
--enable-extra-platforms-in-sdk)
ENABLE_EXTRA_PLATFORMS_IN_SDK=YES
shift # past argument
;;
-r|--runtime)
@@ -349,12 +366,17 @@ esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
if [ "$ENABLE_EXTRA_PLATFORMS_IN_SDK" = "YES" ];
then
EnableExtraPlatformsInSDK
fi
if [ "$BACKEND" = "YES" ];
then
UpdateVersionNumber
if [ "$ENABLE_BSD" = "YES" ];
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
EnableBsdSupport
EnableExtraPlatforms
fi
Build
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
@@ -364,9 +386,10 @@ then
PackageTests "net6.0" "linux-x64"
PackageTests "net6.0" "linux-musl-x64"
PackageTests "net6.0" "osx-x64"
if [ "$ENABLE_BSD" = "YES" ];
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
PackageTests "net6.0" "freebsd-x64"
PackageTests "net6.0" "linux-x86"
fi
else
PackageTests "$FRAMEWORK" "$RID"
@@ -405,9 +428,11 @@ then
Package "net6.0" "linux-musl-arm"
Package "net6.0" "osx-x64"
Package "net6.0" "osx-arm64"
if [ "$ENABLE_BSD" = "YES" ];
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
Package "net6.0" "freebsd-x64"
Package "net6.0" "linux-x86"
Package "net6.0" "linux-arm-vfpv3d16"
fi
else
Package "$FRAMEWORK" "$RID"

View File

@@ -179,6 +179,16 @@ class HistoryRow extends Component {
);
}
if (name === 'sourceTitle') {
return (
<TableRowCell
key={name}
>
{sourceTitle}
</TableRowCell>
);
}
if (name === 'details') {
return (
<TableRowCell

View File

@@ -8,7 +8,7 @@ import AppRoutes from './AppRoutes';
function App({ store, history }) {
return (
<DocumentTitle title="Radarr">
<DocumentTitle title={window.Radarr.instanceName}>
<Provider store={store}>
<ConnectedRouter history={history}>
<PageConnector>

View File

@@ -161,6 +161,7 @@ class DateFilterBuilderRowValue extends Component {
<TextInput
name={NAME}
value={filterValue}
type="date"
placeholder="yyyy-mm-dd"
onChange={this.onValueChange}
/>

View File

@@ -14,7 +14,7 @@ function PageContent(props) {
return (
<ErrorBoundary errorComponent={PageContentError}>
<DocumentTitle title={title ? `${title} - Radarr` : 'Radarr'}>
<DocumentTitle title={title ? `${title} - ${window.Radarr.instanceName}` : window.Radarr.instanceName}>
<div className={className}>
{children}
</div>

View File

@@ -7,3 +7,9 @@
.filteredMessage {
margin-top: 10px;
}
.blankpad {
padding-top: 10px;
padding-bottom: 10px;
padding-left: 2em;
}

View File

@@ -127,21 +127,21 @@ function InteractiveSearchContent(props) {
{
!isFetching && !!error &&
<div>
<div className={styles.blankpad}>
{translate('UnableToLoadResultsIntSearch')}
</div>
}
{
!isFetching && isPopulated && !totalReleasesCount &&
<div>
<div className={styles.blankpad}>
{translate('NoResultsFound')}
</div>
}
{
!!totalReleasesCount && isPopulated && !items.length &&
<div>
<div className={styles.blankpad}>
{translate('AllResultsHiddenFilter')}
</div>
}
@@ -159,7 +159,7 @@ function InteractiveSearchContent(props) {
items.map((item) => {
return (
<InteractiveSearchRowConnector
key={item.guid}
key={`${item.indexerId}-${item.guid}`}
{...item}
searchPayload={searchPayload}
longDateFormat={longDateFormat}

View File

@@ -65,10 +65,10 @@ function DownloadClientOptions(props) {
<FormInputGroup
type={inputTypes.NUMBER}
name="checkForFinishedDownloadInterval"
min={0}
min={1}
max={120}
unit="minutes"
helpText={translate('HelpText')}
helpText={translate('RefreshMonitoredIntervalHelpText')}
onChange={onInputChange}
{...settings.checkForFinishedDownloadInterval}
/>

View File

@@ -20,6 +20,7 @@ function HostSettings(props) {
bindAddress,
port,
urlBase,
instanceName,
enableSsl,
sslPort,
sslCertPath,
@@ -73,6 +74,22 @@ function HostSettings(props) {
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>{translate('InstanceName')}</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="instanceName"
helpText={translate('InstanceNameHelpText')}
helpTextWarning={translate('RestartRequiredHelpTextWarning')}
onChange={onInputChange}
{...instanceName}
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}

View File

@@ -116,7 +116,7 @@ function IndexerOptions(props) {
min={0}
max={120}
unit="minutes"
helpText={translate('HelpText')}
helpText={translate('RssSyncHelpText')}
helpTextWarning={translate('RSSSyncIntervalHelpTextWarning')}
helpLink="https://wiki.servarr.com/radarr/faq#how-does-radarr-work"
onChange={onInputChange}

View File

@@ -116,10 +116,11 @@ class NamingModal extends Component {
const movieTokens = [
{ token: '{Movie Title}', example: 'Movie\'s Title' },
{ token: '{Movie Title:DE}', example: 'Filetitle' },
{ token: '{Movie Title:DE}', example: 'Titel des Films' },
{ token: '{Movie CleanTitle}', example: 'Movies Title' },
{ token: '{Movie TitleThe}', example: 'Movie\'s Title, The' },
{ token: '{Movie OriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie CleanOriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie TitleFirstCharacter}', example: 'M' },
{ token: '{Movie Collection}', example: 'The Movie Collection' },
{ token: '{Movie Certification}', example: 'R' },

View File

@@ -79,6 +79,11 @@ export const defaultState = {
label: translate('ReleaseGroup'),
isVisible: false
},
{
name: 'sourceTitle',
label: translate('SourceTitle'),
isVisible: false
},
{
name: 'details',
columnLabel: translate('Details'),

View File

@@ -44,7 +44,14 @@ function filter(items, state) {
const predicate = filterPredicates[key];
if (Array.isArray(value)) {
accepted = value.some((v) => predicate(item, v, type));
if (
type === filterTypes.NOT_CONTAINS ||
type === filterTypes.NOT_EQUAL
) {
accepted = value.every((v) => predicate(item, v, type));
} else {
accepted = value.some((v) => predicate(item, v, type));
}
} else {
accepted = predicate(item, value, type);
}

View File

@@ -23,6 +23,8 @@ class About extends Component {
isDocker,
runtimeVersion,
migrationVersion,
databaseVersion,
databaseType,
appData,
startupPath,
mode,
@@ -68,6 +70,11 @@ class About extends Component {
data={migrationVersion}
/>
<DescriptionListItem
title={translate('Database')}
data={`${titleCase(databaseType)} ${databaseVersion}`}
/>
<DescriptionListItem
title={translate('AppDataDirectory')}
data={appData}
@@ -108,6 +115,8 @@ About.propTypes = {
runtimeVersion: PropTypes.string.isRequired,
isDocker: PropTypes.bool.isRequired,
migrationVersion: PropTypes.number.isRequired,
databaseType: PropTypes.string.isRequired,
databaseVersion: PropTypes.string.isRequired,
appData: PropTypes.string.isRequired,
startupPath: PropTypes.string.isRequired,
mode: PropTypes.string.isRequired,

View File

@@ -30,7 +30,7 @@
"@fortawesome/free-regular-svg-icons": "6.1.0",
"@fortawesome/free-solid-svg-icons": "6.1.0",
"@fortawesome/react-fontawesome": "0.1.18",
"@microsoft/signalr": "6.0.3",
"@microsoft/signalr": "6.0.5",
"@sentry/browser": "6.18.2",
"@sentry/integrations": "6.18.2",
"classnames": "2.3.1",
@@ -45,7 +45,7 @@
"jquery": "3.6.0",
"lodash": "4.17.21",
"mobile-detect": "1.4.5",
"moment": "2.29.1",
"moment": "2.29.2",
"mousetrap": "1.6.5",
"normalize.css": "8.0.1",
"prop-types": "15.7.2",
@@ -99,8 +99,8 @@
"babel-loader": "8.2.3",
"babel-plugin-inline-classnames": "2.0.1",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"core-js": "3.11.0",
"css-loader": "5.2.4",
"core-js": "3.12.1",
"css-loader": "6.5.1",
"eslint": "8.11.0",
"eslint-plugin-filenames": "1.3.2",
"eslint-plugin-import": "2.25.4",
@@ -115,22 +115,22 @@
"mini-css-extract-plugin": "1.5.0",
"postcss": "8.2.12",
"postcss-color-function": "4.1.0",
"postcss-loader": "5.2.0",
"postcss-mixins": "7.0.3",
"postcss-nested": "5.0.5",
"postcss-loader": "6.2.0",
"postcss-mixins": "8.1.0",
"postcss-nested": "5.0.6",
"postcss-simple-vars": "6.0.3",
"postcss-url": "10.1.3",
"require-nocache": "1.0.0",
"rimraf": "3.0.2",
"run-sequence": "2.2.1",
"streamqueue": "1.1.2",
"style-loader": "2.0.0",
"style-loader": "3.3.1",
"stylelint": "14.6.0",
"stylelint-order": "5.0.0",
"url-loader": "4.1.1",
"webpack": "5.35.1",
"webpack-cli": "4.6.0",
"webpack-livereload-plugin": "3.0.1",
"webpack": "5.64.2",
"webpack-cli": "4.9.1",
"webpack-livereload-plugin": "3.0.2",
"worker-loader": "3.0.8"
}
}

View File

@@ -90,7 +90,7 @@
<!-- Standard testing packages -->
<ItemGroup Condition="'$(TestProject)'=='true'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />
@@ -154,4 +154,9 @@
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
</PropertyGroup>
<!-- Define constant so we can identify the non-standard arch arm-vfpv3d16 -->
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'linux-arm-vfpv3d16'">
<DefineConstants>ARM_VFPV3D16</DefineConstants>
</PropertyGroup>
</Project>

View File

@@ -44,7 +44,7 @@ namespace NzbDrone.Automation.Test
driver.Manage().Window.Size = new System.Drawing.Size(1920, 1080);
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger());
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
_runner.KillAll();
_runner.Start();

View File

@@ -63,6 +63,7 @@ namespace NzbDrone.Common.Test.InstrumentationTests
[TestCase("Hardlink '/home/mySecret/Downloads/abs.mkv' to '/media/abc.mkv' failed.")]
[TestCase("https://notifiarr.com/notifier.php: api=1234530f-422f-4aac-b6b3-01233210aaaa&radarr_health_issue_message=Download")]
[TestCase("/readarr/signalr/messages/negotiate?access_token=1234530f422f4aacb6b301233210aaaa&negotiateVersion=1")]
[TestCase(@"[Info] MigrationController: *** Migrating Database=radarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;Enlist=False ***")]
// Announce URLs (passkeys) Magnet & Tracker
[TestCase(@"magnet_uri"":""magnet:?xt=urn:btih:9pr04sgkillroyimaveql2tyu8xyui&dn=&tr=https%3a%2f%2fxxx.yyy%2f9pr04sg601233210imaveql2tyu8xyui%2fannounce""}")]

View File

@@ -4,11 +4,13 @@ using DryIoc.Microsoft.DependencyInjection;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Composition.Extensions;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Extensions;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Messaging.Events;
@@ -29,7 +31,8 @@ namespace NzbDrone.Common.Test
.AddDummyDatabase()
.AddStartupContext(new StartupContext("first", "second"));
container.RegisterInstance<IHostLifetime>(new Mock<IHostLifetime>().Object);
container.RegisterInstance(new Mock<IHostLifetime>().Object);
container.RegisterInstance(new Mock<IOptions<PostgresOptions>>().Object);
var serviceProvider = container.GetServiceProvider();

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.Win32;
namespace NzbDrone.Common.EnvironmentInfo
{
@@ -51,78 +50,5 @@ namespace NzbDrone.Common.EnvironmentInfo
{
return _version;
}
private static Version GetDotNetVersion()
{
try
{
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
{
if (ndpKey == null)
{
return new Version(4, 0);
}
var releaseKey = (int)ndpKey.GetValue("Release");
if (releaseKey >= 528040)
{
return new Version(4, 8, 0);
}
if (releaseKey >= 461808)
{
return new Version(4, 7, 2);
}
if (releaseKey >= 461308)
{
return new Version(4, 7, 1);
}
if (releaseKey >= 460798)
{
return new Version(4, 7);
}
if (releaseKey >= 394802)
{
return new Version(4, 6, 2);
}
if (releaseKey >= 394254)
{
return new Version(4, 6, 1);
}
if (releaseKey >= 393295)
{
return new Version(4, 6);
}
if (releaseKey >= 379893)
{
return new Version(4, 5, 2);
}
if (releaseKey >= 378675)
{
return new Version(4, 5, 1);
}
if (releaseKey >= 378389)
{
return new Version(4, 5);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Couldnt get .NET framework version: " + ex.ToString());
}
return new Version(4, 0);
}
}
}

View File

@@ -18,6 +18,7 @@ namespace NzbDrone.Common.Instrumentation
new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
new Regex(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=[?& ;])[^=]*?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
new Regex(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce"),

View File

@@ -127,7 +127,18 @@ namespace NzbDrone.Common.Processes
try
{
_logger.Trace("Setting environment variable '{0}' to '{1}'", environmentVariable.Key, environmentVariable.Value);
startInfo.EnvironmentVariables.Add(environmentVariable.Key.ToString(), environmentVariable.Value.ToString());
var key = environmentVariable.Key.ToString();
var value = environmentVariable.Value?.ToString();
if (startInfo.EnvironmentVariables.ContainsKey(key))
{
startInfo.EnvironmentVariables[key] = value;
}
else
{
startInfo.EnvironmentVariables.Add(key, value);
}
}
catch (Exception e)
{

View File

@@ -13,14 +13,13 @@
<PackageReference Include="Sentry" Version="3.15.0" />
<PackageReference Include="NLog.Targets.Syslog" Version="6.0.3" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Text.Json" Version="6.0.2" />
<PackageReference Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="EnsureThat\Resources\ExceptionMessages.Designer.cs">

View File

@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Datastore
public void SingleOrDefault_should_return_null_on_empty_db()
{
Mocker.Resolve<IDatabase>()
.OpenConnection().Query<Movie>("SELECT * FROM Movies")
.OpenConnection().Query<Movie>("SELECT * FROM \"Movies\"")
.SingleOrDefault()
.Should()
.BeNull();

View File

@@ -135,9 +135,9 @@ namespace NzbDrone.Core.Test.Datastore.Migration
private List<Profile147> QueryItems(IDirectDataMapper db)
{
var test = db.Query("SELECT * FROM Profiles");
var test = db.Query("SELECT * FROM \"Profiles\"");
var items = db.Query<Profile147>("SELECT FormatItems, FormatCutoff FROM Profiles");
var items = db.Query<Profile147>("SELECT \"FormatItems\", \"FormatCutoff\" FROM \"Profiles\"");
return items.Select(i =>
{

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Newtonsoft.Json;
@@ -77,7 +77,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
private List<CustomFormatTest149> QueryItems(IDirectDataMapper db)
{
var items = db.Query<CustomFormatTest149>("SELECT Name, FormatTags FROM CustomFormats");
var items = db.Query<CustomFormatTest149>("SELECT \"Name\", \"FormatTags\" FROM \"CustomFormats\"");
return items.Select(i =>
{

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Newtonsoft.Json;
@@ -40,7 +40,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
private List<regex_required_tagsFixture.CustomFormatTest149> QueryItems(IDirectDataMapper db)
{
var items = db.Query<regex_required_tagsFixture.CustomFormatTest149>("SELECT Name, FormatTags FROM CustomFormats");
var items = db.Query<regex_required_tagsFixture.CustomFormatTest149>("SELECT \"Name\", \"FormatTags\" FROM \"CustomFormats\"");
return items.Select(i =>
{

View File

@@ -32,8 +32,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
Monitored = true,
Title = "My Movie",
CleanTitle = "mytitle",
Status = MovieStatusType.Announced,
MinimumAvailability = MovieStatusType.Announced,
Status = (int)MovieStatusType.Announced,
MinimumAvailability = (int)MovieStatusType.Announced,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
HasPreDBEntry = false,
PathState = 1,
@@ -112,7 +112,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", "Japanese");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -130,7 +130,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", "Japanese / French");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(2);
@@ -149,7 +149,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", "");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -166,7 +166,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", "English (USA)");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -184,7 +184,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, "", "");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, null, null);
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -218,7 +218,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, "My.Movie.2018.BluRay-Radarr", "");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -235,7 +235,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, "", "");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM MovieFiles");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -253,7 +253,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddHistory(c, "My.Movie.2018.Italian.BluRay-Radarr");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM History");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"History\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -270,7 +270,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddHistory(c, "");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM History");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"History\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -287,7 +287,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddHistory(c, "Man on Fire");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM History");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"History\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -305,7 +305,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddHistory(c, "My.Movie.2018.Italian.BluRay-Radarr");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM History");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"History\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(3);
@@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddBlacklist(c, "My.Movie.2018.Italian.BluRay-Radarr");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM Blacklist");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"Blacklist\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -341,7 +341,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddBlacklist(c, "");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM Blacklist");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"Blacklist\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);
@@ -358,7 +358,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddBlacklist(c, "Man on Fire");
});
var items = db.Query<ModelWithLanguages154>("SELECT Id, Languages FROM Blacklist");
var items = db.Query<ModelWithLanguages154>("SELECT \"Id\", \"Languages\" FROM \"Blacklist\"");
items.Should().HaveCount(1);
items.First().Languages.Count.Should().Be(1);

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using FluentAssertions;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Enable = true,
Name = "Deluge",
Implementation = "Deluge",
Settings = new DelugeSettings156
@@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<DownloadClientDefinition132>("SELECT * FROM DownloadClients");
var items = db.Query<DownloadClientDefinition132>("SELECT * FROM \"DownloadClients\"");
items.Should().HaveCount(1);
items.First().Priority.Should().Be(1);
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Enable = true,
Name = "Deluge",
Implementation = "Deluge",
Settings = new DelugeSettings156
@@ -56,7 +56,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
ConfigContract = "DelugeSettings"
}).Row(new
{
Enable = 1,
Enable = true,
Name = "Deluge2",
Implementation = "Deluge",
Settings = new DelugeSettings156
@@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
ConfigContract = "DelugeSettings"
}).Row(new
{
Enable = 1,
Enable = true,
Name = "sab",
Implementation = "Sabnzbd",
Settings = new SabnzbdSettings156
@@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<DownloadClientDefinition132>("SELECT * FROM DownloadClients");
var items = db.Query<DownloadClientDefinition132>("SELECT * FROM \"DownloadClients\"");
items.Should().HaveCount(3);
items[0].Priority.Should().Be(1);
@@ -95,7 +95,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 0,
Enable = false,
Name = "Deluge",
Implementation = "Deluge",
Settings = new DelugeSettings156
@@ -107,7 +107,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
ConfigContract = "DelugeSettings"
}).Row(new
{
Enable = 0,
Enable = false,
Name = "Deluge2",
Implementation = "Deluge",
Settings = new DelugeSettings156
@@ -119,7 +119,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
ConfigContract = "DelugeSettings"
}).Row(new
{
Enable = 0,
Enable = false,
Name = "sab",
Implementation = "Sabnzbd",
Settings = new SabnzbdSettings156
@@ -131,7 +131,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<DownloadClientDefinition132>("SELECT * FROM DownloadClients");
var items = db.Query<DownloadClientDefinition132>("SELECT * FROM \"DownloadClients\"");
items.Should().HaveCount(3);
items[0].Priority.Should().Be(1);

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Migration;
@@ -34,7 +34,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var profiles = db.Query<Profile159>("SELECT Items FROM Profiles LIMIT 1");
var profiles = db.Query<Profile159>("SELECT \"Items\" FROM \"Profiles\" LIMIT 1");
var items = profiles.First().Items;
items.Should().HaveCount(5);
@@ -57,7 +57,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var profiles = db.Query<Profile159>("SELECT Items FROM Profiles LIMIT 1");
var profiles = db.Query<Profile159>("SELECT \"Items\" FROM \"Profiles\" LIMIT 1");
var items = profiles.First().Items;
items.Should().HaveCount(5);
@@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var profiles = db.Query<Profile159>("SELECT Items FROM Profiles LIMIT 1");
var profiles = db.Query<Profile159>("SELECT \"Items\" FROM \"Profiles\" LIMIT 1");
var items = profiles.First().Items;
items.Count(c => c.Id == 1001).Should().Be(1);
@@ -104,7 +104,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var profiles = db.Query<Profile159>("SELECT Items FROM Profiles LIMIT 1");
var profiles = db.Query<Profile159>("SELECT \"Items\" FROM \"Profiles\" LIMIT 1");
var items = profiles.First().Items;
items[1].Items.First().Quality.Should().Be((int)Quality.WEBRip480p);

View File

@@ -81,14 +81,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
""imdbId"": """"
}",
Release = "{}",
Reason = PendingReleaseReason.Delay
Reason = (int)PendingReleaseReason.Delay
});
});
var json = db.Query<string>("SELECT ParsedMovieInfo FROM PendingReleases").First();
var json = db.Query<string>("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First();
json.Should().NotContain("customFormats");
var pending = db.Query<ParsedMovieInfo>("SELECT ParsedMovieInfo FROM PendingReleases").First();
var pending = db.Query<ParsedMovieInfo>("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First();
pending.Quality.Quality.Should().Be(Quality.Bluray1080p);
pending.Languages.Should().BeEmpty();
}
@@ -129,15 +129,15 @@ namespace NzbDrone.Core.Test.Datastore.Migration
""imdbId"": """"
}",
Release = "{}",
Reason = PendingReleaseReason.Delay
Reason = (int)PendingReleaseReason.Delay
});
});
var json = db.Query<string>("SELECT ParsedMovieInfo FROM PendingReleases").First();
var json = db.Query<string>("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First();
json.Should().NotContain("customFormats");
json.Should().NotContain("resolution");
var pending = db.Query<ParsedMovieInfo>("SELECT ParsedMovieInfo FROM PendingReleases").First();
var pending = db.Query<ParsedMovieInfo>("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First();
pending.Quality.Quality.Should().Be(Quality.Bluray1080p);
pending.Languages.Should().BeEquivalentTo(new List<Language> { Language.English });
}

View File

@@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var json = db.Query<string>("SELECT Specifications FROM CustomFormats").First();
var json = db.Query<string>("SELECT \"Specifications\" FROM \"CustomFormats\"").First();
ValidateFormatTag(json, "ReleaseTitleSpecification", false, false);
json.Should().Contain($"\"name\": \"Test\"");
@@ -99,7 +99,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var json = db.Query<string>("SELECT Specifications FROM CustomFormats").First();
var json = db.Query<string>("SELECT \"Specifications\" FROM \"CustomFormats\"").First();
ValidateFormatTag(json, "ReleaseTitleSpecification", false, false);
ValidateFormatTag(json, "EditionSpecification", false, false);

View File

@@ -19,12 +19,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("NetImport").Row(new
{
Enabled = 1,
EnableAuto = 1,
Enabled = true,
EnableAuto = true,
RootFolderPath = "D:\\Movies",
ProfileId = 1,
MinimumAvailability = 1,
ShouldMonitor = 1,
ShouldMonitor = true,
Name = "IMDB List",
Implementation = "RadarrLists",
Settings = new RadarrListSettings169
@@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<ListDefinition169>("SELECT * FROM NetImport");
var items = db.Query<ListDefinition169>("SELECT * FROM \"NetImport\"");
items.Should().HaveCount(1);
items.First().Implementation.Should().Be("RadarrListImport");
@@ -52,12 +52,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("NetImport").Row(new
{
Enabled = 1,
EnableAuto = 1,
Enabled = true,
EnableAuto = true,
RootFolderPath = "D:\\Movies",
ProfileId = 1,
MinimumAvailability = 1,
ShouldMonitor = 1,
ShouldMonitor = true,
Name = "TraktImport",
Implementation = "TraktImport",
Settings = new TraktSettings169
@@ -72,7 +72,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<ListDefinition169>("SELECT * FROM NetImport");
var items = db.Query<ListDefinition169>("SELECT * FROM \"NetImport\"");
items.Should().HaveCount(1);
items.First().Implementation.Should().Be("TraktUserImport");
@@ -90,12 +90,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("NetImport").Row(new
{
Enabled = 1,
EnableAuto = 1,
Enabled = true,
EnableAuto = true,
RootFolderPath = "D:\\Movies",
ProfileId = 1,
MinimumAvailability = 1,
ShouldMonitor = 1,
ShouldMonitor = true,
Name = "TraktImport",
Implementation = "TraktImport",
Settings = new TraktSettings169
@@ -110,7 +110,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<ListDefinition169>("SELECT * FROM NetImport");
var items = db.Query<ListDefinition169>("SELECT * FROM \"NetImport\"");
items.Should().HaveCount(1);
items.First().Implementation.Should().Be("TraktPopularImport");
@@ -128,12 +128,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("NetImport").Row(new
{
Enabled = 1,
EnableAuto = 1,
Enabled = true,
EnableAuto = true,
RootFolderPath = "D:\\Movies",
ProfileId = 1,
MinimumAvailability = 1,
ShouldMonitor = 1,
ShouldMonitor = true,
Name = "TraktImport",
Implementation = "TraktImport",
Settings = new TraktSettings169
@@ -149,7 +149,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<ListDefinition169>("SELECT * FROM NetImport");
var items = db.Query<ListDefinition169>("SELECT * FROM \"NetImport\"");
items.Should().HaveCount(1);
items.First().Implementation.Should().Be("TraktListImport");

View File

@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<ProviderDefinition166>("SELECT * FROM Notifications");
var items = db.Query<ProviderDefinition166>("SELECT * FROM \"Notifications\"");
items.Should().HaveCount(1);
items.First().Implementation.Should().Be("Email");

View File

@@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}
});
var items = db.Query<new_list_server.NetImportDefinition178>("SELECT * FROM NetImport");
var items = db.Query<new_list_server.NetImportDefinition178>("SELECT * FROM \"NetImport\"");
items.Should().HaveCount(7);
@@ -157,7 +157,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}
});
var items = db.Query<new_list_server.NetImportDefinition178>("SELECT * FROM NetImport");
var items = db.Query<new_list_server.NetImportDefinition178>("SELECT * FROM \"NetImport\"");
items.Should().HaveCount(5);

View File

@@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
Items = items.ToJson(),
Language = (int)Language.English,
MinFormatScore = 0,
CutOffFormatScore = 0
CutoffFormatScore = 0
};
m.Insert.IntoTable("Profiles").Row(profile);
@@ -50,8 +50,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
Monitored = true,
Title = movieTitle,
CleanTitle = movieTitle,
Status = MovieStatusType.Announced,
MinimumAvailability = MovieStatusType.Announced,
Status = (int)MovieStatusType.Announced,
MinimumAvailability = (int)MovieStatusType.Announced,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
HasPreDBEntry = false,
@@ -89,8 +89,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, "movie", 123456, profileId);
});
var items = db.Query<Movie179>("SELECT Id, ProfileId FROM Movies");
var profiles = db.Query<Profile179>("SELECT Id FROM Profiles");
var items = db.Query<Movie179>("SELECT \"Id\", \"ProfileId\" FROM \"Movies\"");
var profiles = db.Query<Profile179>("SELECT \"Id\" FROM \"Profiles\"");
items.Should().HaveCount(1);
profiles.Should().HaveCount(6);
@@ -108,8 +108,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, "movie", 123456, 17);
});
var items = db.Query<Movie179>("SELECT Id, ProfileId FROM Movies");
var profiles = db.Query<Profile179>("SELECT Id FROM Profiles");
var items = db.Query<Movie179>("SELECT \"Id\", \"ProfileId\" FROM \"Movies\"");
var profiles = db.Query<Profile179>("SELECT \"Id\" FROM \"Profiles\"");
items.Should().HaveCount(1);
profiles.Should().HaveCount(1);
@@ -128,8 +128,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, "movie", 123456, profileId);
});
var items = db.Query<Movie179>("SELECT Id, ProfileId FROM Movies");
var profiles = db.Query<Profile179>("SELECT Id, FormatItems FROM Profiles");
var items = db.Query<Movie179>("SELECT \"Id\", \"ProfileId\" FROM \"Movies\"");
var profiles = db.Query<Profile179>("SELECT \"Id\", \"FormatItems\" FROM \"Profiles\"");
items.Should().HaveCount(1);
profiles.Should().HaveCount(6);
@@ -149,7 +149,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, "movie", 123456, profileId);
});
var items = db.Query<Movie179>("SELECT Id, ProfileId FROM Movies");
var items = db.Query<Movie179>("SELECT \"Id\", \"ProfileId\" FROM \"Movies\"");
items.Should().HaveCount(1);
items.First().ProfileId.Should().Be(profileId);
@@ -166,7 +166,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, "movie", 123456, 1);
});
var items = db.Query<Movie179>("SELECT Id, ProfileId FROM Movies");
var items = db.Query<Movie179>("SELECT \"Id\", \"ProfileId\" FROM \"Movies\"");
items.Should().HaveCount(1);
items.First().ProfileId.Should().Be(profileId);
@@ -193,7 +193,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, "movie9", 123459, otherProfileId);
});
var items = db.Query<Movie179>("SELECT Id, ProfileId FROM Movies");
var items = db.Query<Movie179>("SELECT \"Id\", \"ProfileId\" FROM \"Movies\"");
items.Should().HaveCount(9);
items.Where(x => x.ProfileId == commonProfileId).Should().HaveCount(7);

View File

@@ -20,8 +20,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
Monitored = true,
Title = movieTitle,
CleanTitle = movieTitle,
Status = MovieStatusType.Announced,
MinimumAvailability = MovieStatusType.Announced,
Status = (int)MovieStatusType.Announced,
MinimumAvailability = (int)MovieStatusType.Announced,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
HasPreDBEntry = false,
@@ -53,7 +53,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, 4, "movie", "slug3", tmdbId, 0, dateAdded, dateAdded);
});
var items = db.Query<Movie185>("SELECT Id, TmdbId, MovieFileId FROM Movies");
var items = db.Query<Movie185>("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\"");
items.Should().HaveCount(1);
}
@@ -73,7 +73,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, 5, "movie2", "slug4", 123457, 0, dateAdded, dateAdded);
});
var items = db.Query<Movie185>("SELECT Id, TmdbId, MovieFileId FROM Movies");
var items = db.Query<Movie185>("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\"");
items.Should().HaveCount(2);
items.Where(i => i.TmdbId == tmdbId).Should().HaveCount(1);
@@ -93,7 +93,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, 5, "movie5", "slug4", 123457, 0, dateAdded, dateAdded);
});
var items = db.Query<Movie185>("SELECT Id, TmdbId, MovieFileId FROM Movies");
var items = db.Query<Movie185>("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\"");
items.Should().HaveCount(5);
}
@@ -112,7 +112,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, 4, "movie", "slug3", tmdbId, 0, dateAdded, dateAdded);
});
var items = db.Query<Movie185>("SELECT Id, TmdbId, MovieFileId FROM Movies");
var items = db.Query<Movie185>("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\"");
items.Should().HaveCount(1);
items.First().Id.Should().Be(2);
@@ -132,7 +132,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, 4, "movie", "slug3", tmdbId, 2, dateAdded, dateAdded);
});
var items = db.Query<Movie185>("SELECT Id, TmdbId, MovieFileId FROM Movies");
var items = db.Query<Movie185>("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\"");
items.Should().HaveCount(1);
items.First().MovieFileId.Should().BeGreaterThan(0);
@@ -153,7 +153,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovie(c, 4, "movie", "slug3", tmdbId, 0, null, dateAdded);
});
var items = db.Query<Movie185>("SELECT Id, LastInfoSync, TmdbId, MovieFileId FROM Movies");
var items = db.Query<Movie185>("SELECT \"Id\", \"LastInfoSync\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\"");
items.Should().HaveCount(1);
items.First().LastInfoSync.Should().NotBeNull();

View File

@@ -67,7 +67,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
AddMovieFile(c, 1);
});
var items = db.Query<MovieFile188>("SELECT MediaInfo FROM MovieFiles");
var items = db.Query<MovieFile188>("SELECT \"MediaInfo\" FROM \"MovieFiles\"");
items.Should().HaveCount(1);

View File

@@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Enable = true,
Name = "Deluge",
Implementation = "Deluge",
Priority = 1,
@@ -34,7 +34,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM DownloadClients");
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM \"DownloadClients\"");
items.Should().HaveCount(1);
items.First().RemoveCompletedDownloads.Should().BeFalse();
@@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Enable = true,
Name = "Deluge",
Implementation = "Deluge",
Priority = 1,
@@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM DownloadClients");
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM \"DownloadClients\"");
items.Should().HaveCount(1);
items.First().RemoveCompletedDownloads.Should().BeTrue();
@@ -82,7 +82,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Enable = true,
Name = "RTorrent",
Implementation = "RTorrent",
Priority = 1,
@@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM DownloadClients");
var items = db.Query<DownloadClientDefinition158>("SELECT * FROM \"DownloadClients\"");
items.Should().HaveCount(1);
items.First().RemoveCompletedDownloads.Should().BeFalse();

View File

@@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<NotificationEntity201>("SELECT Id,ConfigContract,Implementation,Name,Settings FROM Notifications");
var items = db.Query<NotificationEntity201>("SELECT \"Id\",\"ConfigContract\",\"Implementation\",\"Name\",\"Settings\" FROM \"Notifications\"");
items.Should().HaveCount(1);
items.First().ConfigContract.Should().Be("DiscordSettings");

View File

@@ -20,12 +20,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
c.Insert.IntoTable("ImportLists").Row(new
{
Enabled = 1,
EnableAuto = 1,
Enabled = true,
EnableAuto = true,
RootFolderPath = "D:\\Movies",
ProfileId = 1,
MinimumAvailability = 4,
ShouldMonitor = 1,
ShouldMonitor = true,
Name = "IMDB List",
Implementation = "RadarrLists",
Settings = new RadarrListSettings169
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<ListDefinition201>("SELECT Id, MinimumAvailability FROM ImportLists");
var items = db.Query<ListDefinition201>("SELECT \"Id\", \"MinimumAvailability\" FROM \"ImportLists\"");
items.Should().HaveCount(1);
items.First().MinimumAvailability.Should().Be(3);
@@ -70,7 +70,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = db.Query<Movie201>("SELECT Id, MinimumAvailability FROM Movies");
var items = db.Query<Movie201>("SELECT \"Id\", \"MinimumAvailability\" FROM \"Movies\"");
items.Should().HaveCount(1);
items.First().MinimumAvailability.Should().Be(3);

View File

@@ -0,0 +1,347 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class movie_metadataFixture : MigrationTest<movie_metadata>
{
[Test]
public void should_add_metadata_from_movie_and_link_back_to_movie()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_credits()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("Credits").Row(new
{
MovieId = 5,
CreditTmdbId = 123,
PersonTmdbId = 456,
Order = 1,
Type = 1,
Name = "Some Person",
Images = new[] { new { CoverType = "Poster" } }.ToJson()
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Credits\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_alt_title()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("AlternativeTitles").Row(new
{
MovieId = 5,
Title = "Some Alt",
CleanTitle = "somealt",
SourceType = 1,
SourceId = 1,
Votes = 0,
VoteCount = 0,
Language = 1
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"AlternativeTitles\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_translation()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("MovieTranslations").Row(new
{
MovieId = 5,
Title = "Some Trans",
Language = 1
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"MovieTranslations\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_add_metadata_from_list_and_link_back()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_not_duplicate_metadata()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 123456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
var listMovies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
listMovies.Should().HaveCount(1);
listMovies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_not_duplicate_metadata_from_lists()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Overview = "Overview 1",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Overview = "Overview 2",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 5,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var listMovies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
listMovies.Should().HaveCount(2);
listMovies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
}
public class MovieMetadata207
{
public int Id { get; set; }
public int TmdbId { get; set; }
public string Title { get; set; }
public bool Monitored { get; set; }
}
public class Movie207
{
public int Id { get; set; }
public int MovieMetadataId { get; set; }
}
}

View File

@@ -0,0 +1,211 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore
{
[TestFixture]
public class WhereBuilderPostgresFixture : CoreTest
{
private WhereBuilderPostgres _subject;
[OneTimeSetUp]
public void MapTables()
{
// Generate table mapping
Mocker.Resolve<DbFactory>();
}
private WhereBuilderPostgres Where(Expression<Func<Movie, bool>> filter)
{
return new WhereBuilderPostgres(filter, true, 0);
}
private WhereBuilderPostgres WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderPostgres(filter, true, 0);
}
[Test]
public void postgres_where_equal_const()
{
_subject = Where(x => x.Id == 10);
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = @Clause1_P1)");
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(10);
}
[Test]
public void postgres_where_equal_variable()
{
var id = 10;
_subject = Where(x => x.Id == id);
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = @Clause1_P1)");
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(id);
}
[Test]
public void postgres_where_equal_property()
{
var movie = new Movie { Id = 10 };
_subject = Where(x => x.Id == movie.Id);
_subject.Parameters.ParameterNames.Should().HaveCount(1);
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = @Clause1_P1)");
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(movie.Id);
}
[Test]
public void postgres_where_equal_joined_property()
{
_subject = Where(x => x.Profile.Id == 1);
_subject.Parameters.ParameterNames.Should().HaveCount(1);
_subject.ToString().Should().Be($"(\"Profiles\".\"Id\" = @Clause1_P1)");
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(1);
}
[Test]
public void postgres_where_throws_without_concrete_condition_if_requiresConcreteCondition()
{
Expression<Func<Movie, Movie, bool>> filter = (x, y) => x.Id == y.Id;
_subject = new WhereBuilderPostgres(filter, true, 0);
Assert.Throws<InvalidOperationException>(() => _subject.ToString());
}
[Test]
public void postgres_where_allows_abstract_condition_if_not_requiresConcreteCondition()
{
Expression<Func<Movie, Movie, bool>> filter = (x, y) => x.Id == y.Id;
_subject = new WhereBuilderPostgres(filter, false, 0);
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = \"Movies\".\"Id\")");
}
[Test]
public void postgres_where_string_is_null()
{
_subject = WhereMeta(x => x.CleanTitle == null);
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_string_is_null_value()
{
string cleanTitle = null;
_subject = WhereMeta(x => x.CleanTitle == cleanTitle);
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_equal_null_property()
{
var movie = new MovieMetadata { CleanTitle = null };
_subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_column_contains_string()
{
var test = "small";
_subject = WhereMeta(x => x.CleanTitle.Contains(test));
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
[Test]
public void postgres_where_string_contains_column()
{
var test = "small";
_subject = WhereMeta(x => test.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
[Test]
public void postgres_where_column_starts_with_string()
{
var test = "small";
_subject = WhereMeta(x => x.CleanTitle.StartsWith(test));
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
[Test]
public void postgres_where_column_ends_with_string()
{
var test = "small";
_subject = WhereMeta(x => x.CleanTitle.EndsWith(test));
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
[Test]
public void postgres_where_in_list()
{
var list = new List<int> { 1, 2, 3 };
_subject = Where(x => list.Contains(x.Id));
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = ANY (('{{1, 2, 3}}')))");
}
[Test]
public void postgres_where_in_list_2()
{
var list = new List<int> { 1, 2, 3 };
_subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" = ANY (('{{1, 2, 3}}'))))");
}
[Test]
public void postgres_where_in_string_list()
{
var list = new List<string> { "first", "second", "third" };
_subject = WhereMeta(x => list.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" = ANY (@Clause1_P1))");
}
[Test]
public void enum_as_int()
{
_subject = WhereMeta(x => x.Status == MovieStatusType.Announced);
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)");
}
[Test]
public void enum_in_list()
{
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))");
}
[Test]
public void enum_in_array()
{
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))");
}
}
}

View File

@@ -11,9 +11,9 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore
{
[TestFixture]
public class WhereBuilderFixture : CoreTest
public class WhereBuilderSqliteFixture : CoreTest
{
private WhereBuilder _subject;
private WhereBuilderSqlite _subject;
[OneTimeSetUp]
public void MapTables()
@@ -22,9 +22,14 @@ namespace NzbDrone.Core.Test.Datastore
Mocker.Resolve<DbFactory>();
}
private WhereBuilder Where(Expression<Func<Movie, bool>> filter)
private WhereBuilderSqlite Where(Expression<Func<Movie, bool>> filter)
{
return new WhereBuilder(filter, true, 0);
return new WhereBuilderSqlite(filter, true, 0);
}
private WhereBuilderSqlite WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderSqlite(filter, true, 0);
}
[Test]
@@ -71,7 +76,7 @@ namespace NzbDrone.Core.Test.Datastore
public void where_throws_without_concrete_condition_if_requiresConcreteCondition()
{
Expression<Func<Movie, Movie, bool>> filter = (x, y) => x.Id == y.Id;
_subject = new WhereBuilder(filter, true, 0);
_subject = new WhereBuilderSqlite(filter, true, 0);
Assert.Throws<InvalidOperationException>(() => _subject.ToString());
}
@@ -79,43 +84,43 @@ namespace NzbDrone.Core.Test.Datastore
public void where_allows_abstract_condition_if_not_requiresConcreteCondition()
{
Expression<Func<Movie, Movie, bool>> filter = (x, y) => x.Id == y.Id;
_subject = new WhereBuilder(filter, false, 0);
_subject = new WhereBuilderSqlite(filter, false, 0);
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = \"Movies\".\"Id\")");
}
[Test]
public void where_string_is_null()
{
_subject = Where(x => x.CleanTitle == null);
_subject = WhereMeta(x => x.CleanTitle == null);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_string_is_null_value()
{
string cleanTitle = null;
_subject = Where(x => x.CleanTitle == cleanTitle);
_subject = WhereMeta(x => x.CleanTitle == cleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_equal_null_property()
{
var movie = new Movie { CleanTitle = null };
_subject = Where(x => x.CleanTitle == movie.CleanTitle);
var movie = new MovieMetadata { CleanTitle = null };
_subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_column_contains_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.Contains(test));
_subject = WhereMeta(x => x.CleanTitle.Contains(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_string_contains_column()
{
var test = "small";
_subject = Where(x => test.Contains(x.CleanTitle));
_subject = WhereMeta(x => test.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"Movies\".\"CleanTitle\" || '%')");
_subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -133,9 +138,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_column_starts_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.StartsWith(test));
_subject = WhereMeta(x => x.CleanTitle.StartsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -143,9 +148,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_column_ends_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.EndsWith(test));
_subject = WhereMeta(x => x.CleanTitle.EndsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1)");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -164,9 +169,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_in_list_2()
{
var list = new List<int> { 1, 2, 3 };
_subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" IN (1, 2, 3)))");
_subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" IN (1, 2, 3)))");
}
[Test]
@@ -174,35 +179,35 @@ namespace NzbDrone.Core.Test.Datastore
{
var list = new List<string> { "first", "second", "third" };
_subject = Where(x => list.Contains(x.CleanTitle));
_subject = WhereMeta(x => list.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IN @Clause1_P1)");
}
[Test]
public void enum_as_int()
{
_subject = Where(x => x.Status == MovieStatusType.Announced);
_subject = WhereMeta(x => x.Status == MovieStatusType.Announced);
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)");
}
[Test]
public void enum_in_list()
{
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)");
}
[Test]
public void enum_in_array()
{
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)");
}
}
}

View File

@@ -53,7 +53,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[TestCase(60, 1000, false)]
public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{
_movie.Runtime = runtime;
_movie.MovieMetadata.Value.Runtime = runtime;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = sizeInMegaBytes.Megabytes();
@@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_size_is_zero()
{
_movie.Runtime = 120;
_movie.MovieMetadata.Value.Runtime = 120;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 0;
_qualityType.MinSize = 10;
@@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_30_minute()
{
_movie.Runtime = 30;
_movie.MovieMetadata.Value.Runtime = 30;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 18457280000;
_qualityType.MaxSize = null;
@@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_60_minute()
{
_movie.Runtime = 60;
_movie.MovieMetadata.Value.Runtime = 60;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 36857280000;
_qualityType.MaxSize = null;
@@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_use_110_minutes_if_runtime_is_0()
{
_movie.Runtime = 0;
_movie.MovieMetadata.Value.Runtime = 0;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 1095.Megabytes();

View File

@@ -31,7 +31,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
Language = Language.English
},
OriginalLanguage = Language.French
MovieMetadata = new MovieMetadata
{
OriginalLanguage = Language.French
}
}
};
}

View File

@@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
MinFormatScore = 0
})
.With(m => m.Title = "A Movie")
.With(m => m.Runtime = runtime).Build();
.With(m => m.MovieMetadata.Value.Runtime = runtime).Build();
remoteMovie.Release = new ReleaseInfo();
remoteMovie.Release.PublishDate = DateTime.Now.AddDays(-age);

View File

@@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.Build();
Mocker.GetMock<ICustomFormatCalculationService>()
.Setup(x => x.ParseCustomFormat(It.IsAny<ParsedMovieInfo>()))
.Setup(x => x.ParseCustomFormat(It.IsAny<ParsedMovieInfo>(), _movie))
.Returns(new List<CustomFormat>());
}

View File

@@ -0,0 +1,66 @@
<rss xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:nyaa="https://nyaa.si/xmlns/nyaa" version="2.0">
<channel>
<title>Nyaa - Home - Torrent File RSS</title>
<description>RSS Feed for Home</description>
<link>https://nyaa.si/</link>
<atom:link href="https://nyaa.si/?page=rss" rel="self" type="application/rss+xml"/>
<item>
<title>[Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv</title>
<link>https://nyaa.si/download/1424896.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424896</guid>
<pubDate>Tue, 24 Aug 2021 22:18:46 -0000</pubDate>
<nyaa:seeders>4</nyaa:seeders>
<nyaa:leechers>3</nyaa:leechers>
<nyaa:downloads>2</nyaa:downloads>
<nyaa:infoHash>e8ca5e20eca876339f41c3d9e95ea66c1d7caaee</nyaa:infoHash>
<nyaa:categoryId>1_3</nyaa:categoryId>
<nyaa:category>Anime - Non-English-translated</nyaa:category>
<nyaa:size>609.6 MiB</nyaa:size>
<nyaa:comments>0</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424896">#1424896 | [Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv</a> | 609.6 MiB | Anime - Non-English-translated | E8CA5E20ECA876339F41C3D9E95EA66C1D7CAAEE ]]>
</description>
</item>
<item>
<title>Macross Zero (BDRip 1920x1080p x265 HEVC TrueHD, FLAC 5.1+2.0)[sxales]</title>
<link>https://nyaa.si/download/1424895.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424895</guid>
<pubDate>Tue, 24 Aug 2021 22:03:11 -0000</pubDate>
<nyaa:seeders>23</nyaa:seeders>
<nyaa:leechers>32</nyaa:leechers>
<nyaa:downloads>17</nyaa:downloads>
<nyaa:infoHash>26f37f26d5b3475b41a98dc575fabfa6f8d32a76</nyaa:infoHash>
<nyaa:categoryId>1_2</nyaa:categoryId>
<nyaa:category>Anime - English-translated</nyaa:category>
<nyaa:size>5.7 GiB</nyaa:size>
<nyaa:comments>2</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424895">#1424895 | Macross Zero (BDRip 1920x1080p x265 HEVC TrueHD, FLAC 5.1+2.0)[sxales]</a> | 5.7 GiB | Anime - English-translated | 26F37F26D5B3475B41A98DC575FABFA6F8D32A76 ]]>
</description>
</item>
<item>
<title>Fumetsu no Anata e - 19 [WEBDL 1080p] Ukr DVO</title>
<link>https://nyaa.si/download/1424887.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424887</guid>
<pubDate>Tue, 24 Aug 2021 21:23:06 -0000</pubDate>
<nyaa:seeders>5</nyaa:seeders>
<nyaa:leechers>4</nyaa:leechers>
<nyaa:downloads>4</nyaa:downloads>
<nyaa:infoHash>3e4300e24b39983802162877755aab4380bd137a</nyaa:infoHash>
<nyaa:categoryId>1_3</nyaa:categoryId>
<nyaa:category>Anime - Non-English-translated</nyaa:category>
<nyaa:size>1.4 GiB</nyaa:size>
<nyaa:comments>0</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424887">#1424887 | Fumetsu no Anata e - 19 [WEBDL 1080p] Ukr DVO</a> | 1.4 GiB | Anime - Non-English-translated | 3E4300E24B39983802162877755AAB4380BD137A ]]>
</description>
</item>
</channel>
</rss>

View File

@@ -0,0 +1,46 @@
{
"MediaContainer": {
"librarySectionID": "watchlist",
"librarySectionTitle": "Watchlist",
"offset": 0,
"totalSize": 3,
"identifier": "tv.plex.provider.metadata",
"size": 3,
"Metadata": [
{
"type": "movie",
"title": "Arrival",
"year": 2016,
"Guid": [
{
"id": "imdb://tt2543164"
}
]
},
{
"type": "movie",
"title": "The Last Witch Hunter",
"year": 2015,
"Guid": [
{
"id": "imdb://tt1618442"
},
{
"id": "tmdb://274854"
}
]
},
{
"type": "movie",
"title": "Avengers: Endgame",
"year": 2019,
"Guid": []
},
{
"type": "movie",
"title": "Avengers",
"year": 2005
}
]
}
}

View File

@@ -1,14 +1,18 @@
using System;
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Linq;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Npgsql;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Test.Common.Datastore;
namespace NzbDrone.Core.Test.Framework
{
@@ -49,6 +53,7 @@ namespace NzbDrone.Core.Test.Framework
public abstract class DbTest : CoreTest
{
private ITestDatabase _db;
private DatabaseType _databaseType;
protected virtual MigrationType MigrationType => MigrationType.Main;
@@ -101,17 +106,39 @@ namespace NzbDrone.Core.Test.Framework
private IDatabase CreateDatabase(MigrationContext migrationContext)
{
if (_databaseType == DatabaseType.PostgreSQL)
{
CreatePostgresDb();
}
var factory = Mocker.Resolve<DbFactory>();
// If a special migration test or log migration then create new
if (migrationContext.BeforeMigration != null)
if (migrationContext.BeforeMigration != null || _databaseType == DatabaseType.PostgreSQL)
{
return factory.Create(migrationContext);
}
return CreateSqliteDatabase(factory, migrationContext);
}
private void CreatePostgresDb()
{
var options = Mocker.Resolve<IOptions<PostgresOptions>>().Value;
PostgresDatabase.Create(options, MigrationType);
}
private void DropPostgresDb()
{
var options = Mocker.Resolve<IOptions<PostgresOptions>>().Value;
PostgresDatabase.Drop(options, MigrationType);
}
private IDatabase CreateSqliteDatabase(IDbFactory factory, MigrationContext migrationContext)
{
// Otherwise try to use a cached migrated db
var cachedDb = GetCachedDatabase(migrationContext.MigrationType);
var testDb = GetTestDb(migrationContext.MigrationType);
var cachedDb = SqliteDatabase.GetCachedDb(migrationContext.MigrationType);
var testDb = GetTestSqliteDb(migrationContext.MigrationType);
if (File.Exists(cachedDb))
{
TestLogger.Info($"Using cached initial database {cachedDb}");
@@ -131,12 +158,7 @@ namespace NzbDrone.Core.Test.Framework
}
}
private string GetCachedDatabase(MigrationType type)
{
return Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_{type}.db");
}
private string GetTestDb(MigrationType type)
private string GetTestSqliteDb(MigrationType type)
{
return type == MigrationType.Main ? TestFolderInfo.GetDatabase() : TestFolderInfo.GetLogDatabase();
}
@@ -151,6 +173,13 @@ namespace NzbDrone.Core.Test.Framework
WithTempAsAppPath();
SetupLogging();
// populate the possible postgres options
var postgresOptions = PostgresDatabase.GetTestOptions();
_databaseType = postgresOptions.Host.IsNotNullOrWhiteSpace() ? DatabaseType.PostgreSQL : DatabaseType.SQLite;
// Set up remaining container services
Mocker.SetConstant(Options.Create(postgresOptions));
Mocker.SetConstant<IConfigFileProvider>(Mocker.Resolve<ConfigFileProvider>());
Mocker.SetConstant<IConnectionStringFactory>(Mocker.Resolve<ConnectionStringFactory>());
Mocker.SetConstant<IMigrationController>(Mocker.Resolve<MigrationController>());
@@ -170,12 +199,19 @@ namespace NzbDrone.Core.Test.Framework
// Make sure there are no lingering connections. (When this happens it means we haven't disposed something properly)
GC.Collect();
GC.WaitForPendingFinalizers();
SQLiteConnection.ClearAllPools();
NpgsqlConnection.ClearAllPools();
if (TestFolderInfo != null)
{
DeleteTempFolder(TestFolderInfo.AppDataFolder);
}
if (_databaseType == DatabaseType.PostgreSQL)
{
DropPostgresDb();
}
}
}
}

View File

@@ -1,5 +1,7 @@
using System.IO;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Test.Common.Datastore;
namespace NzbDrone.Core.Test
{
@@ -10,13 +12,13 @@ namespace NzbDrone.Core.Test
[OneTimeTearDown]
public void ClearCachedDatabase()
{
var mainCache = Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_Main.db");
var mainCache = SqliteDatabase.GetCachedDb(MigrationType.Main);
if (File.Exists(mainCache))
{
File.Delete(mainCache);
}
var logCache = Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_Log.db");
var logCache = SqliteDatabase.GetCachedDb(MigrationType.Log);
if (File.Exists(logCache))
{
File.Delete(logCache);

View File

@@ -23,6 +23,7 @@ namespace NzbDrone.Core.Test.Framework
where T : ModelBase, new();
IDirectDataMapper GetDirectDataMapper();
IDbConnection OpenConnection();
DatabaseType DatabaseType { get; }
}
public class TestDatabase : ITestDatabase
@@ -30,6 +31,8 @@ namespace NzbDrone.Core.Test.Framework
private readonly IDatabase _dbConnection;
private readonly IEventAggregator _eventAggregator;
public DatabaseType DatabaseType => _dbConnection.DatabaseType;
public TestDatabase(IDatabase dbConnection)
{
_eventAggregator = new Mock<IEventAggregator>().Object;

View File

@@ -32,16 +32,16 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
{
movie = Builder<Movie>.CreateListOfSize(amount)
.All()
.With(v => v.Status = MovieStatusType.Released)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released)
.BuildList();
}
else
{
movie = Builder<Movie>.CreateListOfSize(amount)
.All()
.With(v => v.Status = MovieStatusType.Released)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released)
.Random(deleted)
.With(v => v.Status = MovieStatusType.Deleted)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Deleted)
.BuildList();
}

View File

@@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_alternative_title_items()
{
var altTitle = Builder<AlternativeTitle>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.BuildNew();
@@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_alternative_title_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var altTitle = Builder<AlternativeTitle>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(altTitle);

View File

@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_credit_items()
{
var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit")
.BuildNew();
@@ -27,14 +27,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_credit_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit")
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(credit);

View File

@@ -0,0 +1,60 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Housekeeping.Housekeepers;
using NzbDrone.Core.ImportLists.ImportListMovies;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Translations;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
{
[TestFixture]
public class CleanupOrphanedMovieMetadataFixture : DbTest<CleanupOrphanedMovieMetadata, MovieMetadata>
{
[Test]
public void should_delete_orphaned_movie_metadata_items()
{
var metadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(metadata);
Subject.Clean();
AllStoredModels.Should().BeEmpty();
}
[Test]
public void should_not_delete_unorphaned_movie_metadata_items()
{
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movieMetadata);
var movie = Builder<Movie>.CreateNew()
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(movie);
Subject.Clean();
AllStoredModels.Should().HaveCount(1);
}
[Test]
public void should_not_delete_unorphaned_movie_metadata_items_for_lists()
{
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movieMetadata);
var movie = Builder<ImportListMovie>.CreateNew()
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(movie);
Subject.Clean();
AllStoredModels.Should().HaveCount(1);
}
}
}

View File

@@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_movie_translation_items()
{
var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.BuildNew();
@@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_movie_translation_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(translation);

View File

@@ -1,4 +1,4 @@
using FizzWare.NBuilder;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Housekeeping.Housekeepers;

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
@@ -41,7 +41,8 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
Subject.Clean();
AllStoredModels.ToList().ForEach(t => t.LastExecution.Should().Be(expectedTime));
// BeCloseTo handles Postgres rounding times
AllStoredModels.ToList().ForEach(t => t.LastExecution.Should().BeCloseTo(expectedTime));
}
}
}

View File

@@ -38,8 +38,8 @@ namespace NzbDrone.Core.Test.ImportListTests
.Build().ToList();
Mocker.GetMock<ISearchForNewMovie>()
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<Movie>()))
.Returns<Movie>(m => new Movie { TmdbId = m.TmdbId });
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<MovieMetadata>()))
.Returns<MovieMetadata>(m => new MovieMetadata { TmdbId = m.TmdbId });
}
private void GivenList(int id, bool enabled, bool enabledAuto, ImportListFetchResult fetchResult)

View File

@@ -0,0 +1,39 @@
using System.Linq;
using System.Text;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.ImportLists;
using NzbDrone.Core.ImportLists.Plex;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ImportList.Plex
{
[TestFixture]
public class PlexParserFixture : CoreTest<PlexParser>
{
private ImportListResponse CreateResponse(string url, string content)
{
var httpRequest = new HttpRequest(url);
var httpResponse = new HttpResponse(httpRequest, new HttpHeader(), Encoding.UTF8.GetBytes(content));
return new ImportListResponse(new ImportListRequest(httpRequest), httpResponse);
}
[Test]
public void should_parse_plex_watchlist()
{
var json = ReadAllText("Files/plex_watchlist.json");
var result = Subject.ParseResponse(CreateResponse("https://metadata.provider.plex.tv/library/sections/watchlist/all", json));
result.First().Title.Should().Be("Arrival");
result.First().Year.Should().Be(2016);
result.First().ImdbId.Should().Be("tt2543164");
result.First().TmdbId.Should().Be(0);
result[1].TmdbId.Should().Be(274854);
result[1].ImdbId.Should().Be("tt1618442");
}
}
}

View File

@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
.Returns(_movie);
Mocker.GetMock<IMovieTranslationService>()
.Setup(s => s.GetAllTranslationsForMovie(It.IsAny<int>()))
.Setup(s => s.GetAllTranslationsForMovieMetadata(It.IsAny<int>()))
.Returns(new List<MovieTranslation>());
}

View File

@@ -25,7 +25,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NyaaTests
};
}
[Test]
/* [Test]
// Legacy Nyaa feed test
public void should_parse_recent_feed_from_Nyaa()
{
var recentFeed = ReadAllText(@"Files/Indexers/Nyaa/Nyaa.xml");
@@ -53,6 +55,35 @@ namespace NzbDrone.Core.Test.IndexerTests.NyaaTests
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Peers.Should().Be(2 + 1);
torrentInfo.Seeders.Should().Be(1);
}*/
[Test]
public void should_parse_2021_recent_feed_from_Nyaa()
{
var recentFeed = ReadAllText(@"Files/Indexers/Nyaa/Nyaa2021.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(3);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("[Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("https://nyaa.si/download/1424896.torrent");
torrentInfo.InfoUrl.Should().Be("https://nyaa.si/view/1424896");
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("Tue, 24 Aug 2021 22:18:46"));
torrentInfo.Size.Should().Be(639211930); //609.6 MiB
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Seeders.Should().Be(4);
torrentInfo.Peers.Should().Be(3 + 4);
}
}
}

View File

@@ -27,7 +27,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
_movie = Builder<Movie>.CreateNew()
.With(v => v.Id = 2)
.With(v => v.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
.With(v => v.MovieMetadata.Value.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
.Build();
Mocker.GetMock<IMovieService>().Setup(m => m.GetMovie(It.Is<int>(id => id == _movie.Id))).Returns(_movie);

View File

@@ -255,7 +255,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);
@@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);
@@ -431,7 +431,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(new List<ImportResult>());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);

View File

@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
.With(m => m.OriginalLanguage = Language.English)
.With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English)
.Build();
_localMovie = Builder<LocalMovie>.CreateNew()
@@ -72,7 +72,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators
{
var result = Subject.Aggregate(_localMovie, null, false);
result.Languages.Should().Contain(_movie.OriginalLanguage);
result.Languages.Should().Contain(_movie.MovieMetadata.Value.OriginalLanguage);
}
[Test]

View File

@@ -16,20 +16,20 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
[TestFixture]
public class DetectSampleFixture : CoreTest<DetectSample>
{
private Movie _movie;
private MovieMetadata _movie;
private LocalMovie _localMovie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(s => s.Runtime = 30)
.Build();
_localMovie = new LocalMovie
{
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi",
Movie = _movie,
Movie = new Movie { MovieMetadata = _movie },
Quality = new QualityModel(Quality.HDTV720p)
};
}
@@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
{
GivenRuntime(120);
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path);
Mocker.GetMock<IVideoFileInfoReader>().Verify(v => v.GetRunTime(It.IsAny<string>()), Times.Once());
@@ -152,7 +152,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
.Setup(s => s.GetRunTime(It.IsAny<string>()))
.Returns((TimeSpan?)null);
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.Indeterminate);
ExceptionVerification.ExpectedErrors(1);
@@ -160,13 +160,13 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
private void ShouldBeSample()
{
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.Sample);
}
private void ShouldBeNotSample()
{
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.NotSample);
}
}

View File

@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
details.Title.Should().Be(title);
}
private void ValidateMovie(Movie movie)
private void ValidateMovie(MovieMetadata movie)
{
movie.Should().NotBeNull();
movie.Title.Should().NotBeNullOrWhiteSpace();
@@ -41,7 +41,6 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
movie.ImdbId.Should().NotBeNullOrWhiteSpace();
movie.Studio.Should().NotBeNullOrWhiteSpace();
movie.Runtime.Should().BeGreaterThan(0);
movie.TitleSlug.Should().NotBeNullOrWhiteSpace();
//series.TvRageId.Should().BeGreaterThan(0);
movie.TmdbId.Should().BeGreaterThan(0);

View File

@@ -20,14 +20,13 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class AddMovieFixture : CoreTest<AddMovieService>
{
private Movie _fakeMovie;
private MovieMetadata _fakeMovie;
[SetUp]
public void Setup()
{
_fakeMovie = Builder<Movie>
_fakeMovie = Builder<MovieMetadata>
.CreateNew()
.With(s => s.Path = null)
.Build();
}
@@ -35,7 +34,7 @@ namespace NzbDrone.Core.Test.MovieTests
{
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(tmdbId))
.Returns(new Tuple<Movie, List<Credit>>(_fakeMovie, new List<Credit>()));
.Returns(new Tuple<MovieMetadata, List<Credit>>(_fakeMovie, new List<Credit>()));
}
private void GivenValidPath()

View File

@@ -18,16 +18,17 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private AlternativeTitle _title2;
private AlternativeTitle _title3;
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
var titles = Builder<AlternativeTitle>.CreateListOfSize(3).All().With(t => t.MovieId = 0).Build();
var titles = Builder<AlternativeTitle>.CreateListOfSize(3).All().With(t => t.MovieMetadataId = 0).Build();
_title1 = titles[0];
_title2 = titles[1];
_title3 = titles[2];
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(m => m.CleanTitle = "myothertitle")
.With(m => m.Id = 1)
.Build();
@@ -35,7 +36,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private void GivenExistingTitles(params AlternativeTitle[] titles)
{
Mocker.GetMock<IAlternativeTitleRepository>().Setup(r => r.FindByMovieId(_movie.Id))
Mocker.GetMock<IAlternativeTitleRepository>().Setup(r => r.FindByMovieMetadataId(_movie.Id))
.Returns(titles.ToList());
}
@@ -72,7 +73,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
{
GivenExistingTitles();
var titles = new List<AlternativeTitle> { _title1 };
var movie = Builder<Movie>.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build();
var movie = Builder<MovieMetadata>.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build();
Subject.UpdateTitles(titles, movie);
@@ -87,8 +88,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
Subject.UpdateTitles(titles, _movie);
_title1.MovieId.Should().Be(_movie.Id);
_title2.MovieId.Should().Be(_movie.Id);
_title1.MovieMetadataId.Should().Be(_movie.Id);
_title2.MovieMetadataId.Should().Be(_movie.Id);
}
[Test]

View File

@@ -32,18 +32,18 @@ namespace NzbDrone.Core.Test.MovieTests.CreditTests
var credits = Builder<Credit>.CreateListOfSize(5)
.TheFirst(1)
.With(c => c.Id = 0)
.With(c => c.MovieId = _movie2.Id)
.With(c => c.MovieMetadataId = _movie2.Id)
.TheRest()
.With(c => c.Id = 0)
.With(c => c.MovieId = _movie1.Id)
.With(c => c.MovieMetadataId = _movie1.Id)
.BuildListOfNew();
Db.InsertMany(credits);
Subject.DeleteForMovies(new List<int> { _movie1.Id });
var removedMovieCredits = Subject.FindByMovieId(_movie1.Id);
var nonRemovedMovieCredits = Subject.FindByMovieId(_movie2.Id);
var removedMovieCredits = Subject.FindByMovieMetadataId(_movie1.Id);
var nonRemovedMovieCredits = Subject.FindByMovieMetadataId(_movie2.Id);
removedMovieCredits.Should().HaveCount(0);
nonRemovedMovieCredits.Should().HaveCount(1);

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
@@ -18,25 +18,25 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private Credit _credit2;
private Credit _credit3;
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
var credits = Builder<Credit>.CreateListOfSize(3)
.All()
.With(t => t.MovieId = 0).Build();
.With(t => t.MovieMetadataId = 0).Build();
_credit1 = credits[0];
_credit2 = credits[1];
_credit3 = credits[2];
_movie = Builder<Movie>.CreateNew().With(m => m.Id = 1).Build();
_movie = Builder<MovieMetadata>.CreateNew().With(m => m.Id = 1).Build();
}
private void GivenExistingCredits(params Credit[] credits)
{
Mocker.GetMock<ICreditRepository>().Setup(r => r.FindByMovieId(_movie.Id))
Mocker.GetMock<ICreditRepository>().Setup(r => r.FindByMovieMetadataId(_movie.Id))
.Returns(credits.ToList());
}
@@ -77,8 +77,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
Subject.UpdateCredits(titles, _movie);
_credit1.MovieId.Should().Be(_movie.Id);
_credit2.MovieId.Should().Be(_movie.Id);
_credit1.MovieMetadataId.Should().Be(_movie.Id);
_credit2.MovieMetadataId.Should().Be(_movie.Id);
}
[Test]

View File

@@ -21,9 +21,9 @@ namespace NzbDrone.Core.Test.MovieTests
private void SetMovieProperties(DateTime? cinema, DateTime? physical, DateTime? digital, MovieStatusType minimumAvailability)
{
_movie.InCinemas = cinema;
_movie.PhysicalRelease = physical;
_movie.DigitalRelease = digital;
_movie.MovieMetadata.Value.InCinemas = cinema;
_movie.MovieMetadata.Value.PhysicalRelease = physical;
_movie.MovieMetadata.Value.DigitalRelease = digital;
_movie.MinimumAvailability = minimumAvailability;
}

View File

@@ -0,0 +1,62 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.MovieTests.MovieMetadataRepositoryTests
{
[TestFixture]
public class MovieMetadataRepositoryFixture : DbTest<MovieMetadataRepository, MovieMetadata>
{
private MovieMetadataRepository _movieMetadataRepo;
private List<MovieMetadata> _metadataList;
[SetUp]
public void Setup()
{
_movieMetadataRepo = Mocker.Resolve<MovieMetadataRepository>();
_metadataList = Builder<MovieMetadata>.CreateListOfSize(10).All().With(x => x.Id = 0).BuildList();
}
[Test]
public void upsert_many_should_insert_list_of_new()
{
var updated = _movieMetadataRepo.UpsertMany(_metadataList);
AllStoredModels.Should().HaveCount(_metadataList.Count);
updated.Should().BeTrue();
}
[Test]
public void upsert_many_should_upsert_existing_with_id_0()
{
var clone = _metadataList.JsonClone();
var updated = _movieMetadataRepo.UpsertMany(clone);
updated.Should().BeTrue();
AllStoredModels.Should().HaveCount(_metadataList.Count);
updated = _movieMetadataRepo.UpsertMany(_metadataList);
updated.Should().BeFalse();
AllStoredModels.Should().HaveCount(_metadataList.Count);
}
[Test]
public void upsert_many_should_upsert_mixed_list_of_old_and_new()
{
var clone = _metadataList.Take(5).ToList().JsonClone();
var updated = _movieMetadataRepo.UpsertMany(clone);
updated.Should().BeTrue();
AllStoredModels.Should().HaveCount(clone.Count);
updated = _movieMetadataRepo.UpsertMany(_metadataList);
updated.Should().BeTrue();
AllStoredModels.Should().HaveCount(_metadataList.Count);
}
}
}

View File

@@ -19,15 +19,15 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
{
_candidates = Builder<Movie>.CreateListOfSize(3)
.TheFirst(1)
.With(x => x.CleanTitle = "batman")
.With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 2000)
.TheNext(1)
.With(x => x.CleanTitle = "batman")
.With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 1999)
.TheRest()
.With(x => x.CleanTitle = "darkknight")
.With(x => x.MovieMetadata.Value.CleanTitle = "darkknight")
.With(x => x.Year = 2008)
.With(x => x.AlternativeTitles = new List<AlternativeTitle>
.With(x => x.MovieMetadata.Value.AlternativeTitles = new List<AlternativeTitle>
{
new AlternativeTitle
{

View File

@@ -1,79 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MovieTests
{
[TestFixture]
public class MovieTitleSlugValidatorFixture : CoreTest<MovieTitleSlugValidator>
{
private List<Movie> _movies;
private TestValidator<Movie> _validator;
[SetUp]
public void Setup()
{
_movies = Builder<Movie>.CreateListOfSize(1)
.Build()
.ToList();
_validator = new TestValidator<Movie>
{
v => v.RuleFor(s => s.TitleSlug).SetValidator(Subject)
};
Mocker.GetMock<IMovieService>()
.Setup(s => s.AllMovieTitleSlugs())
.Returns(_movies.ToDictionary(m => m.Id, m => m.TitleSlug));
}
[Test]
public void should_not_be_valid_if_there_is_an_existing_movie_with_the_same_title_slug()
{
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(_movies.First().Id))
.Returns(_movies.First());
var movie = Builder<Movie>.CreateNew()
.With(s => s.Id = 100)
.With(s => s.TitleSlug = _movies.First().TitleSlug)
.Build();
_validator.Validate(movie).IsValid.Should().BeFalse();
}
[Test]
public void should_be_valid_if_there_is_not_an_existing_movie_with_the_same_title_slug()
{
var movie = Builder<Movie>.CreateNew()
.With(s => s.TitleSlug = "MyTitleSlug")
.Build();
_validator.Validate(movie).IsValid.Should().BeTrue();
}
[Test]
public void should_be_valid_if_there_is_an_existing_movie_with_a_null_title_slug()
{
_movies.First().TitleSlug = null;
var movie = Builder<Movie>.CreateNew()
.With(s => s.TitleSlug = "MyTitleSlug")
.Build();
_validator.Validate(movie).IsValid.Should().BeTrue();
}
[Test]
public void should_be_valid_when_updating_an_existing_movie()
{
_validator.Validate(_movies.First().JsonClone()).IsValid.Should().BeTrue();
}
}
}

View File

@@ -18,17 +18,26 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class RefreshMovieServiceFixture : CoreTest<RefreshMovieService>
{
private Movie _movie;
private MovieMetadata _movie;
private Movie _existingMovie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(s => s.Status = MovieStatusType.Released)
.Build();
_existingMovie = Builder<Movie>.CreateNew()
.With(s => s.MovieMetadata.Value.Status = MovieStatusType.Released)
.Build();
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(_movie.Id))
.Returns(_existingMovie);
Mocker.GetMock<IMovieMetadataService>()
.Setup(s => s.Get(_movie.Id))
.Returns(_movie);
Mocker.GetMock<IProvideMovieInfo>()
@@ -36,11 +45,11 @@ namespace NzbDrone.Core.Test.MovieTests
.Callback<int>((i) => { throw new MovieNotFoundException(i); });
}
private void GivenNewMovieInfo(Movie movie)
private void GivenNewMovieInfo(MovieMetadata movie)
{
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(_movie.TmdbId))
.Returns(new Tuple<Movie, List<Credit>>(movie, new List<Credit>()));
.Returns(new Tuple<MovieMetadata, List<Credit>>(movie, new List<Credit>()));
}
[Test]
@@ -53,8 +62,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().ImdbId == newMovieInfo.ImdbId), true));
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.ImdbId == newMovieInfo.ImdbId)));
}
[Test]
@@ -62,8 +71,8 @@ namespace NzbDrone.Core.Test.MovieTests
{
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1);
}
@@ -78,8 +87,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().TmdbId == newMovieInfo.TmdbId), true));
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.TmdbId == newMovieInfo.TmdbId)));
ExceptionVerification.ExpectedWarns(1);
}
@@ -89,8 +98,8 @@ namespace NzbDrone.Core.Test.MovieTests
{
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1);
}
@@ -102,8 +111,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.IsAny<Movie>()), Times.Never());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.IsAny<MovieMetadata>()), Times.Never());
ExceptionVerification.ExpectedErrors(1);
}

View File

@@ -10,12 +10,12 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class ShouldRefreshMovieFixture : TestBase<ShouldRefreshMovie>
{
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(v => v.Status = MovieStatusType.InCinemas)
.With(m => m.PhysicalRelease = DateTime.Today.AddDays(-100))
.Build();

View File

@@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
_movie = Builder<Movie>
.CreateNew()
.With(s => s.Title = "South Park")
.With(s => s.OriginalTitle = "South of the Park")
.With(s => s.MovieMetadata.Value.OriginalTitle = "South of the Park")
.Build();
_namingConfig = NamingConfig.Default;
@@ -70,7 +70,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.Returns(new List<CustomFormat>());
Mocker.GetMock<IMovieTranslationService>()
.Setup(v => v.GetAllTranslationsForMovie(It.IsAny<int>()))
.Setup(v => v.GetAllTranslationsForMovieMetadata(It.IsAny<int>()))
.Returns(_movieTranslations);
}
@@ -206,7 +206,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_original_title()
{
_namingConfig.StandardMovieFormat = "{Movie OriginalTitle}";
_movie.OriginalTitle = "South of the Park";
_movie.MovieMetadata.Value.OriginalTitle = "South of the Park";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South of the Park");
@@ -216,7 +216,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_certification()
{
_namingConfig.StandardMovieFormat = "{Movie Certification}";
_movie.Certification = "R";
_movie.MovieMetadata.Value.Certification = "R";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("R");
@@ -226,7 +226,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_collection()
{
_namingConfig.StandardMovieFormat = "{Movie Collection}";
_movie.Collection = new MovieCollection { Name = "South Part Collection" };
_movie.MovieMetadata.Value.Collection = new MovieCollection { Name = "South Part Collection" };
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South Part Collection");

View File

@@ -0,0 +1,29 @@
using System;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Augmenters;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
{
[TestFixture]
public class AugmentWithOriginalLanguageFixture : AugmentMovieInfoFixture<AugmentWithOriginalLanguage>
{
[Test]
public void should_add_movie_original_language()
{
var releaseInfo = new ParsedMovieInfo();
var movie = new Movies.Movie
{
MovieMetadata = new Movies.MovieMetadata
{
OriginalLanguage = Language.English
}
};
var result = Subject.AugmentMovieInfo(releaseInfo, movie);
result.ExtraInfo.Should().ContainKey("OriginalLanguage");
result.ExtraInfo["OriginalLanguage"].Should().Be(Language.English);
}
}
}

View File

@@ -36,11 +36,11 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
{
_movie = Builder<Movie>.CreateNew()
.With(m => m.Title = "Fack Ju Göthe 2")
.With(m => m.CleanTitle = "fackjugoethe2")
.With(m => m.MovieMetadata.Value.CleanTitle = "fackjugoethe2")
.With(m => m.Year = 2015)
.With(m => m.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
.With(m => m.Translations = new List<MovieTranslation> { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } })
.With(m => m.OriginalLanguage = Language.English)
.With(m => m.MovieMetadata.Value.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
.With(m => m.MovieMetadata.Value.Translations = new List<MovieTranslation> { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } })
.With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English)
.Build();
_parsedMovieInfo = new ParsedMovieInfo
@@ -66,14 +66,14 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
_alternativeTitleInfo = new ParsedMovieInfo
{
MovieTitles = new List<string> { _movie.AlternativeTitles.First().Title },
MovieTitles = new List<string> { _movie.MovieMetadata.Value.AlternativeTitles.First().Title },
Languages = new List<Language> { Language.English },
Year = _movie.Year,
};
_translationTitleInfo = new ParsedMovieInfo
{
MovieTitles = new List<string> { _movie.Translations.First().Title },
MovieTitles = new List<string> { _movie.MovieMetadata.Value.Translations.First().Title },
Languages = new List<Language> { Language.English },
Year = _movie.Year,
};

View File

@@ -99,6 +99,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Crappy Anime Movie Name 2017 [RH] [Blu-ray][MKV][h264 10-bit][1080p][FLAC 5.1][Dual Audio][Softsubs (RH)]", "RH")]
[TestCase("Yet Another Anime Movie 2012 [Kametsu] [Blu-ray][MKV][h264 10-bit][1080p][FLAC 5.1][Dual Audio][Softsubs (Kametsu)]", "Kametsu")]
[TestCase("Another.Anime.Film.Name.2016.JPN.Blu-Ray.Remux.AVC.DTS-MA.BluDragon", "BluDragon")]
[TestCase("A Movie in the Name (1964) (1080p BluRay x265 r00t)", "r00t")]
public void should_parse_exception_release_group(string title, string expected)
{
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);

View File

@@ -24,6 +24,7 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.GetLatestUpdate("develop", new Version(10, 0)).Should().BeNull();
}
[Ignore("Pending linux-x86 release")]
[Test]
public void finds_update_when_version_lower()
{
@@ -39,6 +40,7 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.GetLatestUpdate("invalid_branch", new Version(0, 2)).Should().NotBeNull();
}
[Ignore("Pending linux-x86 release")]
[Test]
public void should_get_recent_updates()
{

View File

@@ -190,9 +190,12 @@ namespace NzbDrone.Core.Backup
private void BackupDatabase()
{
_logger.ProgressDebug("Backing up database");
if (_maindDb.DatabaseType == DatabaseType.SQLite)
{
_logger.ProgressDebug("Backing up database");
_makeDatabaseBackup.BackupDatabase(_maindDb, _backupTempFolder);
_makeDatabaseBackup.BackupDatabase(_maindDb, _backupTempFolder);
}
}
private void BackupConfigFile()

View File

@@ -40,7 +40,7 @@ namespace NzbDrone.Core.Blocklisting
Delete(x => movieIds.Contains(x.MovieId));
}
protected override SqlBuilder PagedBuilder() => new SqlBuilder().Join<Blocklist, Movie>((b, m) => b.MovieId == m.Id);
protected override SqlBuilder PagedBuilder() => new SqlBuilder(_database.DatabaseType).Join<Blocklist, Movie>((b, m) => b.MovieId == m.Id);
protected override IEnumerable<Blocklist> PagedQuery(SqlBuilder sql) => _database.QueryJoined<Blocklist, Movie>(sql, (bl, movie) =>
{
bl.Movie = movie;

View File

@@ -5,12 +5,14 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Extensions.Options;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Authentication;
using NzbDrone.Core.Configuration.Events;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
@@ -19,7 +21,7 @@ using NzbDrone.Core.Update;
namespace NzbDrone.Core.Configuration
{
public interface IConfigFileProvider : IHandleAsync<ApplicationStartedEvent>,
IExecute<ResetApiKeyCommand>
IExecute<ResetApiKeyCommand>
{
XDocument LoadConfigFile();
Dictionary<string, object> GetConfigDictionary();
@@ -43,11 +45,19 @@ namespace NzbDrone.Core.Configuration
string SslCertPassword { get; }
string UrlBase { get; }
string UiFolder { get; }
string InstanceName { get; }
bool UpdateAutomatically { get; }
UpdateMechanism UpdateMechanism { get; }
string UpdateScriptPath { get; }
string SyslogServer { get; }
int SyslogPort { get; }
string SyslogLevel { get; }
string PostgresHost { get; }
int PostgresPort { get; }
string PostgresUser { get; }
string PostgresPassword { get; }
string PostgresMainDb { get; }
string PostgresLogDb { get; }
}
public class ConfigFileProvider : IConfigFileProvider
@@ -57,6 +67,7 @@ namespace NzbDrone.Core.Configuration
private readonly IEventAggregator _eventAggregator;
private readonly IDiskProvider _diskProvider;
private readonly ICached<string> _cache;
private readonly PostgresOptions _postgresOptions;
private readonly string _configFile;
private static readonly Regex HiddenCharacterRegex = new Regex("[^a-z0-9]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@@ -66,12 +77,14 @@ namespace NzbDrone.Core.Configuration
public ConfigFileProvider(IAppFolderInfo appFolderInfo,
ICacheManager cacheManager,
IEventAggregator eventAggregator,
IDiskProvider diskProvider)
IDiskProvider diskProvider,
IOptions<PostgresOptions> postgresOptions)
{
_cache = cacheManager.GetCache<string>(GetType());
_eventAggregator = eventAggregator;
_diskProvider = diskProvider;
_configFile = appFolderInfo.GetConfigPath();
_postgresOptions = postgresOptions.Value;
}
public Dictionary<string, object> GetConfigDictionary()
@@ -184,6 +197,12 @@ namespace NzbDrone.Core.Configuration
public string LogLevel => GetValue("LogLevel", "info").ToLowerInvariant();
public string ConsoleLogLevel => GetValue("ConsoleLogLevel", string.Empty, persist: false);
public string PostgresHost => _postgresOptions?.Host ?? GetValue("PostgresHost", string.Empty, persist: false);
public string PostgresUser => _postgresOptions?.User ?? GetValue("PostgresUser", string.Empty, persist: false);
public string PostgresPassword => _postgresOptions?.Password ?? GetValue("PostgresPassword", string.Empty, persist: false);
public string PostgresMainDb => _postgresOptions?.MainDb ?? GetValue("PostgresMainDb", "radarr-main", persist: false);
public string PostgresLogDb => _postgresOptions?.LogDb ?? GetValue("PostgresLogDb", "radarr-log", persist: false);
public int PostgresPort => (_postgresOptions?.Port ?? 0) != 0 ? _postgresOptions.Port : GetValueInt("PostgresPort", 5432, persist: false);
public bool LogSql => GetValueBoolean("LogSql", false, persist: false);
public int LogRotate => GetValueInt("LogRotate", 50, persist: false);
public bool FilterSentryEvents => GetValueBoolean("FilterSentryEvents", true, persist: false);
@@ -206,6 +225,7 @@ namespace NzbDrone.Core.Configuration
}
public string UiFolder => BuildInfo.IsDebug ? Path.Combine("..", "UI") : "UI";
public string InstanceName => GetValue("InstanceName", BuildInfo.AppName);
public bool UpdateAutomatically => GetValueBoolean("UpdateAutomatically", false, false);
@@ -214,8 +234,11 @@ namespace NzbDrone.Core.Configuration
public string UpdateScriptPath => GetValue("UpdateScriptPath", "", false);
public string SyslogServer => GetValue("SyslogServer", "", persist: false);
public int SyslogPort => GetValueInt("SyslogPort", 514, persist: false);
public string SyslogLevel => GetValue("SyslogLevel", LogLevel, false).ToLowerInvariant();
public int GetValueInt(string key, int defaultValue, bool persist = true)
{
return Convert.ToInt32(GetValue(key, defaultValue, persist));

View File

@@ -14,7 +14,7 @@ namespace NzbDrone.Core.CustomFormats
{
public interface ICustomFormatCalculationService
{
List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo);
List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo, Movie movie);
List<CustomFormat> ParseCustomFormat(MovieFile movieFile);
List<CustomFormat> ParseCustomFormat(Blocklist blocklist);
List<CustomFormat> ParseCustomFormat(MovieHistory history);
@@ -76,27 +76,29 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movieFile.Movie.Title },
MovieTitles = new List<string>() { movieFile.Movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = sceneName.SimplifyReleaseTitle(),
Quality = movieFile.Quality,
Languages = movieFile.Languages,
ReleaseGroup = movieFile.ReleaseGroup,
Edition = movieFile.Edition,
Year = movieFile.Movie.Year,
ImdbId = movieFile.Movie.ImdbId,
Year = movieFile.Movie.MovieMetadata.Value.Year,
ImdbId = movieFile.Movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", movieFile.IndexerFlags },
{ "Size", movieFile.Size },
{ "Filename", System.IO.Path.GetFileName(movieFile.RelativePath) }
{ "Filename", Path.GetFileName(movieFile.RelativePath) },
{ "OriginalLanguage", movieFile.Movie.MovieMetadata.Value.OriginalLanguage }
}
};
return ParseCustomFormat(info, allCustomFormats);
}
public List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo)
public List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo, Movie movie)
{
movieInfo = _parsingService.EnhanceMovieInfo(movieInfo, new List<object> { movie }) ?? movieInfo;
return ParseCustomFormat(movieInfo, _formatService.All());
}
@@ -112,14 +114,14 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(),
Quality = blocklist.Quality,
Languages = blocklist.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.Year,
ImdbId = movie.ImdbId,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", blocklist.IndexerFlags },
@@ -127,7 +129,7 @@ namespace NzbDrone.Core.CustomFormats
}
};
return ParseCustomFormat(info);
return ParseCustomFormat(info, movie);
}
public List<CustomFormat> ParseCustomFormat(MovieHistory history)
@@ -140,14 +142,14 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(),
Quality = history.Quality,
Languages = history.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.Year,
ImdbId = movie.ImdbId,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", flags },
@@ -155,7 +157,7 @@ namespace NzbDrone.Core.CustomFormats
}
};
return ParseCustomFormat(info);
return ParseCustomFormat(info, movie);
}
}
}

View File

@@ -14,7 +14,10 @@ namespace NzbDrone.Core.CustomFormats
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
{
return movieInfo?.Languages?.Contains((Language)Value) ?? false;
var comparedLanguage = movieInfo != null && Name == "Original" && movieInfo.ExtraInfo.ContainsKey("OriginalLanguage")
? (Language)movieInfo.ExtraInfo["OriginalLanguage"]
: (Language)Value;
return movieInfo?.Languages?.Contains(comparedLanguage) ?? false;
}
}
}

View File

@@ -67,7 +67,7 @@ namespace NzbDrone.Core.Datastore
_updateSql = GetUpdateSql(_properties);
}
protected virtual SqlBuilder Builder() => new SqlBuilder();
protected virtual SqlBuilder Builder() => new SqlBuilder(_database.DatabaseType);
protected virtual List<TModel> Query(SqlBuilder builder) => _database.Query<TModel>(builder).ToList();
@@ -79,7 +79,7 @@ namespace NzbDrone.Core.Datastore
{
using (var conn = _database.OpenConnection())
{
return conn.ExecuteScalar<int>($"SELECT COUNT(*) FROM {_table}");
return conn.ExecuteScalar<int>($"SELECT COUNT(*) FROM \"{_table}\"");
}
}
@@ -175,6 +175,11 @@ namespace NzbDrone.Core.Datastore
}
}
if (_database.DatabaseType == DatabaseType.PostgreSQL)
{
return $"INSERT INTO \"{_table}\" ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}) RETURNING \"Id\"";
}
return $"INSERT INTO {_table} ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}); SELECT last_insert_rowid() id";
}
@@ -182,7 +187,8 @@ namespace NzbDrone.Core.Datastore
{
SqlBuilderExtensions.LogQuery(_insertSql, model);
var multi = connection.QueryMultiple(_insertSql, model, transaction);
var id = (int)multi.Read().First().id;
var multiRead = multi.Read();
var id = (int)(multiRead.First().id ?? multiRead.First().Id);
_keyProperty.SetValue(model, id);
return model;
@@ -293,7 +299,7 @@ namespace NzbDrone.Core.Datastore
{
using (var conn = _database.OpenConnection())
{
conn.Execute($"DELETE FROM [{_table}]");
conn.Execute($"DELETE FROM \"{_table}\"");
}
if (vacuum)
@@ -352,7 +358,7 @@ namespace NzbDrone.Core.Datastore
private string GetUpdateSql(List<PropertyInfo> propertiesToUpdate)
{
var sb = new StringBuilder();
sb.AppendFormat("UPDATE {0} SET ", _table);
sb.AppendFormat("UPDATE \"{0}\" SET ", _table);
for (var i = 0; i < propertiesToUpdate.Count; i++)
{
@@ -420,9 +426,10 @@ namespace NzbDrone.Core.Datastore
pagingSpec.SortKey = $"{_table}.{_keyProperty.Name}";
}
var sortKey = TableMapping.Mapper.GetSortKey(pagingSpec.SortKey);
var sortDirection = pagingSpec.SortDirection == SortDirection.Descending ? "DESC" : "ASC";
var pagingOffset = (pagingSpec.Page - 1) * pagingSpec.PageSize;
builder.OrderBy($"{pagingSpec.SortKey} {sortDirection} LIMIT {pagingSpec.PageSize} OFFSET {pagingOffset}");
var pagingOffset = Math.Max(pagingSpec.Page - 1, 0) * pagingSpec.PageSize;
builder.OrderBy($"\"{sortKey}\" {sortDirection} LIMIT {pagingSpec.PageSize} OFFSET {pagingOffset}");
return queryFunc(builder).ToList();
}

View File

@@ -1,7 +1,9 @@
using System;
using System.Data.SQLite;
using Npgsql;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.Datastore
{
@@ -14,10 +16,17 @@ namespace NzbDrone.Core.Datastore
public class ConnectionStringFactory : IConnectionStringFactory
{
public ConnectionStringFactory(IAppFolderInfo appFolderInfo)
private readonly IConfigFileProvider _configFileProvider;
public ConnectionStringFactory(IAppFolderInfo appFolderInfo, IConfigFileProvider configFileProvider)
{
MainDbConnectionString = GetConnectionString(appFolderInfo.GetDatabase());
LogDbConnectionString = GetConnectionString(appFolderInfo.GetLogDatabase());
_configFileProvider = configFileProvider;
MainDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) :
GetConnectionString(appFolderInfo.GetDatabase());
LogDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) :
GetConnectionString(appFolderInfo.GetLogDatabase());
}
public string MainDbConnectionString { get; private set; }
@@ -48,5 +57,19 @@ namespace NzbDrone.Core.Datastore
return connectionBuilder.ConnectionString;
}
private string GetPostgresConnectionString(string dbName)
{
var connectionBuilder = new NpgsqlConnectionStringBuilder();
connectionBuilder.Database = dbName;
connectionBuilder.Host = _configFileProvider.PostgresHost;
connectionBuilder.Username = _configFileProvider.PostgresUser;
connectionBuilder.Password = _configFileProvider.PostgresPassword;
connectionBuilder.Port = _configFileProvider.PostgresPort;
connectionBuilder.Enlist = false;
return connectionBuilder.ConnectionString;
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Data;
using System.Text.RegularExpressions;
using Dapper;
using NLog;
using NzbDrone.Common.Instrumentation;
@@ -11,6 +12,7 @@ namespace NzbDrone.Core.Datastore
IDbConnection OpenConnection();
Version Version { get; }
int Migration { get; }
DatabaseType DatabaseType { get; }
void Vacuum();
}
@@ -32,13 +34,44 @@ namespace NzbDrone.Core.Datastore
return _datamapperFactory();
}
public DatabaseType DatabaseType
{
get
{
using (var db = _datamapperFactory())
{
if (db.ConnectionString.Contains(".db"))
{
return DatabaseType.SQLite;
}
else
{
return DatabaseType.PostgreSQL;
}
}
}
}
public Version Version
{
get
{
using (var db = _datamapperFactory())
{
var version = db.QueryFirstOrDefault<string>("SELECT sqlite_version()");
string version;
try
{
version = db.QueryFirstOrDefault<string>("SHOW server_version");
//Postgres can return extra info about operating system on version call, ignore this
version = Regex.Replace(version, @"\(.*?\)", "");
}
catch
{
version = db.QueryFirstOrDefault<string>("SELECT sqlite_version()");
}
return new Version(version);
}
}
@@ -50,7 +83,7 @@ namespace NzbDrone.Core.Datastore
{
using (var db = _datamapperFactory())
{
return db.QueryFirstOrDefault<int>("SELECT version from VersionInfo ORDER BY version DESC LIMIT 1");
return db.QueryFirstOrDefault<int>("SELECT \"Version\" from \"VersionInfo\" ORDER BY \"Version\" DESC LIMIT 1");
}
}
}
@@ -73,4 +106,10 @@ namespace NzbDrone.Core.Datastore
}
}
}
public enum DatabaseType
{
SQLite,
PostgreSQL
}
}

View File

@@ -1,6 +1,8 @@
using System;
using System.Data.Common;
using System.Data.SQLite;
using NLog;
using Npgsql;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Exceptions;
@@ -85,10 +87,19 @@ namespace NzbDrone.Core.Datastore
var db = new Database(migrationContext.MigrationType.ToString(), () =>
{
var conn = SQLiteFactory.Instance.CreateConnection();
conn.ConnectionString = connectionString;
conn.Open();
DbConnection conn;
if (connectionString.Contains(".db"))
{
conn = SQLiteFactory.Instance.CreateConnection();
conn.ConnectionString = connectionString;
}
else
{
conn = new NpgsqlConnection(connectionString);
}
conn.Open();
return conn;
});

View File

@@ -20,7 +20,7 @@ namespace NzbDrone.Core.Datastore
public static SqlBuilder Select(this SqlBuilder builder, params Type[] types)
{
return builder.Select(types.Select(x => TableMapping.Mapper.TableNameMapping(x) + ".*").Join(", "));
return builder.Select(types.Select(x => $"\"{TableMapping.Mapper.TableNameMapping(x)}\".*").Join(", "));
}
public static SqlBuilder SelectDistinct(this SqlBuilder builder, params Type[] types)
@@ -42,41 +42,41 @@ namespace NzbDrone.Core.Datastore
public static SqlBuilder Where<TModel>(this SqlBuilder builder, Expression<Func<TModel, bool>> filter)
{
var wb = new WhereBuilder(filter, true, builder.Sequence);
var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence);
return builder.Where(wb.ToString(), wb.Parameters);
}
public static SqlBuilder OrWhere<TModel>(this SqlBuilder builder, Expression<Func<TModel, bool>> filter)
{
var wb = new WhereBuilder(filter, true, builder.Sequence);
var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence);
return builder.OrWhere(wb.ToString(), wb.Parameters);
}
public static SqlBuilder Join<TLeft, TRight>(this SqlBuilder builder, Expression<Func<TLeft, TRight, bool>> filter)
{
var wb = new WhereBuilder(filter, false, builder.Sequence);
var wb = GetWhereBuilder(builder.DatabaseType, filter, false, builder.Sequence);
var rightTable = TableMapping.Mapper.TableNameMapping(typeof(TRight));
return builder.Join($"{rightTable} ON {wb.ToString()}");
return builder.Join($"\"{rightTable}\" ON {wb.ToString()}");
}
public static SqlBuilder LeftJoin<TLeft, TRight>(this SqlBuilder builder, Expression<Func<TLeft, TRight, bool>> filter)
{
var wb = new WhereBuilder(filter, false, builder.Sequence);
var wb = GetWhereBuilder(builder.DatabaseType, filter, false, builder.Sequence);
var rightTable = TableMapping.Mapper.TableNameMapping(typeof(TRight));
return builder.LeftJoin($"{rightTable} ON {wb.ToString()}");
return builder.LeftJoin($"\"{rightTable}\" ON {wb.ToString()}");
}
public static SqlBuilder GroupBy<TModel>(this SqlBuilder builder, Expression<Func<TModel, object>> property)
{
var table = TableMapping.Mapper.TableNameMapping(typeof(TModel));
var propName = property.GetMemberName().Name;
return builder.GroupBy($"{table}.{propName}");
return builder.GroupBy($"\"{table}\".\"{propName}\"");
}
public static SqlBuilder.Template AddSelectTemplate(this SqlBuilder builder, Type type)
@@ -138,6 +138,18 @@ namespace NzbDrone.Core.Datastore
return sb.ToString();
}
private static WhereBuilder GetWhereBuilder(DatabaseType databaseType, Expression filter, bool requireConcrete, int seq)
{
if (databaseType == DatabaseType.PostgreSQL)
{
return new WhereBuilderPostgres(filter, requireConcrete, seq);
}
else
{
return new WhereBuilderSqlite(filter, requireConcrete, seq);
}
}
private static Dictionary<string, object> ToDictionary(this DynamicParameters dynamicParams)
{
var argsDictionary = new Dictionary<string, object>();

View File

@@ -10,10 +10,12 @@ namespace NzbDrone.Core.Datastore
public class LogDatabase : ILogDatabase
{
private readonly IDatabase _database;
private readonly DatabaseType _databaseType;
public LogDatabase(IDatabase database)
{
_database = database;
_databaseType = _database == null ? DatabaseType.SQLite : _database.DatabaseType;
}
public IDbConnection OpenConnection()
@@ -25,6 +27,8 @@ namespace NzbDrone.Core.Datastore
public int Migration => _database.Migration;
public DatabaseType DatabaseType => _databaseType;
public void Vacuum()
{
_database.Vacuum();

View File

@@ -10,10 +10,12 @@ namespace NzbDrone.Core.Datastore
public class MainDatabase : IMainDatabase
{
private readonly IDatabase _database;
private readonly DatabaseType _databaseType;
public MainDatabase(IDatabase database)
{
_database = database;
_databaseType = _database == null ? DatabaseType.SQLite : _database.DatabaseType;
}
public IDbConnection OpenConnection()
@@ -25,6 +27,8 @@ namespace NzbDrone.Core.Datastore
public int Migration => _database.Migration;
public DatabaseType DatabaseType => _databaseType;
public void Vacuum()
{
_database.Vacuum();

View File

@@ -144,7 +144,7 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("Items").AsString().NotNullable()
.WithColumn("Language").AsInt32().Nullable();
Execute.Sql("UPDATE Profiles SET Language = 1");
Execute.Sql("UPDATE \"Profiles\" SET \"Language\" = 1");
Create.TableForModel("SceneMappings")
.WithColumn("TvdbId").AsInt32()
@@ -243,8 +243,8 @@ namespace NzbDrone.Core.Datastore.Migration
Insert.IntoTable("DelayProfiles").Row(new
{
EnableUsenet = 1,
EnableTorrent = 1,
EnableUsenet = true,
EnableTorrent = true,
PreferredProtocol = 1,
UsenetDelay = 0,
TorrentDelay = 0,

View File

@@ -9,7 +9,7 @@ namespace NzbDrone.Core.Datastore.Migration
protected override void MainDbUpgrade()
{
Alter.Table("ScheduledTasks").AlterColumn("Interval").AsDouble();
Execute.Sql("UPDATE ScheduledTasks SET Interval=0.25 WHERE TypeName='NzbDrone.Core.Download.CheckForFinishedDownloadCommand'");
Execute.Sql("UPDATE \"ScheduledTasks\" SET \"Interval\" = 0.25 WHERE \"TypeName\" = 'NzbDrone.Core.Download.CheckForFinishedDownloadCommand'");
}
}
}

Some files were not shown because too many files have changed in this diff Show More