Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/SIL.Harmony.Sample/SampleDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using SIL.Harmony.Changes;
using SIL.Harmony.Config;
using SIL.Harmony.Db;

namespace SIL.Harmony.Sample;

public class SampleDbContext(DbContextOptions<SampleDbContext> options, IOptions<CrdtConfig> crdtConfig) : DbContext(options), ICrdtDbContext
public class SampleDbContext(DbContextOptions<SampleDbContext> options, IOptions<HarmonyConfig> crdtConfig) : DbContext(options), ICrdtDbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
Expand Down
3 changes: 2 additions & 1 deletion src/SIL.Harmony.Tests/Adapter/CustomObjectAdapterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
using Microsoft.Extensions.Options;
using SIL.Harmony.Adapters;
using SIL.Harmony.Changes;
using SIL.Harmony.Config;
using SIL.Harmony.Db;
using SIL.Harmony.Entities;

namespace SIL.Harmony.Tests.Adapter;

public class CustomObjectAdapterTests
{
public class MyDbContext(DbContextOptions<MyDbContext> options, IOptions<CrdtConfig> crdtConfig)
public class MyDbContext(DbContextOptions<MyDbContext> options, IOptions<HarmonyConfig> crdtConfig)
: DbContext(options), ICrdtDbContext
{
public DbSet<MyClass> MyClasses { get; set; } = null!;
Expand Down
46 changes: 43 additions & 3 deletions src/SIL.Harmony.Tests/ConfigTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using System.Text.Json;
using SIL.Harmony.Changes;
using SIL.Harmony.Config;
using SIL.Harmony.Sample.Changes;
using SIL.Harmony.Sample.Models;
using SIL.Harmony.Tests.Adapter;
Expand All @@ -9,7 +12,7 @@ public class ConfigTests
[Fact]
public void CanGetEntityTypes()
{
var config = new CrdtConfig();
var config = new HarmonyConfig();
config.ObjectTypeListBuilder.DefaultAdapter()
.Add<Word>()
.Add<Definition>();
Expand All @@ -23,10 +26,47 @@ public void CanGetEntityTypes()
[Fact]
public void CanGetChangeTypes()
{
var config = new CrdtConfig();
var config = new HarmonyConfig();
config.ChangeTypeListBuilder.Add<NewDefinitionChange>();
config.ChangeTypeListBuilder.Add<SetWordTextChange>();
config.ChangeTypeListBuilder.Add<DeleteChange<Word>>();
var types = config.ChangeTypes.ToArray();
types.Should().BeEquivalentTo([typeof(NewDefinitionChange), typeof(SetWordTextChange)]);
types.Should().BeEquivalentTo([
new RegisteredChangeType(typeof(NewDefinitionChange), nameof(NewDefinitionChange)),
new RegisteredChangeType(typeof(SetWordTextChange), nameof(SetWordTextChange)),
new RegisteredChangeType(typeof(DeleteChange<Word>), "delete:Word"),
]);
}

[Fact]
public void ConfigureJsonOptions_applies_callback()
{
var config = new HarmonyConfig();
config.ConfigureJsonOptions(o => o.PropertyNamingPolicy = JsonNamingPolicy.CamelCase);

config.JsonSerializerOptions.PropertyNamingPolicy.Should().Be(JsonNamingPolicy.CamelCase);
}

[Fact]
public void ConfigureJsonOptions_composes_multiple_callbacks()
{
var config = new HarmonyConfig();
config.ConfigureJsonOptions(o => o.PropertyNamingPolicy = JsonNamingPolicy.CamelCase);
config.ConfigureJsonOptions(o => o.WriteIndented = true);

config.JsonSerializerOptions.PropertyNamingPolicy.Should().Be(JsonNamingPolicy.CamelCase);
config.JsonSerializerOptions.WriteIndented.Should().BeTrue();
}

[Fact]
public void ConfigureJsonOptions_throws_after_freeze()
{
var config = new HarmonyConfig();
_ = config.JsonSerializerOptions;

var act = () => config.ConfigureJsonOptions(o => o.WriteIndented = true);

act.Should().Throw<InvalidOperationException>()
.WithMessage("*JsonOptionsBuilder* frozen*");
}
}
3 changes: 2 additions & 1 deletion src/SIL.Harmony.Tests/DataModelTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using SIL.Harmony.Changes;
using SIL.Harmony.Config;
using SIL.Harmony.Db;
using SIL.Harmony.Sample;
using SIL.Harmony.Sample.Changes;
Expand Down Expand Up @@ -38,7 +39,7 @@ public DataModelTestBase(SqliteConnection connection, bool alwaysValidate = true
{
builder.UseSqlite(connection, true);
}, performanceTest)
.Configure<CrdtConfig>(config => config.AlwaysValidateCommits = alwaysValidate)
.Configure<HarmonyConfig>(config => config.AlwaysValidateCommits = alwaysValidate)
.Replace(ServiceDescriptor.Singleton<IHybridDateTimeProvider>(MockTimeProvider));
configure?.Invoke(serviceCollection);
_services = serviceCollection.BuildServiceProvider();
Expand Down
3 changes: 2 additions & 1 deletion src/SIL.Harmony.Tests/PersistExtraDataTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using SIL.Harmony.Changes;
using SIL.Harmony.Config;
using SIL.Harmony.Entities;

namespace SIL.Harmony.Tests;
Expand Down Expand Up @@ -53,7 +54,7 @@ public PersistExtraDataTests()
{
_dataModelTestBase = new DataModelTestBase(configure: services =>
{
services.Configure<CrdtConfig>(config =>
services.Configure<HarmonyConfig>(config =>
{
config.ObjectTypeListBuilder.DefaultAdapter().Add<ExtraDataModel>();
config.ChangeTypeListBuilder.Add<CreateExtraDataModelChange>();
Expand Down
1 change: 1 addition & 0 deletions src/SIL.Harmony/Adapters/CustomAdapterProvider.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.Json.Serialization.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using SIL.Harmony.Config;
using SIL.Harmony.Entities;
using SIL.Harmony.Helpers;

Expand Down
1 change: 1 addition & 0 deletions src/SIL.Harmony/Adapters/DefaultAdapterProvider.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.Json.Serialization.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using SIL.Harmony.Config;
using SIL.Harmony.Entities;
using SIL.Harmony.Helpers;

Expand Down
2 changes: 1 addition & 1 deletion src/SIL.Harmony/Changes/Change.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace SIL.Harmony.Changes;

/// <summary>
/// Polymorphic JSON for <see cref="IChange"/> is owned by
/// <c>PeekThenConcreteChangeConverter</c> (via <see cref="CrdtConfig"/>), not
/// <c>PeekThenConcreteChangeConverter</c> (via <see cref="Config.HarmonyConfig"/>), not
/// <see cref="JsonPolymorphicAttribute"/>. Unknown <c>$type</c> values become
/// <see cref="OpaqueChange"/>.
/// </summary>
Expand Down
5 changes: 3 additions & 2 deletions src/SIL.Harmony/Changes/ChangeContext.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using SIL.Harmony.Config;
using SIL.Harmony.Db;

namespace SIL.Harmony.Changes;

internal class ChangeContext : IChangeContext
{
private readonly SnapshotWorker _worker;
private readonly CrdtConfig _crdtConfig;
private readonly HarmonyConfig _crdtConfig;

internal ChangeContext(Commit commit, int commitIndex, IDictionary<Guid, ObjectSnapshot> intermediateSnapshots, SnapshotWorker worker, CrdtConfig crdtConfig)
internal ChangeContext(Commit commit, int commitIndex, IDictionary<Guid, ObjectSnapshot> intermediateSnapshots, SnapshotWorker worker, HarmonyConfig crdtConfig)
{
_worker = worker;
_crdtConfig = crdtConfig;
Expand Down
2 changes: 1 addition & 1 deletion src/SIL.Harmony/Changes/PeekThenConcreteChangeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace SIL.Harmony.Changes;

/// <summary>
/// Owns <see cref="IChange"/> discrimination. Requires <c>$type</c> as the first JSON property
/// (matching synthetic write order from <see cref="CrdtConfig"/>).
/// (matching synthetic write order from <see cref="Config.HarmonyConfig"/>).
/// Known discriminators deserialize via cached concrete <see cref="JsonTypeInfo"/>;
/// unknown → <see cref="OpaqueChange"/> preserving the raw payload.
/// </summary>
Expand Down
35 changes: 35 additions & 0 deletions src/SIL.Harmony/Config/ChangeTypeListBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using SIL.Harmony.Changes;
using SIL.Harmony.Entities;

namespace SIL.Harmony.Config;

public readonly record struct RegisteredChangeType(Type Type, string Discriminator);

public class ChangeTypeListBuilder
{
private bool _frozen;

/// <summary>
/// we call freeze when the builder is used to create a json serializer options, as it is not possible to add new types after that.
/// </summary>
internal void Freeze()
{
_frozen = true;
}

private void CheckFrozen()
{
if (_frozen) throw new InvalidOperationException($"{nameof(ChangeTypeListBuilder)} is frozen");
}

private readonly List<RegisteredChangeType> _types = [];
public IReadOnlyList<RegisteredChangeType> Types => _types.AsReadOnly();

public ChangeTypeListBuilder Add<TDerived>() where TDerived : IChange, IPolyType
{
CheckFrozen();
if (_types.Any(t => t.Type == typeof(TDerived))) return this;
_types.Add(new RegisteredChangeType(typeof(TDerived), TDerived.TypeName));
return this;
}
}
Loading
Loading