package org.infinispan.xsite.backupfailure;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import java.util.HashMap;
import java.util.Map;
import org.infinispan.commons.CacheException;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.testng.annotations.Test;
/**
* @author Mircea Markus
* @since 5.2
*/
@Test (groups = "xsite", testName = "xsite.backupfailure.NonTxBackupFailureTest")
public class NonTxBackupFailureTest extends BaseBackupFailureTest {
@Override
protected ConfigurationBuilder getLonActiveConfig() {
return getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false);
}
@Override
protected ConfigurationBuilder getNycActiveConfig() {
return getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false);
}
public void testPutFailure() {
failureInterceptor.enable();
try {
cache("LON", 0).put("k", "v");
checkFailOnBackupFailure();
} catch (CacheException e) {
checkNonFailOnBackupFailure();
} finally {
failureInterceptor.disable();
}
//in triangle, if an exception is received, the originator doesn't wait for the ack from backup
//it is possible to check the value before the backup handles the BackupWriteRpcCommand.
eventuallyEquals("v", () -> cache("LON", 1).get("k"));
assertTrue(failureInterceptor.putFailed);
assertNull(backup("LON").get("k"));
}
public void testRemoveFailure() {
cache("LON", 0).put("k", "v");
assertEquals("v", cache("LON", 1).get("k"));
assertEquals("v", backup("LON").get("k"));
failureInterceptor.enable();
try {
cache("LON", 0).remove("k");
checkFailOnBackupFailure();
} catch (CacheException e) {
checkNonFailOnBackupFailure();
} finally {
failureInterceptor.disable();
}
eventuallyEquals(null, () -> cache("LON", 0).get("k"));
eventuallyEquals(null, () -> cache("LON", 1).get("k"));
assertTrue(failureInterceptor.removeFailed);
assertEquals("v", backup("LON").get("k"));
}
public void testReplaceFailure() {
failureInterceptor.disable();
cache("LON", 0).put("k", "v");
assertEquals("v", cache("LON", 1).get("k"));
assertEquals("v", backup("LON").get("k"));
failureInterceptor.enable();
try {
cache("LON", 0).replace("k", "v2");
checkFailOnBackupFailure();
} catch (CacheException e) {
checkNonFailOnBackupFailure();
} finally {
failureInterceptor.disable();
}
eventuallyEquals("v2", () -> cache("LON", 0).get("k"));
eventuallyEquals("v2", () -> cache("LON", 1).get("k"));
//the ReplaceCommand is transformed in a PutKeyValueCommand when it succeeds in the originator site!
assertTrue(failureInterceptor.putFailed);
assertEquals("v", backup("LON").get("k"));
}
public void testClearFailure() {
cache("LON", 0).put("k1", "v1");
cache("LON", 0).put("k2", "v2");
cache("LON", 0).put("k3", "v3");
failureInterceptor.enable();
try {
cache("LON", 1).clear();
checkFailOnBackupFailure();
} catch (CacheException e) {
checkNonFailOnBackupFailure();
} finally {
failureInterceptor.disable();
}
eventuallyEquals(null, () -> cache("LON", 0).get("k1"));
eventuallyEquals(null, () -> cache("LON", 0).get("k2"));
eventuallyEquals(null, () -> cache("LON", 0).get("k3"));
eventuallyEquals(null, () -> cache("LON", 1).get("k1"));
eventuallyEquals(null, () -> cache("LON", 1).get("k2"));
eventuallyEquals(null, () -> cache("LON", 1).get("k3"));
assertTrue(failureInterceptor.clearFailed);
assertEquals("v1", backup("LON").get("k1"));
assertEquals("v2", backup("LON").get("k2"));
assertEquals("v3", backup("LON").get("k3"));
}
public void testPutMapFailure() {
Map<String, String> toAdd = new HashMap<>();
for (int i = 0; i < 100; i++) {
toAdd.put("k" + i, "v" + i);
}
failureInterceptor.enable();
try {
cache("LON", 0).putAll(toAdd);
checkFailOnBackupFailure();
} catch (CacheException e) {
checkNonFailOnBackupFailure();
} finally {
failureInterceptor.disable();
}
for (int i = 0; i < 100; i++) {
final int keyIndex = i;
eventuallyEquals("v" + keyIndex, () -> cache("LON", keyIndex % 2).get("k" + keyIndex));
assertNull(backup("LON").get("k" + i));
}
}
private void checkNonFailOnBackupFailure() {
if (!failOnBackupFailure("LON", 0)) throw new AssertionError("Should fail silently!");
}
private void checkFailOnBackupFailure() {
if (failOnBackupFailure("LON", 0)) throw new AssertionError("Exception expected!");
}
}