blob: ec28259ad00d31f6a79a1ff4cae7708c3229d4a7 [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.
*/
// ReSharper disable UnusedMember.Local
// ReSharper disable NotAccessedField.Local
#pragma warning disable 649 // Unassigned field
namespace Apache.Ignite.Core.Tests.Cache.Query
{
using System.IO;
using System.Linq;
using System.Reflection;
using Apache.Ignite.Core.Cache.Affinity;
using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Client;
using NUnit.Framework;
/// <summary>
/// Tests that <see cref="QueryEntity.KeyTypeName"/> and <see cref="QueryEntity.ValueTypeName"/>
/// settings trigger binary metadata registration on cache start for the specified types.
/// <para />
/// Normally, binary metadata is registered in the cluster when an object of the given type is first serialized
/// (for cache storage or other purposes - Services, Compute, etc).
/// However, query engine requires metadata for key/value types on cache start, so an eager registration
/// should be performed.
/// </summary>
public class QueryEntityMetadataRegistrationTest
{
/** */
private const string CacheName = "cache1";
/** */
private const string CacheName2 = "cache2";
/// <summary>
/// Fixture set up.
/// </summary>
[TestFixtureSetUp]
public void StartGrids()
{
var springConfig = Path.Combine("Config", "query-entity-metadata-registration.xml");
for (int i = 0; i < 2; i++)
{
var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
{
SpringConfigUrl = springConfig,
IgniteInstanceName = i.ToString(),
WorkDirectory = Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
"ignite_work_" + GetType().Name + "_" + i),
// Cache configs will be merged with Spring cache configs.
CacheConfiguration = new[]
{
new CacheConfiguration
{
Name = CacheName2,
QueryEntities = new[]
{
new QueryEntity
{
KeyType = typeof(Key3),
ValueType = typeof(string)
}
}
}
}
};
Ignition.Start(cfg);
}
}
/// <summary>
/// Fixture tear down.
/// </summary>
[TestFixtureTearDown]
public void StopGrids()
{
Ignition.StopAll(true);
}
/// <summary>
/// Tests that starting a cache from code with a <see cref="QueryEntity"/> causes binary type registration
/// for key and value types.
/// <para />
/// * Start a new cache with code configuration
/// * Check that query entity is populated correctly
/// * Check that key and value types are registered in the cluster
/// </summary>
[Test]
public void TestCacheStartFromCodeRegistersMetaForQueryEntityTypes()
{
var cfg = new CacheConfiguration
{
Name = TestUtils.TestName,
QueryEntities = new[]
{
new QueryEntity
{
KeyType = typeof(Key1),
ValueType = typeof(Value1)
}
}
};
var cache = Ignition.GetIgnite("0").CreateCache<Key1, Value1>(cfg);
foreach (var ignite in Ignition.GetAll())
{
// Do not use GetBinaryType which always returns something.
// Use GetBinaryTypes to make sure that types are actually registered.
var types = ignite.GetBinary().GetBinaryTypes();
var qryEntity = ignite.GetCache<object, object>(cfg.Name).GetConfiguration().QueryEntities.Single();
var keyType = types.Single(t => t.TypeName == qryEntity.KeyTypeName);
var valType = types.Single(t => t.TypeName == qryEntity.ValueTypeName);
Assert.AreEqual(typeof(Key1).FullName, qryEntity.KeyTypeName);
Assert.AreEqual(typeof(Value1).FullName, qryEntity.ValueTypeName);
Assert.AreEqual("Bar", keyType.AffinityKeyFieldName);
Assert.IsEmpty(keyType.Fields);
Assert.IsNull(valType.AffinityKeyFieldName);
Assert.IsEmpty(valType.Fields);
}
// Verify put/get on server and client.
cache[new Key1{Foo = "a", Bar = 2}] = new Value1 {Name = "x", Value = 1};
using (var client = Ignition.StartClient(new IgniteClientConfiguration("localhost")))
{
var clientCache = client.GetCache<Key1, Value1>(cache.Name);
var val = clientCache.Get(new Key1 {Foo = "a", Bar = 2});
Assert.AreEqual("x", val.Name);
Assert.AreEqual(1, val.Value);
}
}
/// <summary>
/// Tests that starting a cache from code with a <see cref="QueryEntity"/> skips binary type registration
/// for key and value types when those types can't be resolved.
/// <para />
/// * Start a new cache with code configuration and invalid key/value entity type names
/// * Check that query entity is populated correctly
/// </summary>
[Test]
public void TestCacheStartFromCodeSkipsInvalidQueryEntityTypes()
{
var cfg = new CacheConfiguration
{
Name = TestUtils.TestName,
QueryEntities = new[]
{
new QueryEntity
{
KeyTypeName = "Invalid_Name",
ValueTypeName = "Invalid_Name"
}
}
};
Ignition.GetIgnite("0").CreateCache<object, object>(cfg);
foreach (var ignite in Ignition.GetAll())
{
var types = ignite.GetBinary().GetBinaryTypes();
var qryEntity = ignite.GetCache<object, object>(cfg.Name).GetConfiguration().QueryEntities.Single();
var keyType = types.FirstOrDefault(t => t.TypeName == qryEntity.KeyTypeName);
var valType = types.FirstOrDefault(t => t.TypeName == qryEntity.ValueTypeName);
Assert.IsNull(keyType);
Assert.IsNull(valType);
}
}
/// <summary>
/// Tests that starting a cache from Spring XML with a <see cref="QueryEntity"/> causes binary type registration
/// for key and value types.
/// <para />
/// * Get the cache started from Spring XML
/// * Check that query entity is populated correctly
/// * Check that key and value types are registered in the cluster
/// </summary>
[Test]
public void TestCacheStartFromSpringRegistersMetaForQueryEntityTypes()
{
foreach (var ignite in Ignition.GetAll())
{
// Do not use GetBinaryType which always returns something.
// Use GetBinaryTypes to make sure that types are actually registered.
var types = ignite.GetBinary().GetBinaryTypes();
var qryEntity = ignite.GetCache<object, object>(CacheName).GetConfiguration().QueryEntities.Single();
var keyType = types.Single(t => t.TypeName == qryEntity.KeyTypeName);
var valType = types.Single(t => t.TypeName == qryEntity.ValueTypeName);
Assert.AreEqual(typeof(Key2).FullName, qryEntity.KeyTypeName);
Assert.AreEqual(typeof(Value2).FullName, qryEntity.ValueTypeName);
Assert.AreEqual("AffKey", keyType.AffinityKeyFieldName);
Assert.IsEmpty(keyType.Fields);
Assert.IsNull(valType.AffinityKeyFieldName);
Assert.IsEmpty(valType.Fields);
}
}
/// <summary>
/// Tests that starting a cache from <see cref="IgniteConfiguration.CacheConfiguration"/>
/// with a <see cref="QueryEntity"/> causes binary type registration for key and value types.
/// <para />
/// * Get the cache started from <see cref="IgniteConfiguration.CacheConfiguration"/>
/// * Check that query entity is populated correctly
/// * Check that key and value types are registered in the cluster
/// </summary>
[Test]
public void TestCacheStartIgniteConfigurationRegistersMetaForQueryEntityTypes()
{
foreach (var ignite in Ignition.GetAll())
{
var types = ignite.GetBinary().GetBinaryTypes();
var qryEntity = ignite.GetCache<object, object>(CacheName2).GetConfiguration().QueryEntities.Single();
var keyType = types.Single(t => t.TypeName == qryEntity.KeyTypeName);
Assert.AreEqual(typeof(Key3).FullName, qryEntity.KeyTypeName);
Assert.AreEqual("Aff", keyType.AffinityKeyFieldName);
}
}
/** */
private class Key1
{
/** */
[QuerySqlField]
public string Foo;
/** */
[AffinityKeyMapped]
public int Bar;
}
/** */
private class Value1
{
/** */
[QuerySqlField]
public string Name { get; set; }
/** */
[QuerySqlField]
public long Value { get; set; }
}
/** */
private class Key2
{
/** */
public string Baz;
/** */
[AffinityKeyMapped]
public long AffKey;
}
/** */
private class Value2
{
/** */
public string Name { get; set; }
/** */
public decimal Price { get; set; }
}
/** */
private class Key3
{
/** */
public string Qux;
/** */
[AffinityKeyMapped]
public long Aff;
}
}
}