Bureaucracy smoke test and resulting bug fixes
* Added RegistryTester smoke test which randomly creates and destroys agents in batches * Fixed bug where correct agent id was never making it to client * Implemented Bureau.toString (+refactored summarize method) * Fixed nasty bug due to my assumption that SafeSubscriber =~ Subscriber, they are in fact completely different git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5032 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.bureau.server;
|
||||
|
||||
import com.samskivert.util.OneLineLogFormatter;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.Collections;
|
||||
import com.threerings.bureau.data.AgentObject;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Uses a TestServer to pound on the BureauRegistry. Sends random sequences of
|
||||
* startAgent and destroyAgent. Most aspects of the randomness are configurable using system
|
||||
* properties.
|
||||
* TODO: add more types of testing
|
||||
* TODO: allow a quitAfter configuration parameter to shut down automatically
|
||||
*/
|
||||
public class RegistryTester
|
||||
{
|
||||
/**
|
||||
* Convenience function for getting an integral property. Also logs the value.
|
||||
*/
|
||||
public static int intProp (String name, int defaultVal)
|
||||
{
|
||||
String val = System.getProperty(name);
|
||||
if (val == null) {
|
||||
TestServer.log.info("Property " + name + " is " + defaultVal);
|
||||
return defaultVal;
|
||||
}
|
||||
int ival = Integer.parseInt(val);
|
||||
TestServer.log.info("Property " + name + " is " + ival);
|
||||
return ival;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new server and runs the registry tester on it.
|
||||
*/
|
||||
public static void main (String[] args)
|
||||
{
|
||||
// make log pretty
|
||||
OneLineLogFormatter.configureDefaultHandler();
|
||||
|
||||
TestServer server = new TestServer();
|
||||
RegistryTester tester = new RegistryTester(server);
|
||||
|
||||
try {
|
||||
server.init();
|
||||
tester.start();
|
||||
server.run();
|
||||
|
||||
} catch (Exception e) {
|
||||
TestServer.log.warning("Unable to initialize server.");
|
||||
TestServer.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new registry tester.
|
||||
*/
|
||||
public RegistryTester (TestServer server)
|
||||
{
|
||||
_server = server;
|
||||
|
||||
_maxAgents = intProp("maxAgents", 500);
|
||||
_numBureaus = intProp("numBureaus", 5);
|
||||
_maxOps = intProp("maxOps", 5);
|
||||
_createChance = intProp("createChance", 70);
|
||||
_minDelay = intProp("minDelay", 500);
|
||||
_maxDelay = intProp("maxDelay", 2000);
|
||||
|
||||
// stop the tests when the server shuts down
|
||||
// TODO: this is not called on Ctrl-C, need a way to shut down gracefully
|
||||
_server.registerShutdowner(new TestServer.Shutdowner() {
|
||||
public void shutdown () {
|
||||
TestServer.log.info("Shutting down tests");
|
||||
_stop = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the test thread.
|
||||
*/
|
||||
public void start ()
|
||||
{
|
||||
Thread thread = new Thread("Registry test thread") {
|
||||
public void run () {
|
||||
TestServer.log.info(getName() + " started");
|
||||
runTestThread();
|
||||
TestServer.log.info(getName() + " stopped");
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the test thread.
|
||||
*/
|
||||
public void stop ()
|
||||
{
|
||||
_stop = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main loop for the tests.
|
||||
*/
|
||||
protected void runTestThread ()
|
||||
{
|
||||
// set up the rngs (2 are needed since one is called from the dobj thread)
|
||||
long seed = Long.parseLong(System.getProperty("seed", "0"));
|
||||
if (seed == 0) {
|
||||
seed = System.currentTimeMillis();
|
||||
}
|
||||
_rng1 = new Random(seed);
|
||||
_rng2 = new Random(seed);
|
||||
|
||||
TestServer.log.info("Running tests, seed is " + seed);
|
||||
|
||||
// runnable that generates N requests to create or destroy agents
|
||||
Runnable createOrDestroyAgents = new Runnable() {
|
||||
public void run () {
|
||||
int ops = 1 + _rng1.nextInt(_maxOps);
|
||||
TestServer.log.info("Starting " + ops + " agent requests");
|
||||
for (int i = 0; i < ops; ++i) {
|
||||
randomlyCreateOrDestroyAgent();
|
||||
}
|
||||
TestServer.log.info("Finished " + ops + " agent requests");
|
||||
}
|
||||
};
|
||||
|
||||
// the main test loop
|
||||
while (!_stop) {
|
||||
try {
|
||||
// sleep for a bit
|
||||
int sleep = _maxDelay - _minDelay + 1;
|
||||
sleep = _minDelay + _rng2.nextInt(sleep);
|
||||
Thread.sleep(sleep);
|
||||
}
|
||||
catch (InterruptedException ie) {
|
||||
break;
|
||||
}
|
||||
|
||||
// create or destroy some agents
|
||||
_server.omgr.postRunnable(createOrDestroyAgents);
|
||||
}
|
||||
|
||||
// clean up
|
||||
_server.omgr.postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
for (AgentObject obj : _agents) {
|
||||
_server.breg.destroyAgent(obj);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Does what the name says using the configuration values.
|
||||
*/
|
||||
protected void randomlyCreateOrDestroyAgent ()
|
||||
{
|
||||
int size = _agents.size();
|
||||
if (size >= _maxAgents ||
|
||||
(size != 0 && _rng1.nextInt(100) >= _createChance)) {
|
||||
AgentObject toRemove = _agents.remove(_rng1.nextInt(size));
|
||||
TestServer.log.info("Removing agent " + toRemove.getOid());
|
||||
_server.breg.destroyAgent(toRemove);
|
||||
}
|
||||
else {
|
||||
AgentObject added = create(_rng1.nextInt(_numBureaus) + 1);
|
||||
_agents.add(added);
|
||||
TestServer.log.info("Added agent " + added.getOid());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new agent for the given bureau.
|
||||
*/
|
||||
protected AgentObject create (int bureau)
|
||||
{
|
||||
AgentObject obj = new AgentObject();
|
||||
obj.bureauType = "test";
|
||||
obj.bureauId = "test-" + bureau;
|
||||
_server.breg.startAgent(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
protected TestServer _server;
|
||||
protected boolean _stop;
|
||||
protected Random _rng1;
|
||||
protected Random _rng2;
|
||||
protected List<AgentObject> _agents = Lists.newArrayList();
|
||||
|
||||
// maximum number of agents to keep around
|
||||
protected int _maxAgents;
|
||||
|
||||
// number of bureaus to select between
|
||||
protected int _numBureaus;
|
||||
|
||||
// number of operations to perform in one dobj queue task
|
||||
protected int _maxOps;
|
||||
|
||||
// chance of creating a new agent if limit has not been reached
|
||||
protected int _createChance;
|
||||
|
||||
// minimum delay between batches of requests
|
||||
protected int _minDelay;
|
||||
|
||||
// maximum delay between batches of requests
|
||||
protected int _maxDelay;
|
||||
}
|
||||
@@ -21,24 +21,35 @@
|
||||
|
||||
package com.threerings.bureau.server;
|
||||
|
||||
import com.threerings.bureau.Log;
|
||||
import com.threerings.bureau.data.AgentObject;
|
||||
import com.threerings.presents.server.PresentsServer;
|
||||
import com.samskivert.util.OneLineLogFormatter;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Extends a presents server to include a bureau registry.
|
||||
*/
|
||||
public class TestServer extends PresentsServer
|
||||
{
|
||||
/** We dispatch our log messages through this logger. */
|
||||
public static Logger log = Logger.getLogger(TestServer.class.getName());
|
||||
|
||||
/**
|
||||
* The bureau registry for the server. Will be null until <code>init</code> is called.
|
||||
*/
|
||||
public static BureauRegistry breg;
|
||||
|
||||
public static void logStackTrace (Throwable t)
|
||||
{
|
||||
log.log(Level.WARNING, t.getMessage(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new server and runs it.
|
||||
*/
|
||||
@@ -50,21 +61,11 @@ public class TestServer extends PresentsServer
|
||||
final TestServer server = new TestServer();
|
||||
try {
|
||||
server.init();
|
||||
|
||||
// request a new agent
|
||||
// TODO: more tests here - create a thread that posts different kinds of requests
|
||||
// and somehow monitors results from client
|
||||
server.omgr.postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
server.createTestAgent();
|
||||
}
|
||||
});
|
||||
|
||||
server.run();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Unable to initialize server.");
|
||||
Log.logStackTrace(e);
|
||||
log.warning("Unable to initialize server.");
|
||||
logStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,15 +94,4 @@ public class TestServer extends PresentsServer
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the bureau client create an agent.
|
||||
*/
|
||||
protected void createTestAgent ()
|
||||
{
|
||||
AgentObject obj = new AgentObject();
|
||||
obj.bureauType = "test";
|
||||
obj.bureauId = "test";
|
||||
breg.startAgent(obj);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user