Merge branch 'develop'

This commit is contained in:
Mark McDowall 2014-03-07 23:54:11 -08:00
commit 42501b73a1
191 changed files with 3484 additions and 971 deletions

View File

@ -1,6 +1,7 @@
$msBuild = 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe'
$outputFolder = '.\_output'
$outputFolderMono = '.\_output_mono'
$outputFolderOsx = '.\_output_osx'
$testPackageFolder = '.\_tests\'
$testSearchPattern = '*.Test\bin\x86\Release'
$sourceFolder = '.\src'
@ -112,6 +113,23 @@ Function PackageMono()
Write-Host "##teamcity[progressFinish 'Creating Mono Package']"
}
Function PackageOsx()
{
Write-Host "##teamcity[progressStart 'Creating OS X Package']"
if(Test-Path $outputFolderOsx)
{
Remove-Item -Recurse -Force $outputFolderMono -ErrorAction Continue
}
Copy-Item $outputFolderMono $outputFolderOsx -recurse
Write-Host "Adding sqlite dylibs"
Copy-Item "$sourceFolder\Libraries\sqlite\*.dylib" "$outputFolderOsx"
Write-Host "##teamcity[progressFinish 'Creating OS X Package']"
}
Function AddJsonNet()
{
get-childitem $outputFolder -File -Filter Newtonsoft.Json.* -Recurse | foreach ($_) {remove-item $_.fullname}
@ -187,5 +205,6 @@ Function CleanupWindowsPackage()
Build
RunGrunt
PackageMono
PackageOsx
PackageTests
CleanupWindowsPackage

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B1784698-592E-4132-BDFA-9817409E3A96}</ProjectGuid>
@ -27,24 +27,25 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Web" />
<Reference Include="System.XML" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration\ExceptronConfiguration.cs" />

Binary file not shown.

View File

@ -0,0 +1 @@
libsqlite3.0.dylib

Binary file not shown.

View File

@ -160,6 +160,14 @@ namespace Marr.Data
get { return _children; }
}
/// <summary>
/// Adds an Child in the graph for LazyLoaded property.
/// </summary>
public void AddLazyRelationship(Relationship childRelationship)
{
_children.Add(new EntityGraph(childRelationship.RelationshipInfo.EntityType.GetGenericArguments()[0], this, childRelationship));
}
/// <summary>
/// Adds an entity to the appropriate place in the object graph.
/// </summary>
@ -182,7 +190,10 @@ namespace Marr.Data
}
else // RelationTypes.One
{
_relationship.Setter(_parent._entity, entityInstance);
if (_relationship.IsLazyLoaded)
_relationship.Setter(_parent._entity, Activator.CreateInstance(_relationship.MemberType, entityInstance));
else
_relationship.Setter(_parent._entity, entityInstance);
}
EntityReference entityRef = new EntityReference(entityInstance);

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F6FC6BE7-0847-4817-A1ED-223DC647C3D7}</ProjectGuid>
@ -29,6 +29,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath>
@ -38,11 +40,12 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />

View File

@ -551,6 +551,23 @@ namespace Marr.Data.QGen
return Join(joinType, rightMember, filterExpression);
}
public virtual QueryBuilder<T> Join<TLeft, TRight>(JoinType joinType, Expression<Func<TLeft, LazyLoaded<TRight>>> rightEntity, Expression<Func<TLeft, TRight, bool>> filterExpression)
{
_isJoin = true;
MemberInfo rightMember = (rightEntity.Body as MemberExpression).Member;
foreach (var item in EntGraph)
{
if (item.EntityType == typeof(TLeft))
{
var relationship = item.Relationships.Single(v => v.Member == rightMember);
item.AddLazyRelationship(relationship);
}
}
return Join(joinType, rightMember, filterExpression);
}
public virtual QueryBuilder<T> Join<TLeft, TRight>(JoinType joinType, MemberInfo rightMember, Expression<Func<TLeft, TRight, bool>> filterExpression)
{
_isJoin = true;

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{1B9A82C4-BCA1-4834-A33E-226F17BE070B}</ProjectGuid>
@ -19,7 +19,6 @@
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;PERFCOUNTERS</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Microsoft.AspNet.SignalR.Core.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>1591</NoWarn>
@ -27,11 +26,12 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;PERFCOUNTERS</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\Microsoft.AspNet.SignalR.Core.XML</DocumentationFile>
<Optimize>true</Optimize>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@ -40,19 +40,19 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNet.SignalR.Client">
<HintPath>..\packages\Microsoft.AspNet.SignalR.Client.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Security" />
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Common\CommonAssemblyInfo.cs">
@ -273,8 +273,6 @@
</ItemGroup>
<Import Project="..\Common\Microsoft.AspNet.SignalR.targets" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="!HasTrailingSlash('$(SolutionDir)')" />
<Import Project="$(SolutionDir).nuget\NuGet.targets" Condition="HasTrailingSlash('$(SolutionDir)')" />
<Target Name="AfterBuild">
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{2B8C6DAD-4D85-41B1-83FD-248D9F347522}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
@ -14,6 +14,8 @@
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
@ -26,6 +28,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
@ -38,15 +42,15 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f585506a2da1fef4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Common\CommonAssemblyInfo.cs">
@ -97,8 +101,6 @@
</ItemGroup>
<Import Project="..\Common\Microsoft.AspNet.SignalR.targets" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="!HasTrailingSlash('$(SolutionDir)')" />
<Import Project="$(SolutionDir).nuget\NuGet.targets" Condition="HasTrailingSlash('$(SolutionDir)')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{D18A5DEB-5102-4775-A1AF-B75DAAA8907B}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
@ -13,6 +13,8 @@
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
@ -22,6 +24,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
@ -31,15 +35,12 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FizzWare.NBuilder">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
@ -56,6 +57,9 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ClientSchemaTests\SchemaBuilderFixture.cs" />
@ -73,11 +77,11 @@
<Name>NzbDrone.Api</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
<Project>{f2be0fdf-6e47-4827-a420-dd4ef82407f8}</Project>
<Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
<Name>NzbDrone.Common</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{ff5ee3b6-913b-47ce-9ceb-11c51b4e1205}</Project>
<Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Test.Common\NzbDrone.Test.Common.csproj">

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.HealthCheck;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Api.Health
{
public class HealthModule : NzbDroneRestModuleWithSignalR<HealthResource, HealthCheck>,
IHandle<TriggerHealthCheckEvent>
{
private readonly IHealthCheckService _healthCheckService;
public HealthModule(ICommandExecutor commandExecutor, IHealthCheckService healthCheckService)
: base(commandExecutor)
{
_healthCheckService = healthCheckService;
GetResourceAll = GetHealth;
}
private List<HealthResource> GetHealth()
{
return ToListResource(_healthCheckService.PerformHealthCheck);
}
public void Handle(TriggerHealthCheckEvent message)
{
BroadcastResourceChange(ModelAction.Sync);
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using NzbDrone.Api.REST;
using NzbDrone.Core.HealthCheck;
namespace NzbDrone.Api.Health
{
public class HealthResource : RestResource
{
public HealthCheckResultType Type { get; set; }
public String Message { get; set; }
}
}

View File

@ -39,6 +39,11 @@ namespace NzbDrone.Api.History
pagingSpec.SortKey = "series.title";
}
if (pagingResource.FilterKey == "eventType")
{
var filterValue = (HistoryEventType)Convert.ToInt32(pagingResource.FilterValue);
pagingSpec.FilterExpression = v => v.EventType == filterValue;
}
if (episodeId.HasValue)
{

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{FD286DF8-2D3A-4394-8AD5-443FADE55FB2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
@ -15,6 +15,8 @@
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
@ -24,6 +26,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath>
@ -33,33 +37,32 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
</Reference>
<Reference Include="Nancy, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Omu.ValueInjecter">
<HintPath>..\packages\ValueInjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="FluentValidation">
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Nancy">
<HintPath>..\packages\Nancy.0.21.1\lib\net40\Nancy.dll</HintPath>
</Reference>
<Reference Include="Nancy.Authentication.Basic, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Nancy.Authentication.Basic">
<HintPath>..\packages\Nancy.Authentication.Basic.0.21.1\lib\net40\Nancy.Authentication.Basic.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="Omu.ValueInjecter">
@ -129,6 +132,8 @@
<Compile Include="Frontend\Mappers\IMapHttpRequestsToDisk.cs" />
<Compile Include="Frontend\Mappers\StaticResourceMapperBase.cs" />
<Compile Include="Frontend\StaticResourceModule.cs" />
<Compile Include="Health\HistoryResource.cs" />
<Compile Include="Health\HealthModule.cs" />
<Compile Include="History\HistoryResource.cs" />
<Compile Include="History\HistoryModule.cs" />
<Compile Include="Metadata\MetadataResource.cs" />
@ -150,7 +155,9 @@
<Compile Include="Mapping\MappingValidation.cs" />
<Compile Include="Mapping\ResourceMappingException.cs" />
<Compile Include="Mapping\ValueInjectorExtensions.cs" />
<Compile Include="Missing\MissingModule.cs" />
<Compile Include="Wanted\CutoffModule.cs" />
<Compile Include="Wanted\LegacyMissingModule.cs" />
<Compile Include="Wanted\MissingModule.cs" />
<Compile Include="Config\NamingSampleResource.cs" />
<Compile Include="NzbDroneRestModuleWithSignalR.cs" />
<Compile Include="Qualities\QualityProfileValidation.cs" />
@ -200,15 +207,15 @@
<Name>Marr.Data</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
<Project>{f2be0fdf-6e47-4827-a420-dd4ef82407f8}</Project>
<Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
<Name>NzbDrone.Common</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{ff5ee3b6-913b-47ce-9ceb-11c51b4e1205}</Project>
<Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.SignalR\NzbDrone.SignalR.csproj">
<Project>{7c2cc69f-5ca0-4e5c-85cb-983f9f6c3b36}</Project>
<Project>{7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}</Project>
<Name>NzbDrone.SignalR</Name>
</ProjectReference>
</ItemGroup>

View File

@ -1,6 +1,4 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Remoting.Messaging;
using Nancy;
using NzbDrone.Api.Extensions;
using NzbDrone.Api.Mapping;

View File

@ -4,6 +4,7 @@ using NzbDrone.Common;
using NzbDrone.Api.Extensions;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Api.System
{
@ -13,14 +14,16 @@ namespace NzbDrone.Api.System
private readonly IRuntimeInfo _runtimeInfo;
private readonly IRouteCacheProvider _routeCacheProvider;
private readonly IConfigFileProvider _configFileProvider;
private readonly IDatabase _database;
public SystemModule(IAppFolderInfo appFolderInfo, IRuntimeInfo runtimeInfo, IRouteCacheProvider routeCacheProvider, IConfigFileProvider configFileProvider)
public SystemModule(IAppFolderInfo appFolderInfo, IRuntimeInfo runtimeInfo, IRouteCacheProvider routeCacheProvider, IConfigFileProvider configFileProvider, IDatabase database)
: base("system")
{
_appFolderInfo = appFolderInfo;
_runtimeInfo = runtimeInfo;
_routeCacheProvider = routeCacheProvider;
_configFileProvider = configFileProvider;
_database = database;
Get["/status"] = x => GetStatus();
Get["/routes"] = x => GetRoutes();
}
@ -44,6 +47,7 @@ namespace NzbDrone.Api.System
Branch = _configFileProvider.Branch,
Authentication = _configFileProvider.AuthenticationEnabled,
StartOfWeek = (int)OsInfo.FirstDayOfWeek,
SqliteVersion = _database.Version,
UrlBase = _configFileProvider.UrlBase
}.AsResponse();

View File

@ -0,0 +1,48 @@
using System.Linq;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Extensions;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Wanted
{
public class CutoffModule : NzbDroneRestModule<EpisodeResource>
{
private readonly IEpisodeCutoffService _episodeCutoffService;
private readonly SeriesRepository _seriesRepository;
public CutoffModule(IEpisodeCutoffService episodeCutoffService, SeriesRepository seriesRepository)
:base("wanted/cutoff")
{
_episodeCutoffService = episodeCutoffService;
_seriesRepository = seriesRepository;
GetResourcePaged = GetCutoffUnmetEpisodes;
}
private PagingResource<EpisodeResource> GetCutoffUnmetEpisodes(PagingResource<EpisodeResource> pagingResource)
{
var pagingSpec = new PagingSpec<Episode>
{
Page = pagingResource.Page,
PageSize = pagingResource.PageSize,
SortKey = pagingResource.SortKey,
SortDirection = pagingResource.SortDirection
};
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{
pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false;
}
else
{
pagingSpec.FilterExpression = v => v.Monitored == true && v.Series.Monitored == true;
}
PagingResource<EpisodeResource> resource = ApplyToPage(_episodeCutoffService.EpisodesWhereCutoffUnmet, pagingSpec);
resource.Records = resource.Records.LoadSubtype(e => e.SeriesId, _seriesRepository).ToList();
return resource;
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Text;
using Nancy;
namespace NzbDrone.Api.Wanted
{
class LegacyMissingModule : NzbDroneApiModule
{
public LegacyMissingModule() : base("missing")
{
Get["/"] = x =>
{
string queryString = ConvertQueryParams(Request.Query);
var url = String.Format("/api/wanted/missing?{0}", queryString);
return Response.AsRedirect(url);
};
}
private string ConvertQueryParams(DynamicDictionary query)
{
var sb = new StringBuilder();
foreach (var key in query)
{
var value = query[key];
sb.AppendFormat("&{0}={1}", key, value);
}
return sb.ToString().Trim('&');
}
}
}

View File

@ -4,7 +4,7 @@ using NzbDrone.Api.Extensions;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Missing
namespace NzbDrone.Api.Wanted
{
public class MissingModule : NzbDroneRestModule<EpisodeResource>
{
@ -12,7 +12,7 @@ namespace NzbDrone.Api.Missing
private readonly SeriesRepository _seriesRepository;
public MissingModule(IEpisodeService episodeService, SeriesRepository seriesRepository)
:base("missing")
:base("wanted/missing")
{
_episodeService = episodeService;
_seriesRepository = seriesRepository;
@ -29,7 +29,17 @@ namespace NzbDrone.Api.Missing
SortDirection = pagingResource.SortDirection
};
var resource = ApplyToPage(_episodeService.EpisodesWithoutFiles, pagingSpec);
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{
pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false;
}
else
{
pagingSpec.FilterExpression = v => v.Monitored == true && v.Series.Monitored == true;
}
PagingResource<EpisodeResource> resource = ApplyToPage(v => _episodeService.EpisodesWithoutFiles(v), pagingSpec);
resource.Records = resource.Records.LoadSubtype(e => e.SeriesId, _seriesRepository).ToList();
return resource;

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}</ProjectGuid>
@ -23,6 +23,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
@ -32,31 +34,29 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ContainerFixture.cs" />
@ -77,7 +77,7 @@
<Name>NzbDrone.Common</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{ff5ee3b6-913b-47ce-9ceb-11c51b4e1205}</Project>
<Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Host\NzbDrone.Host.csproj">

View File

@ -45,12 +45,12 @@ namespace NzbDrone.Automation.Test
}
[Test]
public void missing_page()
public void wanted_page()
{
page.MissingNavIcon.Click();
page.WantedNavIcon.Click();
page.WaitForNoSpinner();
page.FindByClass("iv-missing-missinglayout").Should().NotBeNull();
page.FindByClass("iv-wanted-missing-missinglayout").Should().NotBeNull();
}
[Test]

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{CC26800D-F67E-464B-88DE-8EB1A0C227A3}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
@ -13,6 +13,8 @@
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
@ -22,6 +24,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
@ -31,12 +35,9 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
@ -57,6 +58,9 @@
<Reference Include="WebDriver.Support">
<HintPath>..\packages\Selenium.Support.2.37.0\lib\net40\WebDriver.Support.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AutomationTestAttribute.cs" />

View File

@ -72,11 +72,11 @@ namespace NzbDrone.Automation.Test.PageModel
}
}
public IWebElement MissingNavIcon
public IWebElement WantedNavIcon
{
get
{
return Find(By.LinkText("Missing"));
return Find(By.LinkText("Wanted"));
}
}
@ -92,7 +92,7 @@ namespace NzbDrone.Automation.Test.PageModel
{
get
{
return Find(By.LinkText("System"));
return Find(By.PartialLinkText("System"));
}
}

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}</ProjectGuid>
@ -23,6 +23,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
@ -32,23 +34,12 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" />
@ -57,6 +48,15 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CacheTests\CachedManagerFixture.cs" />

View File

@ -24,8 +24,6 @@ namespace NzbDrone.Common.Composition
_container.Register<TService, TImplementation>();
}
public TinyIoCContainer TinyContainer { get { return _container; } }
public void Register<T>(T instance) where T : class
{
_container.Register<T>(instance);
@ -48,22 +46,7 @@ namespace NzbDrone.Common.Composition
public void Register<TService>(Func<IContainer, TService> factory) where TService : class
{
_container.Register((c, n) =>
{
return factory(this);
});
}
public void RegisterSingleton<TService, TImplementation>()
where TImplementation : class, TService
where TService : class
{
_container.Register<TService, TImplementation>().AsSingleton();
}
public void RegisterSingleton<T>() where T : class
{
_container.Register<T, T>().AsSingleton();
_container.Register((c, n) => factory(this));
}
public void RegisterSingleton(Type service, Type implementation)
@ -76,16 +59,6 @@ namespace NzbDrone.Common.Composition
return _container.ResolveAll<T>();
}
public IEnumerable<object> ResolveAll(Type type)
{
return _container.ResolveAll(type);
}
public void Register(Type registrationType, object instance)
{
_container.Register(registrationType, instance);
}
public void RegisterAllAsSingleton(Type registrationType, IEnumerable<Type> implementationList)
{
_container.RegisterMultiple(registrationType, implementationList).AsSingleton();

View File

@ -6,7 +6,6 @@ namespace NzbDrone.Common.Composition
{
public interface IContainer
{
TinyIoCContainer TinyContainer { get; }
void Register<T>(T instance) where T : class;
void Register<TService, TImplementation>()
@ -16,14 +15,8 @@ namespace NzbDrone.Common.Composition
object Resolve(Type type);
void Register(Type serviceType, Type implementationType);
void Register<TService>(Func<IContainer, TService> factory) where TService : class;
void RegisterSingleton<TService, TImplementation>()
where TImplementation : class, TService
where TService : class;
void RegisterSingleton<T>() where T : class;
void RegisterSingleton(Type service, Type implementation);
IEnumerable<T> ResolveAll<T>() where T : class;
IEnumerable<object> ResolveAll(Type type);
void Register(Type registrationType, object instance);
void RegisterAllAsSingleton(Type registrationType, IEnumerable<Type> implementationList);
bool IsTypeRegistered(Type type);

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Common
{
public static class DictionaryExtensions
{
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue = default(TValue))
{
TValue value;
return dictionary.TryGetValue(key, out value) ? value : defaultValue;
}
}
}

View File

@ -365,11 +365,6 @@ namespace NzbDrone.Common.Disk
}
public void SetFolderWriteTime(string path, DateTime time)
{
Directory.SetLastWriteTimeUtc(path, time);
}
private static void RemoveReadOnly(string path)
{
if (File.Exists(path))

View File

@ -37,7 +37,6 @@ namespace NzbDrone.Common.Disk
string GetPathRoot(string path);
string GetParentFolder(string path);
void SetPermissions(string filename, WellKnownSidType accountSid, FileSystemRights rights, AccessControlType controlType);
void SetFolderWriteTime(string path, DateTime time);
FileAttributes GetFileAttributes(string path);
void EmptyFolder(string path);
string[] GetFixedDrives();

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</ProjectGuid>
@ -25,6 +25,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath>
@ -34,29 +36,27 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="Loggly, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\loggly-csharp.2.3\lib\net35\Loggly.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" />
<Reference Include="Loggly">
<HintPath>..\packages\loggly-csharp.2.3\lib\net35\Loggly.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ArchiveProvider.cs" />
@ -67,6 +67,7 @@
<Compile Include="Composition\IContainer.cs" />
<Compile Include="Composition\ContainerBuilderBase.cs" />
<Compile Include="DateTimeExtensions.cs" />
<Compile Include="DictionaryExtensions.cs" />
<Compile Include="Disk\DiskProviderBase.cs" />
<Compile Include="EnsureThat\Ensure.cs" />
<Compile Include="EnsureThat\EnsureBoolExtensions.cs" />

View File

@ -52,5 +52,10 @@ namespace NzbDrone.Common
{
return CollapseSpace.Replace(text, " ").Trim();
}
public static bool IsNullOrWhiteSpace(this string text)
{
return String.IsNullOrWhiteSpace(text);
}
}
}

View File

@ -63,28 +63,23 @@
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.Owin">
<HintPath>..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting">
<HintPath>..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs">
@ -118,11 +113,11 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNet.SignalR.Core\Microsoft.AspNet.SignalR.Core.csproj">
<Project>{1b9a82c4-bca1-4834-a33e-226f17be070b}</Project>
<Project>{1B9A82C4-BCA1-4834-A33E-226F17BE070B}</Project>
<Name>Microsoft.AspNet.SignalR.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Microsoft.AspNet.SignalR.Owin\Microsoft.AspNet.SignalR.Owin.csproj">
<Project>{2b8c6dad-4d85-41b1-83fd-248d9f347522}</Project>
<Project>{2B8C6DAD-4D85-41B1-83FD-248D9F347522}</Project>
<Name>Microsoft.AspNet.SignalR.Owin</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
@ -130,7 +125,7 @@
<Name>NzbDrone.Common</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Host\NzbDrone.Host.csproj">
<Project>{95c11a9e-56ed-456a-8447-2c89c1139266}</Project>
<Project>{95C11A9E-56ED-456A-8447-2C89C1139266}</Project>
<Name>NzbDrone.Host</Name>
</ProjectReference>
</ItemGroup>
@ -145,9 +140,6 @@
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>xcopy /s /y "$(SolutionDir)\Libraries\Sqlite\*.*" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Blacklisting
_blacklist = new Blacklist
{
SeriesId = 12345,
EpisodeIds = new List<int> {1},
EpisodeIds = new List<int> { 1 },
Quality = new QualityModel(Quality.Bluray720p),
SourceTitle = "series.title.s01e01",
Date = DateTime.UtcNow
@ -48,7 +48,7 @@ namespace NzbDrone.Core.Test.Blacklisting
{
Subject.Insert(_blacklist);
Subject.Blacklisted(_blacklist.SourceTitle.ToUpperInvariant()).Should().BeTrue();
Subject.Blacklisted(_blacklist.SeriesId, _blacklist.SourceTitle.ToUpperInvariant()).Should().BeTrue();
}
}
}

View File

@ -35,7 +35,7 @@ namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene
_fakeMappings[4].ParseTerm = "Cleaned";
}
[Test]
public void UpdateMappings_purge_existing_mapping_and_add_new_ones()
@ -80,14 +80,14 @@ namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene
private void AssertNoUpdate()
{
Mocker.GetMock<ISceneMappingProxy>().Verify(c => c.Fetch(), Times.Once());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(), Times.Never());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(It.IsAny<bool>()), Times.Never());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.InsertMany(_fakeMappings), Times.Never());
}
private void AssertMappingUpdated()
{
Mocker.GetMock<ISceneMappingProxy>().Verify(c => c.Fetch(), Times.Once());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(), Times.Once());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(It.IsAny<bool>()), Times.Once());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.InsertMany(_fakeMappings), Times.Once());

View File

@ -0,0 +1,36 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore
{
public class DatabaseFixture : DbTest
{
[Test]
public void SingleOrDefault_should_return_null_on_empty_db()
{
Mocker.Resolve<IDatabase>()
.GetDataMapper().Query<Series>()
.SingleOrDefault(c => c.CleanTitle == "SomeTitle")
.Should()
.BeNull();
}
[Test]
public void vaccume()
{
Mocker.Resolve<IDatabase>().Vacuum();
}
[Test]
public void get_version()
{
Mocker.Resolve<IDatabase>().Version.Should().BeGreaterThan(new Version("3.0.0"));
}
}
}

View File

@ -5,6 +5,7 @@ using Marr.Data;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore

View File

@ -0,0 +1,105 @@
using FizzWare.NBuilder;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Test.Datastore
{
[TestFixture]
public class MarrDataLazyLoadingFixture : DbTest
{
[SetUp]
public void Setup()
{
var qualityProfile = new NzbDrone.Core.Qualities.QualityProfile
{
Name = "Test",
Cutoff = Quality.WEBDL720p,
Items = NzbDrone.Core.Test.Qualities.QualityFixture.GetDefaultQualities()
};
qualityProfile = Db.Insert(qualityProfile);
var series = Builder<Series>.CreateListOfSize(1)
.All()
.With(v => v.QualityProfileId = qualityProfile.Id)
.BuildListOfNew();
Db.InsertMany(series);
var episodeFiles = Builder<EpisodeFile>.CreateListOfSize(1)
.All()
.With(v => v.SeriesId = series[0].Id)
.BuildListOfNew();
Db.InsertMany(episodeFiles);
var episodes = Builder<Episode>.CreateListOfSize(10)
.All()
.With(v => v.Monitored = true)
.With(v => v.EpisodeFileId = episodeFiles[0].Id)
.With(v => v.SeriesId = series[0].Id)
.BuildListOfNew();
Db.InsertMany(episodes);
}
[Test]
public void should_lazy_load_qualityprofile_if_not_joined()
{
var db = Mocker.Resolve<IDatabase>();
var DataMapper = db.GetDataMapper();
var episodes = DataMapper.Query<Episode>()
.Join<Episode, Series>(Marr.Data.QGen.JoinType.Inner, v => v.Series, (l, r) => l.SeriesId == r.Id)
.ToList();
foreach (var episode in episodes)
{
Assert.IsNotNull(episode.Series);
Assert.IsFalse(episode.Series.QualityProfile.IsLoaded);
}
}
[Test]
public void should_explicit_load_episodefile_if_joined()
{
var db = Mocker.Resolve<IDatabase>();
var DataMapper = db.GetDataMapper();
var episodes = DataMapper.Query<Episode>()
.Join<Episode, EpisodeFile>(Marr.Data.QGen.JoinType.Inner, v => v.EpisodeFile, (l, r) => l.EpisodeFileId == r.Id)
.ToList();
foreach (var episode in episodes)
{
Assert.IsNull(episode.Series);
Assert.IsTrue(episode.EpisodeFile.IsLoaded);
}
}
[Test]
public void should_explicit_load_qualityprofile_if_joined()
{
var db = Mocker.Resolve<IDatabase>();
var DataMapper = db.GetDataMapper();
var episodes = DataMapper.Query<Episode>()
.Join<Episode, Series>(Marr.Data.QGen.JoinType.Inner, v => v.Series, (l, r) => l.SeriesId == r.Id)
.Join<Series, QualityProfile>(Marr.Data.QGen.JoinType.Inner, v => v.QualityProfile, (l, r) => l.QualityProfileId == r.Id)
.ToList();
foreach (var episode in episodes)
{
Assert.IsNotNull(episode.Series);
Assert.IsTrue(episode.Series.QualityProfile.IsLoaded);
}
}
}
}

View File

@ -7,24 +7,9 @@ using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore
{
public class DatabaseFixture : DbTest
{
[Test]
public void SingleOrDefault_should_return_null_on_empty_db()
{
Mocker.Resolve<IDatabase>()
.GetDataMapper().Query<Series>()
.SingleOrDefault(c => c.CleanTitle == "SomeTitle")
.Should()
.BeNull();
}
}
[TestFixture]
public class ObjectDatabaseFixture : DbTest<BasicRepository<ScheduledTask>, ScheduledTask>
{

View File

@ -1,6 +1,7 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests

View File

@ -1,6 +1,7 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests

View File

@ -131,6 +131,54 @@ namespace NzbDrone.Core.Test.Download
VerifyNoFailedDownloads();
}
[Test]
public void should_not_process_if_grabbed_history_contains_null_downloadclient_id()
{
GivenFailedDownloadClientHistory();
var historyGrabbed = Builder<History.History>.CreateListOfSize(1)
.Build()
.ToList();
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
historyGrabbed.First().Data.Add("downloadClientId", null);
GivenGrabbedHistory(historyGrabbed);
GivenNoFailedHistory();
Subject.Execute(new CheckForFailedDownloadCommand());
VerifyNoFailedDownloads();
}
[Test]
public void should_process_if_failed_history_contains_null_downloadclient_id()
{
GivenFailedDownloadClientHistory();
var historyGrabbed = Builder<History.History>.CreateListOfSize(1)
.Build()
.ToList();
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().Id);
GivenGrabbedHistory(historyGrabbed);
var historyFailed = Builder<History.History>.CreateListOfSize(1)
.Build()
.ToList();
historyFailed.First().Data.Add("downloadClient", "SabnzbdClient");
historyFailed.First().Data.Add("downloadClientId", null);
GivenFailedHistory(historyFailed);
Subject.Execute(new CheckForFailedDownloadCommand());
VerifyFailedDownloads();
}
[Test]
public void should_not_process_if_already_added_to_history_as_failed()
{

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class DownloadClientCheckFixture : CoreTest<DownloadClientCheck>
{
[Test]
public void should_return_warning_when_download_client_has_not_been_configured()
{
Mocker.GetMock<IProvideDownloadClient>()
.Setup(s => s.GetDownloadClient())
.Returns((IDownloadClient)null);
Subject.Check().ShouldBeWarning();
}
[Test]
public void should_return_error_when_download_client_throws()
{
var downloadClient = Mocker.GetMock<IDownloadClient>();
downloadClient.Setup(s => s.GetQueue())
.Throws<Exception>();
Mocker.GetMock<IProvideDownloadClient>()
.Setup(s => s.GetDownloadClient())
.Returns(downloadClient.Object);
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_null_when_download_client_returns()
{
var downloadClient = Mocker.GetMock<IDownloadClient>();
downloadClient.Setup(s => s.GetQueue())
.Returns(new List<QueueItem>());
Mocker.GetMock<IProvideDownloadClient>()
.Setup(s => s.GetDownloadClient())
.Returns(downloadClient.Object);
Subject.Check().Should().BeNull();
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class DroneFactoryCheckFixture : CoreTest<DroneFactoryCheck>
{
private const string DRONE_FACTORY_FOLDER = @"C:\Test\Unsorted";
private void GivenDroneFactoryFolder(bool exists = false)
{
Mocker.GetMock<IConfigService>()
.SetupGet(s => s.DownloadedEpisodesFolder)
.Returns(DRONE_FACTORY_FOLDER);
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.FolderExists(DRONE_FACTORY_FOLDER))
.Returns(exists);
}
[Test]
public void should_return_warning_when_drone_factory_folder_is_not_configured()
{
Mocker.GetMock<IConfigService>()
.SetupGet(s => s.DownloadedEpisodesFolder)
.Returns("");
Subject.Check().ShouldBeWarning();
}
[Test]
public void should_return_error_when_drone_factory_folder_does_not_exist()
{
GivenDroneFactoryFolder();
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_error_when_unable_to_write_to_drone_factory_folder()
{
GivenDroneFactoryFolder(true);
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.WriteAllText(It.IsAny<String>(), It.IsAny<String>()))
.Throws<Exception>();
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_null_when_no_issues_found()
{
GivenDroneFactoryFolder(true);
Subject.Check().Should().BeNull();
}
}
}

View File

@ -0,0 +1,18 @@
using FluentAssertions;
using NzbDrone.Core.HealthCheck;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
public static class HealthCheckFixtureExtensions
{
public static void ShouldBeWarning(this Core.HealthCheck.HealthCheck result)
{
result.Type.Should().Be(HealthCheckResultType.Warning);
}
public static void ShouldBeError(this Core.HealthCheck.HealthCheck result)
{
result.Type.Should().Be(HealthCheckResultType.Error);
}
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Wombles;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class IndexerCheckFixture : CoreTest<IndexerCheck>
{
[Test]
public void should_return_error_when_not_indexers_are_enabled()
{
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer>());
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_warning_when_only_enabled_indexer_is_wombles()
{
var indexer = Mocker.GetMock<IIndexer>();
indexer.SetupGet(s => s.SupportsSearching).Returns(false);
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer>{indexer.Object});
Subject.Check().ShouldBeWarning();
}
[Test]
public void should_return_null_when_multiple_indexers_are_enabled()
{
var indexer1 = Mocker.GetMock<IIndexer>();
indexer1.SetupGet(s => s.SupportsSearching).Returns(true);
var indexer2 = Mocker.GetMock<Wombles>();
indexer2.SetupGet(s => s.SupportsSearching).Returns(false);
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer> { indexer1.Object, indexer2.Object });
Subject.Check().Should().BeNull();
}
[Test]
public void should_return_null_when_indexer_supports_searching()
{
var indexer1 = Mocker.GetMock<IIndexer>();
indexer1.SetupGet(s => s.SupportsSearching).Returns(true);
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer> { indexer1.Object });
Subject.Check().Should().BeNull();
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class UpdateCheckFixture : CoreTest<UpdateCheck>
{
[Test]
public void should_return_error_when_app_folder_is_write_protected()
{
WindowsOnly();
Mocker.GetMock<IAppFolderInfo>()
.Setup(s => s.StartUpFolder)
.Returns(@"C:\NzbDrone");
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.WriteAllText(It.IsAny<String>(), It.IsAny<String>()))
.Throws<Exception>();
Subject.Check().ShouldBeError();
}
}
}

View File

@ -5,6 +5,7 @@ using NLog;
using NUnit.Framework;
using NzbDrone.Common.Instrumentation;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Test.Framework;

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}</ProjectGuid>
@ -23,6 +23,8 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
@ -32,6 +34,7 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
@ -40,72 +43,63 @@
<Reference Include="AutoMoq">
<HintPath>..\packages\AutoMoq.1.6.1\lib\AutoMoq.dll</HintPath>
</Reference>
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator, Version=1.1.1.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentMigrator.1.1.1.0\lib\40\FluentMigrator.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator.Runner, Version=1.1.0.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference>
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity, Version=2.1.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity.Configuration">
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.Configuration.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NCrunch.Framework, Version=1.46.0.9, Culture=neutral, PublicKeyToken=01d101bf6f3e0aea, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NCrunch.Framework.1.46.0.9\lib\net35\NCrunch.Framework.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Prowlin, Version=0.9.4456.26422, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Prowlin.0.9.4456.26422\lib\net40\Prowlin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator">
<HintPath>..\packages\FluentMigrator.1.1.1.0\lib\40\FluentMigrator.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator.Runner">
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference>
<Reference Include="FluentValidation">
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation">
<HintPath>..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity">
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NCrunch.Framework">
<HintPath>..\packages\NCrunch.Framework.1.46.0.9\lib\net35\NCrunch.Framework.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Prowlin">
<HintPath>..\packages\Prowlin.0.9.4456.26422\lib\net40\Prowlin.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Blacklisting\BlacklistServiceFixture.cs" />
<Compile Include="Blacklisting\BlacklistRepositoryFixture.cs" />
<Compile Include="DataAugmentationFixture\Scene\SceneMappingProxyFixture.cs" />
<Compile Include="DataAugmentationFixture\Scene\SceneMappingServiceFixture.cs" />
<Compile Include="Datastore\MarrDataLazyLoadingFixture.cs" />
<Compile Include="Datastore\BasicRepositoryFixture.cs" />
<Compile Include="Datastore\Converters\ProviderSettingConverterFixture.cs" />
<Compile Include="Datastore\DatabaseFixture.cs" />
<Compile Include="Datastore\DatabaseRelationshipFixture.cs" />
<Compile Include="Datastore\MappingExtentionFixture.cs" />
<Compile Include="Datastore\ObjectDatabaseFixture.cs" />
@ -131,6 +125,11 @@
<Compile Include="Framework\CoreTest.cs" />
<Compile Include="Framework\DbTest.cs" />
<Compile Include="Framework\NBuilderExtensions.cs" />
<Compile Include="HealthCheck\Checks\UpdateCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\IndexerCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\DroneFactoryCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\DownloadClientCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\HealthCheckFixtureExtentions.cs" />
<Compile Include="HistoryTests\HistoryServiceFixture.cs" />
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedHistoryItemsFixture.cs" />
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodeFilesFixture.cs" />
@ -211,6 +210,8 @@
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodesFixture.cs" />
<Compile Include="ThingiProviderTests\NullConfigFixture.cs" />
<Compile Include="ThingiProvider\ProviderBaseFixture.cs" />
<Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWithFilesFixture.cs" />
<Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWhereCutoffUnmetFixture.cs" />
<Compile Include="TvTests\RefreshEpisodeServiceFixture.cs" />
<Compile Include="TvTests\EpisodeProviderTests\HandleEpisodeFileDeletedFixture.cs" />
<Compile Include="TvTests\EpisodeRepositoryTests\FindEpisodeFixture.cs" />
@ -254,7 +255,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
<Project>{f6fc6be7-0847-4817-a1ed-223dc647c3d7}</Project>
<Project>{F6FC6BE7-0847-4817-A1ED-223DC647C3D7}</Project>
<Name>Marr.Data</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">

View File

@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Salamander.S01E01.FLEMISH.HDTV.x264-BRiGAND", Language.Flemish)]
[TestCase("H.Polukatoikia.S03E13.Greek.PDTV.XviD-Ouzo", Language.Greek)]
[TestCase("Burn.Notice.S04E15.Brotherly.Love.GERMAN.DUBBED.WS.WEBRiP.XviD.REPACK-TVP", Language.German)]
[TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)", Language.Norwegian)]
[TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)", Language.Dutch)]
[TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD", Language.French)]
[TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike", Language.Russian)]
public void should_parse_language(string postTitle, Language language)

View File

@ -130,7 +130,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), true), Times.Once());
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
}
[Test]
@ -141,7 +141,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), true), Times.Never());
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Never());
}
[Test]
@ -153,7 +153,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), true), Times.Once());
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
}
[Test]
@ -162,7 +162,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), false), Times.Once());
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
}
[Test]
@ -171,7 +171,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), false), Times.Never());
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Never());
}
[Test]
@ -182,7 +182,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), false), Times.Once());
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
}
}
}

View File

@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
{
[TestFixture]
public class EpisodesWhereCutoffUnmetFixture : DbTest<EpisodeRepository, Episode>
{
private Series _monitoredSeries;
private Series _unmonitoredSeries;
private PagingSpec<Episode> _pagingSpec;
private List<QualitiesBelowCutoff> _qualitiesBelowCutoff;
[SetUp]
public void Setup()
{
var qualityProfile = new QualityProfile
{
Id = 1,
Cutoff = Quality.WEBDL480p,
Items = new List<QualityProfileItem>
{
new QualityProfileItem { Allowed = true, Quality = Quality.SDTV },
new QualityProfileItem { Allowed = true, Quality = Quality.WEBDL480p },
new QualityProfileItem { Allowed = true, Quality = Quality.RAWHD }
}
};
_monitoredSeries = Builder<Series>.CreateNew()
.With(s => s.TvRageId = RandomNumber)
.With(s => s.Runtime = 30)
.With(s => s.Monitored = true)
.With(s => s.TitleSlug = "Title3")
.With(s => s.Id = qualityProfile.Id)
.BuildNew();
_unmonitoredSeries = Builder<Series>.CreateNew()
.With(s => s.TvdbId = RandomNumber)
.With(s => s.Runtime = 30)
.With(s => s.Monitored = false)
.With(s => s.TitleSlug = "Title2")
.With(s => s.Id = qualityProfile.Id)
.BuildNew();
_monitoredSeries.Id = Db.Insert(_monitoredSeries).Id;
_unmonitoredSeries.Id = Db.Insert(_unmonitoredSeries).Id;
_pagingSpec = new PagingSpec<Episode>
{
Page = 1,
PageSize = 10,
SortKey = "AirDate",
SortDirection = SortDirection.Ascending
};
_qualitiesBelowCutoff = new List<QualitiesBelowCutoff>
{
new QualitiesBelowCutoff(qualityProfile.Id, new[] {Quality.SDTV.Id})
};
var qualityMet = new EpisodeFile { Path = "a", Quality = new QualityModel { Quality = Quality.WEBDL480p } };
var qualityUnmet = new EpisodeFile { Path = "b", Quality = new QualityModel { Quality = Quality.SDTV } };
var qualityRawHD = new EpisodeFile { Path = "c", Quality = new QualityModel { Quality = Quality.RAWHD } };
MediaFileRepository fileRepository = Mocker.Resolve<MediaFileRepository>();
qualityMet = fileRepository.Insert(qualityMet);
qualityUnmet = fileRepository.Insert(qualityUnmet);
qualityRawHD = fileRepository.Insert(qualityRawHD);
var monitoredSeriesEpisodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _monitoredSeries.Id)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
.With(e => e.Monitored = true)
.With(e => e.EpisodeFileId = qualityUnmet.Id)
.TheFirst(1)
.With(e => e.Monitored = false)
.With(e => e.EpisodeFileId = qualityMet.Id)
.TheNext(1)
.With(e => e.EpisodeFileId = qualityRawHD.Id)
.TheLast(1)
.With(e => e.SeasonNumber = 0)
.Build();
var unmonitoredSeriesEpisodes = Builder<Episode>.CreateListOfSize(3)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _unmonitoredSeries.Id)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
.With(e => e.Monitored = true)
.With(e => e.EpisodeFileId = qualityUnmet.Id)
.TheFirst(1)
.With(e => e.Monitored = false)
.With(e => e.EpisodeFileId = qualityMet.Id)
.TheLast(1)
.With(e => e.SeasonNumber = 0)
.Build();
var unairedEpisodes = Builder<Episode>.CreateListOfSize(1)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _monitoredSeries.Id)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(5))
.With(e => e.Monitored = true)
.With(e => e.EpisodeFileId = qualityUnmet.Id)
.Build();
Db.InsertMany(monitoredSeriesEpisodes);
Db.InsertMany(unmonitoredSeriesEpisodes);
Db.InsertMany(unairedEpisodes);
}
private void GivenMonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == true && e.Series.Monitored == true;
}
private void GivenUnmonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == false || e.Series.Monitored == false;
}
[Test]
public void should_include_episodes_where_cutoff_has_not_be_met()
{
GivenMonitoredFilterExpression();
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
spec.Records.Should().HaveCount(1);
spec.Records.Should().OnlyContain(e => e.EpisodeFile.Value.Quality.Quality == Quality.SDTV);
}
[Test]
public void should_only_contain_monitored_episodes()
{
GivenMonitoredFilterExpression();
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
spec.Records.Should().HaveCount(1);
spec.Records.Should().OnlyContain(e => e.Monitored);
}
[Test]
public void should_only_contain_episode_with_monitored_series()
{
GivenMonitoredFilterExpression();
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
spec.Records.Should().HaveCount(1);
spec.Records.Should().OnlyContain(e => e.Series.Monitored);
}
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
{
[TestFixture]
public class EpisodesWithFilesFixture : DbTest<EpisodeRepository, Episode>
{
private const int SERIES_ID = 1;
private List<Episode> _episodes;
private List<EpisodeFile> _episodeFiles;
[SetUp]
public void Setup()
{
_episodeFiles = Builder<EpisodeFile>.CreateListOfSize(5)
.BuildListOfNew()
.ToList();
Db.InsertMany(_episodeFiles);
_episodes = Builder<Episode>.CreateListOfSize(10)
.All()
.With(e => e.EpisodeFileId = 0)
.With(e => e.SeriesId = SERIES_ID)
.BuildListOfNew()
.ToList();
for (int i = 0; i < _episodeFiles.Count; i++)
{
_episodes[i].EpisodeFileId = _episodeFiles[i].Id;
}
Db.InsertMany(_episodes);
}
[Test]
public void should_only_get_files_that_have_episode_files()
{
var result = Subject.EpisodesWithFiles(SERIES_ID);
result.Should().OnlyContain(e => e.EpisodeFileId > 0);
result.Should().HaveCount(_episodeFiles.Count);
}
[Test]
public void should_only_contain_episodes_for_the_given_series()
{
var episodeFile = Builder<EpisodeFile>.CreateNew()
.With(f => f.Path = "another path")
.BuildNew();
Db.Insert(episodeFile);
var episode = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = SERIES_ID + 10)
.With(e => e.EpisodeFileId = episodeFile.Id)
.BuildNew();
Db.Insert(episode);
Subject.EpisodesWithFiles(episode.SeriesId).Should().OnlyContain(e => e.SeriesId == episode.SeriesId);
}
[Test]
public void should_have_episode_file_loaded()
{
Subject.EpisodesWithFiles(SERIES_ID).Should().OnlyContain(e => e.EpisodeFile.IsLoaded);
}
}
}

View File

@ -72,13 +72,36 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
.Build();
var unairedEpisodes = Builder<Episode>.CreateListOfSize(1)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _monitoredSeries.Id)
.With(e => e.EpisodeFileId = 0)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(5))
.With(e => e.Monitored = true)
.Build();
Db.InsertMany(monitoredSeriesEpisodes);
Db.InsertMany(unmonitoredSeriesEpisodes);
Db.InsertMany(unairedEpisodes);
}
private void GivenMonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == true && e.Series.Monitored == true;
}
private void GivenUnmonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == false || e.Series.Monitored == false;
}
[Test]
public void should_get_monitored_episodes()
{
GivenMonitoredFilterExpression();
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.Records.Should().HaveCount(1);
@ -96,6 +119,8 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[Test]
public void should_not_include_unmonitored_episodes()
{
GivenMonitoredFilterExpression();
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.Records.Should().NotContain(e => e.Monitored == false);
@ -104,17 +129,19 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[Test]
public void should_not_contain_unmonitored_series()
{
GivenMonitoredFilterExpression();
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.Records.Should().NotContain(e => e.SeriesId == _unmonitoredSeries.Id);
}
[Test]
public void should_have_count_of_one()
public void should_not_return_unaired()
{
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.TotalRecords.Should().Be(1);
episodes.TotalRecords.Should().Be(4);
}
}
}

View File

@ -1,4 +1,5 @@
using FizzWare.NBuilder;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
@ -9,46 +10,55 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[TestFixture]
public class FindEpisodeFixture : DbTest<EpisodeRepository, Episode>
{
private Episode _episode;
private Episode _episode1;
private Episode _episode2;
[SetUp]
public void Setup()
{
_episode = Builder<Episode>.CreateNew()
.With(e => e.Id = 0)
.With(e => e.SeriesId = 1)
.With(e => e.SeasonNumber = 1)
.With(e => e.SceneSeasonNumber = 2)
.With(e => e.EpisodeNumber = 3)
.With(e => e.AbsoluteEpisodeNumber = 3)
.With(e => e.SceneEpisodeNumber = 4)
.Build();
_episode1 = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = 1)
.With(e => e.SeasonNumber = 1)
.With(e => e.SceneSeasonNumber = 2)
.With(e => e.EpisodeNumber = 3)
.With(e => e.AbsoluteEpisodeNumber = 3)
.With(e => e.SceneEpisodeNumber = 4)
.BuildNew();
_episode = Db.Insert(_episode);
_episode2 = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = 1)
.With(e => e.SeasonNumber = 1)
.With(e => e.SceneSeasonNumber = 2)
.With(e => e.EpisodeNumber = 4)
.With(e => e.SceneEpisodeNumber = 4)
.BuildNew();
_episode1 = Db.Insert(_episode1);
}
[Test]
public void should_find_episode_by_scene_numbering()
{
Subject.FindEpisodeBySceneNumbering(_episode.SeriesId, _episode.SceneSeasonNumber, _episode.SceneEpisodeNumber)
Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber, _episode1.SceneEpisodeNumber)
.First()
.Id
.Should()
.Be(_episode.Id);
.Be(_episode1.Id);
}
[Test]
public void should_find_episode_by_standard_numbering()
{
Subject.Find(_episode.SeriesId, _episode.SeasonNumber, _episode.EpisodeNumber)
Subject.Find(_episode1.SeriesId, _episode1.SeasonNumber, _episode1.EpisodeNumber)
.Id
.Should()
.Be(_episode.Id);
.Be(_episode1.Id);
}
[Test]
public void should_not_find_episode_that_does_not_exist()
{
Subject.Find(_episode.SeriesId, _episode.SeasonNumber + 1, _episode.EpisodeNumber)
Subject.Find(_episode1.SeriesId, _episode1.SeasonNumber + 1, _episode1.EpisodeNumber)
.Should()
.BeNull();
}
@ -56,10 +66,20 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[Test]
public void should_find_episode_by_absolute_numbering()
{
Subject.Find(_episode.SeriesId, _episode.AbsoluteEpisodeNumber.Value)
Subject.Find(_episode1.SeriesId, _episode1.AbsoluteEpisodeNumber.Value)
.Id
.Should()
.Be(_episode.Id);
.Be(_episode1.Id);
}
[Test]
public void should_return_multiple_episode_if_multiple_match_by_scene_numbering()
{
_episode2 = Db.Insert(_episode2);
Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber, _episode1.SceneEpisodeNumber)
.Should()
.HaveCount(2);
}
}
}

View File

@ -19,7 +19,7 @@ namespace NzbDrone.Core.Test.UpdateTests
public void finds_update_when_version_lower()
{
UseRealHttp();
Subject.GetLatestUpdate("master", new Version(1, 0)).Should().NotBeNull();
Subject.GetLatestUpdate("master", new Version(2, 0)).Should().NotBeNull();
}
}
}

View File

@ -8,7 +8,7 @@ namespace NzbDrone.Core.Blacklisting
{
public interface IBlacklistRepository : IBasicRepository<Blacklist>
{
bool Blacklisted(string sourceTitle);
bool Blacklisted(int seriesId, string sourceTitle);
List<Blacklist> BlacklistedBySeries(int seriesId);
}
@ -19,9 +19,11 @@ namespace NzbDrone.Core.Blacklisting
{
}
public bool Blacklisted(string sourceTitle)
public bool Blacklisted(int seriesId, string sourceTitle)
{
return Query.Where(e => e.SourceTitle.Contains(sourceTitle)).Any();
return Query.Where(e => e.SeriesId == seriesId)
.AndWhere(e => e.SourceTitle.Contains(sourceTitle))
.Any();
}
public List<Blacklist> BlacklistedBySeries(int seriesId)

View File

@ -9,7 +9,7 @@ namespace NzbDrone.Core.Blacklisting
{
public interface IBlacklistService
{
bool Blacklisted(string sourceTitle);
bool Blacklisted(int seriesId,string sourceTitle);
PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec);
void Delete(int id);
}
@ -25,9 +25,9 @@ namespace NzbDrone.Core.Blacklisting
_redownloadFailedDownloadService = redownloadFailedDownloadService;
}
public bool Blacklisted(string sourceTitle)
public bool Blacklisted(int seriesId, string sourceTitle)
{
return _blacklistRepository.Blacklisted(sourceTitle);
return _blacklistRepository.Blacklisted(seriesId,sourceTitle);
}
public PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec)

View File

@ -130,7 +130,7 @@ namespace NzbDrone.Core.Configuration
public string Branch
{
get { return GetValue("Branch", "master"); }
get { return GetValue("Branch", "master").ToLowerInvariant(); }
}
public string Username

View File

@ -6,6 +6,7 @@ using Marr.Data;
using Marr.Data.QGen;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Common;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Messaging.Events;
@ -26,7 +27,7 @@ namespace NzbDrone.Core.Datastore
void InsertMany(IList<TModel> model);
void UpdateMany(IList<TModel> model);
void DeleteMany(List<TModel> model);
void Purge();
void Purge(bool vacuum = false);
bool HasItems();
void DeleteMany(IEnumerable<int> ids);
void SetFields(TModel model, params Expression<Func<TModel, object>>[] properties);
@ -215,9 +216,18 @@ namespace NzbDrone.Core.Datastore
}
}
public void Purge()
public void Purge(bool vacuum = false)
{
DataMapper.Delete<TModel>(c => c.Id > -1);
if (vacuum)
{
Vacuum();
}
}
protected void Vacuum()
{
_database.Vacuum();
}
public bool HasItems()
@ -257,11 +267,6 @@ namespace NzbDrone.Core.Datastore
.Take(pagingSpec.PageSize);
}
public void DeleteAll()
{
DataMapper.Delete<TModel>(c => c.Id > 0);
}
protected void ModelCreated(TModel model)
{
PublishModelEvent(model, ModelAction.Created);

View File

@ -1,25 +1,55 @@
using System;
using Marr.Data;
using NLog;
using NzbDrone.Common.Instrumentation;
namespace NzbDrone.Core.Datastore
{
public interface IDatabase
{
IDataMapper GetDataMapper();
Version Version { get; }
void Vacuum();
}
public class Database : IDatabase
{
private readonly Func<IDataMapper> _dataMapperFactory;
private readonly Func<IDataMapper> _datamapperFactory;
public Database(Func<IDataMapper> dataMapperFactory)
private Logger logger = NzbDroneLogger.GetLogger();
public Database(Func<IDataMapper> datamapperFactory)
{
_dataMapperFactory = dataMapperFactory;
_datamapperFactory = datamapperFactory;
}
public IDataMapper GetDataMapper()
{
return _dataMapperFactory();
return _datamapperFactory();
}
public Version Version
{
get
{
var version = _datamapperFactory().ExecuteScalar("SELECT sqlite_version()").ToString();
return new Version(version);
}
}
public void Vacuum()
{
try
{
logger.Info("Vacuuming database");
_datamapperFactory().ExecuteNonQuery("Vacuum;");
logger.Info("Database Compressed");
}
catch (Exception e)
{
logger.Error("An Error occurred while vacuuming database.", e);
}
}
}
}

View File

@ -29,17 +29,13 @@ namespace NzbDrone.Core.Datastore
public static void RegisterDatabase(IContainer container)
{
container.Resolve<IDbFactory>().Create();
var mainDb = container.Resolve<IDbFactory>().Create();
container.Register(c => c.Resolve<IDbFactory>().Create());
container.Register(mainDb);
container.Resolve<IDbFactory>().Create(MigrationType.Log);
var logDb = container.Resolve<IDbFactory>().Create(MigrationType.Log);
container.Register<ILogRepository>(c =>
{
var db = c.Resolve<IDbFactory>().Create(MigrationType.Log);
return new LogRepository(db, c.Resolve<IEventAggregator>());
});
container.Register<ILogRepository>(c => new LogRepository(logDb, c.Resolve<IEventAggregator>()));
}
public DbFactory(IMigrationController migrationController, IConnectionStringFactory connectionStringFactory)
@ -73,7 +69,7 @@ namespace NzbDrone.Core.Datastore
_migrationController.MigrateToLatest(connectionString, migrationType);
return new Database(() =>
var db = new Database(() =>
{
var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString)
{
@ -82,6 +78,11 @@ namespace NzbDrone.Core.Datastore
return dataMapper;
});
db.Vacuum();
return db;
}
}
}

View File

@ -4,7 +4,7 @@ using Marr.Data;
using Marr.Data.Mapping;
using NzbDrone.Common.Reflection;
namespace NzbDrone.Core.Datastore
namespace NzbDrone.Core.Datastore.Extentions
{
public static class MappingExtensions
{

View File

@ -2,7 +2,7 @@
using System.Linq;
using System.Linq.Expressions;
namespace NzbDrone.Core.Datastore
namespace NzbDrone.Core.Datastore.Extentions
{
public static class PagingSpecExtensions
{

View File

@ -4,7 +4,7 @@ using System.Linq.Expressions;
using Marr.Data;
using Marr.Data.Mapping;
namespace NzbDrone.Core.Datastore
namespace NzbDrone.Core.Datastore.Extentions
{
public static class RelationshipExtensions
{

View File

@ -0,0 +1,26 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(45)]
public class add_indexes : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.Index().OnTable("Blacklist").OnColumn("SeriesId");
Create.Index().OnTable("EpisodeFiles").OnColumn("SeriesId");
Create.Index().OnTable("Episodes").OnColumn("EpisodeFileId");
Create.Index().OnTable("Episodes").OnColumn("SeriesId");
Create.Index().OnTable("History").OnColumn("EpisodeId");
Create.Index().OnTable("History").OnColumn("Date");
Create.Index().OnTable("Series").OnColumn("Path");
Create.Index().OnTable("Series").OnColumn("CleanTitle");
Create.Index().OnTable("Series").OnColumn("TvRageId");
}
}
}

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Reflection;
using System.Reflection;
using FluentMigrator.Runner;
using FluentMigrator.Runner.Initialization;
using FluentMigrator.Runner.Processors.Sqlite;
@ -17,8 +16,6 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
private readonly ISQLiteAlter _sqLiteAlter;
private readonly ISqLiteMigrationHelper _migrationHelper;
private static readonly HashSet<string> MigrationCache = new HashSet<string>();
public MigrationController(IAnnouncer announcer, ISQLiteAlter sqLiteAlter, ISqLiteMigrationHelper migrationHelper)
{
_announcer = announcer;
@ -28,33 +25,26 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
public void MigrateToLatest(string connectionString, MigrationType migrationType)
{
lock (MigrationCache)
{
if (MigrationCache.Contains(connectionString.ToLower())) return;
_announcer.Heading("Migrating " + connectionString);
_announcer.Heading("Migrating " + connectionString);
var assembly = Assembly.GetExecutingAssembly();
var assembly = Assembly.GetExecutingAssembly();
var migrationContext = new RunnerContext(_announcer)
{
Namespace = "NzbDrone.Core.Datastore.Migration",
ApplicationContext = new MigrationContext
{
MigrationType = migrationType,
SQLiteAlter = _sqLiteAlter,
MigrationHelper = _migrationHelper,
}
};
var migrationContext = new RunnerContext(_announcer)
{
Namespace = "NzbDrone.Core.Datastore.Migration",
ApplicationContext = new MigrationContext
{
MigrationType = migrationType,
SQLiteAlter = _sqLiteAlter,
MigrationHelper = _migrationHelper,
}
};
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
var factory = new SqliteProcessorFactory();
var processor = factory.Create(connectionString, _announcer, options);
var runner = new MigrationRunner(assembly, migrationContext, processor);
runner.MigrateUp(true);
MigrationCache.Add(connectionString.ToLower());
}
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
var factory = new SqliteProcessorFactory();
var processor = factory.Create(connectionString, _announcer, options);
var runner = new MigrationRunner(assembly, migrationContext, processor);
runner.MigrateUp(true);
}
}
}

View File

@ -1,4 +1,4 @@
namespace NzbDrone.Core.Datastore
namespace NzbDrone.Core.Datastore.Migration.Framework
{
public enum MigrationType
{

View File

@ -7,6 +7,7 @@ using NzbDrone.Core.Blacklisting;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Download;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Instrumentation;

View File

@ -35,7 +35,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
return true;
}
if (_blacklistService.Blacklisted(subject.Release.Title))
if (_blacklistService.Blacklisted(subject.Series.Id, subject.Release.Title))
{
_logger.Trace("{0} is blacklisted, rejecting.", subject.Release.Title);
return false;

View File

@ -69,14 +69,19 @@ namespace NzbDrone.Core.DiskSpace
try
{
var freeSpace = _diskProvider.GetAvailableSpace(path).Value;
var totalSpace = _diskProvider.GetTotalSize(path).Value;
var freeSpace = _diskProvider.GetAvailableSpace(path);
var totalSpace = _diskProvider.GetTotalSize(path);
if (!freeSpace.HasValue || !totalSpace.HasValue)
{
continue;
}
diskSpace = new DiskSpace
{
Path = path,
FreeSpace = freeSpace,
TotalSpace = totalSpace
FreeSpace = freeSpace.Value,
TotalSpace = totalSpace.Value
};
diskSpace.Label = _diskProvider.GetVolumeLabel(path);

View File

@ -58,11 +58,21 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
{
}
public void Execute(TestBlackholeCommand message)
public override void Test()
{
var testPath = Path.Combine(message.Folder, "drone_test.txt");
PerformTest(Settings.Folder);
}
private void PerformTest(string folder)
{
var testPath = Path.Combine(folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
public void Execute(TestBlackholeCommand message)
{
PerformTest(message.Folder);
}
}
}

View File

@ -0,0 +1,15 @@
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.Download.Clients
{
public class DownloadClientException : NzbDroneException
{
public DownloadClientException(string message, params object[] args) : base(message, args)
{
}
public DownloadClientException(string message) : base(message)
{
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Parser;
@ -42,9 +43,21 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public override IEnumerable<QueueItem> GetQueue()
{
var items = _proxy.GetQueue(Settings);
List<NzbgetQueueItem> queue;
foreach (var nzbGetQueueItem in items)
try
{
queue = _proxy.GetQueue(Settings);
}
catch (DownloadClientException ex)
{
_logger.ErrorException(ex.Message, ex);
return Enumerable.Empty<QueueItem>();
}
var queueItems = new List<QueueItem>();
foreach (var nzbGetQueueItem in queue)
{
var queueItem = new QueueItem();
queueItem.Id = nzbGetQueueItem.NzbId.ToString();
@ -60,9 +73,10 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
if (remoteEpisode.Series == null) continue;
queueItem.RemoteEpisode = remoteEpisode;
yield return queueItem;
queueItems.Add(queueItem);
}
return queueItems;
}
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
@ -80,7 +94,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
throw new NotImplementedException();
}
public VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null)
public override void Test()
{
_proxy.GetVersion(Settings);
}
private VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null)
{
return _proxy.GetVersion(Settings);
}

View File

@ -57,7 +57,10 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
private IRestClient BuildClient(NzbgetSettings settings)
{
var url = String.Format("http://{0}:{1}/jsonrpc",
var protocol = settings.UseSsl ? "https" : "http";
var url = String.Format("{0}://{1}:{2}/jsonrpc",
protocol,
settings.Host,
settings.Port);
@ -82,13 +85,13 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
if (response.ResponseStatus != ResponseStatus.Completed)
{
throw new ApplicationException("Unable to connect to NzbGet, please check your settings");
throw new DownloadClientException("Unable to connect to NzbGet, please check your settings");
}
var result = Json.Deserialize<JsonError>(response.Content);
if (result.Error != null)
throw new ApplicationException(result.Error.ToString());
throw new DownloadClientException("Error response received from nzbget: {0}", result.Error.ToString());
}
}
}

View File

@ -12,8 +12,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
RuleFor(c => c.Host).NotEmpty();
RuleFor(c => c.Port).GreaterThan(0);
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
RuleFor(c => c.Username).NotEmpty().When(c => !String.IsNullOrWhiteSpace(c.Password));
RuleFor(c => c.Password).NotEmpty().When(c => !String.IsNullOrWhiteSpace(c.Username));
}
}
@ -45,12 +45,15 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox)]
public String TvCategory { get; set; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))]
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public Int32 RecentTvPriority { get; set; }
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))]
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public Int32 OlderTvPriority { get; set; }
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
public Boolean UseSsl { get; set; }
public ValidationResult Validate()
{
return Validator.Validate(this);

View File

@ -80,11 +80,21 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
{
}
public void Execute(TestPneumaticCommand message)
public override void Test()
{
var testPath = Path.Combine(message.Folder, "drone_test.txt");
PerformTest(Settings.Folder);
}
private void PerformTest(string folder)
{
var testPath = Path.Combine(folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
public void Execute(TestPneumaticCommand message)
{
PerformTest(message.Folder);
}
}
}

View File

@ -60,11 +60,21 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
return _queueCache.Get("queue", () =>
{
var sabQueue = _sabnzbdProxy.GetQueue(0, 0, Settings).Items;
SabnzbdQueue sabQueue;
try
{
sabQueue = _sabnzbdProxy.GetQueue(0, 0, Settings);
}
catch (DownloadClientException ex)
{
_logger.ErrorException(ex.Message, ex);
return Enumerable.Empty<QueueItem>();
}
var queueItems = new List<QueueItem>();
foreach (var sabQueueItem in sabQueue)
foreach (var sabQueueItem in sabQueue.Items)
{
var queueItem = new QueueItem();
queueItem.Id = sabQueueItem.Id;
@ -91,10 +101,21 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
{
var items = _sabnzbdProxy.GetHistory(start, limit, Settings).Items;
SabnzbdHistory sabHistory;
try
{
sabHistory = _sabnzbdProxy.GetHistory(start, limit, Settings);
}
catch (DownloadClientException ex)
{
_logger.ErrorException(ex.Message, ex);
return Enumerable.Empty<HistoryItem>();
}
var historyItems = new List<HistoryItem>();
foreach (var sabHistoryItem in items)
foreach (var sabHistoryItem in sabHistory.Items)
{
var historyItem = new HistoryItem();
historyItem.Id = sabHistoryItem.Id;
@ -122,6 +143,11 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
_sabnzbdProxy.RemoveFrom("history", id, Settings);
}
public override void Test()
{
_sabnzbdProxy.GetCategories(Settings);
}
public void Execute(TestSabnzbdCommand message)
{
var settings = new SabnzbdSettings();

View File

@ -2,6 +2,7 @@
using System.IO;
using Newtonsoft.Json.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
using RestSharp;
@ -97,7 +98,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
var response = ProcessRequest(request, action, settings);
return Json.Deserialize<SabnzbdQueue>(JObject.Parse(response).SelectToken("queue").ToString());
}
public SabnzbdHistory GetHistory(int start, int limit, SabnzbdSettings settings)
@ -113,14 +113,16 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
var protocol = settings.UseSsl ? "https" : "http";
var url = string.Format(@"{0}://{1}:{2}/api?{3}&apikey={4}&ma_username={5}&ma_password={6}&output=json",
var authentication = settings.ApiKey.IsNullOrWhiteSpace() ?
String.Format("ma_username={0}&ma_password={1}", settings.Username, settings.Password) :
String.Format("apikey={0}", settings.ApiKey);
var url = string.Format(@"{0}://{1}:{2}/api?{3}&{4}&output=json",
protocol,
settings.Host,
settings.Port,
action,
settings.ApiKey,
settings.Username,
settings.Password);
authentication);
_logger.Trace(url);
@ -131,7 +133,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
if (response.ResponseStatus != ResponseStatus.Completed)
{
throw new ApplicationException("Unable to connect to SABnzbd, please check your settings");
throw new DownloadClientException("Unable to connect to SABnzbd, please check your settings");
}
SabnzbdJsonError result;
@ -156,7 +158,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
}
if (result.Failed)
throw new ApplicationException(result.Error);
throw new DownloadClientException("Error response received from SABnzbd: {0}", result.Error);
}
//TODO: Find a better home for this

View File

@ -59,10 +59,10 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox)]
public String TvCategory { get; set; }
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority))]
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public Int32 RecentTvPriority { get; set; }
[FieldDefinition(7, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority))]
[FieldDefinition(7, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public Int32 OlderTvPriority { get; set; }
[FieldDefinition(8, Label = "Use SSL", Type = FieldType.Checkbox)]

View File

@ -44,5 +44,6 @@ namespace NzbDrone.Core.Download
public abstract IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10);
public abstract void RemoveFromQueue(string id);
public abstract void RemoveFromHistory(string id);
public abstract void Test();
}
}

View File

@ -2,6 +2,7 @@
using System.Linq;
using NLog;
using NzbDrone.Common.Composition;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Download
@ -15,8 +16,8 @@ namespace NzbDrone.Core.Download
{
private readonly IDownloadClientRepository _providerRepository;
public DownloadClientFactory(IDownloadClientRepository providerRepository, IEnumerable<IDownloadClient> providers, IContainer container, Logger logger)
: base(providerRepository, providers, container, logger)
public DownloadClientFactory(IDownloadClientRepository providerRepository, IEnumerable<IDownloadClient> providers, IContainer container, IEventAggregator eventAggregator, Logger logger)
: base(providerRepository, providers, container, eventAggregator, logger)
{
_providerRepository = providerRepository;
}

View File

@ -1,9 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Download.Clients.Nzbget;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using System.Linq;
namespace NzbDrone.Core.Download
{

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.History;
using NzbDrone.Core.Messaging.Commands;
@ -72,8 +73,7 @@ namespace NzbDrone.Core.Download
continue;
}
if (failedHistory.Any(h => h.Data.ContainsKey(DOWNLOAD_CLIENT_ID) &&
h.Data[DOWNLOAD_CLIENT_ID].Equals(failedLocal.Id)))
if (failedHistory.Any(h => failedLocal.Id.Equals(h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID))))
{
_logger.Trace("Already added to history as failed");
continue;
@ -118,8 +118,7 @@ namespace NzbDrone.Core.Download
continue;
}
if (failedHistory.Any(h => h.Data.ContainsKey(DOWNLOAD_CLIENT_ID) &&
h.Data[DOWNLOAD_CLIENT_ID].Equals(failedLocal.Id)))
if (failedHistory.Any(h => failedLocal.Id.Equals(h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID))))
{
_logger.Trace("Already added to history as failed");
continue;
@ -137,8 +136,7 @@ namespace NzbDrone.Core.Download
private List<History.History> GetHistoryItems(List<History.History> grabbedHistory, string downloadClientId)
{
return grabbedHistory.Where(h => h.Data.ContainsKey(DOWNLOAD_CLIENT_ID) &&
h.Data[DOWNLOAD_CLIENT_ID].Equals(downloadClientId))
return grabbedHistory.Where(h => downloadClientId.Equals(h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID)))
.ToList();
}
@ -148,17 +146,14 @@ namespace NzbDrone.Core.Download
string downloadClient;
string downloadClientId;
historyItem.Data.TryGetValue(DOWNLOAD_CLIENT, out downloadClient);
historyItem.Data.TryGetValue(DOWNLOAD_CLIENT_ID, out downloadClientId);
_eventAggregator.PublishEvent(new DownloadFailedEvent
{
SeriesId = historyItem.SeriesId,
EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(),
Quality = historyItem.Quality,
SourceTitle = historyItem.SourceTitle,
DownloadClient = downloadClient,
DownloadClientId = downloadClientId,
DownloadClient = historyItem.Data.GetValueOrDefault(DOWNLOAD_CLIENT),
DownloadClientId = historyItem.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID),
Message = message
});
}

View File

@ -11,5 +11,6 @@ namespace NzbDrone.Core.Download
IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0);
void RemoveFromQueue(string id);
void RemoveFromHistory(string id);
void Test();
}
}

View File

@ -0,0 +1,8 @@
using NzbDrone.Core.Messaging.Commands;
namespace NzbDrone.Core.HealthCheck
{
public class CheckHealthCommand : Command
{
}
}

View File

@ -0,0 +1,36 @@
using System;
using NzbDrone.Core.Download;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class DownloadClientCheck : IProvideHealthCheck
{
private readonly IProvideDownloadClient _downloadClientProvider;
public DownloadClientCheck(IProvideDownloadClient downloadClientProvider)
{
_downloadClientProvider = downloadClientProvider;
}
public HealthCheck Check()
{
var downloadClient = _downloadClientProvider.GetDownloadClient();
if (downloadClient == null)
{
return new HealthCheck(HealthCheckResultType.Warning, "No download client is available");
}
try
{
downloadClient.GetQueue();
}
catch (Exception)
{
return new HealthCheck(HealthCheckResultType.Error, "Unable to communicate with download client");
}
return null;
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.IO;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class DroneFactoryCheck : IProvideHealthCheck
{
private readonly IConfigService _configService;
private readonly IDiskProvider _diskProvider;
public DroneFactoryCheck(IConfigService configService, IDiskProvider diskProvider)
{
_configService = configService;
_diskProvider = diskProvider;
}
public HealthCheck Check()
{
var droneFactoryFolder = _configService.DownloadedEpisodesFolder;
if (droneFactoryFolder.IsNullOrWhiteSpace())
{
return new HealthCheck(HealthCheckResultType.Warning, "Drone factory folder is not configured");
}
if (!_diskProvider.FolderExists(droneFactoryFolder))
{
return new HealthCheck(HealthCheckResultType.Error, "Drone factory folder does not exist");
}
try
{
var testPath = Path.Combine(droneFactoryFolder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
catch (Exception)
{
return new HealthCheck(HealthCheckResultType.Error, "Unable to write to drone factory folder");
}
//Todo: Unable to import one or more files/folders from
return null;
}
}
}

View File

@ -0,0 +1,32 @@
using System.Linq;
using NzbDrone.Core.Indexers;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class IndexerCheck : IProvideHealthCheck
{
private readonly IIndexerFactory _indexerFactory;
public IndexerCheck(IIndexerFactory indexerFactory)
{
_indexerFactory = indexerFactory;
}
public HealthCheck Check()
{
var enabled = _indexerFactory.GetAvailableProviders();
if (!enabled.Any())
{
return new HealthCheck(HealthCheckResultType.Error, "No indexers are enabled");
}
if (enabled.All(i => i.SupportsSearching == false))
{
return new HealthCheck(HealthCheckResultType.Warning, "Enabled indexers do not support searching");
}
return null;
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.IO;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Update;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class UpdateCheck : IProvideHealthCheck
{
private readonly IDiskProvider _diskProvider;
private readonly IAppFolderInfo _appFolderInfo;
private readonly ICheckUpdateService _checkUpdateService;
public UpdateCheck(IDiskProvider diskProvider, IAppFolderInfo appFolderInfo, ICheckUpdateService checkUpdateService)
{
_diskProvider = diskProvider;
_appFolderInfo = appFolderInfo;
_checkUpdateService = checkUpdateService;
}
public HealthCheck Check()
{
if (OsInfo.IsWindows)
{
try
{
var testPath = Path.Combine(_appFolderInfo.StartUpFolder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
catch (Exception)
{
return new HealthCheck(HealthCheckResultType.Error,
"Unable to update, running from write-protected folder");
}
}
if (BuildInfo.BuildDateTime < DateTime.UtcNow.AddDays(-14))
{
if (_checkUpdateService.AvailableUpdate() != null)
{
return new HealthCheck(HealthCheckResultType.Warning, "New update is available");
}
}
return null;
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.HealthCheck
{
public class HealthCheck : ModelBase
{
public HealthCheckResultType Type { get; set; }
public String Message { get; set; }
public HealthCheck(HealthCheckResultType type, string message)
{
Type = type;
Message = message;
}
}
public enum HealthCheckResultType
{
Warning = 1,
Error = 2
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Configuration.Events;
using NzbDrone.Core.Download;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.ThingiProvider.Events;
namespace NzbDrone.Core.HealthCheck
{
public interface IHealthCheckService
{
List<HealthCheck> PerformHealthCheck();
}
public class HealthCheckService : IHealthCheckService,
IExecute<CheckHealthCommand>,
IHandleAsync<ConfigSavedEvent>,
IHandleAsync<ProviderUpdatedEvent<IIndexer>>,
IHandleAsync<ProviderUpdatedEvent<IDownloadClient>>
{
private readonly IEnumerable<IProvideHealthCheck> _healthChecks;
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger;
public HealthCheckService(IEnumerable<IProvideHealthCheck> healthChecks, IEventAggregator eventAggregator, Logger logger)
{
_healthChecks = healthChecks;
_eventAggregator = eventAggregator;
_logger = logger;
}
public List<HealthCheck> PerformHealthCheck()
{
_logger.Trace("Checking health");
var result = _healthChecks.Select(c => c.Check()).Where(c => c != null).ToList();
return result;
}
public void Execute(CheckHealthCommand message)
{
//Until we have stored health checks we should just trigger the complete event
//and let the clients check in
//Multiple connected clients means we're going to compute the health check multiple times
//Multiple checks feels a bit ugly, but means the most up to date information goes to the client
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
public void HandleAsync(ConfigSavedEvent message)
{
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
public void HandleAsync(ProviderUpdatedEvent<IIndexer> message)
{
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
public void HandleAsync(ProviderUpdatedEvent<IDownloadClient> message)
{
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
}
}

View File

@ -0,0 +1,7 @@
namespace NzbDrone.Core.HealthCheck
{
public interface IProvideHealthCheck
{
HealthCheck Check();
}
}

View File

@ -0,0 +1,8 @@
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.HealthCheck
{
public class TriggerHealthCheckEvent : IEvent
{
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Marr.Data.QGen;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;

View File

@ -9,6 +9,7 @@ namespace NzbDrone.Core.Indexers
IParseFeed Parser { get; }
DownloadProtocol Protocol { get; }
Boolean SupportsPaging { get; }
Boolean SupportsSearching { get; }
IEnumerable<string> RecentFeed { get; }
IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber);

View File

@ -35,6 +35,7 @@ namespace NzbDrone.Core.Indexers
public abstract DownloadProtocol Protocol { get; }
public abstract bool SupportsPaging { get; }
public virtual bool SupportsSearching { get { return true; } }
protected TSettings Settings
{

View File

@ -2,6 +2,7 @@
using System.Linq;
using NLog;
using NzbDrone.Common.Composition;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers
@ -16,8 +17,13 @@ namespace NzbDrone.Core.Indexers
private readonly IIndexerRepository _providerRepository;
private readonly INewznabTestService _newznabTestService;
public IndexerFactory(IIndexerRepository providerRepository, IEnumerable<IIndexer> providers, IContainer container, INewznabTestService newznabTestService, Logger logger)
: base(providerRepository, providers, container, logger)
public IndexerFactory(IIndexerRepository providerRepository,
IEnumerable<IIndexer> providers,
IContainer container,
IEventAggregator eventAggregator,
INewznabTestService newznabTestService,
Logger logger)
: base(providerRepository, providers, container, eventAggregator, logger)
{
_providerRepository = providerRepository;
_newznabTestService = newznabTestService;

View File

@ -17,12 +17,11 @@ namespace NzbDrone.Core.Indexers.Newznab
var code = Convert.ToInt32(error.Attribute("code").Value);
var errorMessage = error.Attribute("description").Value;
if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key");
if (!url.Contains("apikey=") && errorMessage == "Missing parameter")
{
throw new ApiKeyException("Indexer requires and API key");
throw new ApiKeyException("Indexer requires an API key");
}
throw new NewznabException("Newznab error detected: {0}", errorMessage);

View File

@ -48,11 +48,11 @@ namespace NzbDrone.Core.Indexers
var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
throw new ValidationException(new List<ValidationFailure> { apiKeyFailure }.ToArray());
}
catch (Exception)
catch (Exception ex)
{
_logger.Warn("Indexer doesn't appear to be Newznab based");
_logger.WarnException("Indexer doesn't appear to be Newznab based: " + ex.Message, ex);
var failure = new ValidationFailure("Url", "Invalid Newznab URL entered");
var failure = new ValidationFailure("Url", "Invalid Newznab URL, check log for details");
throw new ValidationException(new List<ValidationFailure> { failure }.ToArray());
}
}

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