mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-09-13 06:07:30 -04:00
Ported from #1949, which surfaces the manual recovery steps the maintainer had been giving out by hand instead of leaving the user with a raw Lucene error. Adapted to the failure now being contained: with the exception no longer escaping into the library change, the scan-failure catch blocks #1949 hooked would never see it, and hooking only those would still miss every other trigger -- removing books is what crashed the GUI. So the guard moves from AppScaffolding into SearchEngineCommands next to the update commands it protects, and raises UpdateFailed from there. Both GUIs subscribe, so any trigger is covered, and the event carries the exception rather than needing #1949's StackTrace string sniffing to find it. The dialog is shown once per session: a damaged index fails on every library change and these steps only need following once. Co-authored-by: rmcrackan <rmcrackan@gmail.com>
96 lines
2.9 KiB
C#
96 lines
2.9 KiB
C#
using ApplicationServices;
|
|
using AssertionHelper;
|
|
using DataLayer;
|
|
using LibationFileManager;
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
namespace SearchIndexUpdateGuardTests;
|
|
|
|
/// <summary>
|
|
/// A library change is committed to the database before the search index is updated, so a failure to update that
|
|
/// index must be reported rather than propagated. Letting it escape reported a successful scan as
|
|
/// "Error importing library" and starved the event's remaining subscribers.
|
|
/// </summary>
|
|
[TestClass]
|
|
[DoNotParallelize]
|
|
public class SearchIndexUpdateGuardTests
|
|
{
|
|
private string tempLibationFiles = string.Empty;
|
|
private readonly List<Exception> reportedFailures = [];
|
|
|
|
[TestInitialize]
|
|
public void Initialize()
|
|
{
|
|
tempLibationFiles = Path.Combine(Path.GetTempPath(), $"libation-search-index-guard-tests-{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(tempLibationFiles);
|
|
|
|
// A fresh Configuration resolves LibationFiles from this variable, so the index lands in the temp dir.
|
|
Environment.SetEnvironmentVariable(LibationFiles.LIBATION_FILES_DIR, tempLibationFiles);
|
|
Configuration.CreateMockInstance();
|
|
|
|
SearchEngineCommands.UpdateFailed += recordFailure;
|
|
}
|
|
|
|
[TestCleanup]
|
|
public void Cleanup()
|
|
{
|
|
SearchEngineCommands.UpdateFailed -= recordFailure;
|
|
Configuration.RestoreSingletonInstance();
|
|
Environment.SetEnvironmentVariable(LibationFiles.LIBATION_FILES_DIR, null);
|
|
|
|
try
|
|
{
|
|
Directory.Delete(tempLibationFiles, recursive: true);
|
|
}
|
|
catch (IOException)
|
|
{
|
|
// a leftover temp directory is not worth failing a test over
|
|
}
|
|
}
|
|
|
|
private void recordFailure(object? sender, Exception ex) => reportedFailures.Add(ex);
|
|
|
|
/// <summary>Occupying the SearchEngine path with a file leaves the engine nowhere to build its index.</summary>
|
|
private void blockTheIndexDirectory()
|
|
=> File.WriteAllText(Path.Combine(tempLibationFiles, "SearchEngine"), "not a directory");
|
|
|
|
private static List<LibraryBook> library()
|
|
{
|
|
var contributor = Contributor.GetEmpty();
|
|
var book = new Book(new AudibleProductId("B0TEST0001"), "Hound of the Baskervilles", null, null, 1, ContentType.Product, [contributor], [contributor], "us");
|
|
return [new LibraryBook(book, new DateTime(2026, 8, 15), "account")];
|
|
}
|
|
|
|
[TestMethod]
|
|
public void a_library_size_change_survives_an_unusable_search_index()
|
|
{
|
|
blockTheIndexDirectory();
|
|
|
|
SearchEngineCommands.OnLibrarySizeChanged(library());
|
|
|
|
reportedFailures.Should().HaveCount(1);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void a_book_detail_change_survives_an_unusable_search_index()
|
|
{
|
|
blockTheIndexDirectory();
|
|
|
|
SearchEngineCommands.OnBookUserDefinedItemCommitted(library());
|
|
|
|
reportedFailures.Should().HaveCount(1);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void a_successful_update_reports_no_failure()
|
|
{
|
|
SearchEngineCommands.OnLibrarySizeChanged(library());
|
|
|
|
reportedFailures.Should().HaveCount(0);
|
|
Directory.Exists(Path.Combine(tempLibationFiles, "SearchEngine")).Should().BeTrue();
|
|
}
|
|
}
|