/**
* Copyright (C) 2012 Ness Computing, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.nesscomputing.service.discovery.server;
import static java.lang.String.format;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.URI;
import java.util.Map;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Files;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Stage;
import org.apache.commons.configuration.MapConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.nesscomputing.config.Config;
import com.nesscomputing.config.ConfigModule;
import com.nesscomputing.jackson.NessJacksonModule;
import com.nesscomputing.lifecycle.Lifecycle;
import com.nesscomputing.lifecycle.LifecycleStage;
import com.nesscomputing.lifecycle.ServiceDiscoveryLifecycle;
import com.nesscomputing.lifecycle.guice.LifecycleModule;
import com.nesscomputing.server.StandaloneServer;
import com.nesscomputing.service.discovery.client.DiscoveryClientModule;
import com.nesscomputing.service.discovery.client.ReadOnlyDiscoveryClient;
import com.nesscomputing.service.discovery.client.ServiceInformation;
import com.nesscomputing.service.discovery.client.ServiceNotAvailableException;
import com.nesscomputing.testing.lessio.AllowLocalFileAccess;
import com.nesscomputing.testing.lessio.AllowNetworkAccess;
import com.nesscomputing.testing.lessio.AllowNetworkListen;
@AllowLocalFileAccess(paths={"%TMP_DIR%"})
@AllowNetworkListen(ports={0})
@AllowNetworkAccess(endpoints= {"127.0.0.1:0"})
public class TestConfiguredStaticAnnouncements
{
StandaloneServer server;
String serverBase;
@Inject
Lifecycle lifecycle;
@Inject
ReadOnlyDiscoveryClient discoveryClient;
@Before
public void spinup() throws Exception
{
final Map<String, String> announceConfig = ImmutableMap.<String, String>builder()
.put("org.quartz.threadPool.threadCount", "1")
.put("ness.discovery.static-announce.65f57132-8415-422e-b44a-7543dda54858.name", "foo")
.put("ness.discovery.static-announce.65f57132-8415-422e-b44a-7543dda54858.scheme", "http")
.put("ness.discovery.static-announce.65f57132-8415-422e-b44a-7543dda54858.address", "127.0.0.1")
.put("ness.discovery.static-announce.65f57132-8415-422e-b44a-7543dda54858.port", "12345")
.put("ness.discovery.static-announce.65f57132-8415-422e-b44a-7543dda54858.type", "bar")
.build();
System.setProperty("ness.discovery.enabled", "true");
server = new DiscoveryServerMain() {
@Override
public Config getConfig()
{
final File tmpDir = Files.createTempDir();
tmpDir.deleteOnExit();
final String httpPort = Integer.toString(findUnusedPort());
serverBase = "http://localhost:" + httpPort;
System.setProperty("galaxy.internal.port.http", httpPort);
System.setProperty("ness.zookeeper.dataDir", tmpDir.getAbsolutePath());
System.setProperty("ness.zookeeper.clientPort", Integer.toString(findUnusedPort()));
System.setProperty("ness.jmx.enabled", "false");
final int port1 = findUnusedPort();
final int port2 = findUnusedPort();
System.setProperty("ness.zookeeper.server.1", format("127.0.0.1:%d:%d", port1, port2));
System.setProperty("ness.zookeeper.clientPortAddress", "127.0.0.1");
return Config.getOverriddenConfig(Config.getConfig(URI.create("classpath:/config"), "discovery-server"),
new MapConfiguration(announceConfig));
}
};
server.startServer();
Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
@Override
protected void configure()
{
binder().requireExplicitBindings();
binder().disableCircularProxies();
install (new ConfigModule(Config.getFixedConfig(new SystemConfiguration())));
install (new LifecycleModule(ServiceDiscoveryLifecycle.class));
install (new NessJacksonModule());
install (new DiscoveryClientModule(true));
}
}).injectMembers(this);
lifecycle.executeTo(LifecycleStage.START_STAGE);
}
@Test
public void testStaticAnnounce() throws Exception
{
discoveryClient.waitForWorldChange();
ServiceInformation si = null;
int tries = 20;
while (true) {
try {
si = discoveryClient.findServiceInformation("foo", "bar");
break;
} catch (final ServiceNotAvailableException e) {
}
if (tries-- == 0) {
fail("Service never appeared");
}
Thread.sleep(100);
}
assertEquals("bar", si.getServiceType());
assertEquals("http", si.getProperty(ServiceInformation.PROP_SERVICE_SCHEME));
assertEquals("127.0.0.1", si.getProperty(ServiceInformation.PROP_SERVICE_ADDRESS));
assertEquals("12345", si.getProperty(ServiceInformation.PROP_SERVICE_PORT));
}
@After
public void shutdown() {
if (lifecycle != null) {
lifecycle.executeTo(LifecycleStage.STOP_STAGE);
}
if (server !=null) {
server.stopServer();
}
}
private static final int findUnusedPort()
{
int port;
ServerSocket socket = null;
try {
socket = new ServerSocket();
socket.bind(new InetSocketAddress(0));
port = socket.getLocalPort();
}
catch (final IOException ioe) {
throw Throwables.propagate(ioe);
}
finally {
try {
socket.close();
} catch (final IOException ioe) {
// GNDN
}
}
return port;
}
}