blob: c9c1fef9c21d06672c38a0970f6826e7fb17ecd4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Apache.Ignite.Tests.Table
{
using System;
using System.Collections.Generic;
using System.Linq;
using Ignite.Table;
using NodaTime;
using NUnit.Framework;
/// <summary>
/// Tests for <see cref="IIgniteTuple"/>.
/// </summary>
public class IgniteTupleTests
{
[TearDown]
public void TearDown()
{
TestUtils.CheckByteArrayPoolLeak();
}
[Test]
public void TestCreateUpdateRead()
{
IIgniteTuple tuple = CreateTuple(new IgniteTuple());
Assert.AreEqual(0, tuple.FieldCount);
tuple["foo"] = 1;
tuple["bar"] = Guid.Empty;
Assert.AreEqual(2, tuple.FieldCount);
Assert.AreEqual(1, tuple["foo"]);
Assert.AreEqual(Guid.Empty, tuple["bar"]);
Assert.AreEqual(1, tuple[0]);
Assert.AreEqual(Guid.Empty, tuple[1]);
Assert.AreEqual("FOO", tuple.GetName(0));
Assert.AreEqual("BAR", tuple.GetName(1));
Assert.AreEqual(0, tuple.GetOrdinal("foo"));
Assert.AreEqual(0, tuple.GetOrdinal("Foo"));
Assert.AreEqual(0, tuple.GetOrdinal("FOO"));
Assert.AreEqual(0, tuple.GetOrdinal("\"FOO\""));
Assert.AreEqual(-1, tuple.GetOrdinal("\"Foo\""));
Assert.AreEqual(1, tuple.GetOrdinal("bar"));
tuple[0] = 2;
tuple["bar"] = "x";
tuple["qux"] = null;
Assert.AreEqual(3, tuple.FieldCount);
Assert.AreEqual(2, tuple["foo"]);
Assert.AreEqual("x", tuple[1]);
Assert.IsNull(tuple[2]);
}
[Test]
public void TestGetNullOrEmptyNameThrowsException()
{
var tuple = CreateTuple(new IgniteTuple { ["Foo"] = 1 });
var ex = Assert.Throws<ArgumentException>(() => tuple.GetOrdinal(string.Empty));
Assert.AreEqual("Column name can not be null or empty.", ex!.Message);
ex = Assert.Throws<ArgumentException>(() => tuple.GetOrdinal(null!));
Assert.AreEqual("Column name can not be null or empty.", ex!.Message);
ex = Assert.Throws<ArgumentException>(() =>
{
var unused = tuple[string.Empty];
});
Assert.AreEqual("Column name can not be null or empty.", ex!.Message);
ex = Assert.Throws<ArgumentException>(() =>
{
var unused = tuple[null!];
});
Assert.AreEqual("Column name can not be null or empty.", ex!.Message);
}
[Test]
public void TestGetNonExistingNameThrowsException()
{
var tuple = CreateTuple(new IgniteTuple { ["Foo"] = 1 });
var ex = Assert.Throws<KeyNotFoundException>(() => { _ = tuple["bar"]; });
Assert.AreEqual("The given key 'BAR' was not present in the dictionary.", ex!.Message);
}
[Test]
public void TestToStringEmpty()
{
var tuple = CreateTuple(new IgniteTuple());
Assert.AreEqual(GetShortClassName() + " { }", tuple.ToString());
}
[Test]
public void TestToStringOneField()
{
var tuple = CreateTuple(new IgniteTuple { ["foo"] = 1 });
Assert.AreEqual(GetShortClassName() + " { FOO = 1 }", tuple.ToString());
}
[Test]
public void TestToStringTwoFields()
{
var tuple = CreateTuple(new IgniteTuple
{
["foo"] = 1,
["b"] = "abcd"
});
Assert.AreEqual(GetShortClassName() + " { FOO = 1, B = abcd }", tuple.ToString());
}
[Test]
public void TestEquality()
{
var guid = Guid.NewGuid();
var t1 = CreateTuple(new IgniteTuple(2) { ["k"] = 1, ["v"] = "2", ["v2"] = guid });
var t2 = CreateTuple(new IgniteTuple(3) { ["K"] = 1, ["V"] = "2", ["V2"] = guid });
var t3 = CreateTuple(new IgniteTuple(4) { ["k"] = 1, ["v"] = null, ["v2"] = guid });
var t4 = CreateTuple(new IgniteTuple(5) { ["v"] = "2", ["k"] = 1, ["V2"] = guid });
var t5 = CreateTuple(new IgniteTuple(6) { ["v"] = "2", ["k"] = 1, ["v2"] = guid, ["v3"] = 1 });
Assert.AreEqual(t1, t2);
Assert.AreEqual(t2, t1);
Assert.AreEqual(t1.GetHashCode(), t2.GetHashCode());
Assert.AreNotEqual(t1, t3);
Assert.AreNotEqual(t1.GetHashCode(), t3.GetHashCode());
Assert.AreNotEqual(t2, t3);
Assert.AreNotEqual(t2.GetHashCode(), t3.GetHashCode());
Assert.AreEqual(t1, t4);
Assert.AreEqual(t2, t4);
Assert.AreEqual(t2.GetHashCode(), t4.GetHashCode());
Assert.AreNotEqual(t4, t5);
Assert.AreNotEqual(t4.GetHashCode(), t5.GetHashCode());
}
[Test]
public void TestTupleEqualityDifferentColumnOrder()
{
var randomBytes = new byte[100];
Random.Shared.NextBytes(randomBytes);
var data = new Dictionary<string, object?>
{
{ "nil", null },
{ "int", Random.Shared.Next() },
{ "short", (short)Random.Shared.Next() },
{ "sbyte", (sbyte)Random.Shared.Next() },
{ "long", Random.Shared.NextInt64() },
{ "dbl", Random.Shared.NextDouble() },
{ "flt", Random.Shared.NextSingle() },
{ "bytes", randomBytes },
{ "str", "s-" + Random.Shared.Next() },
{ "guid", Guid.NewGuid() },
{ "dt", LocalDateTime.FromDateTime(DateTime.UtcNow) },
{ "bool", Random.Shared.Next() % 2 == 0 },
{ "dec", (decimal)Random.Shared.NextDouble() }
};
var tuple1 = CreateTuple(GetRandomizedTuple());
var tuple2 = CreateTuple(GetRandomizedTuple());
Assert.AreEqual(tuple1, tuple2);
Assert.AreEqual(tuple1.GetHashCode(), tuple2.GetHashCode());
Assert.AreNotEqual(tuple1.ToString(), tuple2.ToString());
IgniteTuple GetRandomizedTuple() =>
data
.OrderBy(_ => Random.Shared.Next())
.Aggregate(new IgniteTuple(), (tuple, pair) =>
{
var name = Random.Shared.Next() % 2 == 0
? pair.Key.ToUpperInvariant()
: pair.Key.ToLowerInvariant();
tuple[name] = pair.Value;
return tuple;
});
}
[Test]
public void TestCustomTupleEquality()
{
var tuple = CreateTuple(new IgniteTuple { ["key"] = 42L, ["val"] = "Val1" });
var customTuple = new CustomTestIgniteTuple();
Assert.IsTrue(IIgniteTuple.Equals(tuple, customTuple));
Assert.AreEqual(IIgniteTuple.GetHashCode(tuple), IIgniteTuple.GetHashCode(customTuple));
}
protected virtual string GetShortClassName() => nameof(IgniteTuple);
protected virtual IIgniteTuple CreateTuple(IIgniteTuple source) => source;
}
}