/* * Copyright © 2015 Cask Data, 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 co.cask.cdap.internal.app.runtime.workflow; import co.cask.cdap.api.workflow.WorkflowToken; import org.junit.Assert; import org.junit.Test; /** * Tests for {@link WorkflowToken} */ public class WorkflowTokenTest { @Test public void testNonUpdatableWorkflowToken() { BasicWorkflowToken token = new BasicWorkflowToken(0); token.setCurrentNode("node"); try { token.put("a", "b"); Assert.fail("Workflow token update should fail because the token is non-updatable."); } catch (IllegalStateException e) { assertSizeExceededErrorMessage(e); } } @Test public void testUpdateWithLargeRecord() { BasicWorkflowToken token = new BasicWorkflowToken(1); token.setCurrentNode("node"); try { token.put("k", generateDataInKb(1024)); Assert.fail("Workflow token update should fail because token size should have exceeded limit."); } catch (IllegalStateException e) { assertSizeExceededErrorMessage(e); } } @Test public void testMergeLargeWorkflowToken() { BasicWorkflowToken token1 = new BasicWorkflowToken(1); token1.setCurrentNode("node1"); // total size of token1 after this operation is 512KB token1.put(generateDataInKb(1), generateDataInKb(511)); // add an additional 2 bytes, just so we have size > max size (and not equal to max size) after merge token1.put("k", "v"); BasicWorkflowToken token2 = new BasicWorkflowToken(1); token2.setCurrentNode("node1"); // total size of token2 after this operation is 512KB token2.put(generateDataInKb(1), generateDataInKb(511)); // should succeed, because token1 already contains the NodeValue being merged token1.mergeToken(token2); // set a different node in token2 and add the same data token2.setCurrentNode("node2"); // token2 is at capacity after the following operation token2.put(generateDataInKb(1), generateDataInKb(511)); // merging should now fail, because token1 now does not contain the NodeValue being merged try { token1.mergeToken(token2); Assert.fail("Workflow token merging should fail because token size should have exceeded limit."); } catch (IllegalStateException e) { assertSizeExceededErrorMessage(e); } } @Test public void testRepeatedPutAtSameNode() { BasicWorkflowToken token = new BasicWorkflowToken(1); token.setCurrentNode("node1"); // after this put, size would be 512KB token.put(generateDataInKb(1), generateDataInKb(511)); // after another successful put at a different node, size would be 1024KB. Workflow token would be at capacity. token.setCurrentNode("node2"); token.put(generateDataInKb(1), generateDataInKb(511)); // should succeed because the entry at key k1 should be replaced token.put(generateDataInKb(1), generateDataInKb(511)); // now should fail, because even though we're updating node2's value, we're adding an extra KB try { token.put(generateDataInKb(1), generateDataInKb(512)); Assert.fail("Workflow token update at existing key should fail because token size should have exceeded limit."); } catch (IllegalStateException e) { assertSizeExceededErrorMessage(e); } } private String generateDataInKb(int kb) { int bytes = kb * 1024; StringBuilder sb = new StringBuilder(kb); for (int i = 0; i < bytes; i++) { sb.append("a"); } return sb.toString(); } private void assertSizeExceededErrorMessage(IllegalStateException e) { Assert.assertTrue(e.getMessage().startsWith("Exceeded maximum permitted size of workflow token")); } }