You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Lidarr/src/NzbDrone.Core.Test/ParserTests/FingerprintingServiceFixtur...

273 lines
48 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using FluentAssertions;
using Moq;
using Newtonsoft.Json;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
using static NzbDrone.Core.Parser.FingerprintingService;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class FingerprintingServiceFixture : CoreTest<FingerprintingService>
{
public class FingerPrintTest
{
public string Request { get; set; }
public string Response { get; set; }
}
[SetUp]
public void UseAcoustidResponses()
{
// responses were generated by editing HttpClient to write out the content bytes as a string
// using System.Text.Encoding.UTF8.GetString(request.ContentData.Decompress());
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Fingerprinting", "AcoustidResponses.json");
var responses = JsonConvert.DeserializeObject<List<FingerPrintTest>>(File.ReadAllText(path));
foreach (var response in responses)
{
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Post<LookupResponse>(
It.Is<HttpRequest>(v =>
v.Url.Equals(new HttpUri("https://api.acoustid.org/v2/lookup")) &&
v.Headers.Contains(new KeyValuePair<string, string>("Content-Encoding", "gzip")) &&
v.Headers.ContentType == "application/x-www-form-urlencoded" &&
Encoding.UTF8.GetString(v.ContentData.Decompress()) == response.Request
)))
.Returns<HttpRequest>(r => new HttpResponse<LookupResponse>(new HttpResponse(r, new HttpHeader(), response.Response)));
}
}
[Test]
public void should_parse_fpcalc_json()
{
var json = "{\"duration\": 229.29, \"fingerprint\": \"AQADtFMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-I2mPwd0PeQ8yHsByu4zqHPkfzo4-OtE6R7Dq-5fg3o-kuoVU84VGLIDkNqzEFNt1x7RvOHO7wf8hznDz0KA6F6-g1uE2OPseFvKh-9MGp4we7LLmIhxE1JHeDcLyOUD8uDTozND_apQvyiQ9yQcoRxisuBxeVDd-LRrGO-0xRKwuPh4ivHP8GUQ_ig87RN0czSkf0xEMNcRzxw8elHKIikcKlB5bGY-J9PImJ64K4PCDD7rh8_Ogvo5kOmU0RnjmcC2na9LiGbpKhC48RJvo2hI-HD80sVONx58nQ49CfLtCj59CTBz8eDZ4O7fHwBw-hPhJ0HhqlU0h9XB9qKsh_fNmRiTz-qPido6l3lB0X_DiS90QOOxdxbwJ94XqjwmKyHBeLHzfyH1MuaM9xibgeCe2O5gv-QzUz5NtRay8s7Tj6E1cSHH2eIa0tJB9OBVXa4g9-1M6DOsPTo3wwJQo3PA_4TMh_JJEPb4OzHSUTbcIvPCHcI4-gE7mOp8RxRyX6ySvM2EbJbhEeHVeKZOkR_hJKKTvM_SiPu9FhOUes6kJySTneozfO0HiObSy-7AXDp8gbJMd-4TmebB9KiYKfHNWPG8c9JGvUI5Tz4Xle3FEkhD-01DFy4gnKoOTxw23wOfjRjNKPZNp2Io8OpxmuJsW-7DgvoXYenEEtCT2aKDfIMDv-TEJ0JMtxoZk04Uqi4Ic_HLGP5JLRC80_XFJC9JnwjpNRjTueRSuS_4h4NIfzBl00E5-mo3ckNB-FPIE-5BlO9UL5Dudx5vikFB5DF-FKI7myxPjj4Yzw7OjRxOHxB8f3o9wO34V__IR5UkSf7LiOPhLSL-DR4MKlo5zwr8LFAf8h_oBtVTj8GIcAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARBgmADDNKIEAEoAgAAAQDBAgCHJCAEGG0QkQAaZgAAkpAkBAGImAgIYI5AoQAAiBBiCDMASGIYQAoB4QgCAlBIHFIICaAIM4aJawAxFIBDAFGGEA5AUQAgZhCTgJBgEKAACEMI4gwRRwQDAEEIQFEIaKIQYQBgYgBCjiGgAHEUQGYAIwwQASSylCjgJKMI8AIhIAAgAQwBBChhCIKAyOAVIIZAYBBihIIiBAACKMUUhI6JYAAigBADFAiAGBAhoZApRRQwABAiCCAGGcAQUIaBQBhgjBDACEEWSEsYAQYBIAVAACCmDAhEUAEEEQJhQA\"}";
var result = Subject.ParseFpcalcJsonOutput(json);
result.Duration.Should().Be(229.29);
result.Fingerprint.Should().Be("AQADtFMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-I2mPwd0PeQ8yHsByu4zqHPkfzo4-OtE6R7Dq-5fg3o-kuoVU84VGLIDkNqzEFNt1x7RvOHO7wf8hznDz0KA6F6-g1uE2OPseFvKh-9MGp4we7LLmIhxE1JHeDcLyOUD8uDTozND_apQvyiQ9yQcoRxisuBxeVDd-LRrGO-0xRKwuPh4ivHP8GUQ_ig87RN0czSkf0xEMNcRzxw8elHKIikcKlB5bGY-J9PImJ64K4PCDD7rh8_Ogvo5kOmU0RnjmcC2na9LiGbpKhC48RJvo2hI-HD80sVONx58nQ49CfLtCj59CTBz8eDZ4O7fHwBw-hPhJ0HhqlU0h9XB9qKsh_fNmRiTz-qPido6l3lB0X_DiS90QOOxdxbwJ94XqjwmKyHBeLHzfyH1MuaM9xibgeCe2O5gv-QzUz5NtRay8s7Tj6E1cSHH2eIa0tJB9OBVXa4g9-1M6DOsPTo3wwJQo3PA_4TMh_JJEPb4OzHSUTbcIvPCHcI4-gE7mOp8RxRyX6ySvM2EbJbhEeHVeKZOkR_hJKKTvM_SiPu9FhOUes6kJySTneozfO0HiObSy-7AXDp8gbJMd-4TmebB9KiYKfHNWPG8c9JGvUI5Tz4Xle3FEkhD-01DFy4gnKoOTxw23wOfjRjNKPZNp2Io8OpxmuJsW-7DgvoXYenEEtCT2aKDfIMDv-TEJ0JMtxoZk04Uqi4Ic_HLGP5JLRC80_XFJC9JnwjpNRjTueRSuS_4h4NIfzBl00E5-mo3ckNB-FPIE-5BlO9UL5Dudx5vikFB5DF-FKI7myxPjj4Yzw7OjRxOHxB8f3o9wO34V__IR5UkSf7LiOPhLSL-DR4MKlo5zwr8LFAf8h_oBtVTj8GIcAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARBgmADDNKIEAEoAgAAAQDBAgCHJCAEGG0QkQAaZgAAkpAkBAGImAgIYI5AoQAAiBBiCDMASGIYQAoB4QgCAlBIHFIICaAIM4aJawAxFIBDAFGGEA5AUQAgZhCTgJBgEKAACEMI4gwRRwQDAEEIQFEIaKIQYQBgYgBCjiGgAHEUQGYAIwwQASSylCjgJKMI8AIhIAAgAQwBBChhCIKAyOAVIIZAYBBihIIiBAACKMUUhI6JYAAigBADFAiAGBAhoZApRRQwABAiCCAGGcAQUIaBQBhgjBDACEEWSEsYAQYBIAVAACCmDAhEUAEEEQJhQA");
}
[Test]
public void should_parse_fpcalc_text()
{
var text = @"FILE=Adele - 01 - 21 - Rolling in the Deep.flac
DURATION=229
FINGERPRINT=AQAHJlMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-IehuDm92Q9xDzISyH67jOoc_R_OijI61TJLuObzn-zWi6S2gVT3jUIkhOw2pMgU13XPuGM4c7_B_yHCcPPYpD4Tp6DW6To89xIS-qH31w6vjBLksu4mFEDcndIByvI9SPS4PODM2PdumCfOKDXJByhPGKy8FFZcP3olGs4z5T1MrC4yHiK8e_QdSD-KBz9M3RjNIRPfFQQxxH_PBxKYeoSKRw6YGl8Zh4H09i4rogLg_IsDsuHz_6y2imQ2ZThGcO50KaNj2uoZtk6MJjhIm-DeHj4UMzC9V43Hky9Dj0pwv06Dn05MGPR4OnQ3s8_MFDqI8EnYdG6RRSH9eHmgryH192ZCKPPyp-52jqHWXHBT-O5D2Rw85F3JtAX7jeqLCYLMfF4seN_MeUC9pzXCKuR0K7o_mC_1DNDPl21NoLSzuO_sSVBEefZ0hrC8mHU0GVtviDH7XzoM7w9CgfTInCDc8DPhPyH0nkw9vgbEfJRJvwC08I98gj6ESu4ylx3FGJfvIKM7ZRsluER8eVIll6hL-EUsoOcz_K4250WM4Rq7qQXFKO9-iNMzSeYxuLL3vB8CnyBsmxX3iOJ9uHUqLgJ0f148ZxD8ka9QjlfHieF3cUCeEPLXWMnHiCMih5_HAbfA5-NKP0I5m2ncijw2mGq0mxLzvOS6idB2dQS0KPJsoNMsyOP5MQHclyXGgmTbiSKPjhD0fsI7lk9ELzD5eUEH0mvGONatyFZ9GK5D8iHs3hvEEXzcSn6egdCc1HIU-gD3mGU71QvsN5nDk-KYXH0EW40kiuLDH-eDgjPDt6NHF4PHjw_Si3w3fhHz9hnhTRJzuuI3wk-At4NLhw6Sgn_KtwccB_iD9gWxUOP8bhHb8HT0evRcJ_ouuC5oM0t0K_I_7gTUpwXI6RZ4fIE-kkynhzvMwFnzmI1MXeQ1xW9MqDHqkj3Fl0fDyeHa2iB9-CF2EuaD9yBWdi4cHjKEoCZzGPfOGhK8tx4kyHSh3SROODkIpRW4eW54J-NEckOZJGPH8S_MXX5HgiHj18MUMWj8UJ_SL-HL0HOxF0_MZ3xDDzoL_QKzr8gOGH8IH-Ii9-eE8s1Bc-7cS1EY3KHPON2D3axMa344eWx4JmH1dKnDxRUtvQ3DJO4spyaH8ORx9yLVlRNcbRH-4T3NERTXrwD4pJKoGvDlt9IeQS9Drcx7jEdHCqHdO2436Ea0cZIlkmBrmOx8WHK0eZC36Kylks47mNI8zEndAcFzleM2hWxkR_PMH14UOYH4V6ovvh4j7eGflx68H24P_gUsHx7fCNx7g2IX5QLpwW5FqWGDyH_vAVrCXgZ0F-iIqOSswe_ESPZqxRH9su6ISvoz2OR0Xt4Olx96CO43gl-CHqB7rxpzjR7EPlctDNQl6SoxJpIT3-wD_q4cmRB1qOPkbeKI3wa9ijBU9E-HSRL9uh4_7wKA1RK1GI5tFxGe0PMQmNf0iPPyIeHf_xJg9O5IeYv3geFuHJID96SRs-HGePG47xRsTFBfpxScthJ1Eq1D9Cwj-eLcZVH-5wwfvRN0b8BzvCPAE5HemWLOgqGfehHc2XNMj7oOxxpOijBDrBMES6ZclxesQzvBX8oD9e9IJ_tJOMagpzNNfBC4-OqTua96i3w6_RK-HR8DmSWULcxMOV43fwP2iuTMi14UwERUrI6MgX5J-S4BbmQ-yPPDn85DhxamIC_7hSPMf9IJmSuAhzYg9OUkrw6UHzoCdyfUjAHf05NGoWB2-InCeS2XFwH4we5ThODp2i7-Dn4BaHMJKSC7qObPKD5ktm1BS-oEyuBc1xXoiThTmSJ5Qx5VGHXmFwcnjjCJ6SIHmi3Mgf4EqHR7uC7xFOZQiZdUOy7MaNn8eHv4EZ6cFH4T_uI_mHvA9OxUEj1phEDTlzHP-D_UmIo3FIhCxRPeiX4wmuJEeeT2hCCslOPNjvBI80EqwUFE3xI9bICXpUBM0zfej0tPglnDeYXIuRH2KP_Ivw5LiUB1nictCdEvfRTTma73hyfNEjrEw-iLMS4-GFPWlCZPmOZuyPOcR_9JUGuyb64_iFL_hkxH6g7YiXF009PLlw7DkO_kHPFE2VrcSToVeQPkR16M3x-DjCE8ePH_mFhD8eocdxXiu6w2nC6ehxIkHe4cwMVlqOvfBTnJi6LNPR7B_4HOm-QE-OPW4i5DiPXM6E39AEH6Vz9MeRb8ePA7kh3ugRUnoERxH6CrVjfHvgx7BPo1aON8UlPEiupIgfBeuNShmoTTz-FCGpHMnNDp9wncF1XDqSPUeYxMf4ZMecHKd-8DrEHz--m3h6_Cr6ozluyRISh9ERH4d7nMcXBhPJB83xDZP-obGET1oRH8nzB2dYNCeO6Ua-7NDx7InwRyuaH6F148qSJ_jT4SyJ8BLRjBnk5EmG3KLQHdtJosyiJsFvoheyZKeQPMqOL0yk4jz847mEX3g61NfxBrXwWChPNGd0fAuq7ALV9EJ6aDx-hPlRH9eO0PrRHNehJzmKXxkhH-oKHz_S47iEzyJyHDr8RyjxFtV4iCoz4kj_glbh4xPyBR8P_UGYUcfDo9_hLwdv-Ee0EZdwCbqOnHjg_IeT4_ng4zDJD8ls5Ds-JniEx1sC58jxaNAp9LqhH2r8oIKe6LiOntByCbEjVnguR9gvXAmPc0HZo7k5_A7yGr9GaNnR49GFZwo0xDkcHj2uHL3RHEfeQbuI-3CP-yGq6cZPdB6xxT3-Ii-OK4Mr1I6D58MnPGJihDyaP9AV4kXIT2i4ZCeeHtWPX3jm4jh7pNJ6_PgiiM-DXMnxwEctxkap7YeDjsmJij6uBOYiJPuR48aPhyeOKb9RUQyeF8n7IecPJsyI8iVQ80RzjshTaHmD8J3w6EDVCk9zXOlxHM1lBX-RI_nRLwf_DP7hB5WOPwgbEeJb4algxgcvvIE14zhO4j0cKYRmLS_6HfxxHf0nzCz0H82DWsiDLxEndO3hP-jxo9-FMId-5A8-EndUBVX06Wj64yqOvN3wFb9DqNKGPjouAulROccfaUPEP8KTQ9cWPD_CHPXmDG9wXUb4Q8uFXA6eG4zawzochcd__INP9C2yHOIR_sLR5wqavHjU8Dji74Tma0jJ4MdF8B2-GH5mGXvhG-GhqPzQjDpygrFz2GGDn4iT69izEY7Q_7ieLZAVEU1Elsi_HB4DL8dk9fiWoelQnkF-KErErMSTNHikqCq0PrgmBeEp-HRU9CHCjIfmIdJTNFUmTQF7VE2EJqm0Is9SFeVyatj4IyQZXDl6NFWWDpeI3DtOY_SLJ8sM9k2QZ2huVMcTA4cAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARSABkmFECASIARQAAIBggQBDggASECKMVIgJIwwQQUAKChDAQAQMJEcwRIAQQAAlCBGEOCEEMA0A5IARBSAgCiUMCMQEEcdYoYQUglgpgCDDCAMoJIAIIxBRyEggCFAIECGEYQYQp4oBgCCAICSAKEUUMIgwIRAxQwDEEDCCOCsAEYIQBIpBUhhoFlGQcAUYgBAQAJIAhgAglFFEYGAGkEswIAAxSlEBAhABAGKWQktApAQRQBABigBIBAAMyNAQqpYACBgACBAHEOAMIEtIoAAgThBkCCCHIChMYAQYBYAUAgCAmTEgEEAEEUUIhNRAABgChCACCKAAEAAAQYwghCAAAAEJgMMEYCEhAAiADCAAFRAACOUKII4gBowwwECABgAJAIKgMoogJAwABQiFBODLECMSQAQYoYCRAAABgjBBGEUiAYQAR6ghiAhBKCFMGEeAFEIIAYBBDABEhFDKKIgOYoAQo4QgToElEAPIMIIAQtVZQgxQoBJIKAENGESSIFAQwgBAgADAAAMBEOGKIQMpJAAgQRCljKCGICKQAIQAYYwQXQCCgDBJECWIIGAgwxgRQRAnDhMMOGICMEAgYIYEiAhADCBGEMiMIAsQQoBAiBAgPiHBEGiMMIIoSoJAABCFJDAFEaKAIAIYyQJQBgigCBAMAgGIAQQYRIZBASAhDABEIIgLEEQA4JgCBSgAAnAEKIIYJoIAYAjAkQCAiCAEMIACYAYAIFDxxSgElGGAcEaGMkIQBBDlSEDFBFRKLAOEEJMIQBYgQgEAGAGEEEKIIcYAZIRChSDOLiAXMMGohUk4IYJFQCAkECCGWGCCIMMwAABATlCgghCjMGWCSEMIAAAigwjhjCAMICQCIEAIZA4gwTgACkGKMMEIVUEwABBzAmBnBlBKCSGIMAcAqpagFBUWCgBRIGCuYUYQhwAggggEIjjKKAyAAMwoE5owIziIiBCSGCAIMAEAoggxFCCAmmFTEWMKUYQgNQBhBgCAEjFNIKeOMQ4AwRYBBwAjGgDDAMQSMUUwAIqAR1jpIEEEEKGMEAkYIhBADQgBEqUFAFEqQIYI4JhSwwihRjUCAGAeQAYgAYrRhgBGkjEBACCEBAEYopIAwQCCGBDAAGUAAoooJJKByRkBDiJDCMa2UAQMYYRgQAGBFADBIGKEAYg4AgAgQSgAoHCFMCgCUAEY5BQBCxjMIEBBEEgAA
";
var result = Subject.ParseFpcalcTextOutput(text);
result.Duration.Should().Be(229);
result.Fingerprint.Should().Be("AQAHJlMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-IehuDm92Q9xDzISyH67jOoc_R_OijI61TJLuObzn-zWi6S2gVT3jUIkhOw2pMgU13XPuGM4c7_B_yHCcPPYpD4Tp6DW6To89xIS-qH31w6vjBLksu4mFEDcndIByvI9SPS4PODM2PdumCfOKDXJByhPGKy8FFZcP3olGs4z5T1MrC4yHiK8e_QdSD-KBz9M3RjNIRPfFQQxxH_PBxKYeoSKRw6YGl8Zh4H09i4rogLg_IsDsuHz_6y2imQ2ZThGcO50KaNj2uoZtk6MJjhIm-DeHj4UMzC9V43Hky9Dj0pwv06Dn05MGPR4OnQ3s8_MFDqI8EnYdG6RRSH9eHmgryH192ZCKPPyp-52jqHWXHBT-O5D2Rw85F3JtAX7jeqLCYLMfF4seN_MeUC9pzXCKuR0K7o_mC_1DNDPl21NoLSzuO_sSVBEefZ0hrC8mHU0GVtviDH7XzoM7w9CgfTInCDc8DPhPyH0nkw9vgbEfJRJvwC08I98gj6ESu4ylx3FGJfvIKM7ZRsluER8eVIll6hL-EUsoOcz_K4250WM4Rq7qQXFKO9-iNMzSeYxuLL3vB8CnyBsmxX3iOJ9uHUqLgJ0f148ZxD8ka9QjlfHieF3cUCeEPLXWMnHiCMih5_HAbfA5-NKP0I5m2ncijw2mGq0mxLzvOS6idB2dQS0KPJsoNMsyOP5MQHclyXGgmTbiSKPjhD0fsI7lk9ELzD5eUEH0mvGONatyFZ9GK5D8iHs3hvEEXzcSn6egdCc1HIU-gD3mGU71QvsN5nDk-KYXH0EW40kiuLDH-eDgjPDt6NHF4PHjw_Si3w3fhHz9hnhTRJzuuI3wk-At4NLhw6Sgn_KtwccB_iD9gWxUOP8bhHb8HT0evRcJ_ouuC5oM0t0K_I_7gTUpwXI6RZ4fIE-kkynhzvMwFnzmI1MXeQ1xW9MqDHqkj3Fl0fDyeHa2iB9-CF2EuaD9yBWdi4cHjKEoCZzGPfOGhK8tx4kyHSh3SROODkIpRW4eW54J-NEckOZJGPH8S_MXX5HgiHj18MUMWj8UJ_SL-HL0HOxF0_MZ3xDDzoL_QKzr8gOGH8IH-Ii9-eE8s1Bc-7cS1EY3KHPON2D3axMa344eWx4JmH1dKnDxRUtvQ3DJO4spyaH8ORx9yLVlRNcbRH-4T3NERTXrwD4pJKoGvDlt9IeQS9Drcx7jEdHCqHdO2436Ea0cZIlkmBrmOx8WHK0eZC36Kylks47mNI8zEndAcFzleM2hWxkR_PMH14UOYH4V6ovvh4j7eGflx68H24P_gUsHx7fCNx7g2IX5QLpwW5FqWGDyH_vAVrCXgZ0F-iIqOSswe_ESPZqxRH9su6ISvoz2OR0Xt4Olx96CO43gl-CHqB7rxpzjR7EPlctDNQl6SoxJpIT3-wD_q4cmRB1qOPkbeKI3wa9ijBU9E-HSRL9uh4_7wKA1RK1GI5tFxGe0PMQmNf0iPPyIeHf_xJg9O5IeYv3geFuHJID96SRs-HGePG47xRsTFBfpxScthJ1Eq1D9Cwj-eLcZVH-5wwfvRN0b8BzvCPAE5HemWLOgqGfehHc2XNMj7oOxxpOijBDrBMES6ZclxesQzvBX8oD9e9IJ_tJOMagpzNNfBC4-OqTua96i3w6_RK-HR8DmSWULcxMOV43fwP2iuTMi14UwERUrI6MgX5J-S4BbmQ-yPPDn85DhxamIC_7hSPMf9IJmSuAhzYg9OUkrw6UHzoCdyfUjAHf05NGoWB2-InCeS2XFwH4we5ThODp2i7-Dn4BaHMJKSC7qObPKD5ktm1BS-oEyuBc1xXoiThTmSJ5Qx5VGHXmFwcnjjCJ6SIHmi3Mgf4EqHR7uC7xFOZQiZdUOy7MaNn8eHv4EZ6cFH4T_uI_mHvA9OxUEj1phEDTlzHP-D_UmIo3FIhCxRPeiX4wmuJEeeT2hCCslOPNjvBI80EqwUFE3xI9bICXpUBM0zfej0tPglnDeYXIuRH2KP_Ivw5LiUB1nictCdEvfRTTma73hyfNEjrEw-iLMS4-GFPWlCZPmOZuyPOcR_9JUGuyb64_iFL_hkxH6g7YiXF009PLlw7DkO_kHPFE2VrcSToVeQPkR16M3x-DjCE8ePH_mFhD8eocdxXiu6w2nC6ehxIkHe4cwMVlqOvfBTnJi6LNPR7B_4HOm-QE-OPW4i5DiPXM6E39AEH6Vz9MeRb8ePA7kh3ugRUnoERxH6CrVjfHvgx7BPo1aON8UlPEiupIgfBeuNShmoTTz-FCGpHMnNDp9wncF1XDqSPUeYxMf4ZMecHKd-8DrEHz--m3h6_Cr6ozluyRISh9ERH4d7nMcXBhPJB83xDZP-obGET1oRH8nzB2dYNCeO6Ua-7NDx7InwRyuaH6F148qSJ_jT4SyJ8BLRjBnk5EmG3KLQHdtJosyiJsFvoheyZKeQPMqOL0yk4jz847mEX3g61NfxBrXwWChPNGd0fAuq7ALV9EJ6aDx-hPlRH9eO0PrRHNehJzmKXxkhH-oKHz_S47iEzyJyHDr8RyjxFtV4iCoz4kj_glbh4xPyBR8P_UGYUcfDo9_hLwdv-Ee0EZdwCbqOnHjg_IeT4_ng4zDJD8ls5Ds-JniEx1sC58jxaNAp9LqhH2r8oIKe6LiOntByCbEjVnguR9gvXAmPc0HZo7k5_A7yGr9GaNnR49GFZwo0xDkcHj2uHL3RHEfeQbuI-3CP-yGq6cZPdB6xxT3-Ii-OK4Mr1I6D58MnPGJihDyaP9AV4kXIT2i4ZCeeHtWPX3jm4jh7pNJ6_PgiiM-DXMnxwEctxkap7YeDjsmJij6uBOYiJPuR48aPhyeOKb9RUQyeF8n7IecPJsyI8iVQ80RzjshTaHmD8J3w6EDVCk9zXOlxHM1lBX-RI_nRLwf_DP7hB5WOPwgbEeJb4algxgcvvIE14zhO4j0cKYRmLS_6HfxxHf0nzCz0H82DWsiDLxEndO3hP-jxo9-FMId-5A8-EndUBVX06Wj64yqOvN3wFb9DqNKGPjouAulROccfaUPEP8KTQ9cWPD_CHPXmDG9wXUb4Q8uFXA6eG4zawzochcd__INP9C2yHOIR_sLR5wqavHjU8Dji74Tma0jJ4MdF8B2-GH5mGXvhG-GhqPzQjDpygrFz2GGDn4iT69izEY7Q_7ieLZAVEU1Elsi_HB4DL8dk9fiWoelQnkF-KErErMSTNHikqCq0PrgmBeEp-HRU9CHCjIfmIdJTNFUmTQF7VE2EJqm0Is9SFeVyatj4IyQZXDl6NFWWDpeI3DtOY_SLJ8sM9k2QZ2huVMcTA4cAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARSABkmFECASIARQAAIBggQBDggASECKMVIgJIwwQQUAKChDAQAQMJEcwRIAQQAAlCBGEOCEEMA0A5IARBSAgCiUMCMQEEcdYoYQUglgpgCDDCAMoJIAIIxBRyEggCFAIECGEYQYQp4oBgCCAICSAKEUUMIgwIRAxQwDEEDCCOCsAEYIQBIpBUhhoFlGQcAUYgBAQAJIAhgAglFFEYGAGkEswIAAxSlEBAhABAGKWQktApAQRQBABigBIBAAMyNAQqpYACBgACBAHEOAMIEtIoAAgThBkCCCHIChMYAQYBYAUAgCAmTEgEEAEEUUIhNRAABgChCACCKAAEAAAQYwghCAAAAEJgMMEYCEhAAiADCAAFRAACOUKII4gBowwwECABgAJAIKgMoogJAwABQiFBODLECMSQAQYoYCRAAABgjBBGEUiAYQAR6ghiAhBKCFMGEeAFEIIAYBBDABEhFDKKIgOYoAQo4QgToElEAPIMIIAQtVZQgxQoBJIKAENGESSIFAQwgBAgADAAAMBEOGKIQMpJAAgQRCljKCGICKQAIQAYYwQXQCCgDBJECWIIGAgwxgRQRAnDhMMOGICMEAgYIYEiAhADCBGEMiMIAsQQoBAiBAgPiHBEGiMMIIoSoJAABCFJDAFEaKAIAIYyQJQBgigCBAMAgGIAQQYRIZBASAhDABEIIgLEEQA4JgCBSgAAnAEKIIYJoIAYAjAkQCAiCAEMIACYAYAIFDxxSgElGGAcEaGMkIQBBDlSEDFBFRKLAOEEJMIQBYgQgEAGAGEEEKIIcYAZIRChSDOLiAXMMGohUk4IYJFQCAkECCGWGCCIMMwAABATlCgghCjMGWCSEMIAAAigwjhjCAMICQCIEAIZA4gwTgACkGKMMEIVUEwABBzAmBnBlBKCSGIMAcAqpagFBUWCgBRIGCuYUYQhwAggggEIjjKKAyAAMwoE5owIziIiBCSGCAIMAEAoggxFCCAmmFTEWMKUYQgNQBhBgCAEjFNIKeOMQ4AwRYBBwAjGgDDAMQSMUUwAIqAR1jpIEEEEKGMEAkYIhBADQgBEqUFAFEqQIYI4JhSwwihRjUCAGAeQAYgAYrRhgBGkjEBACCEBAEYopIAwQCCGBDAAGUAAoooJJKByRkBDiJDCMa2UAQMYYRgQAGBFADBIGKEAYg4AgAgQSgAoHCFMCgCUAEY5BQBCxjMIEBBEEgAA");
}
[Test]
public void should_parse_fpcalc_text_with_noninteger_duration()
{
var text = @"FILE=Adele - 01 - 21 - Rolling in the Deep.flac
DURATION=229.29
FINGERPRINT=AQAHJlMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-IehuDm92Q9xDzISyH67jOoc_R_OijI61TJLuObzn-zWi6S2gVT3jUIkhOw2pMgU13XPuGM4c7_B_yHCcPPYpD4Tp6DW6To89xIS-qH31w6vjBLksu4mFEDcndIByvI9SPS4PODM2PdumCfOKDXJByhPGKy8FFZcP3olGs4z5T1MrC4yHiK8e_QdSD-KBz9M3RjNIRPfFQQxxH_PBxKYeoSKRw6YGl8Zh4H09i4rogLg_IsDsuHz_6y2imQ2ZThGcO50KaNj2uoZtk6MJjhIm-DeHj4UMzC9V43Hky9Dj0pwv06Dn05MGPR4OnQ3s8_MFDqI8EnYdG6RRSH9eHmgryH192ZCKPPyp-52jqHWXHBT-O5D2Rw85F3JtAX7jeqLCYLMfF4seN_MeUC9pzXCKuR0K7o_mC_1DNDPl21NoLSzuO_sSVBEefZ0hrC8mHU0GVtviDH7XzoM7w9CgfTInCDc8DPhPyH0nkw9vgbEfJRJvwC08I98gj6ESu4ylx3FGJfvIKM7ZRsluER8eVIll6hL-EUsoOcz_K4250WM4Rq7qQXFKO9-iNMzSeYxuLL3vB8CnyBsmxX3iOJ9uHUqLgJ0f148ZxD8ka9QjlfHieF3cUCeEPLXWMnHiCMih5_HAbfA5-NKP0I5m2ncijw2mGq0mxLzvOS6idB2dQS0KPJsoNMsyOP5MQHclyXGgmTbiSKPjhD0fsI7lk9ELzD5eUEH0mvGONatyFZ9GK5D8iHs3hvEEXzcSn6egdCc1HIU-gD3mGU71QvsN5nDk-KYXH0EW40kiuLDH-eDgjPDt6NHF4PHjw_Si3w3fhHz9hnhTRJzuuI3wk-At4NLhw6Sgn_KtwccB_iD9gWxUOP8bhHb8HT0evRcJ_ouuC5oM0t0K_I_7gTUpwXI6RZ4fIE-kkynhzvMwFnzmI1MXeQ1xW9MqDHqkj3Fl0fDyeHa2iB9-CF2EuaD9yBWdi4cHjKEoCZzGPfOGhK8tx4kyHSh3SROODkIpRW4eW54J-NEckOZJGPH8S_MXX5HgiHj18MUMWj8UJ_SL-HL0HOxF0_MZ3xDDzoL_QKzr8gOGH8IH-Ii9-eE8s1Bc-7cS1EY3KHPON2D3axMa344eWx4JmH1dKnDxRUtvQ3DJO4spyaH8ORx9yLVlRNcbRH-4T3NERTXrwD4pJKoGvDlt9IeQS9Drcx7jEdHCqHdO2436Ea0cZIlkmBrmOx8WHK0eZC36Kylks47mNI8zEndAcFzleM2hWxkR_PMH14UOYH4V6ovvh4j7eGflx68H24P_gUsHx7fCNx7g2IX5QLpwW5FqWGDyH_vAVrCXgZ0F-iIqOSswe_ESPZqxRH9su6ISvoz2OR0Xt4Olx96CO43gl-CHqB7rxpzjR7EPlctDNQl6SoxJpIT3-wD_q4cmRB1qOPkbeKI3wa9ijBU9E-HSRL9uh4_7wKA1RK1GI5tFxGe0PMQmNf0iPPyIeHf_xJg9O5IeYv3geFuHJID96SRs-HGePG47xRsTFBfpxScthJ1Eq1D9Cwj-eLcZVH-5wwfvRN0b8BzvCPAE5HemWLOgqGfehHc2XNMj7oOxxpOijBDrBMES6ZclxesQzvBX8oD9e9IJ_tJOMagpzNNfBC4-OqTua96i3w6_RK-HR8DmSWULcxMOV43fwP2iuTMi14UwERUrI6MgX5J-S4BbmQ-yPPDn85DhxamIC_7hSPMf9IJmSuAhzYg9OUkrw6UHzoCdyfUjAHf05NGoWB2-InCeS2XFwH4we5ThODp2i7-Dn4BaHMJKSC7qObPKD5ktm1BS-oEyuBc1xXoiThTmSJ5Qx5VGHXmFwcnjjCJ6SIHmi3Mgf4EqHR7uC7xFOZQiZdUOy7MaNn8eHv4EZ6cFH4T_uI_mHvA9OxUEj1phEDTlzHP-D_UmIo3FIhCxRPeiX4wmuJEeeT2hCCslOPNjvBI80EqwUFE3xI9bICXpUBM0zfej0tPglnDeYXIuRH2KP_Ivw5LiUB1nictCdEvfRTTma73hyfNEjrEw-iLMS4-GFPWlCZPmOZuyPOcR_9JUGuyb64_iFL_hkxH6g7YiXF009PLlw7DkO_kHPFE2VrcSToVeQPkR16M3x-DjCE8ePH_mFhD8eocdxXiu6w2nC6ehxIkHe4cwMVlqOvfBTnJi6LNPR7B_4HOm-QE-OPW4i5DiPXM6E39AEH6Vz9MeRb8ePA7kh3ugRUnoERxH6CrVjfHvgx7BPo1aON8UlPEiupIgfBeuNShmoTTz-FCGpHMnNDp9wncF1XDqSPUeYxMf4ZMecHKd-8DrEHz--m3h6_Cr6ozluyRISh9ERH4d7nMcXBhPJB83xDZP-obGET1oRH8nzB2dYNCeO6Ua-7NDx7InwRyuaH6F148qSJ_jT4SyJ8BLRjBnk5EmG3KLQHdtJosyiJsFvoheyZKeQPMqOL0yk4jz847mEX3g61NfxBrXwWChPNGd0fAuq7ALV9EJ6aDx-hPlRH9eO0PrRHNehJzmKXxkhH-oKHz_S47iEzyJyHDr8RyjxFtV4iCoz4kj_glbh4xPyBR8P_UGYUcfDo9_hLwdv-Ee0EZdwCbqOnHjg_IeT4_ng4zDJD8ls5Ds-JniEx1sC58jxaNAp9LqhH2r8oIKe6LiOntByCbEjVnguR9gvXAmPc0HZo7k5_A7yGr9GaNnR49GFZwo0xDkcHj2uHL3RHEfeQbuI-3CP-yGq6cZPdB6xxT3-Ii-OK4Mr1I6D58MnPGJihDyaP9AV4kXIT2i4ZCeeHtWPX3jm4jh7pNJ6_PgiiM-DXMnxwEctxkap7YeDjsmJij6uBOYiJPuR48aPhyeOKb9RUQyeF8n7IecPJsyI8iVQ80RzjshTaHmD8J3w6EDVCk9zXOlxHM1lBX-RI_nRLwf_DP7hB5WOPwgbEeJb4algxgcvvIE14zhO4j0cKYRmLS_6HfxxHf0nzCz0H82DWsiDLxEndO3hP-jxo9-FMId-5A8-EndUBVX06Wj64yqOvN3wFb9DqNKGPjouAulROccfaUPEP8KTQ9cWPD_CHPXmDG9wXUb4Q8uFXA6eG4zawzochcd__INP9C2yHOIR_sLR5wqavHjU8Dji74Tma0jJ4MdF8B2-GH5mGXvhG-GhqPzQjDpygrFz2GGDn4iT69izEY7Q_7ieLZAVEU1Elsi_HB4DL8dk9fiWoelQnkF-KErErMSTNHikqCq0PrgmBeEp-HRU9CHCjIfmIdJTNFUmTQF7VE2EJqm0Is9SFeVyatj4IyQZXDl6NFWWDpeI3DtOY_SLJ8sM9k2QZ2huVMcTA4cAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARSABkmFECASIARQAAIBggQBDggASECKMVIgJIwwQQUAKChDAQAQMJEcwRIAQQAAlCBGEOCEEMA0A5IARBSAgCiUMCMQEEcdYoYQUglgpgCDDCAMoJIAIIxBRyEggCFAIECGEYQYQp4oBgCCAICSAKEUUMIgwIRAxQwDEEDCCOCsAEYIQBIpBUhhoFlGQcAUYgBAQAJIAhgAglFFEYGAGkEswIAAxSlEBAhABAGKWQktApAQRQBABigBIBAAMyNAQqpYACBgACBAHEOAMIEtIoAAgThBkCCCHIChMYAQYBYAUAgCAmTEgEEAEEUUIhNRAABgChCACCKAAEAAAQYwghCAAAAEJgMMEYCEhAAiADCAAFRAACOUKII4gBowwwECABgAJAIKgMoogJAwABQiFBODLECMSQAQYoYCRAAABgjBBGEUiAYQAR6ghiAhBKCFMGEeAFEIIAYBBDABEhFDKKIgOYoAQo4QgToElEAPIMIIAQtVZQgxQoBJIKAENGESSIFAQwgBAgADAAAMBEOGKIQMpJAAgQRCljKCGICKQAIQAYYwQXQCCgDBJECWIIGAgwxgRQRAnDhMMOGICMEAgYIYEiAhADCBGEMiMIAsQQoBAiBAgPiHBEGiMMIIoSoJAABCFJDAFEaKAIAIYyQJQBgigCBAMAgGIAQQYRIZBASAhDABEIIgLEEQA4JgCBSgAAnAEKIIYJoIAYAjAkQCAiCAEMIACYAYAIFDxxSgElGGAcEaGMkIQBBDlSEDFBFRKLAOEEJMIQBYgQgEAGAGEEEKIIcYAZIRChSDOLiAXMMGohUk4IYJFQCAkECCGWGCCIMMwAABATlCgghCjMGWCSEMIAAAigwjhjCAMICQCIEAIZA4gwTgACkGKMMEIVUEwABBzAmBnBlBKCSGIMAcAqpagFBUWCgBRIGCuYUYQhwAggggEIjjKKAyAAMwoE5owIziIiBCSGCAIMAEAoggxFCCAmmFTEWMKUYQgNQBhBgCAEjFNIKeOMQ4AwRYBBwAjGgDDAMQSMUUwAIqAR1jpIEEEEKGMEAkYIhBADQgBEqUFAFEqQIYI4JhSwwihRjUCAGAeQAYgAYrRhgBGkjEBACCEBAEYopIAwQCCGBDAAGUAAoooJJKByRkBDiJDCMa2UAQMYYRgQAGBFADBIGKEAYg4AgAgQSgAoHCFMCgCUAEY5BQBCxjMIEBBEEgAA
";
var result = Subject.ParseFpcalcTextOutput(text);
result.Duration.Should().Be(229.29);
result.Fingerprint.Should().Be("AQAHJlMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-IehuDm92Q9xDzISyH67jOoc_R_OijI61TJLuObzn-zWi6S2gVT3jUIkhOw2pMgU13XPuGM4c7_B_yHCcPPYpD4Tp6DW6To89xIS-qH31w6vjBLksu4mFEDcndIByvI9SPS4PODM2PdumCfOKDXJByhPGKy8FFZcP3olGs4z5T1MrC4yHiK8e_QdSD-KBz9M3RjNIRPfFQQxxH_PBxKYeoSKRw6YGl8Zh4H09i4rogLg_IsDsuHz_6y2imQ2ZThGcO50KaNj2uoZtk6MJjhIm-DeHj4UMzC9V43Hky9Dj0pwv06Dn05MGPR4OnQ3s8_MFDqI8EnYdG6RRSH9eHmgryH192ZCKPPyp-52jqHWXHBT-O5D2Rw85F3JtAX7jeqLCYLMfF4seN_MeUC9pzXCKuR0K7o_mC_1DNDPl21NoLSzuO_sSVBEefZ0hrC8mHU0GVtviDH7XzoM7w9CgfTInCDc8DPhPyH0nkw9vgbEfJRJvwC08I98gj6ESu4ylx3FGJfvIKM7ZRsluER8eVIll6hL-EUsoOcz_K4250WM4Rq7qQXFKO9-iNMzSeYxuLL3vB8CnyBsmxX3iOJ9uHUqLgJ0f148ZxD8ka9QjlfHieF3cUCeEPLXWMnHiCMih5_HAbfA5-NKP0I5m2ncijw2mGq0mxLzvOS6idB2dQS0KPJsoNMsyOP5MQHclyXGgmTbiSKPjhD0fsI7lk9ELzD5eUEH0mvGONatyFZ9GK5D8iHs3hvEEXzcSn6egdCc1HIU-gD3mGU71QvsN5nDk-KYXH0EW40kiuLDH-eDgjPDt6NHF4PHjw_Si3w3fhHz9hnhTRJzuuI3wk-At4NLhw6Sgn_KtwccB_iD9gWxUOP8bhHb8HT0evRcJ_ouuC5oM0t0K_I_7gTUpwXI6RZ4fIE-kkynhzvMwFnzmI1MXeQ1xW9MqDHqkj3Fl0fDyeHa2iB9-CF2EuaD9yBWdi4cHjKEoCZzGPfOGhK8tx4kyHSh3SROODkIpRW4eW54J-NEckOZJGPH8S_MXX5HgiHj18MUMWj8UJ_SL-HL0HOxF0_MZ3xDDzoL_QKzr8gOGH8IH-Ii9-eE8s1Bc-7cS1EY3KHPON2D3axMa344eWx4JmH1dKnDxRUtvQ3DJO4spyaH8ORx9yLVlRNcbRH-4T3NERTXrwD4pJKoGvDlt9IeQS9Drcx7jEdHCqHdO2436Ea0cZIlkmBrmOx8WHK0eZC36Kylks47mNI8zEndAcFzleM2hWxkR_PMH14UOYH4V6ovvh4j7eGflx68H24P_gUsHx7fCNx7g2IX5QLpwW5FqWGDyH_vAVrCXgZ0F-iIqOSswe_ESPZqxRH9su6ISvoz2OR0Xt4Olx96CO43gl-CHqB7rxpzjR7EPlctDNQl6SoxJpIT3-wD_q4cmRB1qOPkbeKI3wa9ijBU9E-HSRL9uh4_7wKA1RK1GI5tFxGe0PMQmNf0iPPyIeHf_xJg9O5IeYv3geFuHJID96SRs-HGePG47xRsTFBfpxScthJ1Eq1D9Cwj-eLcZVH-5wwfvRN0b8BzvCPAE5HemWLOgqGfehHc2XNMj7oOxxpOijBDrBMES6ZclxesQzvBX8oD9e9IJ_tJOMagpzNNfBC4-OqTua96i3w6_RK-HR8DmSWULcxMOV43fwP2iuTMi14UwERUrI6MgX5J-S4BbmQ-yPPDn85DhxamIC_7hSPMf9IJmSuAhzYg9OUkrw6UHzoCdyfUjAHf05NGoWB2-InCeS2XFwH4we5ThODp2i7-Dn4BaHMJKSC7qObPKD5ktm1BS-oEyuBc1xXoiThTmSJ5Qx5VGHXmFwcnjjCJ6SIHmi3Mgf4EqHR7uC7xFOZQiZdUOy7MaNn8eHv4EZ6cFH4T_uI_mHvA9OxUEj1phEDTlzHP-D_UmIo3FIhCxRPeiX4wmuJEeeT2hCCslOPNjvBI80EqwUFE3xI9bICXpUBM0zfej0tPglnDeYXIuRH2KP_Ivw5LiUB1nictCdEvfRTTma73hyfNEjrEw-iLMS4-GFPWlCZPmOZuyPOcR_9JUGuyb64_iFL_hkxH6g7YiXF009PLlw7DkO_kHPFE2VrcSToVeQPkR16M3x-DjCE8ePH_mFhD8eocdxXiu6w2nC6ehxIkHe4cwMVlqOvfBTnJi6LNPR7B_4HOm-QE-OPW4i5DiPXM6E39AEH6Vz9MeRb8ePA7kh3ugRUnoERxH6CrVjfHvgx7BPo1aON8UlPEiupIgfBeuNShmoTTz-FCGpHMnNDp9wncF1XDqSPUeYxMf4ZMecHKd-8DrEHz--m3h6_Cr6ozluyRISh9ERH4d7nMcXBhPJB83xDZP-obGET1oRH8nzB2dYNCeO6Ua-7NDx7InwRyuaH6F148qSJ_jT4SyJ8BLRjBnk5EmG3KLQHdtJosyiJsFvoheyZKeQPMqOL0yk4jz847mEX3g61NfxBrXwWChPNGd0fAuq7ALV9EJ6aDx-hPlRH9eO0PrRHNehJzmKXxkhH-oKHz_S47iEzyJyHDr8RyjxFtV4iCoz4kj_glbh4xPyBR8P_UGYUcfDo9_hLwdv-Ee0EZdwCbqOnHjg_IeT4_ng4zDJD8ls5Ds-JniEx1sC58jxaNAp9LqhH2r8oIKe6LiOntByCbEjVnguR9gvXAmPc0HZo7k5_A7yGr9GaNnR49GFZwo0xDkcHj2uHL3RHEfeQbuI-3CP-yGq6cZPdB6xxT3-Ii-OK4Mr1I6D58MnPGJihDyaP9AV4kXIT2i4ZCeeHtWPX3jm4jh7pNJ6_PgiiM-DXMnxwEctxkap7YeDjsmJij6uBOYiJPuR48aPhyeOKb9RUQyeF8n7IecPJsyI8iVQ80RzjshTaHmD8J3w6EDVCk9zXOlxHM1lBX-RI_nRLwf_DP7hB5WOPwgbEeJb4algxgcvvIE14zhO4j0cKYRmLS_6HfxxHf0nzCz0H82DWsiDLxEndO3hP-jxo9-FMId-5A8-EndUBVX06Wj64yqOvN3wFb9DqNKGPjouAulROccfaUPEP8KTQ9cWPD_CHPXmDG9wXUb4Q8uFXA6eG4zawzochcd__INP9C2yHOIR_sLR5wqavHjU8Dji74Tma0jJ4MdF8B2-GH5mGXvhG-GhqPzQjDpygrFz2GGDn4iT69izEY7Q_7ieLZAVEU1Elsi_HB4DL8dk9fiWoelQnkF-KErErMSTNHikqCq0PrgmBeEp-HRU9CHCjIfmIdJTNFUmTQF7VE2EJqm0Is9SFeVyatj4IyQZXDl6NFWWDpeI3DtOY_SLJ8sM9k2QZ2huVMcTA4cAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARSABkmFECASIARQAAIBggQBDggASECKMVIgJIwwQQUAKChDAQAQMJEcwRIAQQAAlCBGEOCEEMA0A5IARBSAgCiUMCMQEEcdYoYQUglgpgCDDCAMoJIAIIxBRyEggCFAIECGEYQYQp4oBgCCAICSAKEUUMIgwIRAxQwDEEDCCOCsAEYIQBIpBUhhoFlGQcAUYgBAQAJIAhgAglFFEYGAGkEswIAAxSlEBAhABAGKWQktApAQRQBABigBIBAAMyNAQqpYACBgACBAHEOAMIEtIoAAgThBkCCCHIChMYAQYBYAUAgCAmTEgEEAEEUUIhNRAABgChCACCKAAEAAAQYwghCAAAAEJgMMEYCEhAAiADCAAFRAACOUKII4gBowwwECABgAJAIKgMoogJAwABQiFBODLECMSQAQYoYCRAAABgjBBGEUiAYQAR6ghiAhBKCFMGEeAFEIIAYBBDABEhFDKKIgOYoAQo4QgToElEAPIMIIAQtVZQgxQoBJIKAENGESSIFAQwgBAgADAAAMBEOGKIQMpJAAgQRCljKCGICKQAIQAYYwQXQCCgDBJECWIIGAgwxgRQRAnDhMMOGICMEAgYIYEiAhADCBGEMiMIAsQQoBAiBAgPiHBEGiMMIIoSoJAABCFJDAFEaKAIAIYyQJQBgigCBAMAgGIAQQYRIZBASAhDABEIIgLEEQA4JgCBSgAAnAEKIIYJoIAYAjAkQCAiCAEMIACYAYAIFDxxSgElGGAcEaGMkIQBBDlSEDFBFRKLAOEEJMIQBYgQgEAGAGEEEKIIcYAZIRChSDOLiAXMMGohUk4IYJFQCAkECCGWGCCIMMwAABATlCgghCjMGWCSEMIAAAigwjhjCAMICQCIEAIZA4gwTgACkGKMMEIVUEwABBzAmBnBlBKCSGIMAcAqpagFBUWCgBRIGCuYUYQhwAggggEIjjKKAyAAMwoE5owIziIiBCSGCAIMAEAoggxFCCAmmFTEWMKUYQgNQBhBgCAEjFNIKeOMQ4AwRYBBwAjGgDDAMQSMUUwAIqAR1jpIEEEEKGMEAkYIhBADQgBEqUFAFEqQIYI4JhSwwihRjUCAGAeQAYgAYrRhgBGkjEBACCEBAEYopIAwQCCGBDAAGUAAoooJJKByRkBDiJDCMa2UAQMYYRgQAGBFADBIGKEAYg4AgAgQSgAoHCFMCgCUAEY5BQBCxjMIEBBEEgAA");
}
[TestCase("nin.mp3")]
[TestCase("nin.flac")]
public void should_fingerprint_file(string file)
{
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", file);
var fingerprint = Subject.GetFingerprint(path);
fingerprint.Should().NotBeNull();
fingerprint.Fingerprint.Should().Be("AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ");
fingerprint.Duration.Should().BeApproximately(85.11, 0.1);
}
[TestCase("nin.mp3")]
[TestCase("nin.flac")]
public void should_lookup_file(string file)
{
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", file);
var localTrack = new LocalTrack { Path = path };
Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
localTrack.AcoustIdResults.Should().NotBeNull();
localTrack.AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
}
[Test]
public void should_lookup_list()
{
var files = new [] {
"nin.mp3",
"nin.flac"
}.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();
Subject.Lookup(files, 0.5);
files[0].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
files[1].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
}
[Test]
public void should_lookup_list_when_fpcalc_fails_for_some_files()
{
var files = new [] {
"nin.mp3",
"missing.mp3",
"nin.flac"
}.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();
var idpairs = files.Select(x => Tuple.Create(x, Subject.GetFingerprint(x.Path))).ToList();
Subject.Lookup(idpairs, 0.5);
files[0].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
files[1].AcoustIdResults.Should().BeNull();
files[2].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
}
[Test]
public void should_lookup_list_when_fpcalc_fails_for_all_files()
{
var files = new [] {
"missing1.mp3",
"missing2.mp3"
}.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();
var idpairs = files.Select(x => Tuple.Create<LocalTrack, AcoustId>(x, null)).ToList();
Subject.Lookup(idpairs, 0.5);
files[0].AcoustIdResults.Should().BeNull();
files[1].AcoustIdResults.Should().BeNull();
}
[Test]
public void should_not_fail_if_duration_reported_as_zero()
{
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "missing.mp3");
var localTrack = new LocalTrack { Path = path };
var acoustId = new AcoustId {
Duration = 0,
Fingerprint = "fingerprint"
};
Subject.Lookup(new List<Tuple<LocalTrack, AcoustId>> { Tuple.Create(localTrack, acoustId)}, 0.5);
}
[Test]
public void should_not_throw_if_fingerprint_invalid()
{
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "missing.mp3");
var localTrack = new LocalTrack { Path = path };
var acoustId = new AcoustId {
Duration = 1,
Fingerprint = "fingerprint"
};
var files = new List<Tuple<LocalTrack, AcoustId>> { Tuple.Create(localTrack, acoustId)};
Subject.Lookup(files, 0.5);
files[0].Item1.AcoustIdResults.Should().BeNull();
}
[Test]
public void should_not_fail_for_some_invalid_fingerprints()
{
var files = new [] {
"nin.mp3",
"nin.flac"
}.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();
var idpairs = files.Select(x => Tuple.Create(x, Subject.GetFingerprint(x.Path))).ToList();
idpairs.Add(Tuple.Create(new LocalTrack(), new AcoustId { Duration = 1, Fingerprint = "fingerprint" }));
Subject.Lookup(idpairs, 0.5);
idpairs[0].Item1.AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
idpairs[1].Item1.AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
idpairs[2].Item1.AcoustIdResults.Should().BeNull();
}
[Test]
public void should_not_throw_if_api_returns_html()
{
Mocker.GetMock<IHttpClient>().Setup(x => x.Post<LookupResponse>(It.IsAny<HttpRequest>()))
.Callback<HttpRequest>(req => throw new UnexpectedHtmlContentException(new HttpResponse(req, req.Headers, "html content", HttpStatusCode.Accepted)));
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "nin.mp3");
var localTrack = new LocalTrack { Path = path };
Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
localTrack.AcoustIdResults.Should().BeNull();
ExceptionVerification.ExpectedWarns(4);
}
[Test]
public void should_not_throw_if_api_times_out()
{
Mocker.GetMock<IHttpClient>().Setup(x => x.Post<LookupResponse>(It.IsAny<HttpRequest>()))
.Throws(new System.Net.WebException("The operation has timed out."));
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "nin.mp3");
var localTrack = new LocalTrack { Path = path };
Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
localTrack.AcoustIdResults.Should().BeNull();
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_retry_if_too_many_requests()
{
var error = "{\"error\": {\"code\": 14, \"message\": \"rate limit (3 requests per second) exceeded, try again later\"}, \"status\": \"error\"}";
var response = "{\"fingerprints\": [{\"index\": \"0\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}], \"status\": \"ok\"}";
Mocker.GetMock<IHttpClient>()
.SetupSequence(o => o.Post<LookupResponse>(It.IsAny<HttpRequest>()))
.Returns(new HttpResponse<LookupResponse>(new HttpResponse(new HttpRequest("dummy"), new HttpHeader(), error, HttpStatusCode.ServiceUnavailable)))
.Returns(new HttpResponse<LookupResponse>(new HttpResponse(new HttpRequest("dummy"), new HttpHeader(), response, HttpStatusCode.OK)));
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "nin.mp3");
var localTrack = new LocalTrack { Path = path };
Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
localTrack.AcoustIdResults.Should().NotBeNull();
localTrack.AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
Mocker.GetMock<IHttpClient>()
.Verify(x => x.Post<LookupResponse>(It.IsAny<HttpRequest>()), Times.Exactly(2));
}
[Test]
public void should_not_retry_indefinitely_if_too_many_requests()
{
var error = "{\"error\": {\"code\": 14, \"message\": \"rate limit (3 requests per second) exceeded, try again later\"}, \"status\": \"error\"}";
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Post<LookupResponse>(It.IsAny<HttpRequest>()))
.Returns(new HttpResponse<LookupResponse>(new HttpResponse(new HttpRequest("dummy"), new HttpHeader(), error, HttpStatusCode.ServiceUnavailable)));
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "nin.mp3");
var localTrack = new LocalTrack { Path = path };
Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
localTrack.AcoustIdResults.Should().BeNull();
Mocker.GetMock<IHttpClient>()
.Verify(x => x.Post<LookupResponse>(It.IsAny<HttpRequest>()), Times.Exactly(4));
}
}
}