/*
* 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.
*/
package org.apache.nifi.web.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.apache.nifi.util.ComponentIdGenerator;
import org.junit.Test;
public class SnippetUtilsTest {
/*
* This test validates condition where component is being replicated across
* the cluster
*/
@Test
public void validateWithSameSeedSameInceptionIdSameInstanceId() throws Exception {
Method generateIdMethod = SnippetUtils.class.getDeclaredMethod("generateId", String.class, String.class,
boolean.class);
generateIdMethod.setAccessible(true);
SnippetUtils utils = new SnippetUtils();
String currentId = ComponentIdGenerator.generateId().toString();
String seed = ComponentIdGenerator.generateId().toString();
String id1 = (String) generateIdMethod.invoke(utils, currentId, seed, true);
String id2 = (String) generateIdMethod.invoke(utils, currentId, seed, true);
String id3 = (String) generateIdMethod.invoke(utils, currentId, seed, true);
assertEquals(id1, id2);
assertEquals(id2, id3);
}
/*
* This test validates condition where components that are being copy/pasted from
* one another are now replicated across the cluster. Such components will
* have different inception id (msb) yet different instance id (lsb). The id
* of these components must be different yet their msb must be the same.
*/
@Test
public void validateWithSameSeedSameInceptionIdNotSameInstanceIdIsCopySet() throws Exception {
Method generateIdMethod = SnippetUtils.class.getDeclaredMethod("generateId", String.class, String.class,
boolean.class);
generateIdMethod.setAccessible(true);
SnippetUtils utils = new SnippetUtils();
String seed = ComponentIdGenerator.generateId().toString();
UUID rootId = ComponentIdGenerator.generateId();
String id1 = (String) generateIdMethod.invoke(utils,
new UUID(rootId.getMostSignificantBits(), ComponentIdGenerator.generateId().getLeastSignificantBits()).toString(),
seed, true);
String id2 = (String) generateIdMethod.invoke(utils,
new UUID(rootId.getMostSignificantBits(), ComponentIdGenerator.generateId().getLeastSignificantBits()).toString(),
seed, true);
String id3 = (String) generateIdMethod.invoke(utils,
new UUID(rootId.getMostSignificantBits(), ComponentIdGenerator.generateId().getLeastSignificantBits()).toString(),
seed, true);
assertNotEquals(id1, id2);
assertNotEquals(id2, id3);
UUID uuid1 = UUID.fromString(id1);
UUID uuid2 = UUID.fromString(id2);
UUID uuid3 = UUID.fromString(id3);
// below simply validates that generated UUID is type-one, since timestamp() operation will result
// in exception if generated UUID is not type-one
uuid1.timestamp();
uuid2.timestamp();
uuid3.timestamp();
assertNotEquals(uuid1.getMostSignificantBits(), uuid2.getMostSignificantBits());
assertNotEquals(uuid2.getMostSignificantBits(), uuid3.getMostSignificantBits());
}
/*
* This test validates condition where components that are being re-created
* from template are now replicated across the cluster. Such components will
* have the same inception id (msb) yet different instance id (lsb). The id
* of these components must be different yet their msb must be the same.
*/
@Test
public void validateWithSameSeedSameInceptionIdNotSameInstanceIdIsCopyNotSet() throws Exception {
Method generateIdMethod = SnippetUtils.class.getDeclaredMethod("generateId", String.class, String.class,
boolean.class);
generateIdMethod.setAccessible(true);
SnippetUtils utils = new SnippetUtils();
String seed = ComponentIdGenerator.generateId().toString();
UUID rootId = ComponentIdGenerator.generateId();
String id1 = (String) generateIdMethod.invoke(utils,
new UUID(rootId.getMostSignificantBits(), ComponentIdGenerator.generateId().getLeastSignificantBits()).toString(),
seed, false);
String id2 = (String) generateIdMethod.invoke(utils,
new UUID(rootId.getMostSignificantBits(), ComponentIdGenerator.generateId().getLeastSignificantBits()).toString(),
seed, false);
String id3 = (String) generateIdMethod.invoke(utils,
new UUID(rootId.getMostSignificantBits(), ComponentIdGenerator.generateId().getLeastSignificantBits()).toString(),
seed, false);
assertNotEquals(id1, id2);
assertNotEquals(id2, id3);
UUID uuid1 = UUID.fromString(id1);
UUID uuid2 = UUID.fromString(id2);
UUID uuid3 = UUID.fromString(id3);
// below simply validates that generated UUID is type-one, since timestamp() operation will result
// in exception if generated UUID is not type-one
uuid1.timestamp();
uuid2.timestamp();
uuid3.timestamp();
assertEquals(uuid1.getMostSignificantBits(), uuid2.getMostSignificantBits());
assertEquals(uuid2.getMostSignificantBits(), uuid3.getMostSignificantBits());
}
/*
* This test validates condition where components are being copied from one
* another. The ids of each components must be completely different (msb and
* lsb) yet each subsequent msb must be > then previous component's msb.
*/
@Test
public void validateWithoutSeedSameCurrentIdIsCopySet() throws Exception {
Method generateIdMethod = SnippetUtils.class.getDeclaredMethod("generateId", String.class, String.class,
boolean.class);
generateIdMethod.setAccessible(true);
boolean isCopy = true;
SnippetUtils utils = new SnippetUtils();
String currentId = ComponentIdGenerator.generateId().toString();
UUID id1 = UUID.fromString((String) generateIdMethod.invoke(utils, currentId, null, isCopy));
UUID id2 = UUID.fromString((String) generateIdMethod.invoke(utils, currentId, null, isCopy));
UUID id3 = UUID.fromString((String) generateIdMethod.invoke(utils, currentId, null, isCopy));
// below simply validates that generated UUID is type-one, since timestamp() operation will result
// in exception if generated UUID is not type-one
id1.timestamp();
id2.timestamp();
id3.timestamp();
assertTrue(id1.getMostSignificantBits() < id2.getMostSignificantBits());
assertTrue(id2.getMostSignificantBits() < id3.getMostSignificantBits());
}
/*
* This test validates condition where new components are being created from
* existing components such as from imported templates. In this case their
* instance id (lsb) is irrelevant and new instance id would have to be
* generated every time yet its inception id (msb) must remain the same.
*/
@Test
public void validateWithoutSeedSameCurrentIdIsCopyNotSet() throws Exception {
Method generateIdMethod = SnippetUtils.class.getDeclaredMethod("generateId", String.class, String.class,
boolean.class);
generateIdMethod.setAccessible(true);
boolean isCopy = false;
SnippetUtils utils = new SnippetUtils();
String currentId = ComponentIdGenerator.generateId().toString();
UUID id1 = UUID.fromString((String) generateIdMethod.invoke(utils, currentId, null, isCopy));
UUID id2 = UUID.fromString((String) generateIdMethod.invoke(utils, currentId, null, isCopy));
UUID id3 = UUID.fromString((String) generateIdMethod.invoke(utils, currentId, null, isCopy));
// below simply validates that generated UUID is type-one, since timestamp() operation will result
// in exception if generated UUID is not type-one
id1.timestamp();
id2.timestamp();
id3.timestamp();
assertEquals(id1.getMostSignificantBits(), id2.getMostSignificantBits());
assertEquals(id2.getMostSignificantBits(), id3.getMostSignificantBits());
}
/*
* This test simply validates that generated IDs are comparable and
* sequentially correct where each subsequent ID is > previous ID.
*/
@Test
public void validateIdOrdering() throws Exception {
UUID seed = ComponentIdGenerator.generateId();
UUID currentId1 = ComponentIdGenerator.generateId();
UUID currentId2 = ComponentIdGenerator.generateId();
UUID currentId3 = ComponentIdGenerator.generateId();
UUID id1 = new UUID(currentId1.getMostSignificantBits(),
UUID.nameUUIDFromBytes((currentId1.toString() + seed.toString()).getBytes(StandardCharsets.UTF_8))
.getLeastSignificantBits());
UUID id2 = new UUID(currentId2.getMostSignificantBits(),
UUID.nameUUIDFromBytes((currentId2.toString() + seed.toString()).getBytes(StandardCharsets.UTF_8))
.getLeastSignificantBits());
UUID id3 = new UUID(currentId3.getMostSignificantBits(),
UUID.nameUUIDFromBytes((currentId3.toString() + seed.toString()).getBytes(StandardCharsets.UTF_8))
.getLeastSignificantBits());
List<UUID> list = new ArrayList<>();
list.add(id2);
list.add(id3);
list.add(id1);
Collections.sort(list);
assertEquals(id1, list.get(0));
assertEquals(id2, list.get(1));
assertEquals(id3, list.get(2));
}
}