LibHac/tests/LibHac.Tests/Kvdb/FlatMapKeyValueStoreTests.cs

584 lines
18 KiB
C#
Raw Normal View History

2020-07-19 04:39:20 +02:00
using System;
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
2020-07-19 04:39:20 +02:00
using LibHac.Kvdb;
using LibHac.Tests.Fs.FileSystemClientTests;
using LibHac.Tools.Fs;
2020-07-19 04:39:20 +02:00
using Xunit;
using TTest = System.Int32;
2021-11-14 20:08:57 +01:00
namespace LibHac.Tests.Kvdb;
public class FlatMapKeyValueStoreTests
2020-07-19 04:39:20 +02:00
{
private static ReadOnlySpan<byte> MountName => "mount"u8;
private static ReadOnlySpan<byte> RootPath => "mount:/"u8;
private static ReadOnlySpan<byte> ArchiveFilePath => "mount:/imkvdb.arc"u8;
2021-11-14 20:08:57 +01:00
private static (FlatMapKeyValueStore<T> kvStore, FileSystemClient fsClient) Create<T>(int capacity)
where T : unmanaged, IEquatable<T>, IComparable<T>
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
FileSystemClient fsClient = FileSystemServerFactory.CreateClient(false);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
using var mountedFs = new UniqueRef<IFileSystem>(new InMemoryFileSystem());
fsClient.Register(MountName, ref mountedFs.Ref).ThrowIfFailure();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<T> kvStore = Create<T>(fsClient, capacity);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
return (kvStore, fsClient);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
private static FlatMapKeyValueStore<T> Create<T>(FileSystemClient fsClient, int capacity)
where T : unmanaged, IEquatable<T>, IComparable<T>
{
var memoryResource = new ArrayPoolMemoryResource();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
var kvStore = new FlatMapKeyValueStore<T>();
kvStore.Initialize(fsClient, RootPath, capacity, memoryResource, memoryResource).ThrowIfFailure();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
return kvStore;
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
private static byte[][] GenerateValues(int count, int startingSize)
{
byte[][] values = new byte[count][];
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
for (int i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
byte[] value = new byte[startingSize + i];
2022-12-10 19:12:43 +01:00
value.AsSpan().Fill(unchecked((byte)count));
2021-11-14 20:08:57 +01:00
values[i] = value;
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
return values;
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
private static Result PopulateKvStore(FlatMapKeyValueStore<TTest> kvStore, out byte[][] addedValues, int count,
int startingValueSize = 20, int seed = -1)
{
addedValues = null;
byte[][] values = GenerateValues(count, startingValueSize);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
if (seed == -1)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
for (TTest i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
Result res = kvStore.Set(in i, values[i]);
if (res.IsFailure()) return res.Miss();
2020-07-19 04:39:20 +02:00
}
2021-11-14 20:08:57 +01:00
}
else
{
var rng = new FullCycleRandom(count, seed);
for (int i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
TTest index = rng.Next();
Result res = kvStore.Set(in index, values[index]);
if (res.IsFailure()) return res.Miss();
2020-07-19 04:39:20 +02:00
}
}
2021-11-14 20:08:57 +01:00
addedValues = values;
return Result.Success;
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Count_EmptyStore_ReturnsZero()
{
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(10);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(0, kvStore.Count);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(1)]
[InlineData(5)]
[InlineData(10)]
public void Count_PopulatedStore_ReturnsCorrectCount(int count)
{
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(10);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(count, kvStore.Count);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Load_FileDoesNotExist_ExistingEntriesAreCleared()
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(kvStore.Load());
Assert.Equal(0, kvStore.Count);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(10)]
public void Load_AfterArchiveHasBeenSaved_AllEntriesAreLoaded(int count)
{
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient fsClient) = Create<TTest>(count + 5);
Assert.Success(PopulateKvStore(kvStore, out byte[][] values, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(kvStore.Save());
kvStore.Dispose();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
kvStore = Create<TTest>(fsClient, count + 5);
Assert.Success(kvStore.Load());
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Check if each key-value pair matches
for (int i = 0; i < count; i++)
{
TTest expectedKey = i;
byte[] expectedValue = values[i];
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
ref FlatMapKeyValueStore<TTest>.KeyValue kv = ref iterator.Get();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(expectedKey, kv.Key);
Assert.Equal(expectedValue, kv.Value.Span.ToArray());
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
iterator.Next();
2020-07-19 04:39:20 +02:00
}
2021-11-14 20:08:57 +01:00
Assert.True(iterator.IsEnd());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Load_CapacityIsTooSmall_ReturnsOutOfKeyResource()
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient fsClient) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(kvStore.Save());
kvStore.Dispose();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
kvStore = Create<TTest>(fsClient, count - 5);
Assert.Result(ResultKvdb.OutOfKeyResource, kvStore.Load());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(10)]
public void Save_ArchiveFileIsWrittenToDisk(int count)
{
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient fsClient) = Create<TTest>(count + 5);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(kvStore.Save());
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(fsClient.GetEntryType(out DirectoryEntryType entryType, ArchiveFilePath));
Assert.Equal(DirectoryEntryType.File, entryType);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Get_PopulatedStoreAndEntryDoesNotExist_ReturnsKeyNotFound()
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest key = 20;
byte[] value = new byte[20];
2020-07-19 04:39:20 +02:00
Result res = kvStore.Get(out int _, in key, value);
Assert.Result(ResultKvdb.KeyNotFound, res);
2021-11-14 20:08:57 +01:00
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Get_PopulatedStore_GetsCorrectValueSizes()
{
const int count = 10;
const int startingValueSize = 20;
const int rngSeed = 220;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count, startingValueSize, rngSeed));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Check the size of each entry
byte[] value = new byte[100];
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
for (TTest i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
Assert.Success(kvStore.Get(out int valueSize, in i, value));
Assert.Equal(startingValueSize + i, valueSize);
}
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Get_PopulatedStoreAndEntryExists_GetsCorrectValue()
{
const int count = 10;
const int startingValueSize = 20;
const int rngSeed = 188;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out byte[][] values, count, startingValueSize, rngSeed));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Check if each value matches
byte[] value = new byte[100];
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
for (int i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
TTest key = i;
Assert.Success(kvStore.Get(out int _, in key, value));
Assert.Equal(values[i], value.AsSpan(0, startingValueSize + i).ToArray());
}
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(1)]
[InlineData(5)]
[InlineData(10)]
public void Set_StoreIsFullAndEntryDoesNotExist_ReturnsOutOfKeyResource(int count)
{
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out byte[][] values, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest key = count;
Result res = kvStore.Set(in key, values[0]);
2020-07-19 04:39:20 +02:00
Assert.Result(ResultKvdb.OutOfKeyResource, res);
2021-11-14 20:08:57 +01:00
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(0)]
[InlineData(5)]
[InlineData(9)]
public void Set_StoreIsFullAndEntryAlreadyExists_ReplacesOriginalValue(int entryToReplace)
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest key = entryToReplace;
byte[] value = new byte[15];
value.AsSpan().Fill(0xFF);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(kvStore.Set(in key, value));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Read back the value
byte[] readValue = new byte[20];
Assert.Success(kvStore.Get(out int valueSize, in key, readValue));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Check the value contents and size
Assert.Equal(value.Length, valueSize);
Assert.Equal(value, readValue.AsSpan(0, valueSize).ToArray());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(10, 89)]
[InlineData(10, 50)]
[InlineData(1000, 75367)]
[InlineData(1000, 117331)]
public void Set_StoreIsFilledInRandomOrder_EntriesAreSorted(int entryCount, int rngSeed)
{
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(entryCount + 10);
Assert.Success(PopulateKvStore(kvStore, out byte[][] values, entryCount, 20, rngSeed));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Check if each key-value pair matches
for (int i = 0; i < entryCount; i++)
{
TTest expectedKey = i;
byte[] expectedValue = values[i];
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
ref FlatMapKeyValueStore<TTest>.KeyValue kv = ref iterator.Get();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(expectedKey, kv.Key);
Assert.Equal(expectedValue, kv.Value.Span.ToArray());
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
iterator.Next();
2020-07-19 04:39:20 +02:00
}
2021-11-14 20:08:57 +01:00
Assert.True(iterator.IsEnd());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Delete_EmptyStore_ReturnsKeyNotFound()
{
const int count = 10;
TTest keyToDelete = 4;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
2020-07-19 04:39:20 +02:00
Result res = kvStore.Delete(in keyToDelete);
Assert.Result(ResultKvdb.KeyNotFound, res);
2021-11-14 20:08:57 +01:00
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void Delete_PopulatedStoreAndEntryDoesNotExist_ReturnsKeyNotFound()
{
const int count = 10;
TTest keyToDelete = 44;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
Result res = kvStore.Delete(in keyToDelete);
Assert.Result(ResultKvdb.KeyNotFound, res);
2021-11-14 20:08:57 +01:00
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(0)]
[InlineData(5)]
[InlineData(9)]
public void Delete_PopulatedStoreAndEntryExists_CannotGetAfterDeletion(int entryToDelete)
{
const int count = 10;
const int startingValueSize = 20;
const int rngSeed = 114;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count, startingValueSize, rngSeed));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest keyToDelete = entryToDelete;
Assert.Success(kvStore.Delete(in keyToDelete));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
byte[] value = new byte[20];
2020-07-19 04:39:20 +02:00
Result res = kvStore.Get(out int _, in keyToDelete, value);
Assert.Result(ResultKvdb.KeyNotFound, res);
2021-11-14 20:08:57 +01:00
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(0)]
[InlineData(5)]
[InlineData(9)]
public void Delete_PopulatedStoreAndEntryExists_CountIsDecremented(int entryToDelete)
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest keyToDelete = entryToDelete;
Assert.Success(kvStore.Delete(in keyToDelete));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(count - 1, kvStore.Count);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(0)]
[InlineData(5)]
[InlineData(9)]
public void Delete_PopulatedStoreAndEntryExists_RemainingEntriesAreSorted(int entryToDelete)
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest keyToDelete = entryToDelete;
Assert.Success(kvStore.Delete(in keyToDelete));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Check if the remaining keys exist in order
for (int i = 0; i < count; i++)
{
if (i == entryToDelete)
continue;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest expectedKey = i;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(expectedKey, iterator.Get().Key);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
iterator.Next();
2020-07-19 04:39:20 +02:00
}
2021-11-14 20:08:57 +01:00
Assert.True(iterator.IsEnd());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(0)]
[InlineData(5)]
[InlineData(9)]
public void GetLowerBoundIterator_EntryExists_StartsIterationAtSpecifiedKey(int startEntry)
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest startingKey = startEntry;
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetLowerBoundIterator(in startingKey);
Assert.False(iterator.IsEnd());
Assert.Equal(startingKey, iterator.Get().Key);
}
[Theory]
[InlineData(1)]
[InlineData(5)]
[InlineData(9)]
public void GetLowerBoundIterator_EntryDoesNotExist_StartsIterationAtNextLargestKey(int startIndex)
{
const int count = 10;
const int startingValueSize = 20;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
byte[][] values = GenerateValues(count, startingValueSize);
for (int i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
TTest key = i * 2;
Assert.Success(kvStore.Set(in key, values[i]));
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest startingKey = startIndex;
TTest nextLargestKey = startIndex + 1;
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetLowerBoundIterator(in startingKey);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.False(iterator.IsEnd());
Assert.Equal(nextLargestKey, iterator.Get().Key);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void GetLowerBoundIterator_LargerThanAllKeysInStore_IteratorIsAtEnd()
{
const int count = 10;
const int startIndex = 20;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest key = startIndex;
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetLowerBoundIterator(in key);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.True(iterator.IsEnd());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(2, 3, 2)]
[InlineData(3, 3, 4)]
[InlineData(5, 3, 5)]
public void FixIterator_RemoveEntry_IteratorPointsToSameEntry(int positionWhenRemoving, int entryToRemove, int expectedNewPosition)
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
while (iterator.Get().Key != positionWhenRemoving)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
iterator.Next();
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest keyToRemove = entryToRemove;
Assert.Success(kvStore.Delete(in keyToRemove));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
kvStore.FixIterator(ref iterator, in keyToRemove);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest expectedKey = expectedNewPosition;
Assert.Equal(expectedKey, iterator.Get().Key);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(6, 7, 6)]
[InlineData(8, 7, 8)]
public void FixIterator_AddEntry_IteratorPointsToSameEntry(int positionWhenAdding, int entryToAdd, int expectedNewPosition)
{
const int count = 10;
const int startingValueSize = 20;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count + 5);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
byte[][] values = GenerateValues(count, startingValueSize);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
for (int i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
TTest key = i * 2;
Assert.Success(kvStore.Set(in key, values[i]));
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
while (iterator.Get().Key != positionWhenAdding)
{
iterator.Next();
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest keyToAdd = entryToAdd;
byte[] valueToAdd = new byte[10];
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(kvStore.Set(in keyToAdd, valueToAdd));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
kvStore.FixIterator(ref iterator, in keyToAdd);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
TTest expectedKey = expectedNewPosition;
Assert.Equal(expectedKey, iterator.Get().Key);
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void IteratorIsEnd_EmptyStore_ReturnsTrue()
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
Assert.True(iterator.IsEnd());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void IteratorIsEnd_PopulatedStore_ReturnsFalseUntilFinishedIterating()
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out _, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
for (int i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
Assert.False(iterator.IsEnd());
iterator.Next();
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Iterated all entries. Should return true now
Assert.True(iterator.IsEnd());
}
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void IteratorGet_PopulatedStore_ReturnsEntriesInOrder()
{
const int count = 10;
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
(FlatMapKeyValueStore<TTest> kvStore, FileSystemClient _) = Create<TTest>(count);
Assert.Success(PopulateKvStore(kvStore, out byte[][] values, count));
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
FlatMapKeyValueStore<TTest>.Iterator iterator = kvStore.GetBeginIterator();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
// Check if each key-value pair matches
for (int i = 0; i < count; i++)
2020-07-19 04:39:20 +02:00
{
2021-11-14 20:08:57 +01:00
TTest expectedKey = i;
byte[] expectedValue = values[i];
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
ref FlatMapKeyValueStore<TTest>.KeyValue kv = ref iterator.Get();
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(expectedKey, kv.Key);
Assert.Equal(expectedValue, kv.Value.Span.ToArray());
2020-07-19 04:39:20 +02:00
2021-11-14 20:08:57 +01:00
iterator.Next();
2020-07-19 04:39:20 +02:00
}
}
}