diff --git a/master/buildbot/data/testhooks.py b/master/buildbot/data/testhooks.py index 59551663ae4..82757018512 100644 --- a/master/buildbot/data/testhooks.py +++ b/master/buildbot/data/testhooks.py @@ -14,6 +14,7 @@ # Copyright Buildbot Team Members import re, inspect +from twisted.python import reflect from twisted.internet import defer from buildbot.data import base, exceptions @@ -23,9 +24,7 @@ class TestHooksEndpoint(base.ControlParamsCheckMixin,base.Endpoint): rootLinkName = 'testhooks' pathPatterns = [ ( 'testhooks',) ] - action_specs = dict(enableFakeDb=dict(), - disableFakeDb=dict(), - playScenario=dict(scenario=dict(re=re.compile("[a-z\.]+"), + action_specs = dict(playScenario=dict(scenario=dict(re=re.compile("[a-z\.]+"), type=str, required=True))) def safeControl(self, action, args, kwargs): @@ -43,18 +42,17 @@ class TestHooksResourceType(base.ResourceType): endpoints = [ TestHooksEndpoint] @base.updateMethod def playTestScenario(self, scenario): - if not self.isFakeDbEnabled(): - raise exceptions.InvalidActionException("FakeDb disabled!") scenario = scenario.split(".") - if len(scenario <3): + if len(scenario) <3: raise exceptions.InvalidOptionException("invalid scenario path") mod = ".".join(scenario[:-2]) sym = scenario[-2] meth = scenario[-1] - if not sym in dir(mod): + module = reflect.namedModule(mod) + if not sym in dir(module): raise exceptions.InvalidOptionException("no class %s in module %s"%(sym, mod)) - obj = getattr(mod, sym) + obj = getattr(module, sym) if not(inspect.isclass(obj) and issubclass(obj, TestHooksScenario)): raise exceptions.InvalidOptionException( "class %s is not subclass of TestHooksScenario"%(meth, diff --git a/master/buildbot/scripts/uitestserver.py b/master/buildbot/scripts/uitestserver.py index 56e7874ac73..04d738987f3 100644 --- a/master/buildbot/scripts/uitestserver.py +++ b/master/buildbot/scripts/uitestserver.py @@ -31,7 +31,7 @@ def _uitestserver(config): reactor.stop() raise defer.returnValue(1) master = yield fakemaster.make_master_for_uitest(int(config['port']), public_html) - webbrowser.open(master.config.www['url']+"bb/tests/runner.html") + webbrowser.open(master.config.www['url']+"static/bb/tests/runner.html") def uitestserver(config): def async(): diff --git a/master/buildbot/test/fake/fakemaster.py b/master/buildbot/test/fake/fakemaster.py index 7f73a4033cc..2a82f923fbb 100644 --- a/master/buildbot/test/fake/fakemaster.py +++ b/master/buildbot/test/fake/fakemaster.py @@ -145,12 +145,15 @@ def make_master_for_uitest(port, public_html): master = FakeMaster() master.db = fakedb.FakeDBConnector(mock.Mock()) master.mq = mqconnector.MQConnector(master) + master.config.mq = dict(type='simple') + master.mq.setup() class testHookedDataConnector(dataconnector.DataConnector): submodules = dataconnector.DataConnector.submodules + ['buildbot.data.testhooks'] master.data = testHookedDataConnector(master) master.config.www = dict(url=url, port=port, public_html=public_html) master.www = service.WWWService(master) + master.data.updates.playTestScenario("buildbot.test.scenarios.base.BaseScenario.populateBaseDb") yield master.www.startService() yield master.www.reconfigService(master.config) defer.returnValue(master) diff --git a/master/buildbot/test/scenarios/__init__.py b/master/buildbot/test/scenarios/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/master/buildbot/test/scenarios/base.py b/master/buildbot/test/scenarios/base.py new file mode 100644 index 00000000000..6bc73dbfd40 --- /dev/null +++ b/master/buildbot/test/scenarios/base.py @@ -0,0 +1,43 @@ +# This file is part of Buildbot. Buildbot is free software: you can +# redistribute it and/or modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation, version 2. +# +# This program 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 General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright Buildbot Team Members + +from buildbot.data import testhooks +from buildbot.test.fake import fakedb +import mock + +class BaseScenario(testhooks.TestHooksScenario): + """buildbot.test.unit.test_www.ui.BaseScenario""" + def populateBaseDb(self): + self.master.db.__init__(mock.Mock) + self.master.db.insertTestData([ + fakedb.Master(id=13, name=u'inactivemaster', active=0, + last_active=0), + fakedb.Master(id=14, name=u'master', active=1, + last_active=0), + fakedb.Master(id=15, name=u'othermaster', active=1, + last_active=0), + ]) + self.master.db.insertTestData([ + fakedb.Change(changeid=13, branch=u'trunk', revision=u'9283', + repository=u'svn://...', codebase=u'cbsvn', + project=u'world-domination'), + fakedb.Change(changeid=14, branch=u'devel', revision=u'9284', + repository=u'svn://...', codebase=u'cbsvn', + project=u'world-domination'), + ]) + def stopMaster(self): + print "stopping master 14" + return self.master.data.updates.masterStopped(name=u'master', masterid=14) + diff --git a/master/buildbot/www/rest.py b/master/buildbot/www/rest.py index fa65625ef72..ac734805ca3 100644 --- a/master/buildbot/www/rest.py +++ b/master/buildbot/www/rest.py @@ -108,13 +108,13 @@ def updateError(msg, jsonrpccode,e=None): def check(name, _types, _val=None): if not name in data: updateError("need '%s' to be present"%(name), JSONRPC_CODES["invalid_request"]) - if not type(data[name]) in _types: + if _types and not type(data[name]) in _types: updateError("need '%s' to be of type %s:%s"%(name, " or ".join(map(str,_types)), json.dumps(data[name])), JSONRPC_CODES["invalid_request"]) if _val != None and data[name] != _val: updateError("need '%s' value to be '%s'"%(name, str(_val)), JSONRPC_CODES["invalid_request"]) check("jsonrpc", (str,unicode), "2.0") check("method", (str,unicode)) - check("id", (str,unicode)) + check("id", None) check("params", (dict,)) # params can be a list in jsonrpc, but we dont support it. reply["id"] = data["id"] return data["params"], data["method"] @@ -177,7 +177,7 @@ def write_error_jsonrpc(msg, errcode=400, jsonrpccode=JSONRPC_CODES["internal_er write_error(repr(e), errcode=500,jsonrpccode=JSONRPC_CODES["internal_error"]) log.err(e) # make sure we log unknown exception return - if data is None: + if data is None and request.method=="GET": write_error("no data") return diff --git a/www/src/bb/jsonapi.js b/www/src/bb/jsonapi.js index 4d2f2f65336..c2f845d5202 100644 --- a/www/src/bb/jsonapi.js +++ b/www/src/bb/jsonapi.js @@ -1,10 +1,11 @@ /* utilities, and code related to direct access to the api deferred based! */ -define(["dojo/_base/declare", "dojo/_base/Deferred", "dojo/_base/xhr"], - function(declare, Deferred, xhr){ +define(["dojo/_base/declare", "dojo/_base/Deferred", "dojo/request/xhr","dojo/json"], + function(declare, Deferred, xhr, json){ var api_url = dojo.baseUrl + "/../../../../api/"; - return declare([], { + var jsonrpc_curid = 0; + return { createAPIPath: function(a) { var path=[]; for (var i = 0;i