Skip to content

Commit

Permalink
add support for lists of decimals/objectids
Browse files Browse the repository at this point in the history
  • Loading branch information
nirinchev committed Sep 20, 2020
1 parent 7e356fa commit d1e0cc4
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 72 deletions.
180 changes: 157 additions & 23 deletions Tests/Realm.Tests/Database/ListOfPrimitivesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,18 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Bson;
using NUnit.Framework;
using Realms.Exceptions;

namespace Realms.Tests.Database
{
[TestFixture, Preserve(AllMembers = true)]
public class ListOfPrimitivesTests
public class ListOfPrimitivesTests : RealmInstanceTest
{
private static readonly Random _random = new Random();
private Lazy<Realm> _lazyRealm;

// We capture the current SynchronizationContext when opening a Realm.
// However, NUnit replaces the SynchronizationContext after the SetUp method and before the async test method.
// That's why we make sure we open the Realm in the test method by accessing it lazily.
private Realm _realm => _lazyRealm.Value;

[SetUp]
public void SetUp()
{
_lazyRealm = new Lazy<Realm>(() => Realm.GetInstance(Path.GetTempFileName()));
}

[TearDown]
public void TearDown()
{
if (_lazyRealm.IsValueCreated)
{
Realm.DeleteRealm(_realm.Config);
}
}

#region TestCaseSources

Expand Down Expand Up @@ -242,6 +221,89 @@ public static IEnumerable<object> NullableInt64TestValues()
}
}

private static readonly IEnumerable<decimal?[]> _decimalValues = new[]
{
new decimal?[] { 1.4M },
new decimal?[] { null },
new decimal?[] { decimal.MinValue, decimal.MaxValue, 0 },
new decimal?[] { -1, 3.4M, null, 5.3M, 9.54375843758349634963634M }
};

public static IEnumerable<object> DecimalTestValues()
{
yield return new object[] { null };
var values = _decimalValues.Select(v => v.Where(b => b.HasValue).Select(b => b.Value).ToArray());
foreach (var value in values.Where(a => a.Any()))
{
yield return new object[] { value.ToArray() };
}
}

public static IEnumerable<object> NullableDecimalTestValues()
{
yield return new object[] { null };
foreach (var value in _decimalValues)
{
yield return new object[] { value.ToArray() };
}
}

private static readonly IEnumerable<Decimal128?[]> _decimal128Values = new[]
{
new Decimal128?[] { 1.4M },
new Decimal128?[] { null },
new Decimal128?[] { Decimal128.MinValue, decimal.MinValue, decimal.MaxValue, Decimal128.MaxValue, 0 },
new Decimal128?[] { -1, 3.4M, null, 5.3M, -23.424389584396384963M }
};

public static IEnumerable<object> Decimal128TestValues()
{
yield return new object[] { null };
var values = _decimal128Values.Select(v => v.Where(b => b.HasValue).Select(b => b.Value).ToArray());
foreach (var value in values.Where(a => a.Any()))
{
yield return new object[] { value.ToArray() };
}
}

public static IEnumerable<object> NullableDecimal128TestValues()
{
yield return new object[] { null };
foreach (var value in _decimal128Values)
{
yield return new object[] { value.ToArray() };
}
}

private static ObjectId GenerateRepetitiveObjectId(byte value) => new ObjectId(Enumerable.Range(0, 12).Select(_ => value).ToArray());

private static readonly IEnumerable<ObjectId?[]> _objectIdValues = new[]
{
new ObjectId?[] { new ObjectId("5f651b09f6cddff534c3cddf") },
new ObjectId?[] { null },
new ObjectId?[] { ObjectId.Empty, GenerateRepetitiveObjectId(0), GenerateRepetitiveObjectId(byte.MaxValue) },
new ObjectId?[] { new ObjectId("5f651b2930643efeef987e5d"), GenerateRepetitiveObjectId(byte.MaxValue), null, new ObjectId("5f651c4cf755604f2fbf7440") }
};

public static IEnumerable<object> ObjectIdTestValues()
{
yield return new object[] { null };
var values = _objectIdValues.Select(v => v.Where(b => b.HasValue).Select(b => b.Value).ToArray());
foreach (var value in values.Where(a => a.Any()))
{
yield return new object[] { value.ToArray() };
}
}

public static IEnumerable<object> NullableObjectIdTestValues()
{
yield return new object[] { null };
foreach (var value in _objectIdValues)
{
yield return new object[] { value.ToArray() };
}
}

private static readonly IEnumerable<DateTimeOffset?[]> _dateValues = new[]
{
new DateTimeOffset?[] { DateTimeOffset.UtcNow.AddDays(-4) },
Expand Down Expand Up @@ -360,6 +422,24 @@ public void Test_ManagedInt64List(long[] values)
RunManagedTests(obj => obj.Int64List, values);
}

[TestCaseSource(nameof(DecimalTestValues))]
public void Test_ManagedDecimalList(decimal[] values)
{
RunManagedTests(obj => obj.DecimalList, values);
}

[TestCaseSource(nameof(Decimal128TestValues))]
public void Test_ManagedDecimal128List(Decimal128[] values)
{
RunManagedTests(obj => obj.Decimal128List, values);
}

[TestCaseSource(nameof(ObjectIdTestValues))]
public void Test_ManagedObjectIdList(ObjectId[] values)
{
RunManagedTests(obj => obj.ObjectIdList, values);
}

[TestCaseSource(nameof(DateTestValues))]
public void Test_ManagedDateTimeOffsetList(DateTimeOffset[] values)
{
Expand Down Expand Up @@ -432,6 +512,24 @@ public void Test_ManagedNullableInt64List(long?[] values)
RunManagedTests(obj => obj.NullableInt64List, values);
}

[TestCaseSource(nameof(NullableDecimalTestValues))]
public void Test_ManagedNullableDecimalList(decimal?[] values)
{
RunManagedTests(obj => obj.NullableDecimalList, values);
}

[TestCaseSource(nameof(NullableDecimal128TestValues))]
public void Test_ManagedNullableDecimal128List(Decimal128?[] values)
{
RunManagedTests(obj => obj.NullableDecimal128List, values);
}

[TestCaseSource(nameof(NullableObjectIdTestValues))]
public void Test_ManagedNullableObjectIdList(ObjectId?[] values)
{
RunManagedTests(obj => obj.NullableObjectIdList, values);
}

[TestCaseSource(nameof(NullableDateTestValues))]
public void Test_ManagedNullableDateTimeOffsetList(DateTimeOffset?[] values)
{
Expand Down Expand Up @@ -814,6 +912,24 @@ public void Test_UnmanagedInt64List(long[] values)
RunUnmanagedTests(o => o.Int64List, values);
}

[TestCaseSource(nameof(DecimalTestValues))]
public void Test_UnmanagedDecimalList(decimal[] values)
{
RunUnmanagedTests(obj => obj.DecimalList, values);
}

[TestCaseSource(nameof(Decimal128TestValues))]
public void Test_UnmanagedDecimal128List(Decimal128[] values)
{
RunUnmanagedTests(obj => obj.Decimal128List, values);
}

[TestCaseSource(nameof(ObjectIdTestValues))]
public void Test_UnmanagedObjectIdList(ObjectId[] values)
{
RunUnmanagedTests(obj => obj.ObjectIdList, values);
}

[TestCaseSource(nameof(DateTestValues))]
public void Test_UnmanagedDateTimeOffsetList(DateTimeOffset[] values)
{
Expand Down Expand Up @@ -886,6 +1002,24 @@ public void Test_UnmanagedNullableInt64List(long?[] values)
RunUnmanagedTests(o => o.NullableInt64List, values);
}

[TestCaseSource(nameof(NullableDecimalTestValues))]
public void Test_UnmanagedNullableDecimalList(decimal?[] values)
{
RunUnmanagedTests(obj => obj.NullableDecimalList, values);
}

[TestCaseSource(nameof(NullableDecimal128TestValues))]
public void Test_UnmanagedNullableDecimal128List(Decimal128?[] values)
{
RunUnmanagedTests(obj => obj.NullableDecimal128List, values);
}

[TestCaseSource(nameof(NullableObjectIdTestValues))]
public void Test_UnmanagedONullablebjectIdList(ObjectId?[] values)
{
RunUnmanagedTests(obj => obj.NullableObjectIdList, values);
}

[TestCaseSource(nameof(NullableDateTestValues))]
public void Test_UnmanagedNullableDateTimeOffsetList(DateTimeOffset?[] values)
{
Expand Down
12 changes: 12 additions & 0 deletions Tests/Realm.Tests/Database/TestObjects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ public class ListsObject : RealmObject

public IList<bool> BooleanList { get; }

public IList<decimal> DecimalList { get; }

public IList<Decimal128> Decimal128List { get; }

public IList<ObjectId> ObjectIdList { get; }

public IList<string> StringList { get; }

public IList<byte[]> ByteArrayList { get; }
Expand All @@ -131,6 +137,12 @@ public class ListsObject : RealmObject

public IList<DateTimeOffset?> NullableDateTimeOffsetList { get; }

public IList<decimal?> NullableDecimalList { get; }

public IList<Decimal128?> NullableDecimal128List { get; }

public IList<ObjectId?> NullableObjectIdList { get; }

public IList<RealmInteger<byte>> ByteCounterList { get; }

public IList<RealmInteger<short>> Int16CounterList { get; }
Expand Down
12 changes: 12 additions & 0 deletions Tests/Weaver/AssemblyToProcess/TestObjects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ public class ListsObject : RealmObject

public IList<DateTimeOffset> DateTimeOffsetList { get; }

public IList<decimal> DecimalList { get; }

public IList<Decimal128> Decimal128List { get; }

public IList<ObjectId> ObjectIdList { get; }

public IList<char?> NullableCharList { get; }

public IList<byte?> NullableByteList { get; }
Expand All @@ -135,6 +141,12 @@ public class ListsObject : RealmObject

public IList<DateTimeOffset?> NullableDateTimeOffsetList { get; }

public IList<decimal?> NullableDecimalList { get; }

public IList<Decimal128?> NullableDecimal128List { get; }

public IList<ObjectId?> NullableObjectIdList { get; }

public IList<RealmInteger<byte>> ByteCounterList { get; }

public IList<RealmInteger<short>> Int16CounterList { get; }
Expand Down
52 changes: 48 additions & 4 deletions wrappers/src/list_cs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ REALM_EXPORT void list_add_primitive(List& list, PrimitiveValue& value, NativeEx
case realm::PropertyType::Date | realm::PropertyType::Nullable:
list.add(value.has_value ? from_ticks(value.value.int_value) : Timestamp());
break;
case realm::PropertyType::Decimal:
list.add(realm::Decimal128(value.value.decimal_bits));
break;
case realm::PropertyType::Decimal | realm::PropertyType::Nullable:
list.add(value.has_value ? realm::Decimal128(value.value.decimal_bits) : Decimal128(null()));
break;
case realm::PropertyType::ObjectId:
list.add(to_object_id(value));
break;
case realm::PropertyType::ObjectId | realm::PropertyType::Nullable:
list.add(value.has_value ? util::Optional<ObjectId>(to_object_id(value)) : util::Optional<ObjectId>());
break;
default:
REALM_UNREACHABLE();
}
Expand Down Expand Up @@ -171,32 +183,44 @@ REALM_EXPORT void list_set_primitive(List& list, size_t list_ndx, PrimitiveValue
list.set(list_ndx, value.value.bool_value);
break;
case realm::PropertyType::Bool | realm::PropertyType::Nullable:
list.set(list_ndx, value.has_value ? util::Optional<bool>(value.value.bool_value) : util::Optional<bool>(none));
list.set(list_ndx, value.has_value ? util::Optional<bool>(value.value.bool_value) : util::Optional<bool>());
break;
case realm::PropertyType::Int:
list.set(list_ndx, value.value.int_value);
break;
case realm::PropertyType::Int | realm::PropertyType::Nullable:
list.set(list_ndx, value.has_value ? util::Optional<int64_t>(value.value.int_value) : util::Optional<int64_t>(none));
list.set(list_ndx, value.has_value ? util::Optional<int64_t>(value.value.int_value) : util::Optional<int64_t>());
break;
case realm::PropertyType::Float:
list.set(list_ndx, value.value.float_value);
break;
case realm::PropertyType::Float | realm::PropertyType::Nullable:
list.set(list_ndx, value.has_value ? util::Optional<float>(value.value.float_value) : util::Optional<float>(none));
list.set(list_ndx, value.has_value ? util::Optional<float>(value.value.float_value) : util::Optional<float>());
break;
case realm::PropertyType::Double:
list.set(list_ndx, value.value.double_value);
break;
case realm::PropertyType::Double | realm::PropertyType::Nullable:
list.set(list_ndx, value.has_value ? util::Optional<double>(value.value.double_value) : util::Optional<double>(none));
list.set(list_ndx, value.has_value ? util::Optional<double>(value.value.double_value) : util::Optional<double>());
break;
case realm::PropertyType::Date:
list.set(list_ndx, from_ticks(value.value.int_value));
break;
case realm::PropertyType::Date | realm::PropertyType::Nullable:
list.set(list_ndx, value.has_value ? from_ticks(value.value.int_value) : Timestamp());
break;
case realm::PropertyType::Decimal:
list.set(list_ndx, realm::Decimal128(value.value.decimal_bits));
break;
case realm::PropertyType::Decimal | realm::PropertyType::Nullable:
list.set(list_ndx, value.has_value ? realm::Decimal128(value.value.decimal_bits) : Decimal128(null()));
break;
case realm::PropertyType::ObjectId:
list.set(list_ndx, to_object_id(value));
break;
case realm::PropertyType::ObjectId | realm::PropertyType::Nullable:
list.set(list_ndx, value.has_value ? util::Optional<ObjectId>(to_object_id(value)) : util::Optional<ObjectId>());
break;
default:
REALM_UNREACHABLE();
}
Expand Down Expand Up @@ -283,6 +307,18 @@ REALM_EXPORT void list_insert_primitive(List& list, size_t list_ndx, PrimitiveVa
case realm::PropertyType::Date | realm::PropertyType::Nullable:
list.insert(list_ndx, value.has_value ? from_ticks(value.value.int_value) : Timestamp());
break;
case realm::PropertyType::Decimal:
list.insert(list_ndx, realm::Decimal128(value.value.decimal_bits));
break;
case realm::PropertyType::Decimal | realm::PropertyType::Nullable:
list.insert(list_ndx, value.has_value ? realm::Decimal128(value.value.decimal_bits) : Decimal128(null()));
break;
case realm::PropertyType::ObjectId:
list.insert(list_ndx, to_object_id(value));
break;
case realm::PropertyType::ObjectId | realm::PropertyType::Nullable:
list.insert(list_ndx, value.has_value ? util::Optional<ObjectId>(to_object_id(value)) : util::Optional<ObjectId>());
break;
default:
REALM_UNREACHABLE();
}
Expand Down Expand Up @@ -386,6 +422,14 @@ REALM_EXPORT size_t list_find_primitive(List& list, PrimitiveValue& value, Nativ
return list.find(from_ticks(value.value.int_value));
case realm::PropertyType::Date | realm::PropertyType::Nullable:
return list.find(value.has_value ? from_ticks(value.value.int_value) : Timestamp());
case realm::PropertyType::Decimal:
return list.find(realm::Decimal128(value.value.decimal_bits));
case realm::PropertyType::Decimal | realm::PropertyType::Nullable:
return list.find(value.has_value ? realm::Decimal128(value.value.decimal_bits) : Decimal128(null()));
case realm::PropertyType::ObjectId:
return list.find(to_object_id(value));
case realm::PropertyType::ObjectId | realm::PropertyType::Nullable:
return list.find(value.has_value ? util::Optional<ObjectId>(to_object_id(value)) : util::Optional<ObjectId>());
default:
REALM_UNREACHABLE();
}
Expand Down
Loading

0 comments on commit d1e0cc4

Please sign in to comment.