Skip to content

Commit

Permalink
fix(addon): cancelClient interface and unit tests fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
bsrdjan committed Aug 21, 2023
1 parent 9fcddde commit 5fbc121
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 77 deletions.
2 changes: 1 addition & 1 deletion doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ loadCryptoLibrary(cryptoLibraryPath: string)
Usage: [usage/addon](usage.md#cancelclient)

```ts
cancelClient(client: Client, callback?: Function): void | Promise<any>;
cancelClient(client: Client, callback?: Function): void | Promise<void>;
```

### languageIsoToSap
Expand Down
1 change: 1 addition & 0 deletions src/cpp/Client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ Napi::Value Client::Release(const Napi::CallbackInfo& info) {

return info.Env().Undefined();
}

void cancelConnection(RFC_RC* rc,
RFC_CONNECTION_HANDLE connectionHandle,
RFC_ERROR_INFO* errorInfo) {
Expand Down
33 changes: 30 additions & 3 deletions src/cpp/Server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -621,13 +621,40 @@ RFC_RC SAP_API genericRequestHandler(RFC_CONNECTION_HANDLE conn_handle,

if (requestBaton->jsHandlerError.length() > 0) {
// return the error message to ABAP
// ref Table 5-A at pg. 48 of SAP NW RFC SDK Programming Guide
strncpyU(errorInfo->message, setString(requestBaton->jsHandlerError), 512);
return RFC_EXTERNAL_FAILURE;
}

return RFC_OK;
}

// to-do
// RFC_RC SAP_API authorizationHandler(RFC_CONNECTION_HANDLE rfcHandle,
// RFC_SECURITY_ATTRIBUTES* secAttributes,
// RFC_ERROR_INFO* errorInfo) {
// // Here you can check any combination of function name, system ID, //
// client,
// // calling ABAP report and username, as well as the backend’s SNC
// credentials. if (!strcmpU(secAttributes->user, cU("ADMIN"))) {
// // User ADMIN is allowed to call function modules FUNCTION_1,
// // ... FUNCTION_3.
// if (!strcmpU(secAttributes->functionName, cU("FUNCTION_1")) ||
// !strcmpU(secAttributes->functionName, cU("FUNCTION_2")) ||
// !strcmpU(secAttributes->functionName, cU("FUNCTION_3")))
// return RFC_OK;
// else if (!strcmpU(secAttributes->user, cU("BUSINESS_USER"))) {
// // User BUSINESS_USER is allowed to call function modules // BAPI_A,
// and
// // BAPI_B.
// if (!strcmpU(secAttributes->functionName, cU("BAPI_A")) ||
// !strcmpU(secAttributes->functionName, cU("BAPI_A")))
// return RFC_OK;
// // All other cases are denied.
// return RFC_AUTHORIZATION_FAILURE;
// }
// }

class StartAsync : public Napi::AsyncWorker {
public:
StartAsync(Napi::Function& callback, Server* server)
Expand Down Expand Up @@ -840,9 +867,9 @@ Napi::Value Server::AddFunction(const Napi::CallbackInfo& info) {

if (abapFunctionName.Utf8Value().length() == 0 ||
abapFunctionName.Utf8Value().length() > 30) {
Napi::TypeError::New(
info.Env(),
"Server addFunction() accepts max. 30 characters long ABAP RFM name")
Napi::TypeError::New(info.Env(),
"Server addFunction() accepts max. 30 characters "
"long ABAP RFM name")
.ThrowAsJavaScriptException();
return info.Env().Undefined();
}
Expand Down
1 change: 0 additions & 1 deletion src/cpp/addon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ Napi::Value SetLogFilePath(const Napi::CallbackInfo& info) {
_log.set_log_file_path(info[0].As<Napi::String>().Utf8Value());
return info.Env().Undefined();
}

Napi::Object RegisterModule(Napi::Env env, Napi::Object exports) {
if (node_rfc::__env == nullptr) {
node_rfc::__env = env;
Expand Down
20 changes: 2 additions & 18 deletions src/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,29 +69,13 @@ function terminate(workerData: unknown) {
export function cancelClient(
client: Client,
callback?: Function
): void | Promise<unknown> {
): void | Promise<void> {
if (callback !== undefined && typeof callback !== "function") {
throw new TypeError(
`cancelClient 2nd argument, if provided, must be a Function. Received: ${typeof callback}`
);
}
const old_handle = client.connectionHandle;
const workerData = { connectionHandle: old_handle };
if (typeof callback === "function") {
return terminate(workerData)
.then((res) => {
sapnwrfcEvents.emit("sapnwrfc:clientCancel", {
id: client.id,
connectionHandle: old_handle,
});
callback(undefined, res);
})
.catch((err) => {
callback(err);
});
} else {
return terminate(workerData);
}
return client.cancel(callback);
}

export function languageIsoToSap(langIso: string): string {
Expand Down
1 change: 1 addition & 0 deletions src/ts/sapnwrfc-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ export class Client {

cancel(callback?: Function): void | Promise<void> {
Client.checkCallbackArg("cancel", callback);

if (typeof callback === "function") {
try {
this.__client.cancel(callback);
Expand Down
45 changes: 23 additions & 22 deletions test/cancel/addon.cancelClient.promise.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { direct_client, cancelClient } from "../utils/setup";

describe.skip("Connection terminate by addon", () => {
describe("Connection terminate by addon", () => {
const DURATION = 3;
const CANCEL = 1;
const RfcCanceledError = {
Expand All @@ -16,27 +16,28 @@ describe.skip("Connection terminate by addon", () => {
message: "Connection was canceled.",
};

test("Non-managed, addon.cancelClient() promise", async () => {
const client = direct_client();
expect.assertions(2);
await client.open();
// call function
const handle = client.connectionHandle;
try {
await client.call("RFC_PING_AND_WAIT", { SECONDS: DURATION });
} catch (err) {
expect(err).toMatchObject(RfcCanceledError);
}
test(
"Non-managed, addon.cancelClient() promise",
async () => {
try {
expect.assertions(1);
const client = direct_client();

// cancel
setTimeout(() => {
async () => {
const res = await (cancelClient(client) as Promise<unknown>);
expect(res).toMatchObject({
connectionHandle: handle,
result: "cancelled",
await client.open();

// cancel after 1 sec
setTimeout(() => {
<void>cancelClient(client);
}, CANCEL * 1000);

// 3 seconds long call
await client.call("RFC_PING_AND_WAIT", {
SECONDS: DURATION,
});
};
}, CANCEL * 1000);
});
} catch (err: unknown) {
return expect(err).toMatchObject(RfcCanceledError);
}
},
DURATION * 1000
);
});
56 changes: 26 additions & 30 deletions test/cancel/addon.cancelClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { direct_client, cancelClient } from "../utils/setup";

describe.skip("Connection terminate by addon", () => {
describe("Connection terminate by addon", () => {
const DURATION = 3;
const CANCEL = 1;
const RfcCanceledError = {
Expand All @@ -16,33 +16,29 @@ describe.skip("Connection terminate by addon", () => {
message: "Connection was canceled.",
};

test("Non-managed, addon.cancelClient() callback", function (done) {
const client = direct_client();
expect.assertions(3);
void client.open(() => {
// call function
const handle = client.connectionHandle;
client.invoke(
"RFC_PING_AND_WAIT",
{
SECONDS: DURATION,
},
function (err) {
expect(err).toMatchObject(RfcCanceledError);
done();
}
);
// cancel

setTimeout(() => {
void cancelClient(client, (err, res) => {
expect(err).toBeUndefined();
expect(res).toMatchObject({
connectionHandle: handle,
result: "cancelled",
});
});
}, CANCEL * 1000);
});
});
test(
"Non-managed, addon.cancelClient() callback",
function (done) {
const client = direct_client();
expect.assertions(1);
void client.open(() => {
// 3 seconds long call
client.invoke(
"RFC_PING_AND_WAIT",
{
SECONDS: DURATION,
},
function (err: unknown) {
expect(err).toMatchObject(RfcCanceledError);
done();
}
);
// cancel after 1 sec
setTimeout(() => {
<void>cancelClient(client);
}, CANCEL * 1000);
});
},
DURATION * 1000
);
});
4 changes: 2 additions & 2 deletions test/cancel/timeout.client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe("Connection terminate timeout", () => {
message: "Connection was canceled.",
};

test.only("Client options timeout", function (done) {
test("Client options timeout", function (done) {
const client = new Client({ dest: "MME" }, { timeout: TIMEOUT });
expect.assertions(3);
void client.open(() => {
Expand All @@ -37,5 +37,5 @@ describe("Connection terminate timeout", () => {
}
);
});
});
}, 10000);
});

0 comments on commit 5fbc121

Please sign in to comment.