gecko/xpcom/tests/TestSettingsAPI.cpp

301 lines
8.9 KiB
C++

#include "TestHarness.h"
#include "nsISettingsService.h"
#include "nsCOMPtr.h"
#include "nsIJSContextStack.h"
#include "nsIObserver.h"
#include "nsIThread.h"
#include "nsComponentManagerUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsThreadUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/Services.h"
#define XPCOM_SHUTDOWN "xpcom-shutdown"
#define MOZSETTINGS_CHANGED "mozsettings-changed"
#define TEST_OBSERVER_KEY "test.observer.key"
#define TEST_OBSERVER_VALUE true
#define TEST_OBSERVER_MESSAGE "test.observer.message"
using namespace mozilla;
static int callbackCount = 10;
static int observerCount = 2;
static int errors = 0;
#define CHECK(x) \
_doCheck(x, #x, __LINE__)
#define CHECK_MSG(x, msg) \
_doCheck(x, msg, __LINE__)
static void _doCheck(bool cond, const char *msg, int line) {
if (cond) return;
fprintf(stderr, "FAIL: line %d: %s\n", line, msg);
errors++;
}
static bool VerifyJSValueIsString(
JSContext *cx, const JS::Value &value, const char *string) {
JSBool match;
if (!value.isString() ||
!JS_StringEqualsAscii(cx, value.toString(), string, &match) ||
(match != JS_TRUE)) {
return false;
}
return true;
}
typedef nsresult(*TestFuncPtr)();
class SettingsServiceCallback MOZ_FINAL : public nsISettingsServiceCallback
{
public:
NS_DECL_ISUPPORTS
SettingsServiceCallback() { }
NS_IMETHOD Handle(const nsAString &name, const JS::Value &result, JSContext *cx) {
if (callbackCount == 9) {
CHECK(JSVAL_IS_BOOLEAN(result));
CHECK(JSVAL_TO_BOOLEAN(result) == true);
passed("boolean");
} else if (callbackCount == 7) {
CHECK(JSVAL_IS_BOOLEAN(result));
CHECK(JSVAL_TO_BOOLEAN(result) == false);
passed("Lock order");
} else if (callbackCount == 5) {
CHECK(JSVAL_IS_INT(result));
CHECK(JSVAL_TO_INT(result) == 9);
passed("integer");
} else if (callbackCount == 3) {
CHECK(JSVAL_IS_DOUBLE(result));
CHECK(JSVAL_TO_DOUBLE(result) == 9.4);
passed("double");
} else if (callbackCount == 2) {
CHECK(JSVAL_IS_BOOLEAN(result));
CHECK(JSVAL_TO_BOOLEAN(result) == false);
passed("Lock order");
} else if (callbackCount == 1) {
CHECK(JSVAL_IS_NULL(result));
passed("null");
}
callbackCount--;
return NS_OK;
};
NS_IMETHOD HandleError(const nsAString &name, JSContext *cx) {
fprintf(stderr, "HANDLE Error! %s\n", NS_LossyConvertUTF16toASCII(name).get());
errors++;
return NS_OK;
};
};
NS_IMPL_THREADSAFE_ISUPPORTS1(SettingsServiceCallback, nsISettingsServiceCallback)
class TestSettingsObserver MOZ_FINAL : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
TestSettingsObserver() {
// Setup an observer to watch changes to the setting.
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (!observerService) {
CHECK_MSG(false, "GetObserverService failed");
return;
}
nsresult rv;
rv = observerService->AddObserver(this, XPCOM_SHUTDOWN, false);
if (NS_FAILED(rv)) {
CHECK_MSG(false,"AddObserver failed");
return;
}
rv = observerService->AddObserver(this, MOZSETTINGS_CHANGED, false);
if (NS_FAILED(rv)) {
CHECK_MSG(false,"AddObserver failed");
return;
}
}
~TestSettingsObserver() {}
};
NS_IMPL_ISUPPORTS1(TestSettingsObserver, nsIObserver)
NS_IMETHODIMP
TestSettingsObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData ) {
// Check if receiving the "xpcom-shutdown" event.
if (strcmp(aTopic, XPCOM_SHUTDOWN) == 0) {
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (!observerService) {
CHECK_MSG(false, "GetObserverService failed");
return NS_OK;
}
observerService->RemoveObserver(this, XPCOM_SHUTDOWN);
observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
return NS_OK;
}
// Check if receiving the "mozsettings-changed" event.
if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
CHECK_MSG(false, "Got non-mozsettings-changed event");
return NS_OK;
}
// Get the safe JS context.
nsCOMPtr<nsIThreadJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
if (!stack) {
CHECK_MSG(false, "Failed to get JSContextStack");
return NS_OK;
}
JSContext *cx = stack->GetSafeJSContext();
if (!cx) {
CHECK_MSG(false, "Failed to GetSafeJSContext");
return NS_OK;
}
// Parse the JSON data.
nsDependentString dataStr(aData);
JS::Value data;
if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &data) ||
!data.isObject()) {
CHECK_MSG(false, "Failed to get the data");
return NS_OK;
}
JSObject &obj(data.toObject());
// Get and check the 'key' value. Should be TEST_OBSERVER_KEY;
// otherwise, skip it (they are from other cases we don't care).
JS::Value key;
if (!JS_GetProperty(cx, &obj, "key", &key)) {
CHECK_MSG(false, "Failed to get the key");
return NS_OK;
}
if (!VerifyJSValueIsString(cx, key, TEST_OBSERVER_KEY)) {
return NS_OK;
}
// Get and check the 'value' value. Should be TEST_OBSERVER_VALUE.
JS::Value value;
if (!JS_GetProperty(cx, &obj, "value", &value)) {
CHECK_MSG(false, "Failed to get the value");
return NS_OK;
}
if (!value.isBoolean() || (value.toBoolean() != TEST_OBSERVER_VALUE)) {
CHECK_MSG(false, "The 'value' value is wrong");
return NS_OK;
}
// Get and check the 'message' value.
// Should be null for case #1 and TEST_OBSERVER_MESSAGE for case #2.
JS::Value message;
if (!JS_GetProperty(cx, &obj, "message", &message)) {
CHECK_MSG(false, "Failed to get the message");
return NS_OK;
}
if ((observerCount == 2 && !message.isNull()) ||
(observerCount == 1 && !VerifyJSValueIsString(cx, message, TEST_OBSERVER_MESSAGE))) {
CHECK_MSG(false, "The 'message' value is wrong");
return NS_OK;
}
--observerCount;
passed("observer");
return NS_OK;
}
nsresult
TestSettingsAPI()
{
nsresult rv;
nsCOMPtr<nsISettingsService> settingsService =
do_CreateInstance("@mozilla.org/settingsService;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISettingsServiceCallback> cb0 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb1 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb2 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb3 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb4 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb5 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb6 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb7 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb8 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsServiceCallback> cb9 = new SettingsServiceCallback();
nsCOMPtr<nsISettingsService> iss = do_GetService("@mozilla.org/settingsService;1");
nsCOMPtr<nsISettingsServiceLock> lock;
iss->CreateLock(getter_AddRefs(lock));
nsCOMPtr<nsISettingsServiceLock> lock1;
iss->CreateLock(getter_AddRefs(lock1));
lock->Set("asdf", BOOLEAN_TO_JSVAL(true), cb0, nullptr);
lock1->Get("asdf", cb1);
lock->Get("asdf", cb2);
lock->Set("asdf", BOOLEAN_TO_JSVAL(false), cb3, nullptr);
lock->Get("asdf", cb4);
lock->Set("int", INT_TO_JSVAL(9), cb5, nullptr);
lock->Get("int", cb6);
lock->Set("doub", DOUBLE_TO_JSVAL(9.4), cb7, nullptr);
lock->Get("doub", cb8);
lock1->Get("asdfxxx", cb9);
// The followings test if the observer can receive correct settings.
// Case #1 won't carry any message; case #2 will carry TEST_OBSERVER_MESSAGE.
nsCOMPtr<nsISettingsServiceLock> lock2;
iss->CreateLock(getter_AddRefs(lock2));
lock2->Set(TEST_OBSERVER_KEY,
BOOLEAN_TO_JSVAL(TEST_OBSERVER_VALUE),
nullptr, nullptr);
lock2->Set(TEST_OBSERVER_KEY,
BOOLEAN_TO_JSVAL(TEST_OBSERVER_VALUE),
nullptr, TEST_OBSERVER_MESSAGE);
return NS_OK;
}
int main(int argc, char** argv)
{
passed("Start TestSettingsAPI");
ScopedXPCOM xpcom("TestSettingsAPI");
nsCOMPtr<nsIProperties> os =
do_GetService("@mozilla.org/file/directory_service;1");
if (!os) {
fprintf(stderr, "DIRSERVICE NULL!!!!!!\n");
return 1;
}
NS_ENSURE_FALSE(xpcom.failed(), 1);
nsRefPtr<TestSettingsObserver> sTestSettingsObserver =
new TestSettingsObserver();
static TestFuncPtr testsToRun[] = {
TestSettingsAPI
};
static uint32_t testCount = sizeof(testsToRun) / sizeof(testsToRun[0]);
for (uint32_t i = 0; i < testCount; i++) {
nsresult rv = testsToRun[i]();
NS_ENSURE_SUCCESS(rv, 1);
}
nsCOMPtr<nsIThread> current(do_GetCurrentThread());
while ((callbackCount > 0 || observerCount > 0) && !errors)
NS_ProcessNextEvent(current);
passed("END!");
return errors;
}