diff options
author | Elias Sjögreen <eliassjogreen1@gmail.com> | 2021-05-07 15:45:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-07 09:45:07 -0400 |
commit | 4ed1428c3401c9e6dc4d737bd7c9a50840054696 (patch) | |
tree | 62888871bee247f35d0f663b784ab072becfc164 /test_plugin | |
parent | c709f5df363887647915f7dd67e1c3bb8df6c526 (diff) |
fix: align plugin api with Extension (#10427)
Diffstat (limited to 'test_plugin')
-rw-r--r-- | test_plugin/src/lib.rs | 128 | ||||
-rw-r--r-- | test_plugin/tests/integration_tests.rs | 8 | ||||
-rw-r--r-- | test_plugin/tests/test.js | 107 |
3 files changed, 162 insertions, 81 deletions
diff --git a/test_plugin/src/lib.rs b/test_plugin/src/lib.rs index 71ba698fc..105071751 100644 --- a/test_plugin/src/lib.rs +++ b/test_plugin/src/lib.rs @@ -1,55 +1,105 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::plugin_api::Interface; -use deno_core::plugin_api::Op; -use deno_core::plugin_api::OpResult; -use deno_core::plugin_api::ZeroCopyBuf; -use futures::future::FutureExt; +use std::borrow::Cow; +use std::cell::RefCell; +use std::rc::Rc; + +use deno_core::error::bad_resource_id; +use deno_core::error::AnyError; +use deno_core::op_async; +use deno_core::op_sync; +use deno_core::Extension; +use deno_core::OpState; +use deno_core::Resource; +use deno_core::ResourceId; +use deno_core::ZeroCopyBuf; #[no_mangle] -pub fn deno_plugin_init(interface: &mut dyn Interface) { - interface.register_op("testSync", op_test_sync); - interface.register_op("testAsync", op_test_async); +pub fn init() -> Extension { + Extension::builder() + .ops(vec![ + ("op_test_sync", op_sync(op_test_sync)), + ("op_test_async", op_async(op_test_async)), + ( + "op_test_resource_table_add", + op_sync(op_test_resource_table_add), + ), + ( + "op_test_resource_table_get", + op_sync(op_test_resource_table_get), + ), + ]) + .build() } fn op_test_sync( - _interface: &mut dyn Interface, + _state: &mut OpState, + _args: (), zero_copy: Option<ZeroCopyBuf>, -) -> Op { - if zero_copy.is_some() { - println!("Hello from plugin."); - } +) -> Result<String, AnyError> { + println!("Hello from sync plugin op."); + if let Some(buf) = zero_copy { - let buf_str = std::str::from_utf8(&buf[..]).unwrap(); + let buf_str = std::str::from_utf8(&buf[..])?; println!("zero_copy: {}", buf_str); } - let result = b"test"; - let result_box: Box<[u8]> = Box::new(*result); - Op::Sync(OpResult::Ok(result_box.into())) + + Ok("test".to_string()) } -fn op_test_async( - _interface: &mut dyn Interface, +async fn op_test_async( + _state: Rc<RefCell<OpState>>, + _args: (), zero_copy: Option<ZeroCopyBuf>, -) -> Op { - if zero_copy.is_some() { - println!("Hello from plugin."); +) -> Result<String, AnyError> { + println!("Hello from async plugin op."); + + if let Some(buf) = zero_copy { + let buf_str = std::str::from_utf8(&buf[..])?; + println!("zero_copy: {}", buf_str); + } + + let (tx, rx) = futures::channel::oneshot::channel::<Result<(), ()>>(); + std::thread::spawn(move || { + std::thread::sleep(std::time::Duration::from_secs(1)); + tx.send(Ok(())).unwrap(); + }); + assert!(rx.await.is_ok()); + + Ok("test".to_string()) +} + +struct TestResource(String); +impl Resource for TestResource { + fn name(&self) -> Cow<str> { + "TestResource".into() } - let fut = async move { - if let Some(buf) = zero_copy { - let buf_str = std::str::from_utf8(&buf[..]).unwrap(); - println!("zero_copy: {}", buf_str); - } - let (tx, rx) = futures::channel::oneshot::channel::<Result<(), ()>>(); - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_secs(1)); - tx.send(Ok(())).unwrap(); - }); - assert!(rx.await.is_ok()); - let result = b"test"; - let result_box: Box<[u8]> = Box::new(*result); - (0, OpResult::Ok(result_box.into())) - }; - - Op::Async(fut.boxed()) +} + +#[allow(clippy::unnecessary_wraps)] +fn op_test_resource_table_add( + state: &mut OpState, + text: String, + _zero_copy: Option<ZeroCopyBuf>, +) -> Result<u32, AnyError> { + println!("Hello from resource_table.add plugin op."); + + Ok(state.resource_table.add(TestResource(text))) +} + +fn op_test_resource_table_get( + state: &mut OpState, + rid: ResourceId, + _zero_copy: Option<ZeroCopyBuf>, +) -> Result<String, AnyError> { + println!("Hello from resource_table.get plugin op."); + + Ok( + state + .resource_table + .get::<TestResource>(rid) + .ok_or_else(bad_resource_id)? + .0 + .clone(), + ) } diff --git a/test_plugin/tests/integration_tests.rs b/test_plugin/tests/integration_tests.rs index b0e1c6a74..203a8bade 100644 --- a/test_plugin/tests/integration_tests.rs +++ b/test_plugin/tests/integration_tests.rs @@ -10,11 +10,6 @@ const BUILD_VARIANT: &str = "debug"; const BUILD_VARIANT: &str = "release"; #[test] -// TODO: re-enable after adapting plugins to new op-layer -// see: -// - https://github.com/denoland/deno/pull/9843 -// - https://github.com/denoland/deno/pull/9850 -#[ignore] fn basic() { let mut build_plugin_base = Command::new("cargo"); let mut build_plugin = @@ -38,8 +33,9 @@ fn basic() { println!("stdout {}", stdout); println!("stderr {}", stderr); } + println!("{:?}", output.status); assert!(output.status.success()); - let expected = "Hello from plugin.\nzero_copy[0]: test\nzero_copy[1]: 123\nzero_copy[2]: cba\nPlugin Sync Response: test\nHello from plugin.\nzero_copy[0]: test\nzero_copy[1]: 123\nzero_copy[2]: cba\nPlugin Async Response: test\n"; + let expected = "Plugin rid: 3\nHello from sync plugin op.\nzero_copy: test\nop_test_sync returned: test\nHello from async plugin op.\nzero_copy: 123\nop_test_async returned: test\nHello from resource_table.add plugin op.\nTestResource rid: 4\nHello from resource_table.get plugin op.\nTestResource get value: hello plugin!\nHello from sync plugin op.\nOps completed count is correct!\nOps dispatched count is correct!\n"; assert_eq!(stdout, expected); assert_eq!(stderr, ""); } diff --git a/test_plugin/tests/test.js b/test_plugin/tests/test.js index 90e6b43ca..716b2ff9a 100644 --- a/test_plugin/tests/test.js +++ b/test_plugin/tests/test.js @@ -1,4 +1,5 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file const filenameBase = "test_plugin"; @@ -17,69 +18,101 @@ const filename = `../target/${ Deno.args[0] }/${filenamePrefix}${filenameBase}${filenameSuffix}`; -// This will be checked against open resources after Plugin.close() -// in runTestClose() below. const resourcesPre = Deno.resources(); -const rid = Deno.openPlugin(filename); - -const { testSync, testAsync } = Deno.core.ops(); -if (!(testSync > 0)) { - throw "bad op id for testSync"; -} -if (!(testAsync > 0)) { - throw "bad op id for testAsync"; +const pluginRid = Deno.openPlugin(filename); +console.log(`Plugin rid: ${pluginRid}`); + +const { + op_test_sync, + op_test_async, + op_test_resource_table_add, + op_test_resource_table_get, +} = Deno.core.ops(); + +if ( + op_test_sync === null || + op_test_async === null || + op_test_resource_table_add === null || + op_test_resource_table_get === null +) { + throw new Error("Not all expected ops were registered"); } -const textDecoder = new TextDecoder(); - function runTestSync() { - const response = Deno.core.dispatch( - testSync, + const result = Deno.core.opSync( + "op_test_sync", + null, new Uint8Array([116, 101, 115, 116]), - new Uint8Array([49, 50, 51]), - new Uint8Array([99, 98, 97]), ); - console.log(`Plugin Sync Response: ${textDecoder.decode(response)}`); -} + console.log(`op_test_sync returned: ${result}`); -Deno.core.setAsyncHandler(testAsync, (response) => { - console.log(`Plugin Async Response: ${textDecoder.decode(response)}`); -}); + if (result !== "test") { + throw new Error("op_test_sync returned an unexpected value!"); + } +} -function runTestAsync() { - const response = Deno.core.dispatch( - testAsync, - new Uint8Array([116, 101, 115, 116]), +async function runTestAsync() { + const promise = Deno.core.opAsync( + "op_test_async", + null, new Uint8Array([49, 50, 51]), - new Uint8Array([99, 98, 97]), ); - if (response != null || response != undefined) { - throw new Error("Expected null response!"); + if (!(promise instanceof Promise)) { + throw new Error("Expected promise!"); + } + + const result = await promise; + console.log(`op_test_async returned: ${result}`); + + if (result !== "test") { + throw new Error("op_test_async promise resolved to an unexpected value!"); } } +function runTestResourceTable() { + const expect = "hello plugin!"; + + const testRid = Deno.core.opSync("op_test_resource_table_add", expect); + console.log(`TestResource rid: ${testRid}`); + + if (testRid === null || Deno.resources()[testRid] !== "TestResource") { + throw new Error("TestResource was not found!"); + } + + const testValue = Deno.core.opSync("op_test_resource_table_get", testRid); + console.log(`TestResource get value: ${testValue}`); + + if (testValue !== expect) { + throw new Error("Did not get correct resource value!"); + } + + Deno.close(testRid); +} + function runTestOpCount() { const start = Deno.metrics(); - Deno.core.dispatch(testSync); + Deno.core.opSync("op_test_sync"); const end = Deno.metrics(); - if (end.opsCompleted - start.opsCompleted !== 2) { - // one op for the plugin and one for Deno.metrics + if (end.opsCompleted - start.opsCompleted !== 1) { throw new Error("The opsCompleted metric is not correct!"); } - if (end.opsDispatched - start.opsDispatched !== 2) { - // one op for the plugin and one for Deno.metrics + console.log("Ops completed count is correct!"); + + if (end.opsDispatched - start.opsDispatched !== 1) { throw new Error("The opsDispatched metric is not correct!"); } + console.log("Ops dispatched count is correct!"); } function runTestPluginClose() { - Deno.close(rid); + // Closing does not yet work + Deno.close(pluginRid); const resourcesPost = Deno.resources(); @@ -92,10 +125,12 @@ Before: ${preStr} After: ${postStr}`, ); } + console.log("Correct number of resources"); } runTestSync(); -runTestAsync(); +await runTestAsync(); +runTestResourceTable(); runTestOpCount(); -runTestPluginClose(); +// runTestPluginClose(); |