| /* |
| * 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 UnusedAutoPropertyAccessor.Local |
| // ReSharper disable NonReadonlyMemberInGetHashCode |
| namespace Apache.Ignite.Core.Tests.Cache.Query.Continuous |
| { |
| using System; |
| using System.Collections; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Threading; |
| using Apache.Ignite.Core.Cache.Event; |
| using Apache.Ignite.Core.Cache.Query.Continuous; |
| using Apache.Ignite.Core.Common; |
| using Apache.Ignite.Core.Interop; |
| using NUnit.Framework; |
| |
| /// <summary> |
| /// Tests query in a cluster with Java-only and .NET nodes. |
| /// </summary> |
| [Category(TestUtils.CategoryIntensive)] |
| public class ContinuousQueryJavaFilterTest |
| { |
| /** */ |
| private const string SpringConfig = @"Config\Compute\compute-grid1.xml"; |
| |
| /** */ |
| private const string SpringConfig2 = @"Config\Compute\compute-grid2.xml"; |
| |
| /** */ |
| private const string StartTask = "org.apache.ignite.platform.PlatformStartIgniteTask"; |
| |
| /** */ |
| private const string StopTask = "org.apache.ignite.platform.PlatformStopIgniteTask"; |
| |
| /** */ |
| private const string PlatformFilter = "org.apache.ignite.platform.PlatformCacheEntryEventFilter"; |
| |
| /** */ |
| private const string PlatformFilterFactory = "org.apache.ignite.platform.PlatformCacheEntryEventFilterFactory"; |
| |
| /** */ |
| private IIgnite _ignite; |
| |
| /** */ |
| private string _javaNodeName; |
| |
| /** */ |
| private static volatile Tuple<int, object> _lastEvent; |
| |
| /// <summary> |
| /// Fixture set up. |
| /// </summary> |
| [TestFixtureSetUp] |
| public void FixtureSetUp() |
| { |
| // Main .NET node |
| _ignite = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration()) |
| { |
| SpringConfigUrl = SpringConfig, |
| }); |
| |
| // Second .NET node |
| Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration()) |
| { |
| SpringConfigUrl = SpringConfig2, |
| IgniteInstanceName = "dotNet2" |
| }); |
| |
| // Java-only node |
| _javaNodeName = _ignite.GetCompute().ExecuteJavaTask<string>(StartTask, SpringConfig2); |
| |
| Assert.IsTrue(_ignite.WaitTopology(3, 5000)); |
| } |
| |
| /// <summary> |
| /// Fixture tear down. |
| /// </summary> |
| [TestFixtureTearDown] |
| public void FixtureTearDown() |
| { |
| _ignite.GetCompute().ExecuteJavaTask<object>(StopTask, _javaNodeName); |
| Ignition.StopAll(true); |
| } |
| |
| /// <summary> |
| /// Tests the filter. |
| /// </summary> |
| [Test] |
| public void TestFilter() |
| { |
| var javaObj = new JavaObject(PlatformFilter) |
| { |
| Properties = |
| { |
| {"startsWith", "valid"}, |
| {"charField", 'a'}, |
| {"byteField", (byte) 1}, |
| {"sbyteField", (sbyte) 2}, |
| {"shortField", (short) 3}, |
| {"ushortField", (ushort) 4}, |
| {"intField", 5}, |
| {"uintField", (uint) 6}, |
| {"longField", (long) 7}, |
| {"ulongField", (ulong) 8}, |
| {"floatField", (float) 9.99}, |
| {"doubleField", 10.123}, |
| {"decimalField", (decimal) 11.245}, |
| {"boolField", true}, |
| {"guidField", Guid.Parse("1c579241-509d-47c6-a1a0-87462ae31e59")}, |
| { |
| "objField", new TestBinary(1, "2") |
| |
| }, |
| {"charArr", new[] {'a'}}, |
| {"byteArr", new[] {(byte) 1}}, |
| {"sbyteArr", new[] {(sbyte) 2}}, |
| {"shortArr", new[] {(short) 3}}, |
| {"ushortArr", new[] {(ushort) 4}}, |
| {"intArr", new[] {5}}, |
| {"uintArr", new[] {(uint) 6}}, |
| {"longArr", new[] {(long) 7}}, |
| {"ulongArr", new[] {(ulong) 8}}, |
| {"floatArr", new[] {(float) 9.99}}, |
| {"doubleArr", new[] {10.123}}, |
| {"boolArr", new[] {true}}, |
| { |
| "objArr", new object[] |
| { |
| new TestBinary(1, "2") |
| } |
| }, |
| {"arrayList", new ArrayList {"x"}}, |
| {"hashTable", new Hashtable {{1, "2"}}} |
| } |
| }; |
| |
| TestFilter(javaObj); |
| } |
| |
| /// <summary> |
| /// Tests the factory class. |
| /// </summary> |
| [Test] |
| public void TestFactory() |
| { |
| var javaObj = new JavaObject(PlatformFilterFactory, |
| new Dictionary<string, object> {{"startsWith", "valid"}}); |
| |
| TestFilter(javaObj); |
| } |
| |
| /// <summary> |
| /// Tests the invalid class name |
| /// </summary> |
| [Test] |
| public void TestInvalidClassName() |
| { |
| var javaObj = new JavaObject("blabla"); |
| |
| var ex = Assert.Throws<IgniteException>(() => TestFilter(javaObj)); |
| |
| Assert.IsTrue(ex.Message.StartsWith("Java object/factory class is not found")); |
| } |
| |
| /// <summary> |
| /// Tests the invalid class name |
| /// </summary> |
| [Test] |
| public void TestInvalidProperty() |
| { |
| var javaObject = new JavaObject(PlatformFilter) |
| { |
| Properties = {{"invalidProp", "123"}} |
| }; |
| |
| var ex = Assert.Throws<IgniteException>(() => TestFilter(javaObject)); |
| |
| Assert.IsTrue(ex.Message.StartsWith("Java object/factory class field is not found")); |
| } |
| |
| /// <summary> |
| /// Tests the specified filter. |
| /// </summary> |
| private void TestFilter(JavaObject obj) |
| { |
| TestFilter(obj, true); |
| TestFilter(obj, false); |
| } |
| |
| /// <summary> |
| /// Tests the specified filter. |
| /// </summary> |
| private void TestFilter(JavaObject obj, bool local) |
| { |
| // Test with cache of strings |
| var pred = obj.ToCacheEntryEventFilter<int, string>(); |
| |
| TestFilter(pred, local, "validValue", "invalidValue"); |
| |
| // Test with cache of binary objects |
| var objPred = obj.ToCacheEntryEventFilter<int, TestBinary>(); |
| |
| TestFilter(objPred, local, new TestBinary(1, "validValue"), new TestBinary(2, "invalidValue")); |
| } |
| |
| /// <summary> |
| /// Tests the specified filter. |
| /// </summary> |
| private void TestFilter<T>(ICacheEntryEventFilter<int, T> pred, bool local, T validVal, T invalidVal) |
| { |
| var cache = _ignite.GetOrCreateCache<int, T>("qry"); |
| cache.Clear(); |
| |
| var qry = new ContinuousQuery<int, T>(new QueryListener<T>(), pred, local); |
| var aff = _ignite.GetAffinity("qry"); |
| var localNode = _ignite.GetCluster().GetLocalNode(); |
| |
| // Get one key per node |
| var keyMap = aff.MapKeysToNodes(Enumerable.Range(1, 100)); |
| Assert.AreEqual(3, keyMap.Count); |
| var keys = local |
| ? keyMap[localNode].Take(1) |
| : keyMap.Select(x => x.Value.First()); |
| |
| using (cache.QueryContinuous(qry)) |
| { |
| // Run on many keys to test all nodes |
| foreach (var key in keys) |
| { |
| _lastEvent = null; |
| cache[key] = validVal; |
| |
| TestUtils.WaitForCondition(() => _lastEvent != null, 2000); |
| Assert.IsNotNull(_lastEvent); |
| Assert.AreEqual(cache[key], _lastEvent.Item2); |
| |
| _lastEvent = null; |
| cache[key] = invalidVal; |
| |
| Thread.Sleep(2000); |
| Assert.IsNull(_lastEvent); |
| } |
| } |
| } |
| |
| /// <summary> |
| /// Test listener. |
| /// </summary> |
| private class QueryListener<T> : ICacheEntryEventListener<int, T> |
| { |
| /** <inheritdoc /> */ |
| public void OnEvent(IEnumerable<ICacheEntryEvent<int, T>> evts) |
| { |
| _lastEvent = evts.Select(e => Tuple.Create(e.Key, (object) e.Value)).FirstOrDefault(); |
| } |
| } |
| |
| /// <summary> |
| /// Test binary object. |
| /// </summary> |
| private class TestBinary |
| { |
| public TestBinary(int i, string s) |
| { |
| Int = i; |
| String = s; |
| } |
| |
| private int Int { get; set; } |
| private string String { get; set; } |
| |
| private bool Equals(TestBinary other) |
| { |
| return Int == other.Int && string.Equals(String, other.String); |
| } |
| |
| public override bool Equals(object obj) |
| { |
| if (ReferenceEquals(null, obj)) return false; |
| if (ReferenceEquals(this, obj)) return true; |
| if (obj.GetType() != GetType()) return false; |
| return Equals((TestBinary) obj); |
| } |
| |
| public override int GetHashCode() |
| { |
| unchecked |
| { |
| return (Int*397) ^ (String != null ? String.GetHashCode() : 0); |
| } |
| } |
| } |
| } |
| } |