Skip to content
Snippets Groups Projects
Commit d16ce6bf authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

Drag in Python llsd module, which greatly simplifies tests.

It only took a few examples of trying to wrangle notation LLSD as string data
to illustrate how clumsy that is. I'd forgotten that a couple other TUT tests
already invoke Python code that depends on the llsd module. The trick is to
recognize that at least as of now, there's still an obsolete version of the
module in the viewer's own source tree. Python code is careful to try
importing llbase.llsd before indra.base.llsd, so that if/when we finally do
clear indra/lib/python from the viewer repo, we need only require that llbase
be installed on every build machine.
parent 9b5fcb78
No related branches found
No related tags found
No related merge requests found
...@@ -83,8 +83,21 @@ namespace tut ...@@ -83,8 +83,21 @@ namespace tut
llleap_data(): llleap_data():
reader(".py", reader(".py",
// This logic is adapted from vita.viewerclient.receiveEvent() // This logic is adapted from vita.viewerclient.receiveEvent()
"import re\n" boost::lambda::_1 <<
"import os\n"
"import sys\n" "import sys\n"
// Don't forget that this Python script is written to some
// temp directory somewhere! Its __file__ is useless in
// finding indra/lib/python. Use our __FILE__, with
// raw-string syntax to deal with Windows pathnames.
"mydir = os.path.dirname(r'" << __FILE__ << "')\n"
"try:\n"
" from llbase import llsd\n"
"except ImportError:\n"
// We expect mydir to be .../indra/llcommon/tests.
" sys.path.insert(0,\n"
" os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n"
" from indra.base import llsd\n"
"LEFTOVER = ''\n" "LEFTOVER = ''\n"
"class ProtocolError(Exception):\n" "class ProtocolError(Exception):\n"
" pass\n" " pass\n"
...@@ -113,29 +126,28 @@ namespace tut ...@@ -113,29 +126,28 @@ namespace tut
" parts[-1] = parts[-1][:excess]\n" " parts[-1] = parts[-1][:excess]\n"
" data = ''.join(parts)\n" " data = ''.join(parts)\n"
" assert len(data) == length\n" " assert len(data) == length\n"
" return data\n" " return llsd.parse(data)\n"
"\n"
"def put(req):\n"
" sys.stdout.write(':'.join((str(len(req)), req)))\n"
" sys.stdout.flush()\n"
"\n" "\n"
"# deal with initial stdin message\n" "# deal with initial stdin message\n"
// this will throw if the initial write to stdin // this will throw if the initial write to stdin doesn't
// doesn't follow len:data protocol // follow len:data protocol, or if we couldn't find 'pump'
"_initial = get()\n" // in the dict
"_match = re.search(r\"'pump':'(.*?)'\", _initial)\n" "_reply = get()['pump']\n"
// this will throw if we couldn't find
// 'pump':'etc.' in the initial write
"_reply = _match.group(1)\n"
"\n" "\n"
"def replypump():\n" "def replypump():\n"
" return _reply\n" " return _reply\n"
"\n" "\n"
"def escape(str):\n" "def put(req):\n"
" return ''.join(('\\\\'+c if c in r\"\\'\" else c) for c in str)\n" " sys.stdout.write(':'.join((str(len(req)), req)))\n"
" sys.stdout.flush()\n"
"\n"
"def send(pump, data):\n"
" put(llsd.format_notation(dict(pump=pump, data=data)))\n"
"\n" "\n"
"def quote(str):\n" "def request(pump, data):\n"
" return \"'%s'\" % escape(str)\n"), " # we expect 'data' is a dict\n"
" data['reply'] = _reply\n"
" send(pump, data)\n"),
// Get the actual pathname of the NamedExtTempFile and trim off // Get the actual pathname of the NamedExtTempFile and trim off
// the ".py" extension. (We could cache reader.getName() in a // the ".py" extension. (We could cache reader.getName() in a
// separate member variable, but I happen to know getName() just // separate member variable, but I happen to know getName() just
...@@ -297,21 +309,18 @@ namespace tut ...@@ -297,21 +309,18 @@ namespace tut
"import sys\n" "import sys\n"
"from " << reader_module << " import *\n" "from " << reader_module << " import *\n"
// make a request on our little API // make a request on our little API
"put(\"{'pump':'" << api.getName() << "','data':{'reply':'%s'}}\" %\n" "request(pump='" << api.getName() << "', data={})\n"
" replypump())\n"
// wait for its response // wait for its response
"resp = get()\n" "resp = get()\n"
// We expect "{'data':'ack','pump':'%s'}", but "result = '' if resp == dict(pump=replypump(), data='ack')\\\n"
// don't depend on the order of the keys. " else 'bad: ' + str(resp)\n"
"result = 'bad: ' + resp\n" "send(pump='" << result.getName() << "', data=result)\n");
"if resp.startswith('{') and resp.endswith('}'):\n"
" expect = set((\"'data':'ack'\", \"'pump':'%s'\" % replypump()))\n"
" actual = set(resp[1:-1].split(','))\n"
" if actual == expect:\n"
" result = ''\n"
"put(\"{'pump':'" << result.getName() << "','data':%s}\" %\n"
" quote(result))\n");
waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName())))); waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName()))));
result.ensure(); result.ensure();
} }
// TODO:
// many many small messages buffered in both directions
// very large message in both directions (md5)
} // namespace tut } // namespace tut
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment