Skip to content

Commit

Permalink
Add test case for AbstractWasmDiscoveryHandler (apache#5453)
Browse files Browse the repository at this point in the history
* Tests

* Updated lib.rs and added a README.md

I updated the `lib.rs` and updated the WASM file and also added a README.md

* Remove TestWasmPluginDiscoveryHandler#handlerDiscoveryUpstreamData

* Revert "Remove TestWasmPluginDiscoveryHandler#handlerDiscoveryUpstreamData"

This reverts commit c85d3db.

* Update AbstractWasmDiscoveryHandlerTest.java

---------

Co-authored-by: loongs-zhang <[email protected]>
  • Loading branch information
Divyansh200102 and loongs-zhang authored Mar 1, 2024
1 parent 02b1e4a commit d430fe8
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base.handler;

import io.github.kawamuray.wasmtime.Func;
import io.github.kawamuray.wasmtime.Store;
import io.github.kawamuray.wasmtime.WasmFunctions;
import io.github.kawamuray.wasmtime.WasmValType;
import org.apache.shenyu.common.dto.DiscoverySyncData;
import org.apache.shenyu.plugin.base.handler.DiscoveryUpstreamDataHandler;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static org.apache.shenyu.plugin.api.ShenyuPlugin.LOG;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.mock;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class AbstractWasmDiscoveryHandlerTest {

private DiscoverySyncData discoverySyncData;

private TestWasmPluginDiscoveryHandler testWasmPluginDiscoveryHandler;

private DiscoveryUpstreamDataHandler discoveryUpstreamDataHandler;

@BeforeEach
public void setUp() {

this.discoverySyncData = mock(DiscoverySyncData.class);
this.testWasmPluginDiscoveryHandler = new TestWasmPluginDiscoveryHandler();
this.discoveryUpstreamDataHandler = testWasmPluginDiscoveryHandler;
when(discoverySyncData.getSelectorId()).thenReturn("SHENYU");
}

/**
* The handlerDiscoveryUpstreamData test.
*/
@Test
public void handlerDiscoveryUpstreamDataTest() {
discoveryUpstreamDataHandler = mock(DiscoveryUpstreamDataHandler.class);
discoveryUpstreamDataHandler.handlerDiscoveryUpstreamData(discoverySyncData);
testWasmPluginDiscoveryHandler.handlerDiscoveryUpstreamData(discoverySyncData);
verify(discoveryUpstreamDataHandler).handlerDiscoveryUpstreamData(discoverySyncData);

}

/**
* The plugin name test.
*/
@Test
public void pluginNameTest() {
assertEquals("SHENYU_TEST", discoveryUpstreamDataHandler.pluginName());
assertEquals("SHENYU_TEST", testWasmPluginDiscoveryHandler.pluginName());
}

static class TestWasmPluginDiscoveryHandler extends AbstractWasmDiscoveryHandler {

private static final Map<Long, String> RESULTS = new ConcurrentHashMap<>();

@Override
protected Map<String, Func> initWasmCallJavaFunc(final Store<Void> store) {
Map<String, Func> funcMap = new HashMap<>();
funcMap.put("get_args", WasmFunctions.wrap(store, WasmValType.I64, WasmValType.I64, WasmValType.I32, WasmValType.I32,
(argId, addr, len) -> {
String config = "hello from java " + argId;
LOG.info("java side->" + config);
assertEquals("hello from java 0", config);
ByteBuffer buf = super.getBuffer();
for (int i = 0; i < len && i < config.length(); i++) {
buf.put(addr.intValue() + i, (byte) config.charAt(i));
}
return Math.min(config.length(), len);
}));
funcMap.put("put_result", WasmFunctions.wrap(store, WasmValType.I64, WasmValType.I64, WasmValType.I32, WasmValType.I32,
(argId, addr, len) -> {
ByteBuffer buf = super.getBuffer();
byte[] bytes = new byte[len];
for (int i = 0; i < len; i++) {
bytes[i] = buf.get(addr.intValue() + i);
}
String result = new String(bytes, StandardCharsets.UTF_8);
assertEquals("rust result", result);
RESULTS.put(argId, result);
LOG.info("java side->" + result);
return 0;
}));
return funcMap;
}

@Override
public String pluginName() {
return "SHENYU_TEST";
}

@Override
protected Long getArgumentId(final DiscoverySyncData discoverySyncData) {
return 0L;
}
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

[package]
name = "rust-discovery-handler-plugin"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# How to build the wasm file

1. install rustup

2. install rust

3. generate the wasm file

```shell
cd {shenyu}/shenyu-plugin/shenyu-plugin-wasm-base/src/test/rust-wasm-discovery-handler-plugin
cargo build --target wasm32-wasi --release
```

then you will see the wasm file
in `{shenyu}/shenyu-plugin/shenyu-plugin-wasm-base/src/test/rust-wasm-discovery-handler-plugin/target/wasm32-wasi/release/rust_wasm_discovery_handler_plugin.wasm`

4. rename the wasm file

rename the file to `org.apache.shenyu.plugin.wasm.base.handler.AbstractWasmDiscoveryHandlerTest$TestWasmPluginDiscoveryHandler.wasm`
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#[link(wasm_import_module = "shenyu")]
extern "C" {
fn get_args(arg_id: i64, addr: i64, len: i32) -> i32;

fn put_result(arg_id: i64, addr: i64, len: i32) -> i32;
}

#[no_mangle]
pub unsafe extern "C" fn handlerDiscoveryUpstreamData(arg_id: i64) {
let mut buf = [0u8; 32];
let buf_ptr = buf.as_mut_ptr() as i64;
eprintln!("rust side-> buffer base address: {}", buf_ptr);
// get arg from java
let len = get_args(arg_id, buf_ptr, buf.len() as i32);
let java_arg = std::str::from_utf8(&buf[..len as usize]).unwrap();
eprintln!("rust side-> recv:{}", java_arg);
// pass rust result to java
let rust_result = "rust result".as_bytes();
let result_ptr = rust_result.as_ptr() as i64;
_ = put_result(arg_id, result_ptr, rust_result.len() as i32);
}

0 comments on commit d430fe8

Please sign in to comment.