2017-09-27 02:06:05 +00:00
using System ;
2019-09-13 12:23:01 +00:00
using System.Collections.Generic ;
2022-01-26 00:08:27 +00:00
using System.Collections.Specialized ;
2013-08-14 03:22:28 +00:00
using System.Diagnostics ;
using System.IO ;
using System.Threading ;
2013-09-21 02:07:42 +00:00
using System.Xml.Linq ;
2014-12-17 07:12:26 +00:00
using NLog ;
2013-08-14 03:22:28 +00:00
using NUnit.Framework ;
using NzbDrone.Common.EnvironmentInfo ;
2019-09-13 12:23:01 +00:00
using NzbDrone.Common.Extensions ;
2013-09-20 23:56:17 +00:00
using NzbDrone.Common.Processes ;
2022-01-26 00:08:27 +00:00
using NzbDrone.Common.Serializer ;
2019-08-22 20:15:25 +00:00
using NzbDrone.Core.Configuration ;
2022-01-26 00:08:27 +00:00
using NzbDrone.Core.Datastore ;
2013-08-14 03:22:28 +00:00
using RestSharp ;
2013-11-12 03:25:54 +00:00
namespace NzbDrone.Test.Common
2013-08-14 03:22:28 +00:00
{
public class NzbDroneRunner
{
private readonly IProcessProvider _processProvider ;
private readonly IRestClient _restClient ;
private Process _nzbDroneProcess ;
2019-09-13 12:23:01 +00:00
private List < string > _startupLog ;
2013-08-14 03:22:28 +00:00
2013-09-21 02:07:42 +00:00
public string AppData { get ; private set ; }
public string ApiKey { get ; private set ; }
2022-01-26 00:08:27 +00:00
public PostgresOptions PostgresOptions { get ; private set ; }
2020-08-15 13:18:51 +00:00
public int Port { get ; private set ; }
2013-09-21 02:07:42 +00:00
2022-01-26 00:08:27 +00:00
public NzbDroneRunner ( Logger logger , PostgresOptions postgresOptions , int port = 8686 )
2013-08-14 03:22:28 +00:00
{
2014-12-17 07:12:26 +00:00
_processProvider = new ProcessProvider ( logger ) ;
2020-08-15 13:18:51 +00:00
_restClient = new RestClient ( $"http://localhost:{port}/api/v1" ) ;
2022-01-26 00:08:27 +00:00
PostgresOptions = postgresOptions ;
2020-08-15 13:18:51 +00:00
Port = port ;
2013-08-14 03:22:28 +00:00
}
public void Start ( )
{
2019-08-22 20:15:25 +00:00
AppData = Path . Combine ( TestContext . CurrentContext . TestDirectory , "_intg_" + TestBase . GetUID ( ) ) ;
Directory . CreateDirectory ( AppData ) ;
2013-08-14 03:22:28 +00:00
2019-08-22 20:15:25 +00:00
GenerateConfigFile ( ) ;
2019-10-28 21:30:08 +00:00
string lidarrConsoleExe ;
if ( OsInfo . IsWindows )
{
lidarrConsoleExe = "Lidarr.Console.exe" ;
}
else
{
lidarrConsoleExe = "Lidarr" ;
}
2013-08-26 19:35:53 +00:00
2019-09-13 12:23:01 +00:00
_startupLog = new List < string > ( ) ;
2013-08-14 03:22:28 +00:00
if ( BuildInfo . IsDebug )
{
2021-12-24 17:40:37 +00:00
Start ( Path . Combine ( TestContext . CurrentContext . TestDirectory , ".." , ".." , "_output" , "net6.0" , lidarrConsoleExe ) ) ;
2013-08-14 03:22:28 +00:00
}
else
{
2019-10-28 21:30:08 +00:00
Start ( Path . Combine ( TestContext . CurrentContext . TestDirectory , ".." , "bin" , lidarrConsoleExe ) ) ;
2013-08-14 03:22:28 +00:00
}
while ( true )
{
_nzbDroneProcess . Refresh ( ) ;
if ( _nzbDroneProcess . HasExited )
{
2019-09-13 21:41:42 +00:00
TestContext . Progress . WriteLine ( "Lidarr has exited unexpectedly" ) ;
2019-09-13 12:23:01 +00:00
Thread . Sleep ( 2000 ) ;
2019-09-13 12:23:01 +00:00
var output = _startupLog . Join ( Environment . NewLine ) ;
Assert . Fail ( "Process has exited: ExitCode={0} Output={1}" , _nzbDroneProcess . ExitCode , output ) ;
2013-08-14 03:22:28 +00:00
}
2013-09-21 02:07:42 +00:00
var request = new RestRequest ( "system/status" ) ;
request . AddHeader ( "Authorization" , ApiKey ) ;
2015-10-01 20:53:55 +00:00
request . AddHeader ( "X-Api-Key" , ApiKey ) ;
2013-08-28 23:14:31 +00:00
2013-09-21 02:07:42 +00:00
var statusCall = _restClient . Get ( request ) ;
2013-08-28 23:14:31 +00:00
if ( statusCall . ResponseStatus = = ResponseStatus . Completed )
2013-08-14 03:22:28 +00:00
{
2019-09-13 12:23:01 +00:00
_startupLog = null ;
2020-08-15 13:18:51 +00:00
TestContext . Progress . WriteLine ( $"Lidarr {Port} is started. Running Tests" ) ;
2013-08-14 03:22:28 +00:00
return ;
}
2019-09-13 21:41:42 +00:00
TestContext . Progress . WriteLine ( "Waiting for Lidarr to start. Response Status : {0} [{1}] {2}" , statusCall . ResponseStatus , statusCall . StatusDescription , statusCall . ErrorException . Message ) ;
2013-08-28 23:14:31 +00:00
2013-08-14 03:22:28 +00:00
Thread . Sleep ( 500 ) ;
}
}
2020-08-15 13:18:51 +00:00
public void Kill ( )
{
try
{
if ( _nzbDroneProcess ! = null )
{
2020-08-16 02:45:12 +00:00
_nzbDroneProcess . Refresh ( ) ;
if ( _nzbDroneProcess . HasExited )
{
2023-05-30 01:38:45 +00:00
var log = File . ReadAllLines ( Path . Combine ( AppData , "logs" , "lidarr.trace.txt" ) ) ;
2020-08-16 02:45:12 +00:00
var output = log . Join ( Environment . NewLine ) ;
TestContext . Progress . WriteLine ( "Process has exited prematurely: ExitCode={0} Output:\n{1}" , _nzbDroneProcess . ExitCode , output ) ;
}
2020-08-15 13:18:51 +00:00
_processProvider . Kill ( _nzbDroneProcess . Id ) ;
}
}
catch ( InvalidOperationException )
{
// May happen if the process closes while being closed
}
TestBase . DeleteTempFolder ( AppData ) ;
}
2013-08-14 03:22:28 +00:00
public void KillAll ( )
{
2019-08-22 20:15:25 +00:00
try
{
if ( _nzbDroneProcess ! = null )
{
_processProvider . Kill ( _nzbDroneProcess . Id ) ;
}
_processProvider . KillAll ( ProcessProvider . LIDARR_CONSOLE_PROCESS_NAME ) ;
_processProvider . KillAll ( ProcessProvider . LIDARR_PROCESS_NAME ) ;
}
catch ( InvalidOperationException )
2015-10-01 20:52:33 +00:00
{
2019-08-22 20:15:25 +00:00
// May happen if the process closes while being closed
2015-10-01 20:52:33 +00:00
}
2019-08-22 20:15:25 +00:00
TestBase . DeleteTempFolder ( AppData ) ;
2013-08-14 03:22:28 +00:00
}
2022-01-26 00:08:27 +00:00
private void Start ( string outputLidarrConsoleExe )
2013-08-14 03:22:28 +00:00
{
2022-01-26 00:08:27 +00:00
StringDictionary envVars = new ( ) ;
if ( PostgresOptions ? . Host ! = null )
{
envVars . Add ( "Lidarr__Postgres__Host" , PostgresOptions . Host ) ;
envVars . Add ( "Lidarr__Postgres__Port" , PostgresOptions . Port . ToString ( ) ) ;
envVars . Add ( "Lidarr__Postgres__User" , PostgresOptions . User ) ;
envVars . Add ( "Lidarr__Postgres__Password" , PostgresOptions . Password ) ;
envVars . Add ( "Lidarr__Postgres__MainDb" , PostgresOptions . MainDb ) ;
envVars . Add ( "Lidarr__Postgres__LogDb" , PostgresOptions . LogDb ) ;
TestContext . Progress . WriteLine ( "Using env vars:\n{0}" , envVars . ToJson ( ) ) ;
}
TestContext . Progress . WriteLine ( "Starting instance from {0} on port {1}" , outputLidarrConsoleExe , Port ) ;
2019-09-13 12:23:01 +00:00
2020-08-16 20:49:46 +00:00
var args = "-nobrowser -nosingleinstancecheck -data=\"" + AppData + "\"" ;
2022-01-26 00:08:27 +00:00
_nzbDroneProcess = _processProvider . Start ( outputLidarrConsoleExe , args , envVars , OnOutputDataReceived , OnOutputDataReceived ) ;
2013-08-14 03:22:28 +00:00
}
private void OnOutputDataReceived ( string data )
{
2020-08-15 13:18:51 +00:00
TestContext . Progress . WriteLine ( $" [{Port}] > " + data ) ;
2019-09-13 12:23:01 +00:00
2019-09-13 12:23:01 +00:00
if ( _startupLog ! = null )
{
_startupLog . Add ( data ) ;
}
2013-08-14 03:22:28 +00:00
if ( data . Contains ( "Press enter to exit" ) )
{
_nzbDroneProcess . StandardInput . WriteLine ( " " ) ;
}
}
2019-08-22 20:15:25 +00:00
private void GenerateConfigFile ( )
2013-09-21 02:07:42 +00:00
{
var configFile = Path . Combine ( AppData , "config.xml" ) ;
2019-08-22 20:15:25 +00:00
// Generate and set the api key so we don't have to poll the config file
var apiKey = Guid . NewGuid ( ) . ToString ( ) . Replace ( "-" , "" ) ;
2014-02-27 17:03:37 +00:00
2019-08-22 20:15:25 +00:00
var xDoc = new XDocument (
2020-01-03 12:49:24 +00:00
new XDeclaration ( "1.0" , "utf-8" , "yes" ) ,
2019-08-22 20:15:25 +00:00
new XElement ( ConfigFileProvider . CONFIG_ELEMENT_NAME ,
new XElement ( nameof ( ConfigFileProvider . ApiKey ) , apiKey ) ,
2020-08-16 02:45:12 +00:00
new XElement ( nameof ( ConfigFileProvider . LogLevel ) , "trace" ) ,
2020-08-15 13:18:51 +00:00
new XElement ( nameof ( ConfigFileProvider . AnalyticsEnabled ) , false ) ,
new XElement ( nameof ( ConfigFileProvider . Port ) , Port ) ) ) ;
2019-08-22 20:15:25 +00:00
var data = xDoc . ToString ( ) ;
File . WriteAllText ( configFile , data ) ;
ApiKey = apiKey ;
2013-09-21 02:07:42 +00:00
}
2013-08-14 03:22:28 +00:00
}
2017-09-27 02:06:05 +00:00
}