Skip to content

Commit

Permalink
test: complete objectRefs tests
Browse files Browse the repository at this point in the history
PR-URL: #1274
Reviewed-By: Michael Dawson <midawson@redhat.com>
  • Loading branch information
JckXia authored and mhdawson committed Mar 2, 2023
1 parent b16c762 commit 464610b
Show file tree
Hide file tree
Showing 2 changed files with 303 additions and 102 deletions.
242 changes: 220 additions & 22 deletions test/object_reference.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
are not Objects by creating a blank Object and setting Values to
it. Subclasses of Objects can only be set using an ObjectReference
by first casting it as an Object. */

#include "assert.h"
#include "napi.h"
#include "test_helper.h"

Expand All @@ -16,11 +16,146 @@ ObjectReference casted_weak;
ObjectReference casted_persistent;
ObjectReference casted_reference;

// info[0] is the key, which can be either a string or a number.
// info[1] is the value.
// info[2] is a flag that differentiates whether the key is a
// C string or a JavaScript string.
void SetObjects(const CallbackInfo& info) {
// Set keys can be one of:
// C style string, std::string& utf8, and const char *

// Set values can be one of:
// Napi::Value
// napi_value (req static_cast)
// const char* (c style string)
// boolean
// double

enum VAL_TYPES { JS = 0, C_STR, CPP_STR, BOOL, INT, DOUBLE, JS_CAST };

void MoveOperatorsTest(const Napi::CallbackInfo& info) {
Napi::ObjectReference existingRef;
Napi::ObjectReference existingRef2;
Napi::Object testObject = Napi::Object::New(info.Env());
testObject.Set("testProp", "tProp");

// ObjectReference(Reference<Object>&& other);
Napi::Reference<Napi::Object> refObj =
Napi::Reference<Napi::Object>::New(testObject);
Napi::ObjectReference objRef = std::move(refObj);
std::string prop = MaybeUnwrap(objRef.Get("testProp")).As<Napi::String>();
assert(prop == "tProp");

// ObjectReference& operator=(Reference<Object>&& other);
Napi::Reference<Napi::Object> refObj2 =
Napi::Reference<Napi::Object>::New(testObject);
existingRef = std::move(refObj2);
prop = MaybeUnwrap(existingRef.Get("testProp")).As<Napi::String>();
assert(prop == "tProp");

// ObjectReference(ObjectReference&& other);
Napi::ObjectReference objRef3 = std::move(existingRef);
prop = MaybeUnwrap(objRef3.Get("testProp")).As<Napi::String>();
assert(prop == "tProp");

// ObjectReference& operator=(ObjectReference&& other);
existingRef2 = std::move(objRef3);
prop = MaybeUnwrap(objRef.Get("testProp")).As<Napi::String>();
assert(prop == "tProp");
}

void SetObjectWithCStringKey(Napi::ObjectReference& obj,
Napi::Value key,
Napi::Value val,
int valType) {
std::string c_key = key.As<Napi::String>().Utf8Value();
switch (valType) {
case JS:
obj.Set(c_key.c_str(), val);
break;

case JS_CAST:
obj.Set(c_key.c_str(), static_cast<napi_value>(val));
break;

case C_STR: {
std::string c_val = val.As<Napi::String>().Utf8Value();
obj.Set(c_key.c_str(), c_val.c_str());
break;
}

case BOOL:
obj.Set(c_key.c_str(), val.As<Napi::Boolean>().Value());
break;

case DOUBLE:
obj.Set(c_key.c_str(), val.As<Napi::Number>().DoubleValue());
break;
}
}

void SetObjectWithCppStringKey(Napi::ObjectReference& obj,
Napi::Value key,
Napi::Value val,
int valType) {
std::string c_key = key.As<Napi::String>();
switch (valType) {
case JS:
obj.Set(c_key, val);
break;

case JS_CAST:
obj.Set(c_key, static_cast<napi_value>(val));
break;

case CPP_STR: {
std::string c_val = val.As<Napi::String>();
obj.Set(c_key, c_val);
break;
}

case BOOL:
obj.Set(c_key, val.As<Napi::Boolean>().Value());
break;

case DOUBLE:
obj.Set(c_key, val.As<Napi::Number>().DoubleValue());
break;
}
}

void SetObjectWithIntKey(Napi::ObjectReference& obj,
Napi::Value key,
Napi::Value val,
int valType) {
uint32_t c_key = key.As<Napi::Number>().Uint32Value();
switch (valType) {
case JS:
obj.Set(c_key, val);
break;

case JS_CAST:
obj.Set(c_key, static_cast<napi_value>(val));
break;

case C_STR: {
std::string c_val = val.As<Napi::String>();
obj.Set(c_key, c_val.c_str());
break;
}

case CPP_STR: {
std::string cpp_val = val.As<Napi::String>();
obj.Set(c_key, cpp_val);
break;
}

case BOOL:
obj.Set(c_key, val.As<Napi::Boolean>().Value());
break;

case DOUBLE:
obj.Set(c_key, val.As<Napi::Number>().DoubleValue());
break;
}
}

void SetObject(const Napi::CallbackInfo& info) {
Env env = info.Env();
HandleScope scope(env);

Expand All @@ -33,20 +168,35 @@ void SetObjects(const CallbackInfo& info) {
reference = Reference<Object>::New(Object::New(env), 2);
reference.SuppressDestruct();

if (info[0].IsString()) {
if (info[2].As<String>() == String::New(env, "javascript")) {
weak.Set(info[0].As<String>(), info[1]);
persistent.Set(info[0].As<String>(), info[1]);
reference.Set(info[0].As<String>(), info[1]);
} else {
weak.Set(info[0].As<String>().Utf8Value(), info[1]);
persistent.Set(info[0].As<String>().Utf8Value(), info[1]);
reference.Set(info[0].As<String>().Utf8Value(), info[1]);
}
} else if (info[0].IsNumber()) {
weak.Set(info[0].As<Number>(), info[1]);
persistent.Set(info[0].As<Number>(), info[1]);
reference.Set(info[0].As<Number>(), info[1]);
Napi::Object configObject = info[0].As<Napi::Object>();

int keyType =
MaybeUnwrap(configObject.Get("keyType")).As<Napi::Number>().Uint32Value();
int valType =
MaybeUnwrap(configObject.Get("valType")).As<Napi::Number>().Uint32Value();
Napi::Value key = MaybeUnwrap(configObject.Get("key"));
Napi::Value val = MaybeUnwrap(configObject.Get("val"));

switch (keyType) {
case CPP_STR:
SetObjectWithCppStringKey(weak, key, val, valType);
SetObjectWithCppStringKey(persistent, key, val, valType);
SetObjectWithCppStringKey(reference, key, val, valType);
break;

case C_STR:
SetObjectWithCStringKey(weak, key, val, valType);
SetObjectWithCStringKey(persistent, key, val, valType);
SetObjectWithCStringKey(reference, key, val, valType);
break;

case INT:
SetObjectWithIntKey(weak, key, val, valType);
SetObjectWithIntKey(persistent, key, val, valType);
SetObjectWithIntKey(reference, key, val, valType);

default:
break;
}
}

Expand Down Expand Up @@ -87,6 +237,53 @@ Value GetFromValue(const CallbackInfo& info) {
}
}

Value GetHelper(ObjectReference& ref,
Object& configObject,
const Napi::Env& env) {
int keyType =
MaybeUnwrap(configObject.Get("keyType")).As<Napi::Number>().Uint32Value();
if (ref.IsEmpty()) {
return String::New(env, "No referenced Value");
}

switch (keyType) {
case C_STR: {
std::string c_key =
MaybeUnwrap(configObject.Get("key")).As<String>().Utf8Value();
return MaybeUnwrap(ref.Get(c_key.c_str()));
break;
}
case CPP_STR: {
std::string cpp_key =
MaybeUnwrap(configObject.Get("key")).As<String>().Utf8Value();
return MaybeUnwrap(ref.Get(cpp_key));
break;
}
case INT: {
uint32_t key =
MaybeUnwrap(configObject.Get("key")).As<Number>().Uint32Value();
return MaybeUnwrap(ref.Get(key));
break;
}

default:
return String::New(env, "Error: Reached end of getter");
break;
}
}

Value GetFromGetters(const CallbackInfo& info) {
std::string object_req = info[0].As<String>();
Object configObject = info[1].As<Object>();
if (object_req == "weak") {
return GetHelper(weak, configObject, info.Env());
} else if (object_req == "persistent") {
return GetHelper(persistent, configObject, info.Env());
}

return GetHelper(reference, configObject, info.Env());
}

// info[0] is a flag to determine if the weak, persistent, or
// multiple reference ObjectReference is being requested.
// info[1] is the key, and it be either a String or a Number.
Expand Down Expand Up @@ -207,13 +404,14 @@ Object InitObjectReference(Env env) {
Object exports = Object::New(env);

exports["setCastedObjects"] = Function::New(env, SetCastedObjects);
exports["setObjects"] = Function::New(env, SetObjects);
exports["setObject"] = Function::New(env, SetObject);
exports["getCastedFromValue"] = Function::New(env, GetCastedFromValue);
exports["getFromGetter"] = Function::New(env, GetFromGetter);
exports["getFromGetters"] = Function::New(env, GetFromGetters);
exports["getCastedFromGetter"] = Function::New(env, GetCastedFromGetter);
exports["getFromValue"] = Function::New(env, GetFromValue);
exports["unrefObjects"] = Function::New(env, UnrefObjects);
exports["refObjects"] = Function::New(env, RefObjects);
exports["moveOpTest"] = Function::New(env, MoveOperatorsTest);

return exports;
}
Loading

0 comments on commit 464610b

Please sign in to comment.