/*
* Copyright 2014-2016 CyberVision, Inc.
*
* Licensed 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.kaaproject.kaa.client.configuration.manager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericArray;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericEnumSymbol;
import org.apache.avro.generic.GenericFixed;
import org.apache.avro.generic.GenericRecord;
import org.junit.Test;
import org.kaaproject.kaa.client.common.CommonRecord;
import org.kaaproject.kaa.client.common.CommonValue;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
public class DefaultConfigurationManagerTest {
public static Schema getArraySchema(GenericRecord delta, String field) {
List<Schema> fieldTypes = delta.getSchema().getField(field).schema().getTypes();
for (Schema type : fieldTypes) {
if (type.getType() == Schema.Type.ARRAY) {
return type;
}
}
return null;
}
public static Schema getDeltaSchemaByFullName(Schema deltaSchema, String fullName) {
Schema deltaT = deltaSchema.getElementType();
Schema deltaUnion = deltaT.getField("delta").schema();
List<Schema> deltas = deltaUnion.getTypes();
for (Schema delta : deltas) {
if (delta.getFullName().equals(fullName)) {
return delta;
}
}
return null;
}
public static Schema getSchemaByFullName(List<Schema> types, String fullName) {
for (Schema type : types) {
if (type.getFullName().equals(fullName)) {
return type;
}
}
return null;
}
public static void fillComplexFullResyncDelta(GenericRecord delta) {
GenericRecord testField2 = new GenericData.Record(getSchemaByFullName(
delta.getSchema().getField("testField2").schema().getTypes(),
"org.kaa.config.testRecordT"));
testField2.put("testField3", 456);
byte[] rawUuid = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
GenericFixed uuid = new GenericData.Fixed(delta.getSchema()
.getField("__uuid").schema(), rawUuid);
delta.put("testField1", "abc");
delta.put("testField2", testField2);
delta.put("__uuid", uuid);
}
public static void fillComplexPartialDelta(GenericRecord delta) {
GenericRecord testField22 = new GenericData.Record(getSchemaByFullName(
delta.getSchema().getField("testField2").schema().getTypes(),
"org.kaa.config.testRecordT"));
testField22.put("testField3", 654);
GenericEnumSymbol unchanged = new GenericData.EnumSymbol(
getSchemaByFullName(delta.getSchema().getField("testField1")
.schema().getTypes(), "org.kaaproject.configuration.unchangedT"),
"unchanged");
delta.put("testField1", unchanged);
delta.put("testField2", testField22);
}
public static void fillArrayFullResyncDelta(GenericRecord delta) {
byte[] rawUuid = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
GenericFixed uuid = new GenericData.Fixed(delta.getSchema()
.getField("__uuid").schema(), rawUuid);
delta.put("__uuid", uuid);
GenericArray testField1 = new GenericData.Array(3, getArraySchema(delta, "testField1"));
delta.put("testField1", testField1);
GenericRecord itemRecord1 = new GenericData.Record(getSchemaByFullName(
testField1.getSchema().getElementType().getTypes(),
"org.kaa.config.testRecordItemT"));
itemRecord1.put("testField2", 1);
byte[] rawItemUuid1 = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
GenericFixed itemUuid1 = new GenericData.Fixed(itemRecord1
.getSchema().getField("__uuid").schema(), rawItemUuid1);
itemRecord1.put("__uuid", itemUuid1);
GenericRecord itemRecord2 = new GenericData.Record(getSchemaByFullName(
testField1.getSchema().getElementType().getTypes(),
"org.kaa.config.testRecordItemT"));
itemRecord2.put("testField2", 2);
byte[] rawItemUuid2 = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2};
GenericFixed itemUuid2 = new GenericData.Fixed(itemRecord2
.getSchema().getField("__uuid").schema(), rawItemUuid2);
itemRecord2.put("__uuid", itemUuid2);
GenericRecord itemRecord3 = new GenericData.Record(getSchemaByFullName(
testField1.getSchema().getElementType().getTypes(),
"org.kaa.config.testRecordItemT"));
itemRecord3.put("testField2", 3);
byte[] rawItemUuid3 = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3};
GenericFixed itemUuid3 = new GenericData.Fixed(itemRecord3
.getSchema().getField("__uuid").schema(), rawItemUuid3);
itemRecord3.put("__uuid", itemUuid3);
testField1.add(itemRecord1);
testField1.add(itemRecord2);
testField1.add(itemRecord3);
}
public static void fillArrayItemUpdateDelta(GenericRecord item) {
byte[] rawItemUuid2 = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2};
GenericFixed itemUuid2 = new GenericData.Fixed(item
.getSchema().getField("__uuid").schema(), rawItemUuid2);
item.put("__uuid", itemUuid2);
item.put("testField2", 22);
}
public static void fillArrayItemRemoveDelta(GenericRecord delta) {
GenericArray testField1 = new GenericData.Array(1, getArraySchema(delta, "testField1"));
byte[] rawUuidToRemove = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
GenericFixed uuidToRemove = new GenericData.Fixed(getSchemaByFullName(
testField1.getSchema().getElementType().getTypes(),
"org.kaaproject.configuration.uuidT"), rawUuidToRemove);
testField1.add(uuidToRemove);
delta.put("testField1", testField1);
}
public static void fillArrayResetDelta(GenericRecord delta) {
GenericEnumSymbol reset = new GenericData.EnumSymbol(
getSchemaByFullName(delta.getSchema().getField("testField1")
.schema().getTypes(), "org.kaaproject.configuration.resetT"), "reset");
delta.put("testField1", reset);
}
@Test
public void testComplexDelta() throws IOException {
DefaultConfigurationManager manager = new DefaultConfigurationManager();
ConfigurationReceiver receiver = mock(ConfigurationReceiver.class);
manager.subscribeForConfigurationUpdates(receiver);
URL schemaUrl = Thread.currentThread().getContextClassLoader().getResource("configuration/manager/complexFieldsDeltaSchema.json");
Schema schema = new Schema.Parser().parse(new File(schemaUrl.getPath()));
// First full resync delta
GenericRecord delta = new GenericData.Record(getDeltaSchemaByFullName(schema, "org.kaa.config.testT"));
fillComplexFullResyncDelta(delta);
manager.onDeltaReceived(0, delta, true);
CommonRecord rootConfig = manager.getConfiguration();
manager.onConfigurationProcessed();
assertTrue(rootConfig.hasField("testField1"));
assertEquals("abc", rootConfig.getField("testField1").getString());
assertTrue(rootConfig.getField("testField1").isString());
assertFalse(rootConfig.getField("testField1").isInteger());
assertTrue(rootConfig.hasField("testField2"));
assertTrue(rootConfig.getField("testField2").isRecord());
assertTrue(rootConfig.getField("testField2").getRecord().getField("testField3").isInteger());
assertEquals(new Integer(456), rootConfig.getField("testField2").getRecord().getField("testField3").getInteger());
// Partial update delta
fillComplexPartialDelta(delta);
manager.onDeltaReceived(0, delta, false);
rootConfig = manager.getConfiguration();
manager.onConfigurationProcessed();
verify(receiver, times(2)).onConfigurationUpdated(any(CommonRecord.class));
assertTrue(rootConfig.hasField("testField1"));
assertEquals("abc", rootConfig.getField("testField1").getString());
assertTrue(rootConfig.getField("testField1").isString());
assertTrue(rootConfig.hasField("testField2"));
assertTrue(rootConfig.getField("testField2").isRecord());
assertTrue(rootConfig.getField("testField2").getRecord().getField("testField3").isInteger());
assertEquals(new Integer(654), rootConfig.getField("testField2").getRecord().getField("testField3").getInteger());
}
@Test
public void testArrayFieldsDelta() throws IOException, URISyntaxException {
DefaultConfigurationManager manager = new DefaultConfigurationManager();
ConfigurationReceiver receiver = mock(ConfigurationReceiver.class);
manager.subscribeForConfigurationUpdates(receiver);
URL schemaUrl = Thread.currentThread().getContextClassLoader().getResource("configuration/manager/arrayFieldsDeltaSchema.json");
Schema schema = new Schema.Parser().parse(new File(schemaUrl.getPath()));
// First full resync delta
GenericRecord delta = new GenericData.Record(getDeltaSchemaByFullName(schema, "org.kaa.config.testT"));
fillArrayFullResyncDelta(delta);
manager.onDeltaReceived(0, delta, true);
manager.onConfigurationProcessed();
CommonRecord rootConfig = manager.getConfiguration();
List<CommonValue> configArray = rootConfig.getField("testField1").getArray().getList();
assertTrue(rootConfig.getField("testField1").isArray());
assertEquals(3, configArray.size());
assertEquals(new Integer(1), configArray.get(0).getRecord().getField("testField2").getInteger());
assertEquals(new Integer(2), configArray.get(1).getRecord().getField("testField2").getInteger());
assertEquals(new Integer(3), configArray.get(2).getRecord().getField("testField2").getInteger());
// Partial update of the item
GenericRecord itemRecord2 = new GenericData.Record(getDeltaSchemaByFullName(schema, "org.kaa.config.testRecordItemT"));
fillArrayItemUpdateDelta(itemRecord2);
manager.onDeltaReceived(1, itemRecord2, false);
manager.onConfigurationProcessed();
rootConfig = manager.getConfiguration();
configArray = rootConfig.getField("testField1").getArray().getList();
assertEquals(new Integer(1), configArray.get(0).getRecord().getField("testField2").getInteger());
assertEquals(new Integer(22), configArray.get(1).getRecord().getField("testField2").getInteger());
assertEquals(new Integer(3), configArray.get(2).getRecord().getField("testField2").getInteger());
// Removing one item by uuid
fillArrayItemRemoveDelta(delta);
manager.onDeltaReceived(0, delta, false);
manager.onConfigurationProcessed();
rootConfig = manager.getConfiguration();
configArray = rootConfig.getField("testField1").getArray().getList();
assertEquals(2, configArray.size());
assertEquals(new Integer(22), configArray.get(0).getRecord().getField("testField2").getInteger());
assertEquals(new Integer(3), configArray.get(1).getRecord().getField("testField2").getInteger());
// Reseting container
fillArrayResetDelta(delta);
manager.onDeltaReceived(0, delta, false);
manager.onConfigurationProcessed();
rootConfig = manager.getConfiguration();
configArray = rootConfig.getField("testField1").getArray().getList();
assertTrue(configArray.isEmpty());
verify(receiver, times(4)).onConfigurationUpdated(any(CommonRecord.class));
}
}