Bug 518924. Add tests for NPAPI timers and async callbacks. r=bsmedberg

This commit is contained in:
Jonathan Griffin 2010-01-22 17:13:26 -08:00
parent ad09806b1d
commit d736eba473
7 changed files with 240 additions and 122 deletions

View File

@ -70,6 +70,8 @@ _MOCHITEST_FILES = \
test_streamNotify.html \
test_instantiation.html \
test_cookies.html \
test_npn_timers.html \
test_npn_asynccall.html \
$(NULL)
# test_npruntime_npnsetexception.html \ Disabled for e10s
@ -93,7 +95,6 @@ _MOCHICHROME_FILES = \
test_npruntime.xul \
test_privatemode.xul \
test_wmode.xul \
test_npapi_timers.xul \
$(NULL)
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))

View File

@ -1,59 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="NPAPI Timer Tests"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>NPAPI Timer Tests</title>
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
<embed id="plugin" type="application/x-test" width="50" height="50"></embed>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
var uniqueIDTestFinished = false;
var shortOneShotTimerFiredOnce = false;
var shortOneShotTimerFiredTwice = false;
var longRepeatingTimerFiredOnce = false;
var longRepeatingTimerFiredTwice = false;
function uniqueID(success) {
is(success, true, "Timers incorrectly given non-unique IDs.");
uniqueIDTestFinished = true;
}
function shortTimerFired() {
is(uniqueIDTestFinished, true, "Unique ID test should have reported back before short timer fired.");
if (shortOneShotTimerFiredOnce)
shortOneShotTimerFiredTwice = true;
else
shortOneShotTimerFiredOnce = true;
}
function longTimerFired() {
is(shortOneShotTimerFiredOnce, true, "Short one-shot timer did not fire.");
is(shortOneShotTimerFiredTwice, false, "Short one-shot timer fired multiple times.");
if (longRepeatingTimerFiredOnce) {
var p = document.getElementById("plugin");
p.unscheduleAllTimers();
SimpleTest.finish();
}
else {
longRepeatingTimerFiredOnce = true;
}
}
function runTests() {
var p = document.getElementById("plugin");
p.timerTest();
}
]]>
</script>
</window>

View File

@ -0,0 +1,33 @@
<html>
<head>
<title>NPN_AsyncCallback Tests</title>
<script type="text/javascript"
src="/MochiKit/packed.js"></script>
<script type="text/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css"
href="/tests/SimpleTest/test.css" />
</head>
<body onload="runTests()">
<p id="display"></p>
<embed id="plugin1" type="application/x-test" width="400" height="100">
</embed>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
function asyncTestsComplete(result) {
ok(result, "asyncCallback tests completed");
SimpleTest.finish();
}
function runTests() {
var plugin = document.getElementById("plugin1");
plugin.asyncCallbackTest("asyncTestsComplete");
}
</script>
</body>
</html>

View File

@ -0,0 +1,33 @@
<html>
<head>
<title>NPN_Timer Tests</title>
<script type="text/javascript"
src="/MochiKit/packed.js"></script>
<script type="text/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css"
href="/tests/SimpleTest/test.css" />
</head>
<body onload="runTests()">
<p id="display"></p>
<embed id="plugin1" type="application/x-test" width="400" height="100">
</embed>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
function pluginTimerTestFinish(result) {
ok(result, "timer tests completed");
SimpleTest.finish();
}
function runTests() {
var plugin = document.getElementById("plugin1");
plugin.timerTest("pluginTimerTestFinish");
}
</script>
</body>
</html>

View File

@ -86,6 +86,14 @@ NPN_GetAuthenticationInfo(). Returns a string "username|password" for
the specified auth criteria, or throws an exception if no data is
available.
* timerTest(callback) - initiates tests of NPN_ScheduleTimer &
NPN_UnscheduleTimer. When finished, calls the script callback
with a boolean value, indicating whether the tests were successful.
* asyncCallbackTest(callback) - initiates tests of
NPN_PluginThreadAsyncCall. When finished, calls the script callback
with a boolean value, indicating whether the tests were successful.
== Private browsing ==
The test plugin object supports the following scriptable methods:

View File

@ -49,6 +49,7 @@
#define getpid _getpid
#else
#include <unistd.h>
#include <pthread.h>
#endif
using namespace std;
@ -95,6 +96,8 @@ static NPClass sNPClass;
static void
testplugin_URLNotify(NPP instance, const char* url, NPReason reason,
void* notifyData);
void
asyncCallback(void* cookie);
//
// identifiers
@ -118,7 +121,6 @@ static bool getClipRegionRectEdge(NPObject* npobj, const NPVariant* args, uint32
static bool startWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool stopWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool unscheduleAllTimers(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getLastMouseX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getLastMouseY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getPaintCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
@ -138,6 +140,7 @@ static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t
static bool setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static const NPUTF8* sPluginMethodIdentifierNames[] = {
"npnEvaluateTest",
@ -155,7 +158,6 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
"startWatchingInstanceCount",
"getInstanceCount",
"stopWatchingInstanceCount",
"unscheduleAllTimers",
"getLastMouseX",
"getLastMouseY",
"getPaintCount",
@ -175,6 +177,7 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
"setCookie",
"getCookie",
"getAuthInfo",
"asyncCallbackTest",
};
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMethodIdentifierNames)] = {
@ -193,7 +196,6 @@ static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMetho
startWatchingInstanceCount,
getInstanceCount,
stopWatchingInstanceCount,
unscheduleAllTimers,
getLastMouseX,
getLastMouseY,
getPaintCount,
@ -213,6 +215,7 @@ static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMetho
setCookie,
getCookie,
getAuthInfo,
asyncCallbackTest,
};
struct URLNotifyData
@ -234,6 +237,30 @@ static const char* SUCCESS_STRING = "pass";
static bool sIdentifiersInitialized = false;
static uint32_t timerEventCount = 0;
struct timerEvent {
int32_t timerIdReceive;
int32_t timerIdSchedule;
uint32_t timerInterval;
bool timerRepeat;
int32_t timerIdUnschedule;
};
static timerEvent timerEvents[] = {
{-1, 0, 200, false, -1},
{0, 0, 400, false, -1},
{0, 0, 200, true, -1},
{0, 1, 100, true, -1},
{1, -1, 0, false, -1},
{0, -1, 0, false, -1},
{1, -1, 0, false, -1},
{1, -1, 0, false, -1},
{0, -1, 0, false, 0},
{1, 2, 600, false, 1},
{2, -1, 0, false, 2},
};
static uint32_t totalTimerEvents = sizeof(timerEvents) / sizeof(timerEvent);
/**
* Incremented for every startWatchingInstanceCount.
*/
@ -1348,6 +1375,12 @@ NPN_GetAuthenticationInfo(NPP instance,
username, ulen, password, plen);
}
void
NPN_PluginThreadAsyncCall(NPP plugin, void (*func)(void*), void* userdata)
{
return sBrowserFuncs->pluginthreadasynccall(plugin, func, userdata);
}
//
// npruntime object functions
//
@ -1726,49 +1759,6 @@ identifierToStringTest(NPObject* npobj, const NPVariant* args, uint32_t argCount
return true;
}
static void timerCallback(NPP npp, uint32_t timerID)
{
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
NPObject* windowObject;
NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
if (!windowObject)
return;
NPVariant rval;
if (timerID == id->timerID1)
NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier("shortTimerFired"), NULL, 0, &rval);
else if (timerID == id->timerID2)
NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier("longTimerFired"), NULL, 0, &rval);
NPN_ReleaseObject(windowObject);
}
static bool
timerTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
NPObject* windowObject;
NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
if (!windowObject)
return false;
id->timerID1 = NPN_ScheduleTimer(npp, 50, false, timerCallback);
id->timerID2 = NPN_ScheduleTimer(npp, 150, true, timerCallback);
NPVariant rval;
NPVariant uniqueIDArgs[1];
BOOLEAN_TO_NPVARIANT((id->timerID1 != id->timerID2), uniqueIDArgs[0]);
NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier("uniqueID"), uniqueIDArgs, 1, &rval);
NPN_ReleaseVariantValue(&uniqueIDArgs[0]);
NPN_ReleaseObject(windowObject);
return true;
}
static bool
queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
@ -1898,20 +1888,6 @@ stopWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCo
return true;
}
static bool
unscheduleAllTimers(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
NPN_UnscheduleTimer(npp, id->timerID1);
id->timerID1 = 0;
NPN_UnscheduleTimer(npp, id->timerID2);
id->timerID2 = 0;
return true;
}
static bool
getLastMouseX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
@ -2348,3 +2324,125 @@ getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant
return true;
}
static void timerCallback(NPP npp, uint32_t timerID)
{
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
timerEventCount++;
timerEvent event = timerEvents[timerEventCount];
NPObject* windowObject;
NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
if (!windowObject)
return;
NPVariant rval;
if (timerID != id->timerID[event.timerIdReceive])
id->timerTestResult = false;
if (timerEventCount == totalTimerEvents - 1) {
NPVariant arg;
BOOLEAN_TO_NPVARIANT(id->timerTestResult, arg);
NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->timerTestScriptCallback.c_str()), &arg, 1, &rval);
NPN_ReleaseVariantValue(&arg);
}
NPN_ReleaseObject(windowObject);
if (event.timerIdSchedule > -1) {
id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback);
}
if (event.timerIdUnschedule > -1) {
NPN_UnscheduleTimer(npp, id->timerID[event.timerIdUnschedule]);
}
}
static bool
timerTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
timerEventCount = 0;
if (argCount < 1 || !NPVARIANT_IS_STRING(args[0]))
return false;
const NPString* argstr = &NPVARIANT_TO_STRING(args[0]);
id->timerTestScriptCallback = argstr->UTF8Characters;
id->timerTestResult = true;
timerEvent event = timerEvents[timerEventCount];
id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback);
return id->timerID[event.timerIdSchedule] != 0;
}
#ifdef XP_WIN
void
ThreadProc(void* cookie)
#else
void*
ThreadProc(void* cookie)
#endif
{
NPObject* npobj = (NPObject*)cookie;
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
id->asyncTestPhase = 1;
NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
#ifndef XP_WIN
return NULL;
#endif
}
void
asyncCallback(void* cookie)
{
NPObject* npobj = (NPObject*)cookie;
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
switch (id->asyncTestPhase) {
// async callback triggered from same thread
case 0:
#ifdef XP_WIN
if (_beginthread(ThreadProc, 0, (void*)npobj) == -1)
id->asyncCallbackResult = false;
#else
pthread_t tid;
if (pthread_create(&tid, 0, ThreadProc, (void*)npobj))
id->asyncCallbackResult = false;
#endif
break;
// async callback triggered from different thread
default:
NPObject* windowObject;
NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
if (!windowObject)
return;
NPVariant arg, rval;
BOOLEAN_TO_NPVARIANT(id->asyncCallbackResult, arg);
NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->asyncTestScriptCallback.c_str()), &arg, 1, &rval);
NPN_ReleaseVariantValue(&arg);
break;
}
}
static bool
asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
if (argCount < 1 || !NPVARIANT_IS_STRING(args[0]))
return false;
const NPString* argstr = &NPVARIANT_TO_STRING(args[0]);
id->asyncTestScriptCallback = argstr->UTF8Characters;
id->asyncTestPhase = 0;
id->asyncCallbackResult = true;
NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
return true;
}

View File

@ -92,8 +92,9 @@ typedef struct InstanceData {
bool hasWidget;
bool npnNewStream;
bool throwOnNextInvoke;
uint32_t timerID1;
uint32_t timerID2;
uint32_t timerID[2];
bool timerTestResult;
bool asyncCallbackResult;
int32_t winX;
int32_t winY;
int32_t lastMouseX;
@ -102,12 +103,15 @@ typedef struct InstanceData {
int32_t paintCount;
int32_t writeCount;
int32_t writeReadyCount;
int32_t asyncTestPhase;
TestFunction testFunction;
TestFunction functionToFail;
NPError failureCode;
PostMode postMode;
std::string testUrl;
std::string frame;
std::string timerTestScriptCallback;
std::string asyncTestScriptCallback;
std::ostringstream err;
uint16_t streamMode;
int32_t streamChunkSize;