You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/18 17:03:13 UTC

[04/64] [abbrv] incubator-brooklyn git commit: BROOKLYN-162 - apply org.apache package prefix to utils-common

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/brooklyn/util/time/DurationTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/brooklyn/util/time/DurationTest.java b/utils/common/src/test/java/brooklyn/util/time/DurationTest.java
deleted file mode 100644
index b59c73b..0000000
--- a/utils/common/src/test/java/brooklyn/util/time/DurationTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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 brooklyn.util.time;
-
-import java.util.concurrent.TimeUnit;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-@Test
-public class DurationTest {
-
-    public void testMinutes() {
-        Assert.assertEquals(3*60*1000, new Duration(3, TimeUnit.MINUTES).toMilliseconds());
-    }
-
-    public void testAdd() {
-        Assert.assertEquals((((4*60+3)*60)+30)*1000, 
-            new Duration(3, TimeUnit.MINUTES).
-                add(new Duration(4, TimeUnit.HOURS)).
-                add(new Duration(30, TimeUnit.SECONDS)).
-            toMilliseconds());
-    }
-
-    public void testStatics() {
-        Assert.assertEquals((((4*60+3)*60)+30)*1000, 
-            Duration.ONE_MINUTE.times(3).
-                add(Duration.ONE_HOUR.times(4)).
-                add(Duration.THIRTY_SECONDS).
-            toMilliseconds());
-    }
-
-    public void testParse() {
-        Assert.assertEquals((((4*60+3)*60)+30)*1000, 
-                Duration.of("4h 3m 30s").toMilliseconds());
-    }
-
-    public void testConvesion() {
-        Assert.assertEquals(1, Duration.nanos(1).toNanoseconds());
-        Assert.assertEquals(1, Duration.nanos(1.1).toNanoseconds());
-        Assert.assertEquals(1, Duration.millis(1).toMilliseconds());
-        Assert.assertEquals(1, Duration.millis(1.0).toMilliseconds());
-        Assert.assertEquals(1, Duration.millis(1.1).toMilliseconds());
-        Assert.assertEquals(1100000, Duration.millis(1.1).toNanoseconds());
-        Assert.assertEquals(500, Duration.seconds(0.5).toMilliseconds());
-    }
-
-    public void testToString() {
-        Assert.assertEquals("4h 3m 30s", 
-                Duration.of("4h 3m 30s").toString());
-    }
-
-    public void testToStringRounded() {
-        Assert.assertEquals("4h 3m", 
-                Duration.of("4h 3m 30s").toStringRounded());
-    }
-
-    public void testParseToString() {
-        Assert.assertEquals(Duration.of("4h 3m 30s"), 
-                Duration.parse(Duration.of("4h 3m 30s").toString()));
-    }
-
-    public void testRoundUp() {
-        Assert.assertEquals(Duration.nanos(1).toMillisecondsRoundingUp(), 1); 
-    }
-
-    public void testRoundZero() {
-        Assert.assertEquals(Duration.ZERO.toMillisecondsRoundingUp(), 0); 
-    }
-
-    public void testRoundUpNegative() {
-        Assert.assertEquals(Duration.nanos(-1).toMillisecondsRoundingUp(), -1); 
-    }
-
-    public void testNotRounding() {
-        Assert.assertEquals(Duration.nanos(-1).toMilliseconds(), 0); 
-    }
-
-    public void testNotRoundingNegative() {
-        Assert.assertEquals(Duration.nanos(-1).toMillisecondsRoundingUp(), -1);
-    }
-
-    public void testComparison() {
-        Assert.assertTrue(Duration.seconds(1.8).isLongerThan(Duration.millis(1600)));
-        Assert.assertTrue(Duration.millis(1600).isShorterThan(Duration.seconds(1.8)));
-        
-        Assert.assertTrue(Duration.seconds(1).isLongerThan(Duration.ZERO));
-        Assert.assertFalse(Duration.seconds(-1).isLongerThan(Duration.ZERO));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/brooklyn/util/time/TimeTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/brooklyn/util/time/TimeTest.java b/utils/common/src/test/java/brooklyn/util/time/TimeTest.java
deleted file mode 100644
index 350b1fe..0000000
--- a/utils/common/src/test/java/brooklyn/util/time/TimeTest.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * 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 brooklyn.util.time;
-
-import java.util.Date;
-import java.util.TimeZone;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-@Test
-public class TimeTest {
-
-    public void testMakeStringExact_secondsAndMillis() {
-        check(1, "1ms");
-        check(1000, "1s");
-        check(1001, "1s 1ms");
-        check(1011, "1s 11ms");
-        check(3*1000, "3s");
-        check(3*1000+1, "3s 1ms");
-        check(3*1000+10, "3s 10ms");
-        check(3*1000+100, "3s 100ms");
-        check(30*1000, "30s");
-        check(30*1000+1, "30s 1ms");
-        check(30*1000+100, "30s 100ms");
-    }
-    
-    public void testMakeStringRounded_secondsAndMillis() {
-        checkR(1, "1ms");
-        checkR(1000, "1s");
-        checkR(1001, "1.00s");
-        checkR(1011, "1.01s");
-        checkR(3*1000, "3s");
-        checkR(3*1000+1, "3.00s");
-        checkR(3*1000+10, "3.01s");
-        checkR(3*1000+100, "3.10s");
-        checkR(30*1000, "30s");
-        checkR(30*1000+1, "30.0s");
-        checkR(30*1000+10, "30.0s");
-        checkR(30*1000+100, "30.1s");
-    }
-    
-    public void testMakeStringExact_days() {
-        check(3*Time.MILLIS_IN_DAY, "3d");
-        check(3*Time.MILLIS_IN_DAY + 2*Time.MILLIS_IN_HOUR + 30*Time.MILLIS_IN_MINUTE + 1001, "3d 2h 30m 1s 1ms");
-    }
-
-    public void testMakeStringRounded_days() {
-        checkR(3*Time.MILLIS_IN_DAY, "3d");
-        checkR(3*Time.MILLIS_IN_DAY + 2*Time.MILLIS_IN_HOUR + 30*Time.MILLIS_IN_MINUTE + 1001, "3d 2h");
-        checkR(3*Time.MILLIS_IN_DAY + 30*Time.MILLIS_IN_MINUTE + 1001, "3d 30m");
-        checkR(3*Time.MILLIS_IN_DAY + 1001, "3d");
-        
-        checkR(30*Time.MILLIS_IN_MINUTE + 1111, "30m 1s");
-    }
-
-    public void testMakeStringExact_nanos() {
-        checkN(1001, "1us 1ns");
-        checkN(123000+456, "123us 456ns");
-        checkN(3*Time.MILLIS_IN_DAY*1000*1000, "3d");
-        checkN(3*Time.MILLIS_IN_DAY*1000*1000 + 1, "3d 1ns");
-        checkN(3*Time.MILLIS_IN_DAY*1000*1000 + 1001, "3d 1us 1ns");
-        checkN((3*Time.MILLIS_IN_DAY + 2*Time.MILLIS_IN_HOUR + 30*Time.MILLIS_IN_MINUTE + 1001)*1000*1000+123000+456, 
-                "3d 2h 30m 1s 1ms 123us 456ns");
-    }
-
-    public void testMakeStringRounded_nanos() {
-        checkRN(3*Time.MILLIS_IN_DAY*1000*1000, "3d");
-        checkRN((3*Time.MILLIS_IN_DAY + 2*Time.MILLIS_IN_HOUR + 30*Time.MILLIS_IN_MINUTE + 1001)*1000*1000+1001, "3d 2h");
-        checkRN((3*Time.MILLIS_IN_DAY + 30*Time.MILLIS_IN_MINUTE + 1001)*1000*1000+1001, "3d 30m");
-        checkRN((3*Time.MILLIS_IN_DAY + 1001)*1000*1000+1001, "3d");
-        
-        checkRN((30*Time.MILLIS_IN_MINUTE + 1111)*1000*1000+1001, "30m 1s");
-        checkRN((30*Time.MILLIS_IN_MINUTE)*1000*1000+1001, "30m");
-        checkRN((31000L)*1000*1000, "31s");
-        checkRN((31000L)*1000*1000+1001, "31.0s");
-        checkRN(1001, "1.001us");
-        checkRN(10101, "10.10us");
-        checkRN(101001, "101.0us");
-        checkRN(123000+456, "123.5us");
-    }
-
-
-    private void check(long millis, String expected) {
-        Assert.assertEquals(Time.makeTimeStringExact(millis), expected);
-    }
-    
-    private void checkR(long millis, String expected) {
-        Assert.assertEquals(Time.makeTimeStringRounded(millis), expected);
-    }
-
-    private void checkN(long nanos, String expected) {
-        Assert.assertEquals(Time.makeTimeStringNanoExact(nanos), expected);
-    }
-    
-    private void checkRN(long nanos, String expected) {
-        Assert.assertEquals(Time.makeTimeStringNanoRounded(nanos), expected);
-    }
-
-    @Test
-    public void testDateRounding() {
-        long x = System.currentTimeMillis();
-        Date d1 = Time.dropMilliseconds(new Date(x));
-        Date d2 = new Date(x - (x%1000));
-        Date d3 = new Date( (x/1000)*1000 );
-        Assert.assertEquals(d1.getTime() % 1000, 0);
-        Assert.assertEquals(d1, d2);
-        Assert.assertEquals(d1, d3);
-    }
-
-    @Test
-    public void testDateRoundingNull() {
-        Assert.assertNull(Time.dropMilliseconds(null));
-    }
-
-    @Test
-    public void testMakeStringExactZero() { check(0, "0ms"); }
-    @Test
-    public void testMakeStringExactNegative() { check(-1, "-1ms"); }
-    @Test
-    public void testMakeStringRoundedZero() { checkR(0, "0ms"); }
-    @Test
-    public void testMakeStringRoundedNegative() { checkR(-1, "-1ms"); }
-
-    @Test
-    public void testElapsedSince() {
-        long aFewSecondsAgo = System.currentTimeMillis() - 7*1000;
-        
-        Duration aFewSeconds = Time.elapsedSince(aFewSecondsAgo);
-        Assert.assertTrue(aFewSeconds.toMilliseconds() > 5*1000);
-        Assert.assertTrue(10*1000 > aFewSeconds.toMilliseconds());
-        
-        Assert.assertTrue(Time.hasElapsedSince(aFewSecondsAgo, Duration.FIVE_SECONDS));
-        Assert.assertFalse(Time.hasElapsedSince(aFewSecondsAgo, Duration.TEN_SECONDS));
-        Assert.assertTrue(Time.hasElapsedSince(-1, Duration.TEN_SECONDS));
-    }
-    
-    @Test
-    public void testMakeDateString() {
-        String in1 = "2015-06-15T12:34:56";
-        Date d1 = Time.parseDate(in1);
-        Assert.assertEquals(Time.makeDateString(d1), in1.replace('T', ' ')+".000");
-        
-        String in2 = "2015-06-15T12:34:56Z";
-        Date d2 = Time.parseDate(in2);
-        Assert.assertEquals(Time.makeDateString(d2, Time.DATE_FORMAT_ISO8601, Time.getTimeZone("UTC")), in1+".000+0000");
-    }
-
-    @Test(groups="Integration")  //because it depends on TZ's set up and parsing months
-    public void testTimeZones() {
-        // useful to debug, if new special time zones needed
-//        for (String id: TimeZone.getAvailableIDs()) {
-//            TimeZone tz = TimeZone.getTimeZone(id);
-//            System.out.println(id+": "+tz.getDisplayName()+" "+tz.getDisplayName(true, TimeZone.SHORT)+" "+tz);
-//        }
-        
-        Assert.assertEquals("+0100", Time.getTimeZoneOffsetString("Europe/London", 2015, 6, 4).get());
-        
-        Assert.assertEquals("-0500", Time.getTimeZoneOffsetString("EST", 2015, 1, 4).get());
-        Assert.assertEquals("-0400", Time.getTimeZoneOffsetString("America/New_York", 2015, 6, 4).get());
-        Assert.assertEquals("-0500", Time.getTimeZoneOffsetString("America/New_York", 2015, 1, 4).get());
-        
-        // BST treated as British Time (not Bangladesh)
-        Assert.assertEquals("+0000", Time.getTimeZoneOffsetString("BST", 2015, 1, 4).get());
-        Assert.assertEquals("+0100", Time.getTimeZoneOffsetString("BST", 2015, 6, 4).get());
-        
-        // EST treated as EDT not fixed -0500
-        Assert.assertEquals("-0400", Time.getTimeZoneOffsetString("EST", 2015, 6, 4).get());
-        
-        // these normally not recognized
-        Assert.assertEquals("-0400", Time.getTimeZoneOffsetString("EDT", 2015, 6, 4).get());
-        Assert.assertEquals("-0500", Time.getTimeZoneOffsetString("EDT", 2015, 1, 4).get());
-        
-        Assert.assertEquals("-0600", Time.getTimeZoneOffsetString("CST", 2015, 1, 4).get());
-        Assert.assertEquals("-0700", Time.getTimeZoneOffsetString("MST", 2015, 1, 4).get());
-        Assert.assertEquals("-0800", Time.getTimeZoneOffsetString("PST", 2015, 1, 4).get());
-        
-        Assert.assertEquals("+0530", Time.getTimeZoneOffsetString("IST", 2015, 1, 4).get());
-    }
-        
-    @Test
-    public void testParseDate() {
-        doTestParseDate(false);
-    }
-    
-    @Test(groups="Integration")  //because it depends on TZ's set up and parsing months
-    public void testParseDateIntegration() {
-        doTestParseDate(true);
-    }
-    
-    private void doTestParseDate(boolean integration) {
-        // explicit TZ inclusion 
-        assertDatesParseToEqual("2015.6.4.0000 +0100", "2015-06-04-0000 +0100");
-        assertDatesParseToEqual("2015.6.4.0100 +0100", "2015-06-04-0000 +0000");
-        assertDatesParseToEqual("2015.6.4.0100 -0100", "2015-06-04-0200 +0000");
-        if (integration) assertDatesParseToEqual("20150604 BST", "2015-06-04 +0100");
-        
-        // no TZ uses server default
-        assertDatesParseToEqual("2015.6.4.0000", "2015-06-04-0000 "+Time.getTimeZoneOffsetString(TimeZone.getDefault(), 2015, 6, 4));
-        assertDatesParseToEqual("20150604", "2015-06-04-0000");
-
-        // parse TZ
-        if (integration) {
-            assertDatesParseToEqual("20150604 +BST", "2015-06-04 +0100");
-            assertDatesParseToEqual("20150604 - - - BST", "2015-06-04 +0100");
-            assertDatesParseToEqual("20150604--BST", "2015-06-04 +0100");
-            assertDatesParseToEqual("20150604-//-BST", "2015-06-04 +0100");
-        }
-        assertDatesParseToEqual("2015.6.4+0100", "2015-06-04-0000+0100");
-        assertDatesParseToEqual("20150604-+0100", "2015-06-04 +0100");
-        assertDatesParseToEqual("20150604, +0100", "2015-06-04 +0100");
-        assertDatesParseToEqual("201506040000, 0100", "2015-06-04 +0100");
-        assertDatesParseToEqual("20150604  , 0000  , 0100", "2015-06-04 +0100");
-        assertDatesParseToEqual("2015-6-4 +0100", "2015-06-04-0000 +0100");
-        assertDatesParseToEqual("2015-6-4 -0100", "2015-06-04-0000 -0100");
-        assertDatesParseToEqual("20150604-0000//-0100", "2015-06-04 -0100");
-        // ambiguous TZ/hours parse prefers hours
-        assertDatesParseToEqual("2015-6-4-0100", "2015-06-04-0100");
-        assertDatesParseToEqual("2015-6-4--0100", "2015-06-04-0100");
-
-        // formats without spaces
-        assertDatesParseToEqual("20150604080012", "2015-06-04-080012");
-        assertDatesParseToEqual("20150604080012 +1000", "2015-06-03-220012 +0000");
-        assertDatesParseToEqual("20150604080012 -1000", "2015-06-04-180012 +0000");
-        assertDatesParseToEqual("20150604080012.345 +1000", "2015-06-03-220012.345 +0000");
-        if (integration) {
-            assertDatesParseToEqual("20150604 BST", "2015-06-04 +0100");
-            assertDatesParseToEqual("20150604 Europe/London", "2015-06-04 +0100");
-        }
-
-        // more misc tests
-        assertDatesParseToEqual("20150604 08:00:12.345", "2015-06-04-080012.345");
-        assertDatesParseToEqual("20150604-080012.345", "2015-06-04-080012.345");
-        assertDatesParseToEqual("2015-12-1", "2015-12-01-0000");
-        assertDatesParseToEqual("1066-12-1", "1066-12-01-0000");
-        
-        assertDatesParseToEqual("20150604T080012.345", "2015-06-04-080012.345");
-        assertDatesParseToEqual("20150604T080012.345Z", "2015-06-04-080012.345+0000");
-        assertDatesParseToEqual("20150604t080012.345 Z", "2015-06-04-080012.345+0000");
-
-        // millis parse, and zero is epoch, but numbers which look like a date or datetime take priority
-        assertDatesParseToEqual("0", "1970-1-1 UTC");
-        assertDatesParseToEqual("20150604", "2015-06-04");
-        assertDatesParseToEqual(""+Time.parseDate("20150604").getTime(), "2015-06-04");
-        assertDatesParseToEqual("20150604080012", "2015-06-04-080012");
-        assertDatesParseToEqual("0", "1970-1-1 UTC");
-
-        // leap year
-        Assert.assertEquals(Time.parseDate("2012-2-29").getTime(), Time.parseDate("2012-3-1").getTime() - 24*60*60*1000);
-        // perverse, but accepted for the time being:
-        Assert.assertEquals(Time.parseDate("2013-2-29").getTime(), Time.parseDate("2013-3-1").getTime());
-
-        // accept am and pm
-        assertDatesParseToEqual("20150604 08:00:12.345a", "2015-06-04-080012.345");
-        assertDatesParseToEqual("20150604 08:00:12.345 PM", "2015-06-04-200012.345");
-        if (integration) assertDatesParseToEqual("20150604 08:00:12.345 am BST", "2015-06-04-080012.345 +0100");
-        
-        // *calendar* parse includes time zone
-        Assert.assertEquals(Time.makeDateString(Time.parseCalendar("20150604 08:00:12.345a +0100"),
-            Time.DATE_FORMAT_ISO8601), "2015-06-04T08:00:12.345+0100");
-        Assert.assertEquals(Time.makeDateString(Time.parseCalendar("20150604 08:00:12.345a "+Time.TIME_ZONE_UTC.getID()),
-            Time.DATE_FORMAT_ISO8601), "2015-06-04T08:00:12.345+0000");
-        
-        // accept month in words
-        if (integration) {
-            assertDatesParseToEqual("2015-Dec-1", "2015-12-01-0000");
-            assertDatesParseToEqual("2015 Dec 1", "2015-12-01-0000");
-            assertDatesParseToEqual("2015-DEC-1", "2015-12-01-0000");
-            assertDatesParseToEqual("2015 December 1", "2015-12-01-0000");
-            assertDatesParseToEqual("2015 December 1", "2015-12-01-0000");
-            assertDatesParseToEqual("2015-Mar-1", "2015-03-01-0000");
-            assertDatesParseToEqual("2015 Mar 1", "2015-03-01-0000");
-            assertDatesParseToEqual("2015-MAR-1", "2015-03-01-0000");
-            assertDatesParseToEqual("2015 March 1", "2015-03-01-0000");
-            assertDatesParseToEqual("2015 March 1", "2015-03-01-0000");
-        }
-        
-        // for month in words, allow selected other orders also
-        if (integration) {
-            assertDatesParseToEqual("1-Jun-2015", "2015-06-01-0000");
-            assertDatesParseToEqual("Jun 1, 2015", "2015-06-01-0000");
-            assertDatesParseToEqual("June 1, 2015, 4pm", "2015-06-01-1600");
-        }
-    
-        // also allow time first if separators are used
-        assertDatesParseToEqual("16:00, 2015-12-30", "2015-12-30-1600");
-        if (integration) {
-            assertDatesParseToEqual("4pm, Dec 1, 2015", "2015-12-01-1600");
-            assertDatesParseToEqual("16:00 30-Dec-2015", "2015-12-30-1600");
-        }
-        
-        // and if time comes first, TZ can be before or after date
-        assertDatesParseToEqual("4pm +0100, 2015-12-30", "2015-12-30-1600 +0100");
-        assertDatesParseToEqual("4pm, 2015-12-30, +0100", "2015-12-30-1600 +0100");
-        
-        // these ambiguous ones are accepted (maybe we'd rather not), 
-        // but they are interpreted sensibly, preferring the more sensible interpretation 
-        if (integration) assertDatesParseToEqual("16 Dec 1 2015", "2015-12-01-1600");
-        if (integration) assertDatesParseToEqual("16:30 1067 Dec 1 1066", "1067-12-01-1630 +1066");
-        assertDatesParseToEqual("1040 1045 12 1", "1045-12-01-1040");
-        assertDatesParseToEqual("1040 1045 12 1 +0", "1045-12-01-1040Z");
-        if (integration) assertDatesParseToEqual("1045 Dec 1 1040", "1045-12-01-1040");
-        if (integration) assertDatesParseToEqual("10:40 Dec 1 1045", "1045-12-01-1040");
-        assertDatesParseToEqual("10.11-2020-12.01", "2020-12-01-1011");
-        if (integration) assertDatesParseToEqual("Oct.11 1045 12.01", "1045-10-11-1201");
-        if (integration) assertDatesParseToEqual("1040 1045 Dec 1 1030", "1045-12-01-1040 +1030");
-        assertDatesParseToEqual("1040 +02 2015 12 1", "2015-12-01-1040 +0200");
-        assertDatesParseToEqual("10:40:+02 2015 12 1", "2015-12-01-1040 +0200");
-    }
-    
-    @Test
-    public void testParseDateToStringWithMillisecond() {
-        Date d = new Date();
-        // clear seconds, but add a milli - to ensure not just toString formatting but also seconds computation
-        d.setTime(d.getTime() - (d.getTime() % 60000) + 1);
-        assertDatesParseToEqual(d.toString(), Time.makeDateStampString(d.getTime()));
-    }
-
-    private void assertDatesParseToEqual(String input, String expected) {
-        Assert.assertEquals(Time.parseDate(input).toString(), Time.parseDate(expected).toString(), "for: "+input+" ("+expected+")");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/brooklyn/util/yaml/YamlsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/brooklyn/util/yaml/YamlsTest.java b/utils/common/src/test/java/brooklyn/util/yaml/YamlsTest.java
deleted file mode 100644
index 6cd90f8..0000000
--- a/utils/common/src/test/java/brooklyn/util/yaml/YamlsTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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 brooklyn.util.yaml;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.testng.Assert;
-import org.testng.TestNG;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.UserFacingException;
-import brooklyn.util.yaml.Yamls.YamlExtract;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-public class YamlsTest {
-
-    @Test
-    public void testGetAs() throws Exception {
-        MutableList<String> list = MutableList.of("x");
-        assertEquals(Yamls.getAs(list.iterator(), List.class), list);
-        assertEquals(Yamls.getAs(list.iterator(), Iterable.class), list);
-        assertEquals(Yamls.getAs(list.iterator(), Iterator.class), list.iterator());
-        assertEquals(Yamls.getAs(list.iterator(), String.class), "x");
-    }
-        
-    @Test
-    public void testGetAt() throws Exception {
-        // leaf of map
-        assertEquals(Yamls.getAt("k1: v", ImmutableList.of("k1")), "v");
-        assertEquals(Yamls.getAt("k1: {k2: v}", ImmutableList.of("k1", "k2")), "v");
-        
-        // get list
-        assertEquals(Yamls.getAt("k1: [v1, v2]", ImmutableList.<String>of("k1")), ImmutableList.of("v1", "v2"));
-
-        // get map
-        assertEquals(Yamls.getAt("k1: v", ImmutableList.<String>of()), ImmutableMap.of("k1", "v"));
-        assertEquals(Yamls.getAt("k1: {k2: v}", ImmutableList.of("k1")), ImmutableMap.of("k2", "v"));
-        
-        // get array index
-        assertEquals(Yamls.getAt("k1: [v1, v2]", ImmutableList.<String>of("k1", "[0]")), "v1");
-        assertEquals(Yamls.getAt("k1: [v1, v2]", ImmutableList.<String>of("k1", "[1]")), "v2");
-    }
-    
-    
-    @Test
-    public void testExtractMap() {
-        String sample = "#before\nk1:\n- v1\nk2:\n  # comment\n  k21: v21\nk3: v3\n#after\n";
-        
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k1").withKeyIncluded(true).getMatchedYamlText(),
-            sample.substring(0, sample.indexOf("k2")));
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k3").withKeyIncluded(true).getMatchedYamlText(),
-            sample.substring(sample.indexOf("k3")));
-        
-        // comments and no key, outdented - the default
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").getMatchedYamlText(),
-            "# comment\nv21");
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").getMatchedYamlText(),
-            "# comment\nv21");
-        // comments and key
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").withKeyIncluded(true).getMatchedYamlText(),
-            "# comment\nk21: v21");
-        // no comments
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").withKeyIncluded(true).withPrecedingCommentsIncluded(false).getMatchedYamlText(),
-            "k21: v21");
-        // no comments and no key
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").withPrecedingCommentsIncluded(false).getMatchedYamlText(),
-            "v21");
-
-        // comments and no key, not outdented
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").withOriginalIndentation(true).getMatchedYamlText(),
-            "  # comment\n  v21");
-        // comments and key
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").withKeyIncluded(true).withOriginalIndentation(true).getMatchedYamlText(),
-            "  # comment\n  k21: v21");
-        // no comments
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").withKeyIncluded(true).withPrecedingCommentsIncluded(false).withOriginalIndentation(true).getMatchedYamlText(),
-            "  k21: v21");
-        // no comments and no key
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "k2", "k21").withPrecedingCommentsIncluded(false).withOriginalIndentation(true).getMatchedYamlText(),
-            "  v21");
-    }
-
-    @Test
-    public void testExtractInList() {
-        String sample = 
-            "- a\n" +
-            "- b: 2\n" +
-            "- # c\n" +
-            " c1:\n" +
-            "  1\n" +
-            " c2:\n" +
-            "  2\n" +
-            "-\n" +
-            " - a # for a\n" +
-            " # for b\n" +
-            " - b\n";
-        
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 0).getMatchedYamlText(), "a");
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 1, "b").getMatchedYamlText(), "2");
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 3, 0).getMatchedYamlText(), 
-            "a"
-            // TODO comments after on same line not yet included - would be nice to add
-//            "a # for a"
-            );
-        
-        // out-dent
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 2).getMatchedYamlText(), "c1:\n 1\nc2:\n 2\n");
-        // don't outdent
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 2).withOriginalIndentation(true).getMatchedYamlText(), " c1:\n  1\n c2:\n  2\n");
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 3, 0).withOriginalIndentation(true).getMatchedYamlText(), 
-            "   a"
-            // as above, comments after not included
-//            "   a # for a"
-            );
-
-        // with preceding comments
-        // TODO final item includes newline (and comments) after - this behaviour might change, it's inconsistent,
-        // but it means the final comments aren't lost
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 3, 1).getMatchedYamlText(), "# for b\nb\n");
-        
-        // exclude preceding comments
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, 3, 1).withPrecedingCommentsIncluded(false).getMatchedYamlText(), "b\n");
-    }
-    
-    @Test
-    public void testExtractMapIgnoringPreviousComments() {
-        String sample = "a: 1 # one\n"
-            + "b: 2 # two";
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath(sample, "b").getMatchedYamlText(),
-            "2 # two");
-    }
-    
-    @Test
-    public void testExtractMapWithOddWhitespace() {
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath("x: a\n bc", "x").getMatchedYamlText(),
-            "a\n bc");
-    }
-
-    @Test
-    public void testReplace() {
-        Assert.assertEquals(Yamls.getTextOfYamlAtPath("x: a\n bc", "x").getFullYamlTextWithExtractReplaced("\nc: 1\nd: 2"),
-            "x: \n   c: 1\n   d: 2");
-    }
-
-    @Test
-    public void testExtractNoOOBE() {
-        // this might log a warning, as item not found, but won't throw
-        YamlExtract r1 = Yamls.getTextOfYamlAtPath(
-            "items:\n- id: sample2\n  itemType: location\n  item:\n    type: jclouds:aws-ec2\n    brooklyn.config:\n      key2: value2\n\n",
-            "item");
-        
-        // won't throw
-        r1.getMatchedYamlTextOrWarn();
-        // will throw
-        try {
-            r1.getMatchedYamlText();
-            Assert.fail();
-        } catch (UserFacingException e) {
-            // expected, it should give a vaguely explanatory exception and no trace
-        }
-    }
-    
-    // convenience, since running with older TestNG IDE plugin will fail (older snakeyaml dependency);
-    // if you run as a java app it doesn't bring in the IDE TestNG jar version, and it works
-    public static void main(String[] args) {
-        TestNG testng = new TestNG();
-        testng.setTestClasses(new Class[] { YamlsTest.class });
-//        testng.setVerbose(9);
-        testng.run();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/test/AssertsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/test/AssertsTest.java b/utils/common/src/test/java/org/apache/brooklyn/test/AssertsTest.java
new file mode 100644
index 0000000..d72be76
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/test/AssertsTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.brooklyn.test;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.util.concurrent.Callables;
+
+public class AssertsTest {
+
+    private static final Runnable NOOP_RUNNABLE = new Runnable() {
+        @Override public void run() {
+        }
+    };
+    
+    // TODO this is confusing -- i'd expect it to fail since it always returns false;
+    // see notes at start of Asserts and in succeedsEventually method
+    @Test
+    public void testSucceedsEventually() {
+        Asserts.succeedsEventually(MutableMap.of("timeout", Duration.millis(50)), Callables.returning(false));
+    }
+    
+    @Test
+    public void testAssertReturnsEventually() throws Exception {
+        Asserts.assertReturnsEventually(NOOP_RUNNABLE, Duration.THIRTY_SECONDS);
+    }
+    
+    @Test
+    public void testAssertReturnsEventuallyTimesOut() throws Exception {
+        final AtomicBoolean interrupted = new AtomicBoolean();
+        
+        try {
+            Asserts.assertReturnsEventually(new Runnable() {
+                public void run() {
+                    try {
+                        Thread.sleep(60*1000);
+                    } catch (InterruptedException e) {
+                        interrupted.set(true);
+                        Thread.currentThread().interrupt();
+                        return;
+                    }
+                }},
+                Duration.of(10, TimeUnit.MILLISECONDS));
+            Assert.fail("Should have thrown AssertionError on timeout");
+        } catch (TimeoutException e) {
+            // success
+        }
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                Assert.assertTrue(interrupted.get());
+            }});
+    }
+    
+    @Test
+    public void testAssertReturnsEventuallyPropagatesException() throws Exception {
+        try {
+            Asserts.assertReturnsEventually(new Runnable() {
+                public void run() {
+                    throw new IllegalStateException("Simulating failure");
+                }},
+                Duration.THIRTY_SECONDS);
+            Assert.fail("Should have thrown AssertionError on timeout");
+        } catch (ExecutionException e) {
+            IllegalStateException ise = Exceptions.getFirstThrowableOfType(e, IllegalStateException.class);
+            if (ise == null || !ise.toString().contains("Simulating failure")) throw e;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/test/FixedLocaleTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/test/FixedLocaleTest.java b/utils/common/src/test/java/org/apache/brooklyn/test/FixedLocaleTest.java
new file mode 100644
index 0000000..cddced4
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/test/FixedLocaleTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.brooklyn.test;
+
+import java.util.Locale;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+
+public class FixedLocaleTest {
+    private Locale defaultLocale;
+    private Locale fixedLocale;
+    
+    public FixedLocaleTest() {
+        this(Locale.UK);
+    }
+    
+    public FixedLocaleTest(Locale fixedLocale) {
+        this.fixedLocale = fixedLocale;
+    }
+
+    @BeforeClass
+    public void setUp() {
+        defaultLocale = Locale.getDefault();
+        Locale.setDefault(fixedLocale);
+    }
+    
+    @AfterClass
+    public void tearDown() {
+        Locale.setDefault(defaultLocale);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/collections/CollectionFunctionalsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/CollectionFunctionalsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/CollectionFunctionalsTest.java
new file mode 100644
index 0000000..1d75297
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/CollectionFunctionalsTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.brooklyn.util.collections;
+
+import org.apache.brooklyn.util.collections.CollectionFunctionals;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class CollectionFunctionalsTest {
+
+    @Test
+    public void testListSize() {
+        Assert.assertTrue(CollectionFunctionals.sizeEquals(2).apply(ImmutableList.of("x", "y")));
+        Assert.assertFalse(CollectionFunctionals.sizeEquals(2).apply(null));
+        Assert.assertTrue(CollectionFunctionals.sizeEquals(0).apply(ImmutableList.of()));
+        Assert.assertFalse(CollectionFunctionals.sizeEquals(0).apply(null));
+    }
+
+    @Test
+    public void testMapSize() {
+        Assert.assertTrue(CollectionFunctionals.<String>mapSizeEquals(2).apply(ImmutableMap.of("x", "1", "y", "2")));
+        Assert.assertFalse(CollectionFunctionals.<String>mapSizeEquals(2).apply(null));
+        Assert.assertTrue(CollectionFunctionals.mapSizeEquals(0).apply(ImmutableMap.of()));
+        Assert.assertFalse(CollectionFunctionals.mapSizeEquals(0).apply(null));
+    }
+
+    @Test
+    public void testMapSizeOfNull() {
+        Assert.assertEquals(CollectionFunctionals.mapSize().apply(null), null);
+        Assert.assertEquals(CollectionFunctionals.mapSize(-1).apply(null), (Integer)(-1));
+    }
+
+    @Test
+    public void testFirstElement() {
+        Assert.assertEquals(CollectionFunctionals.firstElement().apply(null), null);
+        Assert.assertEquals(CollectionFunctionals.firstElement().apply(ImmutableList.of("a")), "a");
+        Assert.assertEquals(CollectionFunctionals.firstElement().apply(ImmutableList.of("a", "b", "c")), "a");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/collections/JsonyaTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/JsonyaTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/JsonyaTest.java
new file mode 100644
index 0000000..9ce77d2
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/JsonyaTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.brooklyn.util.collections;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.util.collections.Jsonya;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.collections.Jsonya.Navigator;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+public class JsonyaTest {
+    
+    public static Navigator<MutableMap<Object,Object>> europeMap() {
+        return Jsonya.newInstance().at("europe", "uk", "edinburgh")
+                .put("population", 500*1000)
+                .put("weather", "wet", "lighting", "dark")
+                .root().at("europe").at("france").put("population", 80*1000*1000)
+                .root();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testJsonyaMapNew() {
+        MutableMap<Object, Object> m = europeMap().getRootMap();
+        
+        Assert.assertEquals(Jsonya.of(m).get("europe", "uk", "edinburgh", "population"), 500*1000);
+        Assert.assertEquals(Jsonya.of(m).at("europe", "uk", "edinburgh", "population").get(), 500*1000);
+        Assert.assertEquals(((Map<Object,Object>)Jsonya.of(m).get("europe")).keySet(), ImmutableSet.of("uk", "france"));
+        Assert.assertEquals(Jsonya.of(m).at("europe").getFocusMap().keySet(), ImmutableSet.of("uk", "france"));
+    }
+    
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testJsonyaMapExistingAndRootModification() {
+        Navigator<MutableMap<Object, Object>> n = Jsonya.of(europeMap().getRootMap()).at("asia")
+            .put(MutableMap.of("china", null))
+            .put(MutableMap.of("japan", null));
+        
+        Assert.assertTrue( n.root().at("asia").get(Map.class).containsKey("china") );
+        Assert.assertTrue( ((Map)n.root().get("asia")).containsKey("japan") );
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testJsonyaWithList() {
+        Navigator<MutableMap<Object, Object>> n = europeMap();
+        n.at("europe", "uk", "neighbours").list().add("ireland")
+            .root().at("europe", "france", "neighbours").list().add("spain", "germany").add("switzerland")
+            .root().at("europe", "france", "neighbours").add("lux");
+        Object l = n.root().at("europe", "france", "neighbours").get();
+        Assert.assertTrue(l instanceof List);
+        Assert.assertEquals(((List)l).size(), 4);
+        // this wants a map, so it creates a map in the list
+        n.put("east", "germany", "south", "spain");
+        Assert.assertEquals(((List)l).size(), 5);
+        Map nd = (Map) ((List)l).get(4);
+        Assert.assertEquals(nd.size(), 2);
+        Map nd2 = (Map) n.root().get("europe", "france", "neighbours", 4);
+        Assert.assertEquals(nd2.size(), 2);
+    }
+    
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testCreateMapInList1() {
+        MutableMap<Object, Object> map = Jsonya.at("countries").list().map().add("europe", "uk").getRootMap();
+        List l = (List)map.get("countries");
+        Assert.assertEquals( ((Map)l.get(0)).get("europe"), "uk" );
+    }
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testCreateMapInList2() {
+        MutableMap<Object, Object> map = Jsonya.at("countries").list().map().add("europe", "uk")
+            .root().at("countries").add("antarctica")
+            .root().at("countries").map().add("asia", (Object)null)
+                .at("asia").list().add("china", "japan").getRootMap();
+        
+        List l = (List)map.get("countries");
+        Assert.assertEquals( ((Map)l.get(0)).get("europe"), "uk" );
+    }
+    
+    @Test
+    public void testJsonyaDeepSimple() {
+        Navigator<MutableMap<Object, Object>> n = Jsonya.of(europeMap())
+                .at("europe").add("spain", "plains");
+        Assert.assertEquals( n.root().get("europe", "spain"), "plains" );
+        Assert.assertEquals( n.getRootMap().size(), 1 );
+        Assert.assertEquals( n.root().at("europe").getFocusMap().size(), 3 );
+    }
+    
+    @Test(expectedExceptions=Exception.class)
+    public void testJsonyaDeepSimpleFailure() {
+        Jsonya.of(europeMap()).at("euroope").add("spain");
+    }
+
+    @Test
+    public void testJsonyaDeepMoreComplicated() {
+        Navigator<MutableMap<Object, Object>> n = Jsonya.of(europeMap()).at("asia")
+            .list().add("china", "japan")
+            .root().add( Jsonya.newInstance().at("europe", "uk", "glasgow").put("weather", "even wetter").getRootMap() );
+        
+        Assert.assertEquals( n.getRootMap().size(), 2 );
+        Assert.assertTrue( n.root().at("asia").get(List.class).contains("china") );
+        Assert.assertTrue( ((List<?>)n.root().get("asia")).contains("japan") );
+        
+        Assert.assertEquals(n.root().at("europe", "uk").get(Map.class).size(), 2);
+        Assert.assertEquals(n.root().at("europe", "uk", "edinburgh", "weather").get(), "wet");
+        Assert.assertEquals(n.root().at("europe", "uk", "glasgow", "weather").get(), "even wetter");
+    }
+    
+    @Test
+    public void testJsonyaToString() {
+        Assert.assertEquals(europeMap().toString(), 
+            "{ \"europe\": { \"uk\": { \"edinburgh\": { \"population\": 500000, \"weather\": \"wet\", \"lighting\": \"dark\" } },"
+            + " \"france\": { \"population\": 80000000 } } }");
+    }
+
+    @Test
+    public void testPrimitivedAndLiteralledMap() {
+        Object foo = new Object() {
+            public String toString() { return "FOO"; }
+        };
+        
+        MutableMap<Object, Object> map = MutableMap.<Object,Object>of("a", 1, 2, Arrays.<Object>asList(true, 8, "8"), 'C', foo);
+        
+        Map<Object, Object> mapL = Jsonya.newInstanceLiteral().put(map).getRootMap();
+        Assert.assertEquals(mapL, map);
+        Assert.assertEquals(mapL.get('C'), foo);
+        
+        Map<Object, Object> mapP = Jsonya.newInstancePrimitive().put(map).getRootMap();
+        Assert.assertNotEquals(mapP, map);
+        Assert.assertEquals(mapP.get('C'), foo.toString());
+        Assert.assertEquals(MutableMap.copyOf(mapP).add('C', null), MutableMap.copyOf(map).add('C', null));
+    }
+
+    @Test
+    public void testJsonyaBadPathNull() {
+        Navigator<MutableMap<Object, Object>> m = europeMap();
+        // does not create (but if we 'pushed' it would)
+        Assert.assertNull( m.at("europe",  "spain", "barcelona").get() );
+        Assert.assertNull( m.root().at("europe").at("spain").at("barcelona").get() );
+    }
+    @Test
+    public void testJsonyaMaybe() {
+        Navigator<MutableMap<Object, Object>> m = europeMap();
+        Assert.assertEquals( m.at("europe",  "spain", "barcelona").getMaybe().or("norealabc"), "norealabc" );
+        Assert.assertEquals(m.root().at("europe").getFocusMap().keySet(), MutableSet.of("uk", "france"));
+    }
+    
+    @Test
+    public void testJsonyaPushPop() {
+        Navigator<MutableMap<Object, Object>> m = europeMap();
+        Assert.assertTrue(m.getFocusMap().containsKey("europe"));
+        Assert.assertFalse(m.getFocusMap().containsKey("edinburgh"));
+        m.push();
+        
+        m.at("europe", "uk");
+        Assert.assertTrue(m.getFocusMap().containsKey("edinburgh"));
+        Assert.assertFalse(m.getFocusMap().containsKey("europe"));
+        
+        m.pop();
+        Assert.assertTrue(m.getFocusMap().containsKey("europe"));
+        Assert.assertFalse(m.getFocusMap().containsKey("edinburgh"));
+
+        // also check 'get' does not change focus
+        m.get("europe", "uk");
+        Assert.assertTrue(m.getFocusMap().containsKey("europe"));
+        Assert.assertFalse(m.getFocusMap().containsKey("edinburgh"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java
new file mode 100644
index 0000000..5d3a140
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.brooklyn.util.collections;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.brooklyn.util.collections.MutableList;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test
+public class MutableListTest {
+
+    public void testBuilderAddArray() throws Exception {
+        List<Object> vals = MutableList.builder().addAll(new Object[] {1,2,3}).build();
+        Assert.assertEquals(vals, ImmutableList.of(1,2,3));
+    }
+    
+    public void testBuilderAddVarargs() throws Exception {
+        List<Object> vals = MutableList.builder().add(1,2,3).build();
+        Assert.assertEquals(vals, ImmutableList.of(1,2,3));
+    }
+    
+    public void testBuilderAddIterable() throws Exception {
+        List<Object> vals = MutableList.builder().addAll(ImmutableList.of(1,2)).addAll(ImmutableList.of(2,3)).build();
+        Assert.assertEquals(vals, ImmutableList.of(1,2,2,3));
+    }
+    
+    public void testBuilderAddIterator() throws Exception {
+        List<Object> vals = MutableList.builder().addAll(ImmutableList.of(1,2).iterator()).build();
+        Assert.assertEquals(vals, ImmutableList.of(1,2));
+    }
+    
+    public void testBuilderRemoval() throws Exception {
+        List<Object> vals = MutableList.builder()
+                .add(1,2,3)
+                .remove(2)
+                .add(4)
+                .build();
+        Assert.assertEquals(vals, ImmutableList.of(1,3,4));
+    }
+    
+    public void testBuilderRemoveAll() throws Exception {
+        List<Object> vals = MutableList.builder()
+                .add(1,2,3)
+                .removeAll(ImmutableList.of(2,3))
+                .add(4)
+                .build();
+        Assert.assertEquals(vals, ImmutableList.of(1,4));
+    }
+    
+    public void testEqualsExact() {
+        List<Object> a = MutableList.<Object>of("a", 1, "b", false);
+        List<Object> b = MutableList.<Object>of("a", 1, "b", false);
+        Assert.assertEquals(a, b);
+    }
+    
+    public void testNotEqualsUnordered() {
+        List<Object> a = MutableList.<Object>of("a", 1, "b", false);
+        List<Object> b = MutableList.<Object>of("b", false, "a", 1);
+        Assert.assertNotEquals(a, b);
+    }
+
+    public void testEqualsDifferentTypes() {
+        List<Object> a = MutableList.<Object>of("a", 1, "b", false);
+        List<Object> b = Arrays.<Object>asList("a", 1, "b", false);
+        Assert.assertEquals(a, b);
+        Assert.assertEquals(b, a);
+    }
+
+    public void testEqualsDifferentTypes2() {
+        List<Object> a = MutableList.<Object>of("http");
+        List<String> b = Arrays.<String>asList("http");
+        Assert.assertEquals(a, b);
+        Assert.assertEquals(b, a);
+    }
+
+    public void testContainingNullAndUnmodifiable() {
+        MutableList<Object> x = MutableList.<Object>of("x", null);
+        Assert.assertTrue(x.contains(null));
+        
+        List<Object> x1 = x.asUnmodifiable();
+        List<Object> x2 = x.asUnmodifiableCopy();
+        List<Object> x3 = x.asImmutableCopy();
+        
+        x.remove(null);
+        Assert.assertFalse(x.contains(null));
+        Assert.assertFalse(x1.contains(null));
+        Assert.assertTrue(x2.contains(null));
+        Assert.assertTrue(x3.contains(null));
+        
+        try { x1.remove("x"); Assert.fail(); } catch (Exception e) { /* expected */ }
+        try { x2.remove("x"); Assert.fail(); } catch (Exception e) { /* expected */ }
+        try { x3.remove("x"); Assert.fail(); } catch (Exception e) { /* expected */ }
+        
+        Assert.assertTrue(x1.contains("x"));
+        Assert.assertTrue(x2.contains("x"));
+        Assert.assertTrue(x3.contains("x"));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableMapTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableMapTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableMapTest.java
new file mode 100644
index 0000000..807e077
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableMapTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.brooklyn.util.collections;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+@Test
+public class MutableMapTest {
+
+    public void testEqualsExact() {
+        Map<Object,Object> a = MutableMap.<Object,Object>of("a", 1, "b", false);
+        Map<Object,Object> b = MutableMap.<Object,Object>of("a", 1, "b", false);
+        Assert.assertEquals(a, b);
+    }
+    
+    public void testEqualsUnordered() {
+        Map<Object,Object> a = MutableMap.<Object,Object>of("a", 1, "b", false);
+        Map<Object,Object> b = MutableMap.<Object,Object>of("b", false, "a", 1);
+        Assert.assertEquals(a, b);
+    }
+
+    public void testEqualsDifferentTypes() {
+        Map<Object,Object> a = MutableMap.<Object,Object>of("a", 1, "b", false);
+        Map<Object,Object> b = ImmutableMap.<Object,Object>of("b", false, "a", 1);
+        Assert.assertEquals(a, b);
+    }
+
+    public void testListOfMaps() {
+        MutableMap<Object, Object> map = MutableMap.<Object,Object>of("a", 1, 2, Arrays.<Object>asList(true, "8"));
+        ArrayList<Object> l = new ArrayList<Object>();
+        l.add(true); l.add("8");
+        MutableMap<Object, Object> map2 = MutableMap.<Object,Object>of(2, l, "a", 1);
+        Assert.assertEquals(map, map2);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/collections/QuorumChecksTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/QuorumChecksTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/QuorumChecksTest.java
new file mode 100644
index 0000000..4210921
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/QuorumChecksTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.brooklyn.util.collections;
+
+import org.apache.brooklyn.util.collections.QuorumCheck;
+import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class QuorumChecksTest {
+
+    @Test
+    public void testAll() {
+        QuorumCheck q = QuorumChecks.all();
+        Assert.assertTrue(q.isQuorate(2, 2));
+        Assert.assertFalse(q.isQuorate(1, 2));
+        Assert.assertTrue(q.isQuorate(0, 0));
+    }
+    
+    @Test
+    public void testAlwaysTrue() {
+        QuorumCheck q = QuorumChecks.alwaysTrue();
+        Assert.assertTrue(q.isQuorate(0, 2));
+        Assert.assertTrue(q.isQuorate(1, 2));
+        Assert.assertTrue(q.isQuorate(0, 0));
+    }
+    
+    @Test
+    public void testAtLeastOne() {
+        QuorumCheck q = QuorumChecks.atLeastOne();
+        Assert.assertTrue(q.isQuorate(2, 2));
+        Assert.assertTrue(q.isQuorate(1, 2));
+        Assert.assertFalse(q.isQuorate(0, 0));
+    }
+    
+    @Test
+    public void testAllAndAtLeastOne() {
+        QuorumCheck q = QuorumChecks.atLeastOne();
+        Assert.assertFalse(q.isQuorate(0, 2));
+        Assert.assertTrue(q.isQuorate(1, 2));
+        Assert.assertFalse(q.isQuorate(0, 0));
+    }
+    
+    @Test
+    public void testAtLeastOneUnlessEmpty() {
+        QuorumCheck q = QuorumChecks.atLeastOneUnlessEmpty();
+        Assert.assertFalse(q.isQuorate(0, 2));
+        Assert.assertTrue(q.isQuorate(1, 2));
+        Assert.assertTrue(q.isQuorate(0, 0));
+    }
+    
+    @Test
+    public void testAtLeastOneUnlessEmptyString() {
+        QuorumCheck q = QuorumChecks.of("atLeastOneUnlessEmpty");
+        Assert.assertFalse(q.isQuorate(0, 2));
+        Assert.assertTrue(q.isQuorate(1, 2));
+        Assert.assertTrue(q.isQuorate(0, 0));
+    }
+    
+    @Test
+    public void testLinearTwoPointsNeedMinTwo() {
+        QuorumCheck q = QuorumChecks.of("[ [0,2], [1,2] ]");
+        Assert.assertTrue(q.isQuorate(2, 2));
+        Assert.assertTrue(q.isQuorate(2, 10));
+        Assert.assertFalse(q.isQuorate(1, 1));
+    }
+    
+    @Test
+    public void testLinearNeedHalfToTenAndTenPercentAtHundred() {
+        QuorumCheck q = QuorumChecks.of("[ [0,0], [10,5], [100,10], [200, 20] ]");
+        Assert.assertTrue(q.isQuorate(2, 2));
+        Assert.assertTrue(q.isQuorate(1, 2));
+        Assert.assertTrue(q.isQuorate(0, 0));
+        Assert.assertFalse(q.isQuorate(1, 10));
+        Assert.assertTrue(q.isQuorate(6, 10));
+        Assert.assertFalse(q.isQuorate(7, 50));
+        Assert.assertTrue(q.isQuorate(8, 50));
+        Assert.assertFalse(q.isQuorate(9, 100));
+        Assert.assertTrue(q.isQuorate(11, 100));
+        Assert.assertFalse(q.isQuorate(19, 200));
+        Assert.assertTrue(q.isQuorate(21, 200));
+        Assert.assertFalse(q.isQuorate(29, 300));
+        Assert.assertTrue(q.isQuorate(31, 300));
+    }
+    
+    
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/collections/TimeWindowedListTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/TimeWindowedListTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/TimeWindowedListTest.java
new file mode 100644
index 0000000..412a7c3
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/TimeWindowedListTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.brooklyn.util.collections;
+
+import static org.apache.brooklyn.util.time.Duration.ONE_MILLISECOND;
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.TimeWindowedList;
+import org.apache.brooklyn.util.collections.TimestampedValue;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+
+@SuppressWarnings({"rawtypes","unchecked"})
+public class TimeWindowedListTest {
+
+    private static final Duration TEN_MILLISECONDS = Duration.millis(10);
+    private static final Duration HUNDRED_MILLISECONDS = Duration.millis(100);
+    private static final Duration TWO_MILLISECONDS = Duration.millis(2);
+
+    @Test
+    public void testKeepsMinVals() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 1L, "minVals", 2));
+        assertEquals(list.getValues(2L), timestampedValues());
+        
+        list.add("a", 0L);
+        assertEquals(list.getValues(2L), timestampedValues("a", 0L));
+        
+        list.add("b", 100L);
+        assertEquals(list.getValues(102L), timestampedValues("a", 0L, "b", 100L));
+        
+        list.add("c", 200L);
+        assertEquals(list.getValues(202L), timestampedValues("b", 100L, "c", 200L));
+    }
+    
+    @Test
+    public void testKeepsOnlyRecentVals() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 1000L));
+        
+        list.add("a", 0L);
+        list.add("b", 100L);
+        assertEquals(list.getValues(1000L), timestampedValues("a", 0L, "b", 100L));
+        assertEquals(list.getValues(1100L), timestampedValues("b", 100L));
+        assertEquals(list.getValues(1101L), Lists.newArrayList());
+    }
+    
+    @Test
+    public void testKeepsMinExpiredVals() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 1000L, "minExpiredVals", 1));
+        
+        list.add("a", 0L);
+        list.add("b", 100L);
+        assertEquals(list.getValues(1001L), timestampedValues("a", 0L, "b", 100L));
+        assertEquals(list.getValues(1101L), timestampedValues("b", 100L));
+    }
+    
+    @Test
+    public void testGetsSubSetOfRecentVals() {
+        TimeWindowedList list = new TimeWindowedList<Object>(Duration.ONE_SECOND);
+        
+        list.add("a", 0L);
+        list.add("b", 100L);
+        assertEquals(list.getValuesInWindow(100L, HUNDRED_MILLISECONDS), timestampedValues("a", 0L, "b", 100L));
+        assertEquals(list.getValuesInWindow(101L, ONE_MILLISECOND), timestampedValues("b", 100L));
+    }
+    
+    @Test
+    public void testGetsSubSetOfValsIncludingOneMinExpiredVal() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 1000L, "minExpiredVals", 1));
+        
+        list.add("a", 0L);
+        list.add("b", 100L);
+        assertEquals(list.getValuesInWindow(100L, HUNDRED_MILLISECONDS), timestampedValues("a", 0L, "b", 100L));
+        assertEquals(list.getValuesInWindow(101L, TWO_MILLISECONDS), timestampedValues("a", 0L, "b", 100L));
+        assertEquals(list.getValuesInWindow(102L, ONE_MILLISECOND), timestampedValues("b", 100L));
+        assertEquals(list.getValuesInWindow(1001L, ONE_MILLISECOND), timestampedValues("b", 100L));
+    }
+    
+    @Test
+    public void testGetsWindowWithMinWhenEmpty() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 1L, "minVals", 1));
+        assertEquals(list.getValuesInWindow(1000L, TEN_MILLISECONDS), timestampedValues());
+    }
+
+    @Test
+    public void testGetsWindowWithMinExpiredWhenEmpty() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 1L, "minExpiredVals", 1));
+        assertEquals(list.getValuesInWindow(1000L, TEN_MILLISECONDS), timestampedValues());
+    }
+
+    @Test
+    public void testGetsWindowWithMinValsWhenExpired() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 1L, "minVals", 1));
+        list.add("a", 0L);
+        list.add("b", 1L);
+        
+        assertEquals(list.getValuesInWindow(1000L, TEN_MILLISECONDS), timestampedValues("b", 1L));
+    }
+
+    @Test
+    public void testZeroSizeWindowWithOneExpiredContainsOnlyMostRecentValue() {
+        TimeWindowedList list = new TimeWindowedList<Object>(MutableMap.of("timePeriod", 0L, "minExpiredVals", 1));
+        
+        list.add("a", 0L);
+        assertEquals(list.getValuesInWindow(0L, HUNDRED_MILLISECONDS), timestampedValues("a", 0L));
+        assertEquals(list.getValuesInWindow(2L, ONE_MILLISECOND), timestampedValues("a", 0L));
+        
+        list.add("b", 100L);
+        assertEquals(list.getValuesInWindow(100L, ONE_MILLISECOND), timestampedValues("b", 100L));
+        assertEquals(list.getValuesInWindow(102L, ONE_MILLISECOND), timestampedValues("b", 100L));
+    }
+    
+    private <T> List<TimestampedValue<T>> timestampedValues() {
+        return Lists.newArrayList();
+    }
+    
+    private <T> List<TimestampedValue<T>> timestampedValues(T v1, long t1) {
+        return Lists.newArrayList(new TimestampedValue<T>(v1, t1));
+    }
+    
+    private <T> List<TimestampedValue<T>> timestampedValues(T v1, long t1, T v2, long t2) {
+        return Lists.newArrayList(new TimestampedValue<T>(v1, t1), new TimestampedValue<T>(v2, t2));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/exceptions/ExceptionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/exceptions/ExceptionsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/exceptions/ExceptionsTest.java
new file mode 100644
index 0000000..13e077f
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/exceptions/ExceptionsTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.brooklyn.util.exceptions;
+
+import java.util.ConcurrentModificationException;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.ExceptionsTest;
+import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ExceptionsTest {
+
+    private static final Logger log = LoggerFactory.getLogger(ExceptionsTest.class);
+    
+    @Test
+    public void test12CollapseCompound() throws Exception {
+        RuntimeException e = Exceptions.create("test1", MutableSet.of(new IllegalStateException("test2"), new IllegalStateException("test3")));
+        assert12StandardChecks(e, false);
+    }
+    
+    @Test
+    public void test12CollapsePropagatedExecutionCompoundBoring() throws Exception {
+        RuntimeException e = new PropagatedRuntimeException("test1", 
+            new ExecutionException(Exceptions.create(MutableSet.of(new IllegalStateException("test2"), new IllegalStateException("test3")))));
+        assert12StandardChecks(e, true);
+    }
+
+    @Test
+    public void test12CollapsePropagatedCompoundConcMod() throws Exception {
+        RuntimeException e = new PropagatedRuntimeException("test1", 
+            new ExecutionException(Exceptions.create(MutableSet.of(new ConcurrentModificationException("test2"), new ConcurrentModificationException("test3")))));
+        assert12StandardChecks(e, true);
+        assertContains(e, "ConcurrentModification");
+    }
+    
+    @Test
+    public void testCollapseTextWhenExceptionMessageEmpty() throws Exception {
+        String text = Exceptions.collapseText(new ExecutionException(new IllegalStateException()));
+        Assert.assertNotNull(text);
+    }
+    
+    private void assert12StandardChecks(RuntimeException e, boolean isPropagated) {
+        String collapseText = Exceptions.collapseText(e);
+        log.info("Exception collapsing got: "+collapseText+" ("+e+")");
+        assertContains(e, "test1");
+        assertContains(e, "test2");
+        
+        if (isPropagated)
+            assertContains(e, "2 errors, including");
+        else
+            assertContains(e, "2 errors including");
+        
+        assertNotContains(e, "IllegalState");
+        assertNotContains(e, "CompoundException");
+        Assert.assertFalse(collapseText.contains("Propagated"), "should NOT have had Propagated: "+collapseText);
+        
+        if (isPropagated)
+            Assert.assertTrue(e.toString().contains("Propagate"), "SHOULD have had Propagated: "+e);
+        else
+            Assert.assertFalse(e.toString().contains("Propagate"), "should NOT have had Propagated: "+e);
+    }
+    
+    private static void assertContains(Exception e, String keyword) {
+        Assert.assertTrue(e.toString().contains(keyword), "Missing keyword '"+keyword+"' in exception toString: "+e);
+        Assert.assertTrue(Exceptions.collapseText(e).contains(keyword), "Missing keyword '"+keyword+"' in collapseText: "+Exceptions.collapseText(e));
+    }
+    private static void assertNotContains(Exception e, String keyword) {
+        Assert.assertFalse(e.toString().contains(keyword), "Unwanted keyword '"+keyword+"' in exception toString: "+e);
+        Assert.assertFalse(Exceptions.collapseText(e).contains(keyword), "Unwanted keyword '"+keyword+"' in collapseText: "+Exceptions.collapseText(e));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/guava/FunctionalsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/guava/FunctionalsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/guava/FunctionalsTest.java
new file mode 100644
index 0000000..d33552b
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/guava/FunctionalsTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.brooklyn.util.guava;
+
+import org.apache.brooklyn.util.guava.Functionals;
+import org.apache.brooklyn.util.math.MathFunctions;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicates;
+import com.google.common.base.Suppliers;
+
+public class FunctionalsTest {
+
+    @Test
+    public void testChain() {
+        Assert.assertEquals(Functionals.chain(MathFunctions.plus(1), MathFunctions.times(2)).apply(3), (Integer)8);
+        Assert.assertEquals(Functionals.chain(MathFunctions.times(2), MathFunctions.plus(1)).apply(3), (Integer)7);
+    }
+
+    @Test
+    public void testIf() {
+        IfFunctionsTest.checkTF(Functionals.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build(), "?");
+    }
+
+    @Test
+    public void testIfNoBuilder() {
+        IfFunctionsTest.checkTF(Functionals.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?"), "?");
+    }
+    
+    @Test
+    public void testIfPredicateAndSupplier() {
+        IfFunctionsTest.checkTF(Functionals.ifPredicate(Predicates.equalTo(false)).get(Suppliers.ofInstance("F"))
+            .ifEquals(true).value("T").defaultGet(Suppliers.ofInstance("?")).build(), "?");
+    }
+
+    @Test
+    public void testIfNotEqual() {
+        IfFunctionsTest.checkTF(Functionals.ifNotEquals(false).value("T").defaultValue("F").build(), "T");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/guava/IfFunctionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/guava/IfFunctionsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/guava/IfFunctionsTest.java
new file mode 100644
index 0000000..7e14060
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/guava/IfFunctionsTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.brooklyn.util.guava;
+
+import org.apache.brooklyn.util.guava.IfFunctions;
+import org.apache.brooklyn.util.guava.IfFunctions.IfFunctionBuilder;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.base.Suppliers;
+
+public class IfFunctionsTest {
+
+    @Test
+    public void testCommonUsage() {
+        checkTF(IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build(), "?");
+    }
+
+    @Test
+    public void testNoBuilder() {
+        checkTF(IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?"), "?");
+    }
+    
+    @Test
+    public void testPredicateAndSupplier() {
+        // we cannot use checkTF here as an IntelliJ issues causes the project to fail to launch as IntelliJ does not
+        // recognize the return value of IfFunctions.ifPredicate as Function<Boolean, String>
+        Function function = IfFunctions.ifPredicate(Predicates.equalTo(false)).get(Suppliers.ofInstance("F"))
+                .ifEquals(true).value("T").defaultGet(Suppliers.ofInstance("?")).build();
+        Assert.assertEquals(function.apply(true), "T");
+        Assert.assertEquals(function.apply(false), "F");
+        Assert.assertEquals(function.apply(null), "?");
+    }
+
+    @Test
+    public void testNoDefault() {
+        checkTF(IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").build(), null);
+    }
+
+    @Test
+    public void testNotEqual() {
+        checkTF(IfFunctions.ifNotEquals(false).value("T").defaultValue("F").build(), "T");
+    }
+
+    @Test
+    public void testFunction() {
+        checkTF(IfFunctions.ifNotEquals((Boolean)null).apply(new Function<Boolean, String>() {
+            @Override
+            public String apply(Boolean input) {
+                return input.toString().toUpperCase().substring(0, 1);
+            }
+        }).defaultValue("?"), "?");
+    }
+
+    @Test
+    public void testWithCast() {
+        Function<Boolean, String> f = IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build();
+        checkTF(f, "?");
+    }
+
+    @Test
+    public void testWithoutCast() {
+        Function<Boolean, String> f = IfFunctions.newInstance(Boolean.class, String.class).ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build();
+        checkTF(f, "?");
+    }
+
+    @Test
+    public void testSupportsReplace() {
+        checkTF(IfFunctions.ifEquals(false).value("false").ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build(), "?");
+    }
+
+    @Test
+    public void testIsImmutableAndSupportsReplace() {
+        IfFunctionBuilder<Boolean, String> f = IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?");
+        IfFunctionBuilder<Boolean, String> f2 = f.ifEquals(false).value("false").defaultValue("X");
+        IfFunctionBuilder<Boolean, String> f3 = f2.ifEquals(false).value("F");
+        checkTF(f, "?");
+        checkTF(f3, "X");
+        Assert.assertEquals(f2.apply(false), "false");
+    }
+
+    static void checkTF(Function<Boolean, String> f, Object defaultValue) {
+        Assert.assertEquals(f.apply(true), "T");
+        Assert.assertEquals(f.apply(false), "F");
+        Assert.assertEquals(f.apply(null), defaultValue);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/test/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCacheTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCacheTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCacheTest.java
new file mode 100644
index 0000000..abc7c45
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCacheTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.brooklyn.util.guava;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.util.guava.KeyTransformingLoadingCache;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+public class KeyTransformingLoadingCacheTest {
+
+    LoadingCache<Integer, Integer> doublingCache;
+    LoadingCache<String, Integer> stringDoubler;
+    LoadingCache<Map<String, Integer>, Map<Integer, String>> keyValueSwapCache;
+
+    @BeforeMethod(alwaysRun = true)
+    public void setUp() {
+        // Doubles Integer inputs
+        doublingCache = CacheBuilder.newBuilder()
+                .recordStats()
+                .build(new CacheLoader<Integer, Integer>() {
+                    @Override
+                    public Integer load(Integer key) throws Exception {
+                        return key * 2;
+                    }
+                });
+        // Turns string to integer and doubles
+        stringDoubler = KeyTransformingLoadingCache.from(doublingCache,
+                new Function<String, Integer>(){
+                    @Override
+                    public Integer apply(String input) {
+                        return Integer.valueOf(input);
+                    }
+                });
+        // Swaps keys with values
+        keyValueSwapCache = CacheBuilder.newBuilder()
+                .recordStats()
+                .build(new CacheLoader<Map<String, Integer>, Map<Integer, String>>() {
+                    @Override
+                    public Map<Integer, String> load(Map<String, Integer> key) throws Exception {
+                        Map<Integer, String> out = Maps.newHashMapWithExpectedSize(key.size());
+                        for (Map.Entry<String, Integer> entry : key.entrySet()) {
+                            out.put(entry.getValue(), entry.getKey());
+                        }
+                        return out;
+                    }
+                });
+    }
+
+    @Test
+    public void testIdentityCache() {
+        assertEquals(stringDoubler.getUnchecked("10"), Integer.valueOf(20));
+    }
+
+    @Test
+    public void testGetIfPresent() {
+        assertNull(stringDoubler.getIfPresent("10"), "Cache should be empty");
+        assertEquals(stringDoubler.getUnchecked("10"), Integer.valueOf(20), "Cache should load value for '10'");
+        assertEquals(stringDoubler.getIfPresent("10"), Integer.valueOf(20), "Cache should load value for '10'");
+        assertNull(stringDoubler.getIfPresent("20"), "Cache should have no value for '20'");
+        assertNull(stringDoubler.getIfPresent(new Object()), "Cache should have no value for arbitrary Object");
+    }
+
+    @Test
+    public void testInvalidate() {
+        stringDoubler.getUnchecked("10");
+        assertEquals(stringDoubler.size(), 1);
+        stringDoubler.invalidate(new Object());
+        assertEquals(stringDoubler.size(), 1);
+        stringDoubler.invalidate("10");
+        assertEquals(stringDoubler.size(), 0, "Expected cache to be empty after sole entry was invalidated");
+    }
+
+    @Test
+    public void testSubsetOfMapKeys() {
+        final Set<String> validKeys = ImmutableSet.of("a", "b", "c");
+        LoadingCache<Map<String, Integer>, Map<Integer, String>> keySubset =
+                KeyTransformingLoadingCache.from(keyValueSwapCache, new Function<Map<String, Integer>, Map<String, Integer>>() {
+                    @Override
+                    public Map<String, Integer> apply(Map<String, Integer> input) {
+                        Map<String, Integer> replacement = Maps.newHashMap(input);
+                        replacement.keySet().retainAll(validKeys);
+                        return replacement;
+                    }
+                });
+
+        Map<Integer, String> output = keySubset.getUnchecked(ImmutableMap.of("a", 1, "b", 2, "d", 4));
+        assertEquals(output, ImmutableMap.of(1, "a", 2, "b"));
+        assertEquals(keySubset.size(), 1, "Expected cache to contain one value");
+        assertEquals(keySubset.stats().loadCount(), 1, "Expected cache to have loaded one value");
+
+        // Check input with different key reducing to same map gives same output
+        Map<Integer, String> output2 = keySubset.getUnchecked(ImmutableMap.of("a", 1, "b", 2, "z", 26));
+        assertEquals(output2, output);
+        assertEquals(keySubset.size(), 1, "Expected cache to contain one value");
+        assertEquals(keySubset.stats().loadCount(), 1, "Expected cache to have loaded one value");
+
+        // And
+        keySubset.getUnchecked(ImmutableMap.of("c", 3));
+        assertEquals(keySubset.size(), 2, "Expected cache to contain two values");
+        assertEquals(keySubset.stats().loadCount(), 2, "Expected cache to have loaded a second value");
+    }
+
+}