com.blackberry.bdp.common.versioned.ZkVersionedTest.java Source code

Java tutorial

Introduction

Here is the source code for com.blackberry.bdp.common.versioned.ZkVersionedTest.java

Source

/*
 * Copyright 2015 BlackBerry Limited.
 *
 * 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 com.blackberry.bdp.common.versioned;

import com.blackberry.bdp.common.exception.InvalidUserRoleException;
import com.blackberry.bdp.common.exception.VersionMismatchException;
import com.fasterxml.jackson.core.JsonProcessingException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.junit.AfterClass;
import org.junit.BeforeClass;

import static org.junit.Assert.*;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ZkVersionedTest {

    private static final Logger LOG = LoggerFactory.getLogger(ZkVersionedTest.class);
    private static CuratorFramework curator;
    private static LocalZkServer zk;

    private static CuratorFramework buildCuratorFramework() {
        String connectionString = "localhost:21818";
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        LOG.info("attempting to connect to ZK with connection string {}", "localhost:21818");
        CuratorFramework newCurator = CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
        newCurator.start();
        return newCurator;
    }

    @BeforeClass
    public static void setup() throws Exception {
        zk = new LocalZkServer();
        curator = buildCuratorFramework();
    }

    private TestObject getTestObject() {
        TestObject testObject = new TestObject(curator, "/testObject");

        testObject.setLongObject(Long.MIN_VALUE);
        testObject.setStringObject("String");

        Pojo pojo1 = new Pojo();
        Pojo pojo2 = new Pojo();

        List<Pojo> pojos = new ArrayList<>();
        pojos.add(pojo1);
        pojos.add(pojo2);
        testObject.setPojoList(pojos);
        return testObject;
    }

    @Test(expected = VersionMismatchException.class)
    public void testSaveNewNonNullVersion() throws VersionMismatchException, Exception {
        TestObject testObject = getTestObject();
        testObject.setVersion(1);
        testObject.save();
    }

    @Test(expected = VersionMismatchException.class)
    public void testSaveExistingWithNullVersion() throws VersionMismatchException, Exception {
        TestObject testObject = new TestObject(curator, "/testObjectUniquePath");
        testObject.save();
        testObject.setVersion(null);
        testObject.save();
    }

    @Test
    public void testSaveFetchNewObject() throws VersionMismatchException, Exception {
        TestObject testObject = getTestObject();
        testObject.save();
        TestObject retrievedObject = TestObject.get(TestObject.class, curator, "/testObject");
        assertEquals(testObject.toJSON(), retrievedObject.toJSON());
    }

    @Test(expected = InvalidUserRoleException.class)
    public void testSavingNonExistentRole() throws Exception {
        TestObject testObject = getTestObject();
        testObject.save("no-role");
    }

    @Test
    public void testApplyRole() throws IOException, JsonProcessingException, InvalidUserRoleException {
        TestObject testObject = getTestObject();
        testObject.setSensitive1("This text should not be serialized if protected by 1");
        testObject.setSensitive2("This text should not be serialized if protected by 2");

        testObject.registerMixIn("protectedBy1", TestObject.class, TestObjectProtected1.class);
        testObject.registerMixIn("protectedBy2", TestObject.class, TestObjectProtected2.class);

        // No role: Both sensitive fields should exist
        assertEquals(testObject.toJsonNode().has("sensitive1"), true);
        assertEquals(testObject.toJsonNode().has("sensitive1"), true);

        // protectedBy1 role: sensitive1 should not exist, sensitive 2 should exist
        assertEquals(testObject.toJsonNode("protectedBy1").has("sensitive1"), false);
        assertEquals(testObject.toJsonNode("protectedBy1").has("sensitive2"), true);

        // Role: protectedBy2, neither sensitive fields should exist
        assertEquals(testObject.toJsonNode("protectedBy2").has("sensitive1"), false);
        assertEquals(testObject.toJsonNode("protectedBy2").has("sensitive2"), false);

        assertEquals(testObject.toJsonNode().get("pojoList").get(0).has("protectedString"), true);

        testObject.registerMixIn("pojoProtected", Pojo.class, PojoProtected1.class);

        testObject.getPojoList().get(0)
                .setProtectedString("This text should not be serialized if protected by PojoProtected1");
        assertEquals(testObject.toJsonNode("pojoProtected").get("pojoList").get(0).has("protectedString"), false);
    }

    /**
     * Various assumptions are made for this abstraction to work properly 
     * and they need to be proven correct or we're going to have a bad time
     */
    @Test
    public void testNaiveAssumptions() throws Exception {
        // I would expect that I can update ephemeral nodes, is that true?
        byte[] testBytes1 = "first test".getBytes();
        byte[] testBytes2 = "another test".getBytes();
        curator.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/test1", testBytes1);
        curator.setData().forPath("/test1", testBytes2);

        // I would expect that versions still increment when updating ephemeral      
        curator.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/test2", testBytes1);
        assertEquals(curator.checkExists().forPath("/test2").getVersion(), 0);
        assertEquals(curator.setData().forPath("/test2", testBytes2).getVersion(), 1);

        // I would expect that closing a curator removes an ephermal when there
        // are still other curators created from the same factory/connection string      
        CuratorFramework tempCurator = buildCuratorFramework();
        tempCurator.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/test3", testBytes1);
        assertEquals(curator.checkExists().forPath("/test3").getVersion(), 0);
        tempCurator.close();
        Thread.sleep(10 * 1000); // Give the ephemeral time to timeout
        assertEquals(curator.checkExists().forPath("/test3"), null);

        LOG.info("Looks like our assumptions are solid");
    }

    /**
     * @throws Exception
     */
    @Test
    public void testMergingArrays() throws Exception {
        List<Pojo> pojoList1 = new ArrayList<>();
        pojoList1.add(new Pojo("p1", "p1"));
        pojoList1.add(new Pojo("p2", "p2"));

        List<Pojo> pojoList2 = new ArrayList<>();
        pojoList1.add(new Pojo("p3", "p3"));

        TestObject t1 = new TestObject(curator, "/t1");
        t1.registerMixIn("protectedBy1", TestObject.class, TestObjectProtected1.class);

        t1.setPojoList(pojoList1);
        t1.save();
        LOG.info("Before protecting with mixin: {}", t1.toJSON());

        t1.setPojoList(pojoList2);
        t1.save("protectedBy1");
        LOG.info("After protecting with mixin and saving with more array objects: {}", t1.toJSON());
    }

    /**
     * @throws Exception
     */
    @Test
    public void testProtectingArrays() throws Exception {
        List<Pojo> pojoList1 = new ArrayList<>();
        pojoList1.add(new Pojo("p1", "p1"));
        pojoList1.add(new Pojo("p2", "p2"));

        TestObject t1 = new TestObject(curator, "/t1");
        t1.registerMixIn("protectedBy3", TestObject.class, TestObjectProtected3.class);
        t1.setPojoList(pojoList1);
        // Non-protected JSON node contains an array for pojoList
        assertEquals(t1.toJsonNode().get("pojoList").isArray(), true);
        // Protected JSON node doesn't contain an array for pojoList
        assertEquals(t1.toJsonNode("protectedBy3").get("pojoList"), null);
        LOG.info("JSON should not contain a pojoList: {}", t1.toJSON("protectedBy3"));
    }

    /**
     * @throws Exception
     */
    @Test
    public void testProtectingDeeplyNestedArrays() throws Exception {
        List<Pojo> pojoList1 = new ArrayList<>();
        pojoList1.add(new Pojo("p1", "p1"));
        pojoList1.add(new Pojo("p2", "p2"));

        TestObject t2 = new TestObject();
        t2.setPojoList(pojoList1);
        List<TestObject> testObjects = new ArrayList<>();
        testObjects.add(t2);

        TestParentObject parent1 = new TestParentObject(curator, "/p1");
        parent1.setTestObjects(testObjects);
        parent1.registerMixIn("protectedBy3", TestObject.class, TestObjectProtected3.class);

        // Non-protected JSON node contains an array for pojoList
        //assertEquals(parent1.toJsonNode().get("pojoList").isArray(), true);
        // Protected JSON node doesn't contain an array for pojoList
        //assertEquals(t1.toJsonNode("protectedBy3").get("pojoList"), null);
        LOG.info("Deeply Nested JSON should not contain a pojoList: {}", parent1.toJSON("protectedBy3"));
    }

    @AfterClass
    public static void cleanup() throws Exception {
        curator.close();
        zk.shutdown();
    }

}