/* * Copyright (c) 2008-2017 the original author or authors. * * 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.cometd.server; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Map; import org.cometd.bayeux.Message; import org.cometd.bayeux.server.ServerMessage; import org.cometd.common.JSONContext; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestWatcher; import org.junit.runner.Description; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class ServerMessageImplTest { @Rule public final TestWatcher testName = new TestWatcher() { @Override protected void starting(Description description) { super.starting(description); System.err.printf("Running %s.%s%n", description.getTestClass().getName(), description.getMethodName()); } }; @Test public void testSimpleContent() throws Exception { ServerMessageImpl message = new ServerMessageImpl(); message.put("channel", "/foo/bar"); assertEquals(1, message.size()); assertEquals("/foo/bar", message.getChannel()); Assert.assertEquals("channel", message.keySet().iterator().next()); Assert.assertEquals("/foo/bar", message.values().iterator().next()); } @Test public void testFrozenBehavior() throws Exception { String originalJSON = "{" + "\"id\":\"12345\"," + "\"clientId\":\"jva73siaj92jdafa\"," + "\"data\":{" + " \"dataName\":\"dataValue\"," + " \"innerData\":{" + " }" + "}," + "\"ext\":{" + " \"extName\":\"extValue\"" + "}" + "}"; JSONContext.Server jsonContext = new JettyJSONContextServer(); ServerMessage.Mutable[] messages = jsonContext.parse(originalJSON); ServerMessageImpl message = (ServerMessageImpl)messages[0]; String json = jsonContext.generate(message); assertTrue(json.contains("\"ext\":{\"extName\":\"extValue\"}")); assertTrue(json.contains("\"clientId\":\"jva73siaj92jdafa\"")); assertTrue(json.contains("\"dataName\":\"dataValue\"")); assertTrue(json.contains("\"id\":\"12345\"")); assertEquals("12345", message.getId()); // Modify the message message.put("id", "54321"); Assert.assertEquals("54321", message.getId()); // Be sure the JSON reflects the modifications json = jsonContext.generate(message); assertTrue(json.contains("\"id\":\"54321\"")); // Freeze the message message.freeze(json); try { message.put("id", "666"); fail(); } catch (UnsupportedOperationException expected) { } Assert.assertEquals("54321", message.getId()); Assert.assertEquals("54321", message.get(Message.ID_FIELD)); try { message.getDataAsMap().put("x", "9"); fail(); } catch (UnsupportedOperationException expected) { } try { message.getDataAsMap().put("x", "9"); fail(); } catch (UnsupportedOperationException expected) { } try { message.getExt().put("x", "9"); fail(); } catch (UnsupportedOperationException expected) { } // Deep modifications after the message is frozen are discarded @SuppressWarnings("unchecked") Map<String, Object> innerData = (Map<String, Object>)message.getDataAsMap().get("innerData"); innerData.put("newContent", true); String json2 = message.getJSON(); assertEquals(json, json2); } @Test public void testSerialization() throws Exception { ServerMessageImpl message = new ServerMessageImpl(); message.setChannel("/channel"); message.setClientId("clientId"); message.setId("id"); message.setSuccessful(true); message.getDataAsMap(true).put("data1", "dataValue1"); message.getExt(true).put("ext1", "extValue1"); message.setLazy(true); ServerMessageImpl associated = new ServerMessageImpl(); associated.put("associated", true); message.setAssociated(associated); String json = new JettyJSONContextServer().generate(message); message.freeze(json); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(message); oos.close(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); ServerMessageImpl deserialized = (ServerMessageImpl)ois.readObject(); assertEquals(message, deserialized); assertTrue(deserialized.isLazy()); assertNull(deserialized.getAssociated()); // Make sure the message is still frozen try { deserialized.put("a", "b"); fail(); } catch (UnsupportedOperationException expected) { } } @Test public void testModificationViaEntrySet() throws Exception { ServerMessageImpl message = new ServerMessageImpl(); message.setChannel("/channel"); for (Map.Entry<String, Object> field : message.entrySet()) { if (Message.CHANNEL_FIELD.equals(field.getKey())) { field.setValue("/foo"); break; } } String json = new JettyJSONContextServer().generate(message); message.freeze(json); for (Map.Entry<String, Object> field : message.entrySet()) { if (Message.CHANNEL_FIELD.equals(field.getKey())) { try { field.setValue("/foo"); fail(); } catch (UnsupportedOperationException expected) { break; } } } } @Test public void testNullValue() throws Exception { String originalJSON = "{" + "\"id\":\"12345\"," + "\"clientId\":\"jva73siaj92jdafa\"," + "\"data\":{" + " \"bar\":5," + " \"nullData\":null" + " }" + "}"; JSONContext.Server jsonContext = new JettyJSONContextServer(); ServerMessage.Mutable[] messages = jsonContext.parse(originalJSON); ServerMessageImpl message = (ServerMessageImpl)messages[0]; Map<String, Object> data = message.getDataAsMap(); assertNull(data.get("nullData")); assertTrue(data.containsKey("nullData")); assertEquals(2, data.size()); } }