From a400f156925a046e7e3a7a8446134a973a736837 Mon Sep 17 00:00:00 2001 From: ccx1024cc <1261138729@qq.com> Date: Thu, 2 Dec 2021 14:41:28 +0800 Subject: [PATCH] feat(java-sdk): java sdk support File API (#325) --- sdk/java-sdk/README-zh.md | 1 + sdk/java-sdk/README.md | 1 + sdk/java-sdk/examples/pom.xml | 2 +- .../io/mosn/layotto/examples/file/File.java | 132 +++++ sdk/java-sdk/pom.xml | 2 +- sdk/java-sdk/sdk/pom.xml | 2 +- .../io/mosn/layotto/v1/RuntimeClientGrpc.java | 494 +++++++++++++++++- .../sdk/runtime/v1/domain/FileRuntime.java | 48 ++ .../v1/domain/file/DelFileRequest.java | 56 ++ .../v1/domain/file/DelFileResponse.java | 18 + .../sdk/runtime/v1/domain/file/FileInfo.java | 69 +++ .../v1/domain/file/GetFileRequest.java | 55 ++ .../v1/domain/file/GetFileResponse.java | 34 ++ .../v1/domain/file/GetMetaRequest.java | 55 ++ .../v1/domain/file/GetMeteResponse.java | 53 ++ .../v1/domain/file/ListFileRequest.java | 73 +++ .../v1/domain/file/ListFileResponse.java | 52 ++ .../v1/domain/file/PutFileRequest.java | 66 +++ .../v1/domain/file/PutFileResponse.java | 18 + .../java/io/mosn/layotto/v1/FileTest.java | 360 +++++++++++++ .../layotto/v1/FileTestWithRealServer.java | 366 +++++++++++++ .../mosn/layotto/v1/mock/MyFileService.java | 143 +++++ 22 files changed, 2095 insertions(+), 5 deletions(-) create mode 100644 sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java create mode 100644 sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java create mode 100644 sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java create mode 100644 sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java diff --git a/sdk/java-sdk/README-zh.md b/sdk/java-sdk/README-zh.md index 4c80e9fb67..bffda113df 100644 --- a/sdk/java-sdk/README-zh.md +++ b/sdk/java-sdk/README-zh.md @@ -78,6 +78,7 @@ mvn clean install * [Hello world](./examples/src/test/java/io/mosn/layotto/examples/helloworld) * [State management](./examples/src/test/java/io/mosn/layotto/examples/state) * [Pubsub API](./examples/src/test/java/io/mosn/layotto/examples/pubsub) +* [File API](./examples/src/test/java/io/mosn/layotto/examples/file) ## java sdk开发指南 ### java sdk职责 diff --git a/sdk/java-sdk/README.md b/sdk/java-sdk/README.md index 66a34ad8e2..ad241c07d8 100644 --- a/sdk/java-sdk/README.md +++ b/sdk/java-sdk/README.md @@ -49,6 +49,7 @@ Try the following examples to learn more about this SDK: * [Hello world](./examples/src/test/java/io/mosn/layotto/examples/helloworld) * [State management](./examples/src/test/java/io/mosn/layotto/examples/state) * [Pubsub API](./examples/src/test/java/io/mosn/layotto/examples/pubsub) +* [File API](./examples/src/test/java/io/mosn/layotto/examples/file) ## java sdk developer guide ### How to format java sdk code diff --git a/sdk/java-sdk/examples/pom.xml b/sdk/java-sdk/examples/pom.xml index 039d2dbef8..015e86ba45 100644 --- a/sdk/java-sdk/examples/pom.xml +++ b/sdk/java-sdk/examples/pom.xml @@ -7,7 +7,7 @@ runtime-sdk-parent io.mosn.layotto - 1.0.0 + 1.1.0-SNAPSHOT examples diff --git a/sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java b/sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java new file mode 100644 index 0000000000..d5ccd1acae --- /dev/null +++ b/sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java @@ -0,0 +1,132 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 io.mosn.layotto.examples.file; + +import io.mosn.layotto.v1.RuntimeClientBuilder; +import io.mosn.layotto.v1.config.RuntimeProperties; +import spec.sdk.runtime.v1.client.RuntimeClient; +import spec.sdk.runtime.v1.domain.file.PutFileRequest; +import spec.sdk.runtime.v1.domain.file.GetFileRequest; +import spec.sdk.runtime.v1.domain.file.ListFileRequest; +import spec.sdk.runtime.v1.domain.file.GetMetaRequest; +import spec.sdk.runtime.v1.domain.file.DelFileRequest; +import spec.sdk.runtime.v1.domain.file.GetFileResponse; +import spec.sdk.runtime.v1.domain.file.ListFileResponse; +import spec.sdk.runtime.v1.domain.file.FileInfo; +import spec.sdk.runtime.v1.domain.file.GetMeteResponse; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +/** + * Specially + *

+ * 1. add `"local:{}` to "files" node in layotto/configs/config_file.json + * 2. start server by `./layotto start -c ../../configs/config_file.json` + */ +public class File { + + private static final Logger logger = Logger.getLogger(File.class.getName()); + + static String storeName = "local"; + static String fileName = "/tmp/test.log"; + + public static void main(String[] args) throws Exception { + + RuntimeClient client = new RuntimeClientBuilder() + .withPort(RuntimeProperties.DEFAULT_PORT) + .build(); + + putFile(client); + getFile(client); + listFile(client); + getFileMeta(client); + delFile(client); + } + + public static void putFile(RuntimeClient client) throws Exception { + + PutFileRequest request = new PutFileRequest(); + request.setStoreName(storeName); + request.setFileName(fileName); + + Map meta = new HashMap<>(); + meta.put("FileMode", "521"); + meta.put("FileFlag", "0777"); + request.setMetaData(meta); + + request.setIn(new ByteArrayInputStream("hello world".getBytes())); + + client.putFile(request, 3000); + } + + public static void getFile(RuntimeClient client) throws Exception { + + GetFileRequest request = new GetFileRequest(); + request.setStoreName(storeName); + request.setFileName(fileName); + + Map meta = new HashMap<>(); + meta.put("k1", "v1"); + request.setMetaData(meta); + + GetFileResponse resp = client.getFile(request, 3000); + + InputStream reader = resp.getIn(); + + byte[] buf = new byte[128]; + for (int len = reader.read(buf); len > 0; len = reader.read(buf)) { + logger.info(new String(buf, 0, len)); + } + } + + public static void delFile(RuntimeClient client) throws Exception { + + DelFileRequest request = new DelFileRequest(); + request.setStoreName(storeName); + request.setFileName(fileName); + + client.delFile(request, 3000); + } + + public static void listFile(RuntimeClient client) throws Exception { + + ListFileRequest request = new ListFileRequest(); + request.setStoreName(storeName); + request.setMarker("test.log"); + request.setName("/tmp"); + request.setPageSize(10); + + ListFileResponse resp = client.listFile(request, 3000); + + for (FileInfo f : resp.getFiles()) { + logger.info(f.getFileName()); + } + } + + public static void getFileMeta(RuntimeClient client) throws Exception { + + GetMetaRequest request = new GetMetaRequest(); + request.setStoreName(storeName); + request.setFileName(fileName); + + GetMeteResponse response = client.getFileMeta(request, 3000); + logger.info(response.getLastModified()); + logger.info("" + response.getMeta().size()); + } +} diff --git a/sdk/java-sdk/pom.xml b/sdk/java-sdk/pom.xml index 800fcc5d1d..8539decf36 100644 --- a/sdk/java-sdk/pom.xml +++ b/sdk/java-sdk/pom.xml @@ -5,7 +5,7 @@ io.mosn.layotto runtime-sdk-parent - 1.0.0 + 1.1.0-SNAPSHOT pom runtime-sdk-parent diff --git a/sdk/java-sdk/sdk/pom.xml b/sdk/java-sdk/sdk/pom.xml index c1a567ccc6..57e8d51182 100644 --- a/sdk/java-sdk/sdk/pom.xml +++ b/sdk/java-sdk/sdk/pom.xml @@ -6,7 +6,7 @@ io.mosn.layotto runtime-sdk-parent - 1.0.0 + 1.1.0-SNAPSHOT runtime-sdk diff --git a/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java b/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java index 31b5a1b444..fdc14dda2b 100644 --- a/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java +++ b/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java @@ -17,8 +17,11 @@ import com.google.common.base.Strings; import com.google.protobuf.Any; import com.google.protobuf.ByteString; +import com.google.protobuf.Empty; import io.grpc.Metadata; +import io.grpc.StatusRuntimeException; import io.grpc.stub.MetadataUtils; +import io.grpc.stub.StreamObserver; import io.mosn.layotto.v1.config.RuntimeProperties; import io.mosn.layotto.v1.exceptions.RuntimeClientException; import io.mosn.layotto.v1.grpc.GrpcRuntimeClient; @@ -27,13 +30,37 @@ import org.slf4j.Logger; import spec.proto.runtime.v1.RuntimeGrpc; import spec.proto.runtime.v1.RuntimeProto; +import spec.sdk.runtime.v1.domain.file.GetFileRequest; +import spec.sdk.runtime.v1.domain.file.PutFileRequest; +import spec.sdk.runtime.v1.domain.file.DelFileRequest; +import spec.sdk.runtime.v1.domain.file.GetFileResponse; +import spec.sdk.runtime.v1.domain.file.PutFileResponse; +import spec.sdk.runtime.v1.domain.file.DelFileResponse; +import spec.sdk.runtime.v1.domain.file.ListFileResponse; +import spec.sdk.runtime.v1.domain.file.ListFileRequest; +import spec.sdk.runtime.v1.domain.file.GetMeteResponse; +import spec.sdk.runtime.v1.domain.file.GetMetaRequest; +import spec.sdk.runtime.v1.domain.file.FileInfo; import spec.sdk.runtime.v1.domain.invocation.InvokeResponse; -import spec.sdk.runtime.v1.domain.state.*; +import spec.sdk.runtime.v1.domain.state.DeleteStateRequest; +import spec.sdk.runtime.v1.domain.state.SaveStateRequest; +import spec.sdk.runtime.v1.domain.state.State; +import spec.sdk.runtime.v1.domain.state.StateOptions; +import spec.sdk.runtime.v1.domain.state.ExecuteStateTransactionRequest; +import spec.sdk.runtime.v1.domain.state.TransactionalStateOperation; +import spec.sdk.runtime.v1.domain.state.GetStateRequest; +import spec.sdk.runtime.v1.domain.state.GetBulkStateRequest; import java.io.IOException; +import java.io.PipedOutputStream; +import java.io.PipedInputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.HashMap; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; public class RuntimeClientGrpc extends AbstractRuntimeClient implements GrpcRuntimeClient { @@ -108,7 +135,7 @@ public InvokeResponse invokeMethod(String appId, String methodName, byte // 3. parse result InvokeResponse result = new InvokeResponse<>(); result.setContentType(resp.getContentType()); - byte[] bytes = new byte[] {}; + byte[] bytes = new byte[]{}; result.setData(bytes); if (resp.getData() == null) { return result; @@ -501,4 +528,467 @@ public StubManager get public void shutdown() { stubManager.destroy(); } + + @Override + public PutFileResponse putFile(PutFileRequest request, int timeoutMs) throws Exception { + + checkParamOfPutFile(request); + + PutFileFuture putFuture = new PutFileFuture(request.getFileName()); + StreamObserver observer = createPutFileObserver(putFuture, timeoutMs); + + observer.onNext(buildPutFileMetaDataRequest(request.getStoreName(), request.getFileName(), + request.getMetaData())); + + byte[] buf = new byte[4096]; + for (int size = request.getIn().read(buf); size > 0; size = request.getIn().read(buf)) { + observer.onNext(buildPutFileDataRequest(buf, size)); + } + + observer.onCompleted(); + + putFuture.awaitDone(timeoutMs); + + return new PutFileResponse(); + } + + @Override + public GetFileResponse getFile(GetFileRequest request, int timeoutMs) throws Exception { + + checkParamOfGetFile(request); + + GetFilePipe pipe = new GetFilePipe(request.getFileName()); + + stubManager. + getAsyncStub(). + getFile( + buildGetFileRequest( + request.getStoreName(), + request.getFileName(), + request.getMetaData()), + pipe); + + return new GetFileResponse(pipe.getReader()); + } + + @Override + public ListFileResponse listFile(ListFileRequest request, int timeoutMs) throws Exception { + + checkParamOfListFile(request); + + RuntimeProto.ListFileResp response = stubManager. + getBlockingStub(). + withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS). + listFile( + buildListFileRequest( + request.getStoreName(), + request.getName(), + request.getMarker(), + request.getPageSize(), + request.getMetaData())); + + return buildListFileResponse(response); + } + + @Override + public DelFileResponse delFile(DelFileRequest request, int timeoutMs) throws Exception { + + checkParamOfDeleteFile(request); + + stubManager. + getBlockingStub(). + withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS). + delFile( + buildDelFileRequest(request.getStoreName(), request.getFileName(), request.getMetaData())); + + return new DelFileResponse(); + } + + @Override + public GetMeteResponse getFileMeta(GetMetaRequest request, int timeoutMs) throws Exception { + + checkParamOfGetFileMeta(request); + + RuntimeProto.GetFileMetaResponse resp = stubManager. + getBlockingStub(). + withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS). + getFileMeta( + buildGetFileMetaRequest(request.getStoreName(), request.getFileName(), request.getMetaData())); + + return buildGetFileMetaResponse(resp); + } + + private void checkParamOfGetFile(GetFileRequest request) { + + // check request + if (request == null) { + throw new IllegalArgumentException("miss request"); + } + + // check store name + if (request.getStoreName() == null) { + throw new IllegalArgumentException("miss store name"); + } + + // check file name + if (request.getFileName() == null) { + throw new IllegalArgumentException("miss file name"); + } + } + + private void checkParamOfPutFile(PutFileRequest request) { + + // check request + if (request == null) { + throw new IllegalArgumentException("miss request"); + } + + // check store name + if (request.getStoreName() == null) { + throw new IllegalArgumentException("miss store name"); + } + + // check file name + if (request.getFileName() == null) { + throw new IllegalArgumentException("miss file name"); + } + + // check input stream + if (request.getIn() == null) { + throw new IllegalArgumentException("miss file stream"); + } + } + + private void checkParamOfListFile(ListFileRequest request) { + + // check request + if (request == null) { + throw new IllegalArgumentException("miss request"); + } + + // check store name + if (request.getStoreName() == null) { + throw new IllegalArgumentException("miss store name"); + } + } + + private void checkParamOfDeleteFile(DelFileRequest request) { + + // check request + if (request == null) { + throw new IllegalArgumentException("miss request"); + } + + // check file name + if (request.getFileName() == null) { + throw new IllegalArgumentException("miss file name"); + } + + // check store name + if (request.getStoreName() == null) { + throw new IllegalArgumentException("miss store name"); + } + } + + private void checkParamOfGetFileMeta(GetMetaRequest request) { + + // check request + if (request == null) { + throw new IllegalArgumentException("miss request"); + } + + // check store name + if (request.getStoreName() == null) { + throw new IllegalArgumentException("miss store name"); + } + + // check file name + if (request.getFileName() == null) { + throw new IllegalArgumentException("miss file name"); + } + } + + private class PutFileFuture implements StreamObserver { + + private final String fileName; + private final CountDownLatch latch; + + private volatile Throwable t; + + PutFileFuture(String fileName) { + this.fileName = fileName; + this.latch = new CountDownLatch(1); + } + + @Override + public void onNext(Empty value) { + logger.info(String.format("put File %s successfully", this.fileName)); + } + + @Override + public void onError(Throwable t) { + logger.error(String.format("put File error, file=%s", this.fileName), t); + this.t = t; + this.latch.countDown(); + } + + @Override + public void onCompleted() { + logger.info(String.format("put File %s complete", this.fileName)); + latch.countDown(); + } + + public void awaitDone(int timeoutMs) throws Exception { + + boolean finished = latch.await(timeoutMs, TimeUnit.MILLISECONDS); + if (!finished) { + String tip = String.format("put file timeout, file=%s", fileName); + throw new RuntimeClientException("PUT_FILE", tip); + } + + // do not wrap for grpc Exception + if (t instanceof StatusRuntimeException) { + throw (StatusRuntimeException) t; + } + + // wrap exception for non grpc Exception + if (t != null) { + throw new RuntimeClientException(t); + } + } + } + + private class PipeFileInputStream extends PipedInputStream { + + private volatile Throwable cause; + + PipeFileInputStream(PipedOutputStream out) throws IOException { + super(out); + } + + @Override + public synchronized int read() throws IOException { + + checkCause(); + + return super.read(); + } + + @Override + public int read(byte[] b) throws IOException { + + checkCause(); + + return super.read(b); + } + + @Override + public synchronized int read(byte[] b, int off, int len) throws IOException { + + checkCause(); + + return super.read(b, off, len); + } + + private void checkCause() throws IOException { + if (this.cause != null) { + this.close(); + throw new IOException(this.cause); + } + } + + public void setCause(Throwable cause) { + this.cause = cause; + } + } + + private class GetFilePipe implements StreamObserver { + + private final String fileName; + private final PipeFileInputStream reader; + private final PipedOutputStream dataSource; + + GetFilePipe(String fileName) throws IOException { + this.fileName = fileName; + this.dataSource = new PipedOutputStream(); + this.reader = new PipeFileInputStream(this.dataSource); + } + + @Override + public void onNext(RuntimeProto.GetFileResponse value) { + + logger.info(String.format("get File %s successfully", this.fileName)); + + pipe(value.getData().toByteArray()); + } + + @Override + public void onError(Throwable t) { + + logger.error(String.format("get File error, file=%s", this.fileName), t); + + reader.setCause(t); + + pipe(t.getMessage().getBytes()); + } + + @Override + public void onCompleted() { + + logger.info(String.format("get File %s complete", this.fileName)); + + close(); + } + + private void pipe(byte[] data) { + try { + dataSource.write(data); + } catch (IOException e) { + logger.error("get File transform err", e); + } + } + + private void close() { + try { + dataSource.close(); + } catch (IOException e) { + logger.error("get File close stream err", e); + } + } + + public InputStream getReader() { + return this.reader; + } + } + + private StreamObserver createPutFileObserver( + StreamObserver callBackObserver, + int timeoutMs) { + + return stubManager. + getAsyncStub(). + withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS). + putFile(callBackObserver); + } + + private RuntimeProto.PutFileRequest buildPutFileMetaDataRequest(String storeName, + String fileName, + Map meta) { + return RuntimeProto.PutFileRequest. + newBuilder(). + setStoreName(storeName). + setName(fileName). + putAllMetadata(meta). + build(); + } + + private RuntimeProto.PutFileRequest buildPutFileDataRequest(byte[] bytes, int size) { + + return RuntimeProto.PutFileRequest. + newBuilder(). + setData(ByteString.copyFrom(bytes, 0, size)). + build(); + } + + private RuntimeProto.GetFileRequest buildGetFileRequest(String storeName, + String fileName, + Map meta) { + + return RuntimeProto.GetFileRequest. + newBuilder(). + setStoreName(storeName). + setName(fileName). + putAllMetadata(meta). + build(); + } + + private RuntimeProto.ListFileRequest buildListFileRequest(String storeName, String name, String marker, + int pageSize, Map meta) { + + RuntimeProto.FileRequest fileRequest = RuntimeProto.FileRequest. + newBuilder(). + setStoreName(storeName). + setName(name). + putAllMetadata(meta). + build(); + + return RuntimeProto.ListFileRequest. + newBuilder(). + setRequest(fileRequest). + setMarker(marker). + setPageSize(pageSize). + build(); + } + + private RuntimeProto.DelFileRequest buildDelFileRequest(String storeName, + String fileName, + Map meta) { + + RuntimeProto.FileRequest fileRequest = RuntimeProto.FileRequest. + newBuilder(). + setStoreName(storeName). + setName(fileName). + putAllMetadata(meta). + build(); + + return RuntimeProto.DelFileRequest. + newBuilder(). + setRequest(fileRequest). + build(); + } + + private RuntimeProto.GetFileMetaRequest buildGetFileMetaRequest(String storeName, + String fileName, + Map meta) { + + RuntimeProto.FileRequest fileRequest = RuntimeProto.FileRequest. + newBuilder(). + setStoreName(storeName). + setName(fileName). + putAllMetadata(meta). + build(); + + return RuntimeProto.GetFileMetaRequest. + newBuilder(). + setRequest(fileRequest). + build(); + } + + private GetMeteResponse buildGetFileMetaResponse(RuntimeProto.GetFileMetaResponse resp) { + + Map metas = new HashMap<>(); + resp.getResponse(). + getMetadataMap(). + forEach( + (s, fileMetaValue) -> + metas.put(s, fileMetaValue.getValueList().toArray(new String[0]))); + + GetMeteResponse result = new GetMeteResponse(); + result.setSize(resp.getSize()); + result.setLastModified(resp.getLastModified()); + result.setMeta(metas); + + return result; + } + + private ListFileResponse buildListFileResponse(RuntimeProto.ListFileResp resp) { + + FileInfo[] files = resp.getFilesList(). + stream(). + map( + fileInfo -> + new FileInfo( + fileInfo.getFileName(), + fileInfo.getSize(), + fileInfo.getLastModified(), + fileInfo.getMetadataMap())). + toArray(FileInfo[]::new); + + ListFileResponse result = new ListFileResponse(); + result.setFiles(files); + result.setTruncated(resp.getIsTruncated()); + result.setMarker(resp.getMarker()); + + return result; + } } diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java index 6d05dfd9ad..ac502ad981 100644 --- a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java @@ -14,5 +14,53 @@ */ package spec.sdk.runtime.v1.domain; +import spec.sdk.runtime.v1.domain.file.GetFileRequest; +import spec.sdk.runtime.v1.domain.file.PutFileRequest; +import spec.sdk.runtime.v1.domain.file.DelFileRequest; +import spec.sdk.runtime.v1.domain.file.ListFileResponse; +import spec.sdk.runtime.v1.domain.file.ListFileRequest; +import spec.sdk.runtime.v1.domain.file.GetMetaRequest; +import spec.sdk.runtime.v1.domain.file.GetMeteResponse; +import spec.sdk.runtime.v1.domain.file.PutFileResponse; +import spec.sdk.runtime.v1.domain.file.GetFileResponse; +import spec.sdk.runtime.v1.domain.file.DelFileResponse; + public interface FileRuntime { + + /** + * save or update file + * + * @param request + * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all. + * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException + */ + PutFileResponse putFile(PutFileRequest request, int timeoutMs) throws Exception; + + /** + * @param request + * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all. + * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException + */ + GetFileResponse getFile(GetFileRequest request, int timeoutMs) throws Exception; + + /** + * @param request + * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all. + * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException + */ + ListFileResponse listFile(ListFileRequest request, int timeoutMs) throws Exception; + + /** + * @param request + * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all. + * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException + */ + DelFileResponse delFile(DelFileRequest request, int timeoutMs) throws Exception; + + /** + * @param request + * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all. + * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException + */ + GetMeteResponse getFileMeta(GetMetaRequest request, int timeoutMs) throws Exception; } diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java new file mode 100644 index 0000000000..79b8cf0d8f --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.util.HashMap; +import java.util.Map; + +public class DelFileRequest { + + private String storeName; + private String fileName; + + private Map metaData; + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public Map getMetaData() { + + if (metaData == null) { + metaData = new HashMap<>(); + } + + return metaData; + } + + public void setMetaData(Map metaData) { + this.metaData = metaData; + } + +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java new file mode 100644 index 0000000000..97dad5a05d --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java @@ -0,0 +1,18 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +public class DelFileResponse { +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java new file mode 100644 index 0000000000..a3a0ae6fc8 --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java @@ -0,0 +1,69 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.util.HashMap; +import java.util.Map; + +public class FileInfo { + private String fileName; + private long size; + private String lastModified; + private Map metaData; + + public FileInfo(String fileName, long size, String lastModified, Map metaData) { + this.fileName = fileName; + this.size = size; + this.lastModified = lastModified; + this.metaData = metaData; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public String getLastModified() { + return lastModified; + } + + public void setLastModified(String lastModified) { + this.lastModified = lastModified; + } + + public Map getMetaData() { + + if (metaData == null) { + metaData = new HashMap<>(); + } + + return metaData; + } + + public void setMetaData(Map metaData) { + this.metaData = metaData; + } +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java new file mode 100644 index 0000000000..1d8e534778 --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.util.HashMap; +import java.util.Map; + +public class GetFileRequest { + + private String storeName; + private String fileName; + + private Map metaData; + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public Map getMetaData() { + + if (metaData == null) { + metaData = new HashMap<>(); + } + + return metaData; + } + + public void setMetaData(Map metaData) { + this.metaData = metaData; + } +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java new file mode 100644 index 0000000000..905e55c25e --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java @@ -0,0 +1,34 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.io.InputStream; + +public class GetFileResponse { + + private InputStream in; + + public GetFileResponse(InputStream in) { + this.in = in; + } + + public InputStream getIn() { + return in; + } + + public void setIn(InputStream in) { + this.in = in; + } +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java new file mode 100644 index 0000000000..b1f856bf16 --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.util.HashMap; +import java.util.Map; + +public class GetMetaRequest { + + private String storeName; + private String fileName; + + private Map metaData; + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public Map getMetaData() { + + if (metaData == null) { + metaData = new HashMap<>(); + } + + return metaData; + } + + public void setMetaData(Map metaData) { + this.metaData = metaData; + } +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java new file mode 100644 index 0000000000..38553e786f --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.util.HashMap; +import java.util.Map; + +public class GetMeteResponse { + private long size; + private String lastModified; + private Map meta; + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public String getLastModified() { + return lastModified; + } + + public void setLastModified(String lastModified) { + this.lastModified = lastModified; + } + + public Map getMeta() { + + if (meta == null) { + meta = new HashMap<>(); + } + + return meta; + } + + public void setMeta(Map meta) { + this.meta = meta; + } +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java new file mode 100644 index 0000000000..86ea4d8fc8 --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.util.HashMap; +import java.util.Map; + +public class ListFileRequest { + + private String storeName; + private String name; + private Map metaData; + + private int pageSize; + private String marker; + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map getMetaData() { + + if (metaData == null) { + metaData = new HashMap<>(); + } + + return metaData; + } + + public void setMetaData(Map metaData) { + this.metaData = metaData; + } + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public String getMarker() { + return marker; + } + + public void setMarker(String marker) { + this.marker = marker; + } +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java new file mode 100644 index 0000000000..23db57dba5 --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java @@ -0,0 +1,52 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +public class ListFileResponse { + + private boolean isTruncated; + private String marker; + + private FileInfo[] files; + + public boolean isTruncated() { + return isTruncated; + } + + public void setTruncated(boolean truncated) { + isTruncated = truncated; + } + + public String getMarker() { + return marker; + } + + public void setMarker(String marker) { + this.marker = marker; + } + + public FileInfo[] getFiles() { + + if (files == null) { + files = new FileInfo[0]; + } + + return files; + } + + public void setFiles(FileInfo[] files) { + this.files = files; + } +} \ No newline at end of file diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java new file mode 100644 index 0000000000..fdef7c75f8 --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +public class PutFileRequest { + + private String storeName; + private String fileName; + + private Map metaData; + + private InputStream in; + + public String getStoreName() { + return storeName; + } + + public void setStoreName(String storeName) { + this.storeName = storeName; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public Map getMetaData() { + + if (metaData == null) { + metaData = new HashMap<>(); + } + + return metaData; + } + + public void setMetaData(Map metaData) { + this.metaData = metaData; + } + + public InputStream getIn() { + return in; + } + + public void setIn(InputStream in) { + this.in = in; + } +} diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java new file mode 100644 index 0000000000..44ac87680a --- /dev/null +++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java @@ -0,0 +1,18 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 spec.sdk.runtime.v1.domain.file; + +public class PutFileResponse { +} diff --git a/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java new file mode 100644 index 0000000000..0af7c573c9 --- /dev/null +++ b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java @@ -0,0 +1,360 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 io.mosn.layotto.v1; + +import io.grpc.ManagedChannel; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.testing.GrpcCleanupRule; +import io.mosn.layotto.v1.mock.MyFileService; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import spec.proto.runtime.v1.RuntimeGrpc; +import spec.sdk.runtime.v1.client.RuntimeClient; +import spec.sdk.runtime.v1.domain.file.GetFileRequest; +import spec.sdk.runtime.v1.domain.file.PutFileRequest; +import spec.sdk.runtime.v1.domain.file.DelFileRequest; +import spec.sdk.runtime.v1.domain.file.ListFileRequest; +import spec.sdk.runtime.v1.domain.file.GetMetaRequest; +import spec.sdk.runtime.v1.domain.file.GetMeteResponse; +import spec.sdk.runtime.v1.domain.file.GetFileResponse; +import spec.sdk.runtime.v1.domain.file.ListFileResponse; +import spec.sdk.runtime.v1.domain.file.FileInfo; + +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.AdditionalAnswers.delegatesTo; +import static org.mockito.Mockito.mock; + +@RunWith(JUnit4.class) +public class FileTest { + @Rule + public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + + RuntimeGrpc.RuntimeImplBase fileService = new MyFileService(); + + private final RuntimeGrpc.RuntimeImplBase serviceImpl = mock(RuntimeGrpc.RuntimeImplBase.class, + delegatesTo(fileService)); + + private RuntimeClient client; + + @Before + public void setUp() throws Exception { + String serverName = InProcessServerBuilder.generateName(); + grpcCleanup.register(InProcessServerBuilder + .forName(serverName).directExecutor() + .addService(serviceImpl) + .build().start()); + ManagedChannel channel = grpcCleanup.register( + InProcessChannelBuilder.forName(serverName).directExecutor().build()); + client = new RuntimeClientBuilder() + .buildGrpcWithExistingChannel(channel); + } + + // normal case + @Test + public void testPutFile1() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setIn(new ByteArrayInputStream("hello world".getBytes())); + req.setStoreName( "oss"); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testPutFile2() throws Exception { + client.putFile(null, 10000); + } + + // miss in stream + @Test(expected = IllegalArgumentException.class) + public void testPutFile3() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setStoreName("oss"); + req.setFileName("test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testPutFile4() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setIn(new ByteArrayInputStream("hello world".getBytes())); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testPutFile5() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setIn(new ByteArrayInputStream("hello world".getBytes())); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // normal case + @Test + public void testGetFile1() throws Exception { + + GetFileRequest req = new GetFileRequest(); + req.setStoreName( "oss"); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + GetFileResponse resp = client.getFile(req, 10000); + + byte[] buf = new byte[126]; + int len = resp.getIn().read(buf); + + String echo = new String(buf,0,len); + Assert.assertEquals("get file store name oss, meta 2, file name test.log", echo); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testGetFile2() throws Exception { + client.getFile(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testGetFile3() throws Exception { + + GetFileRequest req = new GetFileRequest(); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.getFile(req, 10000); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testGetFile4() throws Exception { + + GetFileRequest req = new GetFileRequest(); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.getFile(req, 10000); + } + + // normal case + @Test + public void testDelFile1() throws Exception { + + DelFileRequest req = new DelFileRequest(); + req.setStoreName( "oss"); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.delFile(req, 10000); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testDelFile2() throws Exception { + client.delFile(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testDelFile3() throws Exception { + + DelFileRequest req = new DelFileRequest(); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.delFile(req, 10000); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testDelFile4() throws Exception { + + DelFileRequest req = new DelFileRequest(); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.delFile(req, 10000); + } + + // normal + @Test + public void testListFile1() throws Exception { + + ListFileRequest req = new ListFileRequest(); + req.setStoreName( "oss"); + req.setName("dir"); + req.setMarker("test.log"); + req.setPageSize(10); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + ListFileResponse resp = client.listFile(req, 10000); + + Assert.assertTrue(resp.isTruncated()); + Assert.assertEquals("marker", resp.getMarker()); + Assert.assertEquals(1, resp.getFiles().length); + + FileInfo f = resp.getFiles()[0]; + Assert.assertEquals("put file store name oss, meta 2", f.getFileName()); + Assert.assertEquals(100L, f.getSize()); + Assert.assertEquals("2021-11-23 10:24:11", f.getLastModified()); + Assert.assertEquals("v1", f.getMetaData().get("k1")); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testListFile2() throws Exception { + client.listFile(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testListFile3() throws Exception { + + ListFileRequest req = new ListFileRequest(); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + ListFileResponse notUsed = client.listFile(req, 10000); + } + + // normal + @Test + public void testGetFileMeta1() throws Exception { + + GetMetaRequest req = new GetMetaRequest(); + req.setStoreName( "oss"); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + GetMeteResponse res = client.getFileMeta(req, 10000); + + Assert.assertEquals(100L, res.getSize()); + Assert.assertEquals("2021-11-22 10:24:11", res.getLastModified()); + Assert.assertArrayEquals(new String[]{"v1", "v2"}, res.getMeta().get("k1")); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testGetFileMeta2() throws Exception { + client.getFileMeta(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testGetFileMeta3() throws Exception { + + GetMetaRequest req = new GetMetaRequest(); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + GetMeteResponse res = client.getFileMeta(req, 10000); + + Assert.assertEquals(100L, res.getSize()); + Assert.assertEquals("2021-11-22 10:24:11", res.getLastModified()); + Assert.assertArrayEquals(new String[]{"v1", "v2"}, res.getMeta().get("k1")); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testGetFileMeta4() throws Exception { + + GetMetaRequest req = new GetMetaRequest(); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.getFileMeta(req, 10000); + } +} diff --git a/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java new file mode 100644 index 0000000000..15402b2fb5 --- /dev/null +++ b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java @@ -0,0 +1,366 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 io.mosn.layotto.v1; + +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.mosn.layotto.v1.grpc.ExceptionHandler; +import io.mosn.layotto.v1.grpc.GrpcRuntimeClient; +import io.mosn.layotto.v1.mock.MyFileService; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import spec.proto.runtime.v1.RuntimeGrpc; +import spec.sdk.runtime.v1.domain.file.GetFileRequest; +import spec.sdk.runtime.v1.domain.file.PutFileRequest; +import spec.sdk.runtime.v1.domain.file.DelFileRequest; +import spec.sdk.runtime.v1.domain.file.ListFileRequest; +import spec.sdk.runtime.v1.domain.file.GetMetaRequest; +import spec.sdk.runtime.v1.domain.file.GetMeteResponse; +import spec.sdk.runtime.v1.domain.file.GetFileResponse; +import spec.sdk.runtime.v1.domain.file.ListFileResponse; +import spec.sdk.runtime.v1.domain.file.FileInfo; + +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.Map; + +@RunWith(JUnit4.class) +public class FileTestWithRealServer { + + private final RuntimeGrpc.RuntimeImplBase fileService = new MyFileService(); + + private Server srv; + private GrpcRuntimeClient client; + + int port = 9999; + String ip = "127.0.0.1"; + + @Before + public void setUp() throws Exception { + // start grpc server + /* The port on which the server should run */ + srv = ServerBuilder.forPort(port) + .addService(fileService) + .intercept(new ExceptionHandler()) + .build() + .start(); + + // build a client + client = new RuntimeClientBuilder() + .withIp(ip) + .withPort(port) + .withConnectionPoolSize(4) + .withTimeout(1000) + .buildGrpc(); + } + + @After + public void shutdown() { + client.shutdown(); + srv.shutdownNow(); + } + + // normal case + @Test + public void testPutFile1() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setIn( new ByteArrayInputStream("hello world".getBytes())); + req.setStoreName("oss"); + req.setFileName("test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testPutFile2() throws Exception { + client.putFile(null, 10000); + } + + // miss in stream + @Test(expected = IllegalArgumentException.class) + public void testPutFile3() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setStoreName( "oss"); + req.setFileName("test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testPutFile4() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setIn( new ByteArrayInputStream("hello world".getBytes())); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testPutFile5() throws Exception { + + PutFileRequest req = new PutFileRequest(); + req.setIn( new ByteArrayInputStream("hello world".getBytes())); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.putFile(req, 10000); + } + + // normal case + @Test + public void testGetFile1() throws Exception { + + GetFileRequest req = new GetFileRequest(); + req.setStoreName( "oss"); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + GetFileResponse resp = client.getFile(req, 10000); + + byte[] buf = new byte[126]; + int len = resp.getIn().read(buf); + + String echo = new String(buf,0,len); + Assert.assertEquals("get file store name oss, meta 2, file name test.log", echo); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testGetFile2() throws Exception { + client.getFile(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testGetFile3() throws Exception { + + GetFileRequest req = new GetFileRequest(); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.getFile(req, 10000); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testGetFile4() throws Exception { + + GetFileRequest req = new GetFileRequest(); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.getFile(req, 10000); + } + + // normal case + @Test + public void testDelFile1() throws Exception { + + DelFileRequest req = new DelFileRequest(); + req.setStoreName( "oss"); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.delFile(req, 10000); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testDelFile2() throws Exception { + client.delFile(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testDelFile3() throws Exception { + + DelFileRequest req = new DelFileRequest(); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.delFile(req, 10000); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testDelFile4() throws Exception { + + DelFileRequest req = new DelFileRequest(); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.delFile(req, 10000); + } + + // normal + @Test + public void testListFile1() throws Exception { + + ListFileRequest req = new ListFileRequest(); + req.setStoreName( "oss"); + req.setName("dir"); + req.setMarker("test.log"); + req.setPageSize(10); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + ListFileResponse resp = client.listFile(req, 10000); + + Assert.assertTrue(resp.isTruncated()); + Assert.assertEquals("marker", resp.getMarker()); + Assert.assertEquals(1, resp.getFiles().length); + + FileInfo f = resp.getFiles()[0]; + Assert.assertEquals("put file store name oss, meta 2", f.getFileName()); + Assert.assertEquals(100L, f.getSize()); + Assert.assertEquals("2021-11-23 10:24:11", f.getLastModified()); + Assert.assertEquals("v1", f.getMetaData().get("k1")); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testListFile2() throws Exception { + client.listFile(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testListFile3() throws Exception { + + ListFileRequest req = new ListFileRequest(); + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + ListFileResponse resp = client.listFile(req, 10000); + } + + // normal + @Test + public void testGetFileMeta1() throws Exception { + + GetMetaRequest req = new GetMetaRequest(); + req.setStoreName( "oss"); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + GetMeteResponse res = client.getFileMeta(req, 10000); + + Assert.assertEquals(100L,res.getSize()); + Assert.assertEquals("2021-11-22 10:24:11",res.getLastModified()); + Assert.assertArrayEquals(new String[]{"v1","v2"},res.getMeta().get("k1")); + } + + // miss request + @Test(expected = IllegalArgumentException.class) + public void testGetFileMeta2() throws Exception { + client.getFileMeta(null, 10000); + } + + // miss store name + @Test(expected = IllegalArgumentException.class) + public void testGetFileMeta3() throws Exception { + + GetMetaRequest req = new GetMetaRequest(); + req.setFileName( "test.log"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + GetMeteResponse res = client.getFileMeta(req, 10000); + + Assert.assertEquals(100L,res.getSize()); + Assert.assertEquals("2021-11-22 10:24:11",res.getLastModified()); + Assert.assertArrayEquals(new String[]{"v1","v2"},res.getMeta().get("k1")); + } + + // miss file name + @Test(expected = IllegalArgumentException.class) + public void testGetFileMeta4() throws Exception { + + GetMetaRequest req = new GetMetaRequest(); + req.setStoreName( "oss"); + + Map metaData = new HashMap<>(); + metaData.put("k1", "v1"); + metaData.put("k2", "v2"); + req.setMetaData(metaData); + + client.getFileMeta(req, 10000); + } +} diff --git a/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java new file mode 100644 index 0000000000..106423c0e7 --- /dev/null +++ b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java @@ -0,0 +1,143 @@ +/* + * Copyright 2021 Layotto Authors + * Licensed 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 io.mosn.layotto.v1.mock; + +import com.google.protobuf.ByteString; +import com.google.protobuf.Empty; +import io.grpc.stub.StreamObserver; +import spec.proto.runtime.v1.RuntimeGrpc; +import spec.proto.runtime.v1.RuntimeProto; + +public class MyFileService extends RuntimeGrpc.RuntimeImplBase { + + @Override + public StreamObserver putFile(StreamObserver responseObserver) { + + return new StreamObserver() { + + @Override + public void onNext(RuntimeProto.PutFileRequest putFileRequest) { + + String log = String.format("put file store name %s, meta %d, file name %s, data size %d", + putFileRequest.getStoreName(), + putFileRequest.getMetadataCount(), + putFileRequest.getName(), + putFileRequest.getData().size()); + + System.out.println(log); + } + + @Override + public void onError(Throwable throwable) { + if (throwable != null) { + System.err.println("put file err: " + throwable); + } + } + + @Override + public void onCompleted() { + System.out.println("finished put file"); + responseObserver.onNext(Empty.newBuilder().build()); + responseObserver.onCompleted(); + } + }; + } + + @Override + public void getFile(RuntimeProto.GetFileRequest request, + StreamObserver responseObserver) { + + String echo = String.format("get file store name %s, meta %d, file name %s", + request.getStoreName(), + request.getMetadataCount(), + request.getName()); + + responseObserver.onNext( + RuntimeProto.GetFileResponse.newBuilder(). + setData( + ByteString.copyFrom(echo.getBytes())). + build()); + + responseObserver.onCompleted(); + } + + @Override + public void delFile(RuntimeProto.DelFileRequest request, StreamObserver responseObserver) { + + String log = String.format("del file store name %s, meta %d, file name %s", + request.getRequest().getStoreName(), + request.getRequest().getMetadataCount(), + request.getRequest().getName()); + + System.out.println(log); + + responseObserver.onNext(Empty.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public void listFile(RuntimeProto.ListFileRequest request, + StreamObserver responseObserver) { + + String echo = String.format("put file store name %s, meta %d", + request.getRequest().getStoreName(), + request.getRequest().getMetadataCount()); + + responseObserver.onNext( + RuntimeProto.ListFileResp.newBuilder(). + addFiles( + RuntimeProto.FileInfo.newBuilder(). + setFileName(echo). + setSize(100). + setLastModified("2021-11-23 10:24:11"). + putMetadata("k1", "v1"). + build()). + setMarker("marker"). + setIsTruncated(true). + build() + ); + + responseObserver.onCompleted(); + } + + @Override + public void getFileMeta(RuntimeProto.GetFileMetaRequest request, + StreamObserver responseObserver) { + + String log = String.format("get file meta store name %s, meta %d, file name %s", + request.getRequest().getStoreName(), + request.getRequest().getMetadataCount(), + request.getRequest().getName()); + + System.out.println(log); + + responseObserver.onNext( + RuntimeProto.GetFileMetaResponse.newBuilder(). + setSize(100). + setLastModified("2021-11-22 10:24:11"). + setResponse( + RuntimeProto.FileMeta.newBuilder(). + putMetadata( + "k1", + RuntimeProto.FileMetaValue.newBuilder(). + addValue("v1"). + addValue("v2"). + build()). + build()). + build()); + + responseObserver.onCompleted(); + } +}