From 802e1dec3b03c410616fa4721844c1426ddcd420 Mon Sep 17 00:00:00 2001 From: G-XD Date: Tue, 26 Sep 2023 15:56:33 +0800 Subject: [PATCH] test(binding/java): add create_dir test (#3184) --- bindings/java/src/blocking_operator.rs | 20 +++++ .../org/apache/opendal/BlockingOperator.java | 6 ++ .../java/org/apache/opendal/Operator.java | 7 ++ bindings/java/src/operator.rs | 34 ++++++++ .../test/behavior/AbstractBehaviorTest.java | 78 +++++++++++++++++++ 5 files changed, 145 insertions(+) diff --git a/bindings/java/src/blocking_operator.rs b/bindings/java/src/blocking_operator.rs index 8604287bf6c2..55a645a4763b 100644 --- a/bindings/java/src/blocking_operator.rs +++ b/bindings/java/src/blocking_operator.rs @@ -129,3 +129,23 @@ fn intern_delete(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> let path = env.get_string(&path)?; Ok(op.delete(path.to_str()?)?) } + +/// # Safety +/// +/// This function should not be called before the Operator are ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_createDir( + mut env: JNIEnv, + _: JClass, + op: *mut BlockingOperator, + path: JString, +) { + intern_create_dir(&mut env, &mut *op, path).unwrap_or_else(|e| { + e.throw(&mut env); + }) +} + +fn intern_create_dir(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { + let path = env.get_string(&path)?; + Ok(op.create_dir(path.to_str()?)?) +} diff --git a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java b/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java index a2739388b02b..1c30f3ebc555 100644 --- a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java +++ b/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java @@ -70,6 +70,10 @@ public Metadata stat(String path) { return new Metadata(stat(nativeHandle, path)); } + public void createDir(String path) { + createDir(nativeHandle, path); + } + @Override protected native void disposeInternal(long handle); @@ -80,4 +84,6 @@ public Metadata stat(String path) { private static native void delete(long nativeHandle, String path); private static native long stat(long nativeHandle, String path); + + private static native long createDir(long nativeHandle, String path); } diff --git a/bindings/java/src/main/java/org/apache/opendal/Operator.java b/bindings/java/src/main/java/org/apache/opendal/Operator.java index 4debbaa3bdb9..9a1f46a7d80e 100644 --- a/bindings/java/src/main/java/org/apache/opendal/Operator.java +++ b/bindings/java/src/main/java/org/apache/opendal/Operator.java @@ -177,6 +177,11 @@ public CompletableFuture delete(String path) { return AsyncRegistry.take(requestId); } + public CompletableFuture createDir(String path) { + final long requestId = createDir(nativeHandle, path); + return AsyncRegistry.take(requestId); + } + @Override protected native void disposeInternal(long handle); @@ -201,4 +206,6 @@ public CompletableFuture delete(String path) { private static native OperatorInfo makeOperatorInfo(long nativeHandle); private static native long makeBlockingOp(long nativeHandle); + + private static native long createDir(long nativeHandle, String path); } diff --git a/bindings/java/src/operator.rs b/bindings/java/src/operator.rs index 4721144a8dfe..8f0c1549ec33 100644 --- a/bindings/java/src/operator.rs +++ b/bindings/java/src/operator.rs @@ -296,6 +296,40 @@ fn intern_make_operator_info(env: &mut JNIEnv, op: *mut Operator) -> Result jlong { + intern_create_dir(&mut env, op, path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_create_dir(env: &mut JNIEnv, op: *mut Operator, path: JString) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = env.get_string(&path)?.to_str()?.to_string(); + + unsafe { get_global_runtime() }.spawn(async move { + let result = do_create_dir(op, path).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_create_dir(op: &mut Operator, path: String) -> Result<()> { + Ok(op.create_dir(&path).await?) +} + /// # Safety /// /// This function should not be called before the Operator are ready. diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java index bfa28978e6aa..9df34a604bfb 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java @@ -164,6 +164,45 @@ public void testAppendCreateAppend() { } } + @TestInstance(TestInstance.Lifecycle.PER_CLASS) + @Nested + class AsyncCreateDirTest { + @BeforeAll + public void precondition() { + final Capability capability = operator.info.fullCapability; + assumeTrue(capability.createDir); + } + + /** + * Create dir with dir path should succeed. + */ + @Test + public void testCreateDir() { + final String path = String.format("%s/", UUID.randomUUID().toString()); + operator.createDir(path).join(); + + try (final Metadata meta = operator.stat(path).join()) { + assertThat(meta.isFile()).isFalse(); + } + operator.delete(path).join(); + } + + /** + * Create dir on existing dir should succeed. + */ + @Test + public void testCreateDirExisting() { + final String path = String.format("%s/", UUID.randomUUID().toString()); + operator.createDir(path).join(); + operator.createDir(path).join(); + + try (final Metadata meta = operator.stat(path).join()) { + assertThat(meta.isFile()).isFalse(); + } + operator.delete(path).join(); + } + } + @TestInstance(TestInstance.Lifecycle.PER_CLASS) @Nested class BlockingWriteTest { @@ -212,6 +251,45 @@ public void testBlockingStatFile() { } } + @TestInstance(TestInstance.Lifecycle.PER_CLASS) + @Nested + class BlockingCreateDirTest { + @BeforeAll + public void precondition() { + final Capability capability = blockingOperator.info.fullCapability; + assumeTrue(capability.createDir); + } + + /** + * Create dir with dir path should succeed. + */ + @Test + public void testBlockingCreateDir() { + final String path = String.format("%s/", UUID.randomUUID().toString()); + blockingOperator.createDir(path); + + try (final Metadata meta = blockingOperator.stat(path)) { + assertThat(meta.isFile()).isFalse(); + } + blockingOperator.delete(path); + } + + /** + * Create dir on existing dir should succeed. + */ + @Test + public void testBlockingDirExisting() { + final String path = String.format("%s/", UUID.randomUUID().toString()); + blockingOperator.createDir(path); + blockingOperator.createDir(path); + + try (final Metadata meta = blockingOperator.stat(path)) { + assertThat(meta.isFile()).isFalse(); + } + blockingOperator.delete(path); + } + } + /** * Generates a byte array of random content. */