Esempio n. 1
0
  /**
   * @param ignoredTests Tests don't include in the execution.
   * @return Test suite.
   * @throws Exception Thrown in case of the failure.
   */
  public static TestSuite suite(Set<Class> ignoredTests) throws Exception {
    TestSuite suite = new TestSuite("Ignite Basic Test Suite");

    suite.addTest(IgniteLangSelfTestSuite.suite());
    suite.addTest(IgniteUtilSelfTestSuite.suite(ignoredTests));
    suite.addTest(IgniteMarshallerSelfTestSuite.suite(ignoredTests));

    suite.addTest(IgniteKernalSelfTestSuite.suite(ignoredTests));
    suite.addTest(IgniteStartUpTestSuite.suite());
    suite.addTest(IgniteExternalizableSelfTestSuite.suite());
    suite.addTest(IgniteP2PSelfTestSuite.suite());
    suite.addTest(IgniteCacheP2pUnmarshallingErrorTestSuite.suite(ignoredTests));
    suite.addTest(IgniteStreamSelfTestSuite.suite());

    suite.addTest(new TestSuite(GridSelfTest.class));
    suite.addTest(new TestSuite(ClusterGroupHostsSelfTest.class));
    suite.addTest(new TestSuite(IgniteMessagingWithClientTest.class));

    GridTestUtils.addTestIfNeeded(suite, ClusterGroupSelfTest.class, ignoredTests);
    GridTestUtils.addTestIfNeeded(suite, GridMessagingSelfTest.class, ignoredTests);
    GridTestUtils.addTestIfNeeded(
        suite, GridMessagingNoPeerClassLoadingSelfTest.class, ignoredTests);

    if (U.isLinux() || U.isMacOs()) suite.addTest(IgniteIpcSharedMemorySelfTestSuite.suite());

    GridTestUtils.addTestIfNeeded(suite, GridReleaseTypeSelfTest.class, ignoredTests);
    suite.addTestSuite(GridProductVersionSelfTest.class);
    suite.addTestSuite(GridAffinityProcessorRendezvousSelfTest.class);
    suite.addTestSuite(GridClosureProcessorSelfTest.class);
    suite.addTestSuite(ClosureServiceClientsNodesTest.class);
    suite.addTestSuite(GridStartStopSelfTest.class);
    suite.addTestSuite(GridProjectionForCachesSelfTest.class);
    suite.addTestSuite(GridProjectionForCachesOnDaemonNodeSelfTest.class);
    suite.addTestSuite(GridSpiLocalHostInjectionTest.class);
    suite.addTestSuite(GridLifecycleBeanSelfTest.class);
    suite.addTestSuite(GridStopWithCancelSelfTest.class);
    suite.addTestSuite(GridReduceSelfTest.class);
    suite.addTestSuite(GridEventConsumeSelfTest.class);
    suite.addTestSuite(GridSuppressedExceptionSelfTest.class);
    suite.addTestSuite(GridLifecycleAwareSelfTest.class);
    suite.addTestSuite(GridMessageListenSelfTest.class);
    suite.addTestSuite(GridFailFastNodeFailureDetectionSelfTest.class);
    suite.addTestSuite(OffHeapTieredTransactionSelfTest.class);
    suite.addTestSuite(IgniteSlowClientDetectionSelfTest.class);
    suite.addTestSuite(IgniteDaemonNodeMarshallerCacheTest.class);

    suite.addTestSuite(IgniteExceptionInNioWorkerSelfTest.class);

    return suite;
  }
  /** @throws Exception Exception. */
  private void checkLock(final boolean fair) throws Exception {
    // Check only 'false' cases here. Successful lock is tested over the grid.
    final IgniteLock lock = createReentrantLock("acquire", false, fair);

    lock.lock();

    IgniteInternalFuture fut =
        GridTestUtils.runAsync(
            new Callable<Void>() {
              @Override
              public Void call() throws Exception {
                assertNotNull(lock);

                assert !lock.tryLock();

                assert !lock.tryLock(10, MICROSECONDS);

                return null;
              }
            });

    fut.get();

    lock.unlock();

    removeReentrantLock("acquire", fair);
  }
  /** @throws Exception If failed. */
  public void testGridStartRollback() throws Exception {
    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Nullable
          @Override
          public Object call() throws Exception {
            IgniteConfiguration cfg = new IgniteConfiguration();

            cfg.setConnectorConfiguration(null);

            cfg.setDiscoverySpi(
                new TcpDiscoverySpi() {
                  @Override
                  public void spiStart(String gridName) throws IgniteSpiException {
                    throw new IgniteSpiException("This SPI will never start.");
                  }
                });

            G.start(cfg);

            info("Thread finished.");

            return null;
          }
        },
        IgniteException.class,
        null);
  }
 /**
  * Wrapper around {@link GridTestUtils#retryAssert(org.apache.ignite.IgniteLogger, int, long,
  * GridAbsClosure)}. For the given closure provides count of retries, configured by {@link
  * #retries} attribute.
  *
  * @param assertion Closure with assertion inside.
  */
 private static void assertWithRetries(GridAbsClosureX assertion) {
   try {
     GridTestUtils.retryAssert(null, retries, 5000, assertion);
   } catch (IgniteInterruptedCheckedException e) {
     throw new IgniteException(e);
   }
 }
  /** @throws Exception If failed. */
  public void testClusterNodeMetrics() throws Exception {
    final Ignite ignite0 = grid();
    final Ignite ignite1 = startGrid(1);

    GridTestUtils.waitForCondition(
        new GridAbsPredicate() {
          @Override
          public boolean apply() {
            return ignite0.cluster().nodes().size() == 2 && ignite1.cluster().nodes().size() == 2;
          }
        },
        3000L);

    ClusterMetrics metrics0 = ignite0.cluster().localNode().metrics();

    ClusterMetrics nodesMetrics =
        ignite0
            .cluster()
            .forNode(ignite0.cluster().localNode(), ignite1.cluster().localNode())
            .metrics();

    assertEquals(metrics0.getTotalCpus(), nodesMetrics.getTotalCpus());
    assertEquals(1, metrics0.getTotalNodes());
    assertEquals(2, nodesMetrics.getTotalNodes());

    assert metrics0.getHeapMemoryUsed() > 0;
    assert metrics0.getHeapMemoryTotal() > 0;
    assert metrics0.getNonHeapMemoryMaximum() > 0;
  }
  /** Tests concurrent grid initialization */
  public void testConcurrentGridGetOrStartCon() throws Exception {
    final IgniteConfiguration cfg = getConfiguration(null);

    final AtomicReference<Ignite> ref = new AtomicReference<>();

    try {
      GridTestUtils.runMultiThreaded(
          new Runnable() {
            @Override
            public void run() {
              // must return same instance in each thread

              try {
                Ignite ignite = Ignition.getOrStart(cfg);

                boolean set = ref.compareAndSet(null, ignite);

                if (!set) assertEquals(ref.get(), ignite);
              } catch (IgniteException e) {
                throw new RuntimeException("Ignite error", e);
              }
            }
          },
          CONCURRENCY,
          "GridCreatorThread");
    } catch (Exception ignored) {
      fail("Exception is not expected");
    }

    G.stopAll(true);

    assertTrue(G.allGrids().isEmpty());
  }
  public void testAllFieldsSerialization() {
    GridBinaryTestClasses.TestObjectAllTypes obj = new GridBinaryTestClasses.TestObjectAllTypes();
    obj.setDefaultData();
    obj.enumArr = null;

    GridBinaryTestClasses.TestObjectAllTypes deserialized =
        builder(toBinary(obj)).build().deserialize();

    GridTestUtils.deepEquals(obj, deserialized);
  }
  /**
   * @param lock IgniteLock.
   * @throws Exception If failed.
   */
  protected void checkRemovedReentrantLock(final IgniteLock lock) throws Exception {
    assert GridTestUtils.waitForCondition(
        new PA() {
          @Override
          public boolean apply() {
            return lock.removed();
          }
        },
        5000);

    assert lock.removed();
  }
  /** @throws Exception If failed. */
  @SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"})
  public void testStartMultipleGridsFromSpring() throws Exception {
    File cfgFile =
        GridTestUtils.resolveIgnitePath(
            GridTestProperties.getProperty("loader.self.multipletest.config"));

    assert cfgFile != null;

    String path = cfgFile.getAbsolutePath();

    info("Loading Grid from configuration file: " + path);

    final GridTuple<IgniteState> gridState1 = F.t(null);
    final GridTuple<IgniteState> gridState2 = F.t(null);

    final Object mux = new Object();

    IgnitionListener factoryLsnr =
        new IgnitionListener() {
          @Override
          public void onStateChange(String name, IgniteState state) {
            synchronized (mux) {
              if ("grid-factory-test-1".equals(name)) gridState1.set(state);
              else if ("grid-factory-test-2".equals(name)) gridState2.set(state);
            }
          }
        };

    G.addListener(factoryLsnr);

    G.start(path);

    assert G.ignite("grid-factory-test-1") != null;
    assert G.ignite("grid-factory-test-2") != null;

    synchronized (mux) {
      assert gridState1.get() == STARTED
          : "Invalid grid state [expected=" + STARTED + ", returned=" + gridState1 + ']';
      assert gridState2.get() == STARTED
          : "Invalid grid state [expected=" + STARTED + ", returned=" + gridState2 + ']';
    }

    G.stop("grid-factory-test-1", true);
    G.stop("grid-factory-test-2", true);

    synchronized (mux) {
      assert gridState1.get() == STOPPED
          : "Invalid grid state [expected=" + STOPPED + ", returned=" + gridState1 + ']';
      assert gridState2.get() == STOPPED
          : "Invalid grid state [expected=" + STOPPED + ", returned=" + gridState2 + ']';
    }
  }
Esempio n. 10
0
  /** @throws Exception If failed. */
  @SuppressWarnings({"TooBroadScope"})
  public void testAsyncListen() throws Exception {
    final String hello = "HELLO!";

    final String bye = "BYE!";

    final Ignite g = grid(0);

    final UUID locNodeId = g.cluster().localNode().id();

    g.message()
        .remoteListen(
            null,
            new MessagingListenActor<String>() {
              @Override
              protected void receive(UUID nodeId, String rcvMsg) throws Throwable {
                if (hello.equals(rcvMsg)) {
                  assertEquals(locNodeId, nodeId);
                  assertEquals(hello, rcvMsg);

                  stop(bye);
                }
              }
            });

    final AtomicInteger cnt = new AtomicInteger();

    g.message()
        .localListen(
            null,
            new P2<UUID, String>() {
              @Override
              public boolean apply(UUID nodeId, String msg) {
                if (msg.equals(bye)) cnt.incrementAndGet();

                return true;
              }
            });

    g.message().send(null, hello);

    GridTestUtils.waitForCondition(
        new GridAbsPredicate() {
          @Override
          public boolean apply() {
            return cnt.get() == g.cluster().nodes().size();
          }
        },
        5000);

    assertEquals(cnt.get(), g.cluster().nodes().size());
  }
  /** @throws Exception If any error occurs. */
  public void testMultipleStartOnCoordinatorStop() throws Exception {
    for (int k = 0; k < 3; k++) {
      log.info("Iteration: " + k);

      clientFlagGlobal = false;

      final int START_NODES = 5;
      final int JOIN_NODES = 10;

      startGrids(START_NODES);

      final CyclicBarrier barrier = new CyclicBarrier(JOIN_NODES + 1);

      final AtomicInteger startIdx = new AtomicInteger(START_NODES);

      IgniteInternalFuture<?> fut =
          GridTestUtils.runMultiThreadedAsync(
              new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                  int idx = startIdx.getAndIncrement();

                  Thread.currentThread().setName("start-thread-" + idx);

                  barrier.await();

                  Ignite ignite = startGrid(idx);

                  assertFalse(ignite.configuration().isClientMode());

                  log.info("Started node: " + ignite.name());

                  return null;
                }
              },
              JOIN_NODES,
              "start-thread");

      barrier.await();

      U.sleep(ThreadLocalRandom.current().nextInt(10, 100));

      for (int i = 0; i < START_NODES; i++) stopGrid(i);

      fut.get();

      stopAllGrids();
    }
  }
  /**
   * @return AOP test suite.
   * @throws Exception If failed.
   */
  public static TestSuite suite() throws Exception {
    TestSuite suite = new TestSuite("Ignite AOP Test Suite");

    // Test configuration.
    suite.addTest(new TestSuite(BasicAopSelfTest.class));

    suite.addTest(new TestSuite(SpringAopSelfTest.class));
    suite.addTest(new TestSuite(NonSpringAopSelfTest.class));
    suite.addTest(new TestSuite(GridifySetToXXXSpringAopSelfTest.class));
    suite.addTest(new TestSuite(GridifySetToXXXNonSpringAopSelfTest.class));
    suite.addTest(new TestSuite(ExternalNonSpringAopSelfTest.class));

    // Examples
    System.setProperty(
        IGNITE_OVERRIDE_MCAST_GRP,
        GridTestUtils.getNextMulticastGroup(IgniteAopSelfTestSuite.class));

    return suite;
  }
  /** @throws Exception If failed. */
  public void testLoadBean() throws Exception {
    final String path = "modules/spring/src/test/java/org/apache/ignite/internal/cache.xml";

    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            Ignition.loadSpringBean(path, "wrongName");

            return null;
          }
        },
        IgniteException.class,
        null);

    CacheConfiguration cfg = Ignition.loadSpringBean(path, "cache-configuration");

    assertEquals("TestDynamicCache", cfg.getName());
  }
  /** @throws Exception If failed. */
  public void testStartGridWithConfigUrl() throws Exception {
    GridEmbeddedHttpServer srv = null;
    String gridName = "grid_with_url_config";

    try {
      srv =
          GridEmbeddedHttpServer.startHttpServer()
              .withFileDownloadingHandler(
                  null,
                  GridTestUtils.resolveIgnitePath(
                      "modules/core/src/test/config/default-spring-url-testing.xml"));

      Ignite ignite = G.start(new URL(srv.getBaseUrl()));

      assert gridName.equals(ignite.name()) : "Unexpected grid name: " + ignite.name();
    } finally {
      if (srv != null) srv.stop(1);

      G.stop(gridName, false);
    }
  }
Esempio n. 15
0
  /** @throws Exception If failed. */
  public void testFindColumn() throws Exception {
    final ResultSet rs = stmt.executeQuery(SQL);

    assertNotNull(rs);
    assertTrue(rs.next());

    assert rs.findColumn("id") == 1;

    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            rs.findColumn("wrong");

            return null;
          }
        },
        SQLException.class,
        "Column not found: wrong");
  }
  /** @throws Exception If failed. */
  public void testSystemCache() throws Exception {
    CollectionConfiguration colCfg = collectionConfiguration();

    IgniteQueue queue = grid(0).queue("Queue1", 0, colCfg);

    final CacheConfiguration ccfg = getQueueCache(queue);

    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            grid(0).cache(ccfg.getName());
            return null;
          }
        },
        IllegalStateException.class,
        "Failed to get cache because it is a system cache");

    assertNotNull(((IgniteKernal) grid(0)).internalCache(ccfg.getName()));
  }
  /** @throws Exception If failed. */
  private void testReentrantLockMultinode1(final boolean fair) throws Exception {
    if (gridCount() == 1) return;

    IgniteLock lock = grid(0).reentrantLock("s1", true, fair, true);

    List<IgniteInternalFuture<?>> futs = new ArrayList<>();

    for (int i = 0; i < gridCount(); i++) {
      final Ignite ignite = grid(i);

      futs.add(
          GridTestUtils.runAsync(
              new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                  IgniteLock lock = ignite.reentrantLock("s1", true, fair, false);

                  assertNotNull(lock);

                  IgniteCondition cond1 = lock.getOrCreateCondition("c1");

                  IgniteCondition cond2 = lock.getOrCreateCondition("c2");

                  try {
                    boolean wait = lock.tryLock(30_000, MILLISECONDS);

                    assertTrue(wait);

                    cond2.signal();

                    cond1.await();
                  } finally {
                    lock.unlock();
                  }

                  return null;
                }
              }));
    }

    boolean done = false;

    while (!done) {
      done = true;

      for (IgniteInternalFuture<?> fut : futs) {
        if (!fut.isDone()) done = false;
      }

      try {
        lock.lock();

        lock.getOrCreateCondition("c1").signal();

        lock.getOrCreateCondition("c2").await(10, MILLISECONDS);
      } finally {
        lock.unlock();
      }
    }

    for (IgniteInternalFuture<?> fut : futs) fut.get(30_000);
  }
  /** @throws Exception If failed. */
  public void testReconnectQueryInProgress() throws Exception {
    Ignite cln = grid(serverCount());

    assertTrue(cln.cluster().localNode().isClient());

    final Ignite srv = clientRouter(cln);

    final IgniteCache<Integer, Person> clnCache = cln.getOrCreateCache(QUERY_CACHE);

    clnCache.put(1, new Person(1, "name1", "surname1"));
    clnCache.put(2, new Person(2, "name2", "surname2"));
    clnCache.put(3, new Person(3, "name3", "surname3"));

    blockMessage(GridQueryNextPageResponse.class);

    final SqlQuery<Integer, Person> qry = new SqlQuery<>(Person.class, "_key <> 0");

    qry.setPageSize(1);

    final QueryCursor<Cache.Entry<Integer, Person>> cur1 = clnCache.query(qry);

    final IgniteInternalFuture<Object> fut =
        GridTestUtils.runAsync(
            new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                try {
                  cur1.getAll();
                } catch (CacheException e) {
                  checkAndWait(e);

                  return true;
                }

                return false;
              }
            });

    // Check that client waiting operation.
    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            return fut.get(200);
          }
        },
        IgniteFutureTimeoutCheckedException.class,
        null);

    assertNotDone(fut);

    unblockMessage();

    reconnectClientNode(cln, srv, null);

    assertTrue((Boolean) fut.get(2, SECONDS));

    QueryCursor<Cache.Entry<Integer, Person>> cur2 = clnCache.query(qry);

    assertEquals(3, cur2.getAll().size());
  }
  /**
   * @param setPart If {@code true} sets partition for scan query.
   * @throws Exception If failed.
   */
  private void scanQueryReconnectInProgress(boolean setPart) throws Exception {
    Ignite cln = grid(serverCount());

    assertTrue(cln.cluster().localNode().isClient());

    final Ignite srv = clientRouter(cln);

    final IgniteCache<Integer, Person> clnCache = cln.getOrCreateCache(QUERY_CACHE);

    clnCache.put(1, new Person(1, "name1", "surname1"));
    clnCache.put(2, new Person(2, "name2", "surname2"));
    clnCache.put(3, new Person(3, "name3", "surname3"));

    final ScanQuery<Integer, Person> scanQry = new ScanQuery<>();

    scanQry.setPageSize(1);

    scanQry.setFilter(
        new IgniteBiPredicate<Integer, Person>() {
          @Override
          public boolean apply(Integer integer, Person person) {
            return true;
          }
        });

    if (setPart) scanQry.setPartition(1);

    blockMessage(GridCacheQueryResponse.class);

    final IgniteInternalFuture<Object> fut =
        GridTestUtils.runAsync(
            new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                try {
                  QueryCursor<Cache.Entry<Integer, Person>> qryCursor = clnCache.query(scanQry);

                  qryCursor.getAll();
                } catch (CacheException e) {
                  checkAndWait(e);

                  return true;
                }

                return false;
              }
            });

    // Check that client waiting operation.
    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            return fut.get(200);
          }
        },
        IgniteFutureTimeoutCheckedException.class,
        null);

    assertNotDone(fut);

    unblockMessage();

    reconnectClientNode(cln, srv, null);

    assertTrue((Boolean) fut.get(2, SECONDS));

    QueryCursor<Cache.Entry<Integer, Person>> qryCursor2 = clnCache.query(scanQry);

    assertEquals(setPart ? 1 : 3, qryCursor2.getAll().size());
  }
  /**
   * Check how prefetch override works.
   *
   * @throws Exception IF failed.
   */
  public void testOpenPrefetchOverride() throws Exception {
    create(igfsSecondary, paths(DIR, SUBDIR), paths(FILE));

    // Write enough data to the secondary file system.
    final int blockSize = IGFS_BLOCK_SIZE;

    IgfsOutputStream out = igfsSecondary.append(FILE, false);

    int totalWritten = 0;

    while (totalWritten < blockSize * 2 + chunk.length) {
      out.write(chunk);

      totalWritten += chunk.length;
    }

    out.close();

    awaitFileClose(igfsSecondary.asSecondary(), FILE);

    // Instantiate file system with overridden "seq reads before prefetch" property.
    Configuration cfg = new Configuration();

    cfg.addResource(U.resolveIgniteUrl(PRIMARY_CFG));

    int seqReads = SEQ_READS_BEFORE_PREFETCH + 1;

    cfg.setInt(String.format(PARAM_IGFS_SEQ_READS_BEFORE_PREFETCH, "igfs:grid@"), seqReads);

    FileSystem fs = FileSystem.get(new URI(PRIMARY_URI), cfg);

    // Read the first two blocks.
    Path fsHome = new Path(PRIMARY_URI);
    Path dir = new Path(fsHome, DIR.name());
    Path subdir = new Path(dir, SUBDIR.name());
    Path file = new Path(subdir, FILE.name());

    FSDataInputStream fsIn = fs.open(file);

    final byte[] readBuf = new byte[blockSize * 2];

    fsIn.readFully(0, readBuf, 0, readBuf.length);

    // Wait for a while for prefetch to finish (if any).
    IgfsMetaManager meta = igfs.context().meta();

    IgfsFileInfo info = meta.info(meta.fileId(FILE));

    IgfsBlockKey key = new IgfsBlockKey(info.id(), info.affinityKey(), info.evictExclude(), 2);

    IgniteCache<IgfsBlockKey, byte[]> dataCache =
        igfs.context().kernalContext().cache().jcache(igfs.configuration().getDataCacheName());

    for (int i = 0; i < 10; i++) {
      if (dataCache.containsKey(key)) break;
      else U.sleep(100);
    }

    fsIn.close();

    // Remove the file from the secondary file system.
    igfsSecondary.delete(FILE, false);

    // Try reading the third block. Should fail.
    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            IgfsInputStream in0 = igfs.open(FILE);

            in0.seek(blockSize * 2);

            try {
              in0.read(readBuf);
            } finally {
              U.closeQuiet(in0);
            }

            return null;
          }
        },
        IOException.class,
        "Failed to read data due to secondary file system exception: /dir/subdir/file");
  }
  public GridFactorySelfTest() {
    super(false);

    System.setProperty(
        IGNITE_OVERRIDE_MCAST_GRP, GridTestUtils.getNextMulticastGroup(GridFactorySelfTest.class));
  }
  /** @throws Exception If failed. */
  public void testInvalidRangeUpdates() throws Exception {
    final IgfsFileMap map = new IgfsFileMap();

    final IgniteUuid affKey1 = IgniteUuid.randomUuid();
    final IgniteUuid affKey2 = IgniteUuid.randomUuid();

    map.addRange(new IgfsFileAffinityRange(10, 19, affKey1));
    map.addRange(new IgfsFileAffinityRange(30, 39, affKey1));

    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            map.updateRangeStatus(new IgfsFileAffinityRange(0, 5, affKey1), RANGE_STATUS_MOVING);

            return null;
          }
        },
        IgfsInvalidRangeException.class,
        null);

    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            map.updateRangeStatus(new IgfsFileAffinityRange(15, 19, affKey1), RANGE_STATUS_MOVING);

            return null;
          }
        },
        IgfsInvalidRangeException.class,
        null);

    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            map.updateRangeStatus(new IgfsFileAffinityRange(10, 19, affKey2), RANGE_STATUS_MOVING);

            return null;
          }
        },
        AssertionError.class,
        null);

    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            map.updateRangeStatus(new IgfsFileAffinityRange(10, 22, affKey1), RANGE_STATUS_MOVING);

            return null;
          }
        },
        AssertionError.class,
        null);

    assertEquals(2, map.ranges().size());
  }
  /**
   * @param cacheMode Cache mode.
   * @param sameAff If {@code false} uses different number of partitions for caches.
   * @param concurrency Transaction concurrency.
   * @param isolation Transaction isolation.
   * @throws Exception If failed.
   */
  private void crossCacheTxFailover(
      CacheMode cacheMode,
      boolean sameAff,
      final TransactionConcurrency concurrency,
      final TransactionIsolation isolation)
      throws Exception {
    IgniteKernal ignite0 = (IgniteKernal) ignite(0);

    final AtomicBoolean stop = new AtomicBoolean();

    try {
      ignite0.createCache(cacheConfiguration(CACHE1, cacheMode, 256));
      ignite0.createCache(cacheConfiguration(CACHE2, cacheMode, sameAff ? 256 : 128));

      final AtomicInteger threadIdx = new AtomicInteger();

      IgniteInternalFuture<?> fut =
          GridTestUtils.runMultiThreadedAsync(
              new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                  int idx = threadIdx.getAndIncrement();

                  Ignite ignite = ignite(idx % GRID_CNT);

                  log.info(
                      "Started update thread [node="
                          + ignite.name()
                          + ", client="
                          + ignite.configuration().isClientMode()
                          + ']');

                  IgniteCache<TestKey, TestValue> cache1 = ignite.cache(CACHE1);
                  IgniteCache<TestKey, TestValue> cache2 = ignite.cache(CACHE2);

                  assertNotSame(cache1, cache2);

                  IgniteTransactions txs = ignite.transactions();

                  ThreadLocalRandom rnd = ThreadLocalRandom.current();

                  long iter = 0;

                  while (!stop.get()) {
                    boolean sameKey = rnd.nextBoolean();

                    try {
                      try (Transaction tx = txs.txStart(concurrency, isolation)) {
                        if (sameKey) {
                          TestKey key = new TestKey(rnd.nextLong(KEY_RANGE));

                          cacheOperation(rnd, cache1, key);
                          cacheOperation(rnd, cache2, key);
                        } else {
                          TestKey key1 = new TestKey(rnd.nextLong(KEY_RANGE));
                          TestKey key2 = new TestKey(key1.key() + 1);

                          cacheOperation(rnd, cache1, key1);
                          cacheOperation(rnd, cache2, key2);
                        }

                        tx.commit();
                      }
                    } catch (CacheException | IgniteException e) {
                      log.info("Update error: " + e);
                    }

                    if (iter++ % 500 == 0) log.info("Iteration: " + iter);
                  }

                  return null;
                }

                /**
                 * @param rnd Random.
                 * @param cache Cache.
                 * @param key Key.
                 */
                private void cacheOperation(
                    ThreadLocalRandom rnd, IgniteCache<TestKey, TestValue> cache, TestKey key) {
                  switch (rnd.nextInt(4)) {
                    case 0:
                      cache.put(key, new TestValue(rnd.nextLong()));

                      break;

                    case 1:
                      cache.remove(key);

                      break;

                    case 2:
                      cache.invoke(key, new TestEntryProcessor(rnd.nextBoolean() ? 1L : null));

                      break;

                    case 3:
                      cache.get(key);

                      break;

                    default:
                      assert false;
                  }
                }
              },
              10,
              "tx-thread");

      long stopTime = System.currentTimeMillis() + 3 * 60_000;

      long topVer = ignite0.cluster().topologyVersion();

      boolean failed = false;

      while (System.currentTimeMillis() < stopTime) {
        log.info("Start node.");

        IgniteKernal ignite = (IgniteKernal) startGrid(GRID_CNT);

        assertFalse(ignite.configuration().isClientMode());

        topVer++;

        IgniteInternalFuture<?> affFut =
            ignite
                .context()
                .cache()
                .context()
                .exchange()
                .affinityReadyFuture(new AffinityTopologyVersion(topVer));

        try {
          if (affFut != null) affFut.get(30_000);
        } catch (IgniteFutureTimeoutCheckedException e) {
          log.error("Failed to wait for affinity future after start: " + topVer);

          failed = true;

          break;
        }

        Thread.sleep(500);

        log.info("Stop node.");

        stopGrid(GRID_CNT);

        topVer++;

        affFut =
            ignite0
                .context()
                .cache()
                .context()
                .exchange()
                .affinityReadyFuture(new AffinityTopologyVersion(topVer));

        try {
          if (affFut != null) affFut.get(30_000);
        } catch (IgniteFutureTimeoutCheckedException e) {
          log.error("Failed to wait for affinity future after stop: " + topVer);

          failed = true;

          break;
        }
      }

      stop.set(true);

      fut.get();

      assertFalse("Test failed, see log for details.", failed);
    } finally {
      stop.set(true);

      ignite0.destroyCache(CACHE1);
      ignite0.destroyCache(CACHE2);

      awaitPartitionMapExchange();
    }
  }
  /** {@inheritDoc} */
  @Override
  protected void afterTest() throws Exception {
    Transaction tx = jcache().unwrap(Ignite.class).transactions().tx();

    if (tx != null) {
      tx.close();

      fail("Cache transaction remained after test completion: " + tx);
    }

    for (int i = 0; i < gridCount(); i++) {
      info("Checking grid: " + i);

      while (true) {
        try {
          final int fi = i;

          assertTrue(
              "Cache is not empty: "
                  + " localSize = "
                  + jcache(fi).localSize(CachePeekMode.ALL)
                  + ", local entries "
                  + entrySet(jcache(fi).localEntries()),
              GridTestUtils.waitForCondition(
                  // Preloading may happen as nodes leave, so we need to wait.
                  new GridAbsPredicateX() {
                    @Override
                    public boolean applyx() throws IgniteCheckedException {
                      jcache(fi).removeAll();

                      if (jcache(fi).size(CachePeekMode.ALL) > 0) {
                        for (Cache.Entry<String, ?> k : jcache(fi).localEntries())
                          jcache(fi).remove(k.getKey());
                      }

                      return jcache(fi).localSize(CachePeekMode.ALL) == 0;
                    }
                  },
                  getTestTimeout()));

          int primaryKeySize = jcache(i).localSize(CachePeekMode.PRIMARY);
          int keySize = jcache(i).localSize();
          int size = jcache(i).localSize();
          int globalSize = jcache(i).size();
          int globalPrimarySize = jcache(i).size(CachePeekMode.PRIMARY);

          info(
              "Size after [idx="
                  + i
                  + ", size="
                  + size
                  + ", keySize="
                  + keySize
                  + ", primarySize="
                  + primaryKeySize
                  + ", globalSize="
                  + globalSize
                  + ", globalPrimarySize="
                  + globalPrimarySize
                  + ", entrySet="
                  + jcache(i).localEntries()
                  + ']');

          assertEquals(
              "Cache is not empty [idx=" + i + ", entrySet=" + jcache(i).localEntries() + ']',
              0,
              jcache(i).localSize(CachePeekMode.ALL));

          break;
        } catch (Exception e) {
          if (X.hasCause(e, ClusterTopologyCheckedException.class)) {
            info("Got topology exception while tear down (will retry in 1000ms).");

            U.sleep(1000);
          } else throw e;
        }
      }

      for (Cache.Entry<String, Integer> entry : jcache(i).localEntries(CachePeekMode.SWAP))
        jcache(i).remove(entry.getKey());
    }

    assert jcache().unwrap(Ignite.class).transactions().tx() == null;
    assertEquals("Cache is not empty", 0, jcache().localSize(CachePeekMode.ALL));

    resetStore();
  }