http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/70aceb39/core/src/test/java/org/apache/brooklyn/core/network/OnPublicNetworkEnricherTest.java
----------------------------------------------------------------------
diff --git
a/core/src/test/java/org/apache/brooklyn/core/network/OnPublicNetworkEnricherTest.java
b/core/src/test/java/org/apache/brooklyn/core/network/OnPublicNetworkEnricherTest.java
new file mode 100644
index 0000000..354bd2f
--- /dev/null
+++
b/core/src/test/java/org/apache/brooklyn/core/network/OnPublicNetworkEnricherTest.java
@@ -0,0 +1,326 @@
+/*
+ * 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.core.network;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.EnricherSpec;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.location.access.PortForwardManager;
+import
org.apache.brooklyn.core.location.access.PortForwardManagerLocationResolver;
+import org.apache.brooklyn.core.network.OnPublicNetworkEnricher;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.net.HostAndPort;
+
+public class OnPublicNetworkEnricherTest extends BrooklynAppUnitTestSupport {
+
+ private static final Duration VERY_SHORT_WAIT = Duration.millis(100);
+
+ private TestEntity entity;
+ private SshMachineLocation machine;
+ private PortForwardManager portForwardManager;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ machine =
mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+ .configure("address", "127.0.0.1"));
+ portForwardManager = (PortForwardManager)
mgmt.getLocationRegistry().getLocationManaged(PortForwardManagerLocationResolver.PFM_GLOBAL_SPEC);
+ }
+
+ @DataProvider(name = "variants")
+ public static Object[][] provideVariants() {
+ AttributeSensor<HostAndPort> hostAndPortSensor =
Sensors.newSensor(HostAndPort.class, "test.endpoint");
+ List<Object[]> result = Lists.newArrayList();
+ for (Timing setSensor : Timing.values()) {
+ for (Timing createAssociation : Timing.values()) {
+ for (Timing addLocation : Timing.values()) {
+ result.add(new Object[] {setSensor, createAssociation,
addLocation, Attributes.MAIN_URI,
+ URI.create("http://127.0.0.1:1234/my/path"),
"main.uri.mapped.public", "http://mypublichost:5678/my/path"});
+ result.add(new Object[] {setSensor, createAssociation,
addLocation, TestEntity.NAME,
+ "http://127.0.0.1:1234/my/path",
"test.name.mapped.public", "http://mypublichost:5678/my/path"});
+ result.add(new Object[] {setSensor, createAssociation,
addLocation, Attributes.HTTP_PORT,
+ 1234, "http.endpoint.mapped.public",
"mypublichost:5678"});
+ result.add(new Object[] {setSensor, createAssociation,
addLocation, TestEntity.NAME,
+ "1234", "test.name.mapped.public",
"mypublichost:5678"});
+ result.add(new Object[] {setSensor, createAssociation,
addLocation, TestEntity.NAME,
+ "127.0.0.1:1234", "test.name.mapped.public",
"mypublichost:5678"});
+ result.add(new Object[] {setSensor, createAssociation,
addLocation, hostAndPortSensor,
+ HostAndPort.fromString("127.0.0.1:1234"),
"test.endpoint.mapped.public", "mypublichost:5678"});
+ }
+ }
+ }
+ return result.toArray(new Object[result.size()][]);
+ }
+
+ @DataProvider(name = "invalidVariants")
+ public static Object[][] provideInvalidVariants() {
+ AttributeSensor<HostAndPort> hostAndPortSensor =
Sensors.newSensor(HostAndPort.class, "test.hostAndPort");
+ List<Object[]> result = Lists.newArrayList();
+ result.add(new Object[] {Attributes.MAIN_URI, (URI)null});
+ result.add(new Object[] {TestEntity.NAME, "127.0.0.1:1234/my/path"});
// must have scheme
+ result.add(new Object[] {Attributes.HTTP_PORT, null});
+ result.add(new Object[] {Attributes.HTTP_PORT, 1234567});
+ result.add(new Object[] {TestEntity.NAME, null});
+ result.add(new Object[] {TestEntity.NAME, "1234567"});
+ result.add(new Object[] {TestEntity.NAME, "thisHasNoPort"});
+ result.add(new Object[] {TestEntity.NAME, "portIsTooBig:1234567"});
+ result.add(new Object[] {hostAndPortSensor, (HostAndPort)null});
+ return result.toArray(new Object[result.size()][]);
+ }
+
+ enum Timing {
+ BEFORE,
+ AFTER;
+ }
+
+ /**
+ * The sensorVal must include port 1234, so that it will be converted to
mypublichost:5678
+ */
+ @Test(dataProvider = "variants")
+ public <T> void testSensorTransformed(Timing setUri, Timing
createAssociation, Timing addLocation,
+ AttributeSensor<T> sensor, T sensorVal, String targetSensorName,
String expectedVal) throws Exception {
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ if (setUri == Timing.BEFORE) {
+ entity.sensors().set(sensor, sensorVal);
+ }
+ if (createAssociation == Timing.BEFORE) {
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 1234);
+ }
+ if (addLocation == Timing.BEFORE) {
+ entity.addLocations(ImmutableList.of(machine));
+ }
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class)
+ .configure(OnPublicNetworkEnricher.SENSOR, sensor));
+
+ if (setUri == Timing.AFTER) {
+ entity.sensors().set(sensor, sensorVal);
+ }
+ if (createAssociation == Timing.AFTER) {
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 1234);
+ }
+ if (addLocation == Timing.AFTER) {
+ entity.addLocations(ImmutableList.of(machine));
+ }
+
+ EntityAsserts.assertAttributeEqualsEventually(entity,
Sensors.newStringSensor(targetSensorName), expectedVal);
+ EntityAsserts.assertAttributeEquals(entity, sensor, sensorVal);
+ }
+
+
+ @Test(dataProvider = "invalidVariants")
+ public <T> void testIgnoresWhenInvalidAttribute(AttributeSensor<T> sensor,
T sensorVal) throws Exception {
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(sensor, sensorVal);
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 1234);
+ entity.addLocations(ImmutableList.of(machine));
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class)
+ .configure(OnPublicNetworkEnricher.SENSOR, sensor));
+
+
EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout",
VERY_SHORT_WAIT), entity,
Sensors.newStringSensor(sensor.getName()+".mapped.public"), null);
+ }
+
+ @Test
+ public <T> void testTransformsDefaultHttp80() throws Exception {
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(Attributes.MAIN_URI,
URI.create("http://127.0.0.1/my/path"));
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 80);
+ entity.addLocations(ImmutableList.of(machine));
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class)
+ .configure(OnPublicNetworkEnricher.SENSOR,
Attributes.MAIN_URI));
+
+ EntityAsserts.assertAttributeEqualsEventually(entity,
Sensors.newStringSensor(Attributes.MAIN_URI.getName()+".mapped.public"),
"http://mypublichost:5678/my/path");
+ }
+
+ @Test
+ public <T> void testTransformsDefaultHttps443() throws Exception {
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(Attributes.MAIN_URI,
URI.create("https://127.0.0.1/my/path"));
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 443);
+ entity.addLocations(ImmutableList.of(machine));
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class)
+ .configure(OnPublicNetworkEnricher.SENSOR,
Attributes.MAIN_URI));
+
+ EntityAsserts.assertAttributeEqualsEventually(entity,
Sensors.newStringSensor(Attributes.MAIN_URI.getName()+".mapped.public"),
"https://mypublichost:5678/my/path");
+ }
+
+ @Test
+ public void testIgnoresWhenNoMapping() throws Exception {
+ // Creates associate for a non-matching port
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(Attributes.HTTP_PORT, 1234);
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 4321);
+ entity.addLocations(ImmutableList.of(machine));
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class)
+ .configure(OnPublicNetworkEnricher.SENSOR,
Attributes.HTTP_PORT));
+
+
EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout",
VERY_SHORT_WAIT), entity,
Sensors.newStringSensor(Attributes.HTTP_PORT.getName()+".mapped.public"), null);
+ }
+
+ @Test
+ public void testIgnoresWhenNoMachine() throws Exception {
+ // Does not call entity.addLocation
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(Attributes.HTTP_PORT, 1234);
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 1234);
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class)
+ .configure(OnPublicNetworkEnricher.SENSOR,
Attributes.HTTP_PORT));
+
+
EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout",
VERY_SHORT_WAIT), entity,
Sensors.newStringSensor(Attributes.HTTP_PORT.getName()+".mapped.public"), null);
+ }
+
+ @Test
+ public void testIgnoresWithNoPort() throws Exception {
+ // Sensor value does not have any port number
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(TestEntity.NAME, "myval");
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 1234);
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class)
+ .configure(OnPublicNetworkEnricher.SENSOR, TestEntity.NAME));
+
+
EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout",
VERY_SHORT_WAIT), entity,
Sensors.newStringSensor(TestEntity.NAME.getName()+".mapped.public"), null);
+ }
+
+ @Test
+ public <T> void testTransformsAllMatchingSensors() throws Exception {
+ AttributeSensor<URI> stronglyTypedUri = Sensors.newSensor(URI.class,
"strongly.typed.uri");
+ AttributeSensor<String> stringUri =
Sensors.newStringSensor("string.uri");
+ AttributeSensor<URL> stronglyTypedUrl = Sensors.newSensor(URL.class,
"strongly.typed.url");
+ AttributeSensor<String> stringUrl =
Sensors.newStringSensor("string.url");
+ AttributeSensor<Integer> intPort =
Sensors.newIntegerSensor("int.port");
+ AttributeSensor<String> stringPort =
Sensors.newStringSensor("string.port");
+ AttributeSensor<HostAndPort> hostAndPort =
Sensors.newSensor(HostAndPort.class, "hostAndPort.endpoint");
+ AttributeSensor<String> stringHostAndPort =
Sensors.newStringSensor("stringHostAndPort.endpoint");
+
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(stronglyTypedUri,
URI.create("http://127.0.0.1:1234/my/path"));
+ entity.sensors().set(stringUri, "http://127.0.0.1:1234/my/path");
+ entity.sensors().set(stronglyTypedUrl, new
URL("http://127.0.0.1:1234/my/path"));
+ entity.sensors().set(stringUrl, "http://127.0.0.1:1234/my/path");
+ entity.sensors().set(intPort, 1234);
+ entity.sensors().set(stringPort, "1234");
+ entity.sensors().set(hostAndPort, HostAndPort.fromParts("127.0.0.1",
1234));
+ entity.sensors().set(stringHostAndPort, "127.0.0.1:1234");
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 1234);
+ entity.addLocations(ImmutableList.of(machine));
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class));
+
+ assertAttributeEqualsEventually("strongly.typed.uri.mapped.public",
"http://mypublichost:5678/my/path");
+ assertAttributeEqualsEventually("string.uri.mapped.public",
"http://mypublichost:5678/my/path");
+ assertAttributeEqualsEventually("strongly.typed.url.mapped.public",
"http://mypublichost:5678/my/path");
+ assertAttributeEqualsEventually("string.url.mapped.public",
"http://mypublichost:5678/my/path");
+ assertAttributeEqualsEventually("int.endpoint.mapped.public",
"mypublichost:5678");
+ assertAttributeEqualsEventually("string.endpoint.mapped.public",
"mypublichost:5678");
+ assertAttributeEqualsEventually("hostAndPort.endpoint.mapped.public",
"mypublichost:5678");
+
assertAttributeEqualsEventually("stringHostAndPort.endpoint.mapped.public",
"mypublichost:5678");
+ }
+
+ @Test
+ public <T> void testIgnoresNonMatchingSensors() throws Exception {
+ AttributeSensor<URI> sensor1 = Sensors.newSensor(URI.class,
"my.different");
+ AttributeSensor<URL> sensor2 = Sensors.newSensor(URL.class,
"my.different2");
+ AttributeSensor<String> sensor3 =
Sensors.newStringSensor("my.different3");
+ AttributeSensor<Integer> sensor4 =
Sensors.newIntegerSensor("my.different4");
+ AttributeSensor<HostAndPort> sensor5 =
Sensors.newSensor(HostAndPort.class, "my.different5");
+
+ entity.sensors().set(Attributes.SUBNET_ADDRESS, "127.0.0.1");
+ entity.sensors().set(sensor1,
URI.create("http://127.0.0.1:1234/my/path"));
+ entity.sensors().set(sensor2, new
URL("http://127.0.0.1:1234/my/path"));
+ entity.sensors().set(sensor3, "http://127.0.0.1:1234/my/path");
+ entity.sensors().set(sensor4, 1234);
+ entity.sensors().set(sensor5, HostAndPort.fromParts("127.0.0.1",
1234));
+ portForwardManager.associate("myPublicIp",
HostAndPort.fromParts("mypublichost", 5678), machine, 1234);
+ entity.addLocations(ImmutableList.of(machine));
+
+
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class));
+
+ Asserts.succeedsContinually(ImmutableMap.of("timeout",
VERY_SHORT_WAIT), new Runnable() {
+ @Override public void run() {
+ Map<AttributeSensor<?>, Object> allSensors =
entity.sensors().getAll();
+ String errMsg = "sensors="+allSensors;
+ for (AttributeSensor<?> sensor : allSensors.keySet()) {
+ String name = sensor.getName();
+ assertFalse(name.startsWith("my.different") &&
sensor.getName().contains("public"), errMsg);
+ }
+ }});
+ }
+
+ protected void assertAttributeEqualsEventually(String sensorName, String
expectedVal) throws Exception {
+ try {
+ EntityAsserts.assertAttributeEqualsEventually(entity,
Sensors.newStringSensor(sensorName), expectedVal);
+ } catch (Exception e) {
+ throw new Exception("Failed assertion for sensor '"+sensorName+"';
attributes are "+entity.sensors().getAll(), e);
+ }
+ }
+
+ @Test
+ public void testSensorNameConverter() throws Exception {
+ OnPublicNetworkEnricher enricher =
entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class));
+ Function<? super String, String> converter =
enricher.getConfig(OnPublicNetworkEnricher.SENSOR_NAME_CONVERTER);
+
+ Map<String, String> testCases = ImmutableMap.<String, String>builder()
+ .put("my.uri", "my.uri.mapped.public")
+ .put("myuri", "myuri.mapped.public")
+ .put("my.UrI", "my.UrI.mapped.public")
+ .put("my.url", "my.url.mapped.public")
+ .put("myurl", "myurl.mapped.public")
+ .put("my.endpoint", "my.endpoint.mapped.public")
+ .put("myendpoint", "myendpoint.mapped.public")
+ .put("my.port", "my.endpoint.mapped.public")
+ .put("myport", "my.endpoint.mapped.public")
+ .build();
+
+ for (Map.Entry<String, String> entry : testCases.entrySet()) {
+ assertEquals(converter.apply(entry.getKey()), entry.getValue(),
"input="+entry.getKey());
+ }
+ }
+}