| @@ -59,7 +59,7 @@ class UntypedCall { | |||
| public: | |||
| virtual ~UntypedCall() {} | |||
| virtual Status operator()() = 0; | |||
| virtual Status process() = 0; | |||
| virtual bool JudgeFinish() = 0; | |||
| @@ -93,12 +93,12 @@ class CallData : public UntypedCall { | |||
| EnqueueFunction enqueue_function, HandleRequestFunction handle_request_function) { | |||
| auto call = new CallData<ServiceImpl, AsyncService, RequestMessage, ResponseMessage>( | |||
| service_impl, async_service, cq, enqueue_function, handle_request_function); | |||
| Status status = (*call)(); | |||
| Status status = call->process(); | |||
| if (status != SUCCESS) return status; | |||
| return SUCCESS; | |||
| } | |||
| Status operator()() override { | |||
| Status process() override { | |||
| if (status_ == STATE::CREATE) { | |||
| status_ = STATE::PROCESS; | |||
| (async_service_->*enqueue_function_)(&ctx_, &request_, &responder_, cq_, cq_, this); | |||
| @@ -184,7 +184,7 @@ class MasterGrpcServer : public GrpcAsyncServer { | |||
| if (rq->JudgeFinish()) { | |||
| DelRequest(); | |||
| } else { | |||
| Status status = (*rq)(); | |||
| Status status = rq->process(); | |||
| if (status != SUCCESS) { | |||
| return status; | |||
| } | |||
| @@ -36,6 +36,9 @@ namespace mindspore { | |||
| namespace serving { | |||
| Status Server::StartGrpcServer(const std::string &ip, uint32_t grpc_port, int max_msg_mb_size) { | |||
| if (grpc_async_server_ != nullptr) { | |||
| return INFER_STATUS_LOG_ERROR(SYSTEM_ERROR) << "Serving Error: Serving gRPC server is already running"; | |||
| } | |||
| ExitSignalHandle::Instance().Start(); // handle ctrl+c to exit | |||
| if (max_msg_mb_size > gRpcMaxMBMsgSize) { | |||
| MSI_LOG_WARNING << "The maximum Serving gRPC message size is 512MB and will be updated from " << max_msg_mb_size | |||
| @@ -63,6 +66,7 @@ void Server::Clear() { | |||
| restful_server_.Stop(); | |||
| grpc_server_.Stop(); | |||
| grpc_manager_server_.Stop(); | |||
| grpc_async_server_ = nullptr; | |||
| } | |||
| Server::Server() = default; | |||
| @@ -54,7 +54,7 @@ class UntypedCall { | |||
| public: | |||
| virtual ~UntypedCall() {} | |||
| virtual Status operator()() = 0; | |||
| virtual Status process() = 0; | |||
| virtual bool JudgeFinish() = 0; | |||
| }; | |||
| @@ -84,12 +84,12 @@ class CallData : public UntypedCall { | |||
| EnqueueFunction enqueue_function, HandleRequestFunction handle_request_function) { | |||
| auto call = new CallData<ServiceImpl, AsyncService, RequestMessage, ResponseMessage>( | |||
| service_impl, async_service, cq, enqueue_function, handle_request_function); | |||
| Status status = (*call)(); | |||
| Status status = call->process(); | |||
| if (status != SUCCESS) return status; | |||
| return SUCCESS; | |||
| } | |||
| Status operator()() override { | |||
| Status process() override { | |||
| if (status_ == STATE::CREATE) { | |||
| status_ = STATE::PROCESS; | |||
| (async_service_->*enqueue_function_)(&ctx_, &request_, &responder_, cq_, cq_, this); | |||
| @@ -155,7 +155,7 @@ class WorkerGrpcServer : public GrpcAsyncServer { | |||
| if (rq->JudgeFinish()) { | |||
| delete rq; | |||
| } else { | |||
| Status status = (*rq)(); | |||
| Status status = rq->process(); | |||
| if (status != SUCCESS) return status; | |||
| } | |||
| return SUCCESS; | |||
| @@ -44,6 +44,9 @@ Worker &Worker::GetInstance() { | |||
| } | |||
| Status Worker::StartGrpcServer(const std::string &ip, uint32_t grpc_port) { | |||
| if (grpc_async_worker_server_ != nullptr) { | |||
| return INFER_STATUS_LOG_ERROR(SYSTEM_ERROR) << "Serving Error: Worker gRPC server is already running"; | |||
| } | |||
| grpc_async_worker_server_ = std::make_unique<MSWorkerServer>(ip, grpc_port); | |||
| return grpc_async_worker_server_->Init(); | |||
| } | |||
| @@ -387,6 +390,7 @@ void Worker::Clear() { | |||
| cpp_preprocess_.Stop(); | |||
| cpp_postprocess_.Stop(); | |||
| ServableStorage::Instance().Clear(); | |||
| grpc_async_worker_server_ = nullptr; | |||
| servable_started_ = false; | |||
| MSI_LOG_INFO << "End clear worker session"; | |||
| } | |||
| @@ -259,6 +259,29 @@ class Client: | |||
| print(status_code.value) | |||
| return ClientGrpcAsyncError({"error": "Grpc Error, " + str(status_code.value)}) | |||
| def close(self): | |||
| """ | |||
| Used to release gRPC connection avoiding influence on the connection to the next restarted Serving server. | |||
| Examples: | |||
| >>> from mindspore_serving.client import Client | |||
| >>> import numpy as np | |||
| >>> instance = {"x1": np.ones((2, 2), np.int32), "x2": np.ones((2, 2), np.int32)} | |||
| >>> client = Client("localhost", 5500, "add", "add_cast") | |||
| >>> result = client.infer(instance) | |||
| >>> client.close() | |||
| >>> print(result) | |||
| """ | |||
| if self.stub: | |||
| del self.stub | |||
| self.stub = None | |||
| def __enter__(self): | |||
| return self | |||
| def __exit__(self, exc_type, exc_val, exc_tb): | |||
| self.close() | |||
| def _create_request(self, instances): | |||
| """Used to create request spec.""" | |||
| if not isinstance(instances, (tuple, list)): | |||
| @@ -118,6 +118,7 @@ class PyTask: | |||
| raise RuntimeError( | |||
| f"expecting '{self.task_name}' yield count equal to instance size {self.instances_size}") | |||
| except ServingSystemException as e: | |||
| self.push_failed(self.instances_size - self.index) | |||
| raise e | |||
| except Exception as e: # catch exception and try next | |||
| logger.warning(f"{self.task_name} get result catch exception: {e}") | |||
| @@ -1,2 +1,110 @@ | |||
| add_library(protobuf::libprotobuf ALIAS protobuf::protobuf) | |||
| add_executable(protobuf::libprotoc ALIAS protobuf::protoc) | |||
| set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) | |||
| if(CMAKE_CROSSCOMPILING) | |||
| find_program(_PROTOBUF_PROTOC protoc) | |||
| else() | |||
| set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>) | |||
| endif() | |||
| # Find gRPC installation | |||
| # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. | |||
| if(EXISTS ${grpc_ROOT}/lib64) | |||
| set(gRPC_DIR "${grpc_ROOT}/lib64/cmake/grpc") | |||
| else() | |||
| set(gRPC_DIR "${grpc_ROOT}/lib/cmake/grpc") | |||
| endif() | |||
| message("serving using grpc_DIR : " ${gPRC_DIR}) | |||
| find_package(gRPC CONFIG REQUIRED) | |||
| message(STATUS "Using gRPC ${gRPC_VERSION}") | |||
| set(_GRPC_GRPCPP gRPC::grpc++) | |||
| set(_REFLECTION gRPC::grpc++_reflection) | |||
| if(CMAKE_CROSSCOMPILING) | |||
| find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) | |||
| find_program(_GRPC_PYTHON_PLUGIN_EXECUTABLE grpc_python_plugin) | |||
| else() | |||
| set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>) | |||
| set(_GRPC_PYTHON_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_python_plugin>) | |||
| endif() | |||
| # Proto file | |||
| # Generated sources | |||
| file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/proto/") | |||
| file(GLOB_RECURSE PROTO_FILE_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ../../mindspore_serving/proto/*.proto) | |||
| foreach(proto_file_with_path ${PROTO_FILE_LIST}) | |||
| message(------proto file: ${proto_file_with_path}) | |||
| get_filename_component(proto_I_DIR "../../" ABSOLUTE) | |||
| get_filename_component(proto_file_absolute "${proto_file_with_path}" ABSOLUTE) | |||
| string(REGEX REPLACE .*/proto/ "" proto_file ${proto_file_with_path}) | |||
| set(proto_file_relative "mindspore_serving/proto/${proto_file}") | |||
| string(REGEX REPLACE .proto "" proto_file_prefix ${proto_file}) | |||
| set(protoc_output_prefix ${CMAKE_CURRENT_BINARY_DIR}/mindspore_serving/proto) | |||
| set(hw_proto_srcs "${protoc_output_prefix}/${proto_file_prefix}.pb.cc") | |||
| set(hw_proto_hdrs "${protoc_output_prefix}/${proto_file_prefix}.pb.h") | |||
| set(hw_grpc_srcs "${protoc_output_prefix}/${proto_file_prefix}.grpc.pb.cc") | |||
| set(hw_grpc_hdrs "${protoc_output_prefix}/${proto_file_prefix}.grpc.pb.h") | |||
| set(hw_py_pb2 "${protoc_output_prefix}/${proto_file_prefix}_pb2.py") | |||
| set(hw_py_pb2_grpc "${protoc_output_prefix}/${proto_file_prefix}_pb2_grpc.py") | |||
| add_custom_command( | |||
| OUTPUT ${hw_proto_srcs} ${hw_proto_hdrs} ${hw_grpc_srcs} ${hw_grpc_hdrs} ${hw_py_pb2} ${hw_py_pb2_grpc} | |||
| WORKING_DIRECTORY ${proto_I_DIR} | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${proto_I_DIR}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" | |||
| "${proto_file_relative}" | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --python_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${proto_I_DIR}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_PYTHON_PLUGIN_EXECUTABLE}" | |||
| "${proto_file_relative}" | |||
| DEPENDS "${proto_file_absolute}") | |||
| list(APPEND PROTO_SRC_LIST ${hw_proto_srcs} ${hw_grpc_srcs}) | |||
| endforeach() | |||
| include_directories("${CMAKE_CURRENT_BINARY_DIR}/mindspore_serving") # for proto header file | |||
| include_directories("${CMAKE_CURRENT_BINARY_DIR}") | |||
| include_directories("${CMAKE_SOURCE_DIR}/mindspore_serving") | |||
| # serving_common for c++ server and python interface | |||
| file(GLOB_RECURSE UT_SERVING_CORE_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||
| "../../mindspore_serving/ccsrc/common/*.cc" | |||
| "../../mindspore_serving/ccsrc/master/*.cc" | |||
| "../../mindspore_serving/ccsrc/worker/*.cc") | |||
| file(GLOB_RECURSE UT_SERVING_STUB RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "stub/*.cc") | |||
| set(UT_SERVING_COMMON ${UT_SERVING_CORE_SRC} ${UT_SERVING_STUB} ${PROTO_SRC_LIST}) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}) | |||
| include_directories(stub) | |||
| include_directories(stub/include) | |||
| include_directories(${CMAKE_SOURCE_DIR}) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../mindspore_serving/ccsrc) | |||
| link_directories(${CMKAE_BINARY_DIR}/securec/src) | |||
| add_library(serving_ut_common STATIC ${UT_SERVING_COMMON}) | |||
| target_link_libraries(serving_ut_common PRIVATE ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF}) | |||
| target_link_libraries(serving_ut_common PRIVATE mindspore_serving::event mindspore_serving::event_pthreads) | |||
| target_link_libraries(serving_ut_common PRIVATE pthread mindspore::glog) | |||
| target_link_libraries(serving_ut_common PRIVATE ${SECUREC_LIBRARY}) | |||
| # copy libevent lib | |||
| file(GLOB_RECURSE LIBEVENT_LIB_LIST ${libevent_LIBPATH}/libevent* libevent_LIBPATH}/libevent_pthreads*) | |||
| file(COPY ${LIBEVENT_LIB_LIST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/lib) | |||
| # copy glog lib | |||
| file(GLOB_RECURSE GLOG_LIB_LIST ${glog_LIBPATH}/libglog*) | |||
| file(COPY ${GLOG_LIB_LIST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/lib) | |||
| add_subdirectory("cpp") | |||
| add_subdirectory("python") | |||
| @@ -5,115 +5,18 @@ | |||
| # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-rpath,$ORIGIN:$ORIGIN/lib") | |||
| add_library(protobuf::libprotobuf ALIAS protobuf::protobuf) | |||
| add_executable(protobuf::libprotoc ALIAS protobuf::protoc) | |||
| set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) | |||
| if (CMAKE_CROSSCOMPILING) | |||
| find_program(_PROTOBUF_PROTOC protoc) | |||
| else () | |||
| set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>) | |||
| endif () | |||
| # Find gRPC installation | |||
| # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. | |||
| if (EXISTS ${grpc_ROOT}/lib64) | |||
| set(gRPC_DIR "${grpc_ROOT}/lib64/cmake/grpc") | |||
| else () | |||
| set(gRPC_DIR "${grpc_ROOT}/lib/cmake/grpc") | |||
| endif () | |||
| message("serving using grpc_DIR : " ${gPRC_DIR}) | |||
| find_package(gRPC CONFIG REQUIRED) | |||
| message(STATUS "Using gRPC ${gRPC_VERSION}") | |||
| set(_GRPC_GRPCPP gRPC::grpc++) | |||
| set(_REFLECTION gRPC::grpc++_reflection) | |||
| if (CMAKE_CROSSCOMPILING) | |||
| find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) | |||
| find_program(_GRPC_PYTHON_PLUGIN_EXECUTABLE grpc_python_plugin) | |||
| else () | |||
| set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>) | |||
| set(_GRPC_PYTHON_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_python_plugin>) | |||
| endif () | |||
| # Proto file | |||
| # Generated sources | |||
| file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/proto/") | |||
| file(GLOB_RECURSE PROTO_FILE_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/mindspore_serving/proto/ FOLLOW_SYMLINKS *.proto) | |||
| foreach (proto_file ${PROTO_FILE_LIST}) | |||
| message(------proto file: ${proto_file}) | |||
| get_filename_component(proto_I_DIR "./" ABSOLUTE) | |||
| get_filename_component(proto_file_absolute "mindspore_serving/proto/${proto_file}" ABSOLUTE) | |||
| set(proto_file_relative "mindspore_serving/proto/${proto_file}") | |||
| string(REGEX REPLACE .proto "" proto_file_prefix ${proto_file}) | |||
| set(protoc_output_prefix ${CMAKE_CURRENT_BINARY_DIR}/mindspore_serving/proto) | |||
| set(hw_proto_srcs "${protoc_output_prefix}/${proto_file_prefix}.pb.cc") | |||
| set(hw_proto_hdrs "${protoc_output_prefix}/${proto_file_prefix}.pb.h") | |||
| set(hw_grpc_srcs "${protoc_output_prefix}/${proto_file_prefix}.grpc.pb.cc") | |||
| set(hw_grpc_hdrs "${protoc_output_prefix}/${proto_file_prefix}.grpc.pb.h") | |||
| set(hw_py_pb2 "${protoc_output_prefix}/${proto_file_prefix}_pb2.py") | |||
| set(hw_py_pb2_grpc "${protoc_output_prefix}/${proto_file_prefix}_pb2_grpc.py") | |||
| add_custom_command( | |||
| OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" "${hw_py_pb2}" "${hw_py_pb2_grpc}" | |||
| WORKING_DIRECTORY ${proto_I_DIR} | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${proto_I_DIR}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" | |||
| "${proto_file_relative}" | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --python_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${proto_I_DIR}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_PYTHON_PLUGIN_EXECUTABLE}" | |||
| "${proto_file_relative}" | |||
| DEPENDS "${proto_file_absolute}") | |||
| list(APPEND PROTO_SRC_LIST ${hw_proto_srcs} ${hw_grpc_srcs}) | |||
| endforeach (proto_file) | |||
| include_directories("${CMAKE_CURRENT_BINARY_DIR}/mindspore_serving") # for proto header file | |||
| include_directories("${CMAKE_CURRENT_BINARY_DIR}") | |||
| # serving_common for c++ server and python interface | |||
| file(GLOB_RECURSE UT_SERVING_CORE_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||
| "../../../mindspore_serving/ccsrc/master/*.cc" | |||
| "../../../mindspore_serving/ccsrc/common/*.cc" | |||
| "../../../mindspore_serving/ccsrc/worker/*.cc") | |||
| file(GLOB_RECURSE UT_SERVING_STUB RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "stub/*.cc") | |||
| set(UT_SERVING_COMMON ${UT_SERVING_CORE_SRC} ${UT_SERVING_STUB} ${PROTO_SRC_LIST}) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/stub) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/stub/include) | |||
| include_directories(${CMAKE_SOURCE_DIR}) | |||
| include_directories(${CMAKE_SOURCE_DIR}/mindspore_serving) | |||
| include_directories(${CMAKE_SOURCE_DIR}/mindspore_serving/ccsrc) | |||
| link_directories(${CMAKE_BINARY_DIR}/googletest/googlemock/gtest) | |||
| link_directories(${CMKAE_BINARY_DIR}/securec/src) | |||
| file(GLOB_RECURSE UT_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "common/*.cc" "tests/*.cc") | |||
| add_executable(serving_ut ${UT_LIST} ${UT_SERVING_COMMON}) | |||
| target_link_libraries(serving_ut mindspore_serving::gtest) | |||
| target_link_libraries(serving_ut mindspore_serving::event mindspore_serving::event_pthreads) | |||
| target_link_libraries(serving_ut ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF} pthread mindspore::glog) | |||
| target_link_libraries(serving_ut ${SECUREC_LIBRARY}) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/) | |||
| add_executable(serving_ut ${UT_LIST}) | |||
| target_link_libraries(serving_ut PRIVATE mindspore_serving::gtest) | |||
| target_link_libraries(serving_ut PRIVATE -Wl,--whole-archive serving_ut_common -Wl,--no-whole-archive) | |||
| # disable auto rpath | |||
| set_target_properties(serving_ut PROPERTIES SKIP_BUILD_RPATH TRUE) | |||
| # copy gtest lib | |||
| file(GLOB_RECURSE GTEST_LIB_LIST ${gtest_LIBPATH}/libgtest*) | |||
| file(COPY ${GTEST_LIB_LIST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) | |||
| # copy libevent lib | |||
| file(GLOB_RECURSE LIBEVENT_LIB_LIST ${libevent_LIBPATH}/libevent* libevent_LIBPATH}/libevent_pthreads*) | |||
| file(COPY ${LIBEVENT_LIB_LIST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) | |||
| # copy glog lib | |||
| file(GLOB_RECURSE GLOG_LIB_LIST ${glog_LIBPATH}/libglog*) | |||
| file(COPY ${GLOG_LIB_LIST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) | |||
| @@ -1 +0,0 @@ | |||
| ../../../../mindspore_serving/proto/ | |||
| @@ -23,6 +23,7 @@ else | |||
| echo "BUILD_PATH = $BUILD_PATH" | |||
| fi | |||
| cd ${BUILD_PATH}/mindspore_serving/tests/ut/cpp | |||
| export LD_LIBRARY_PATH=${BUILD_PATH}/mindspore_serving/tests/ut/lib:${LD_LIBRARY_PATH} | |||
| export LD_LIBRARY_PATH=${BUILD_PATH}/mindspore_serving/tests/ut/cpp:${LD_LIBRARY_PATH} | |||
| if [ $# -gt 0 ]; then | |||
| @@ -5,127 +5,26 @@ | |||
| # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. | |||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-rpath,$ORIGIN:$ORIGIN/lib") | |||
| add_library(protobuf::libprotobuf ALIAS protobuf::protobuf) | |||
| add_executable(protobuf::libprotoc ALIAS protobuf::protoc) | |||
| set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) | |||
| if (CMAKE_CROSSCOMPILING) | |||
| find_program(_PROTOBUF_PROTOC protoc) | |||
| else () | |||
| set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>) | |||
| endif () | |||
| # Find gRPC installation | |||
| # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. | |||
| if (EXISTS ${grpc_ROOT}/lib64) | |||
| set(gRPC_DIR "${grpc_ROOT}/lib64/cmake/grpc") | |||
| else () | |||
| set(gRPC_DIR "${grpc_ROOT}/lib/cmake/grpc") | |||
| endif () | |||
| message("serving using grpc_DIR : " ${gPRC_DIR}) | |||
| find_package(gRPC CONFIG REQUIRED) | |||
| message(STATUS "Using gRPC ${gRPC_VERSION}") | |||
| set(_GRPC_GRPCPP gRPC::grpc++) | |||
| set(_REFLECTION gRPC::grpc++_reflection) | |||
| if (CMAKE_CROSSCOMPILING) | |||
| find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) | |||
| find_program(_GRPC_PYTHON_PLUGIN_EXECUTABLE grpc_python_plugin) | |||
| else () | |||
| set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>) | |||
| set(_GRPC_PYTHON_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_python_plugin>) | |||
| endif () | |||
| # Proto file | |||
| # Generated sources | |||
| file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/proto/") | |||
| file(GLOB_RECURSE PROTO_FILE_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/mindspore_serving/proto/ FOLLOW_SYMLINKS *.proto) | |||
| foreach (proto_file ${PROTO_FILE_LIST}) | |||
| message(------proto file: ${proto_file}) | |||
| get_filename_component(proto_I_DIR "./" ABSOLUTE) | |||
| get_filename_component(proto_file_absolute "mindspore_serving/proto/${proto_file}" ABSOLUTE) | |||
| set(proto_file_relative "mindspore_serving/proto/${proto_file}") | |||
| string(REGEX REPLACE .proto "" proto_file_prefix ${proto_file}) | |||
| set(protoc_output_prefix ${CMAKE_CURRENT_BINARY_DIR}/mindspore_serving/proto) | |||
| set(hw_proto_srcs "${protoc_output_prefix}/${proto_file_prefix}.pb.cc") | |||
| set(hw_proto_hdrs "${protoc_output_prefix}/${proto_file_prefix}.pb.h") | |||
| set(hw_grpc_srcs "${protoc_output_prefix}/${proto_file_prefix}.grpc.pb.cc") | |||
| set(hw_grpc_hdrs "${protoc_output_prefix}/${proto_file_prefix}.grpc.pb.h") | |||
| set(hw_py_pb2 "${protoc_output_prefix}/${proto_file_prefix}_pb2.py") | |||
| set(hw_py_pb2_grpc "${protoc_output_prefix}/${proto_file_prefix}_pb2_grpc.py") | |||
| add_custom_command( | |||
| OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" "${hw_py_pb2}" "${hw_py_pb2_grpc}" | |||
| WORKING_DIRECTORY ${proto_I_DIR} | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${proto_I_DIR}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" | |||
| "${proto_file_relative}" | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --python_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${proto_I_DIR}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_PYTHON_PLUGIN_EXECUTABLE}" | |||
| "${proto_file_relative}" | |||
| DEPENDS "${proto_file_absolute}") | |||
| list(APPEND PROTO_SRC_LIST ${hw_proto_srcs} ${hw_grpc_srcs}) | |||
| endforeach (proto_file) | |||
| include_directories("${CMAKE_CURRENT_BINARY_DIR}/mindspore_serving") # for proto header file | |||
| include_directories("${CMAKE_CURRENT_BINARY_DIR}") | |||
| # serving_common for c++ server and python interface | |||
| file(GLOB_RECURSE UT_SERVING_CORE_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||
| "../../../mindspore_serving/ccsrc/master/*.cc" | |||
| "../../../mindspore_serving/ccsrc/common/*.cc" | |||
| "../../../mindspore_serving/ccsrc/worker/*.cc") | |||
| file(GLOB_RECURSE UT_SERVING_STUB RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "../cpp/stub/*.cc") | |||
| set(UT_SERVING_COMMON ${UT_SERVING_CORE_SRC} ${UT_SERVING_STUB} ${PROTO_SRC_LIST}) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../cpp/) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../cpp/stub) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../cpp/stub/include) | |||
| include_directories(${CMAKE_SOURCE_DIR}) | |||
| include_directories(${CMAKE_SOURCE_DIR}/mindspore_serving/ccsrc) | |||
| link_directories(${CMKAE_BINARY_DIR}/securec/src) | |||
| # python ut | |||
| add_compile_definitions(ENABLE_PYTHON) | |||
| file(GLOB_RECURSE PY_SRC_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "../../../mindspore_serving/ccsrc/python/*.cc") | |||
| find_package(Python3 3.7 COMPONENTS Interpreter Development) | |||
| if (Python3_FOUND) | |||
| if(Python3_FOUND) | |||
| set(PYTHON_INCLUDE_DIRS "${Python3_INCLUDE_DIRS}") | |||
| set(PYTHON_LIBRARIES "${Python3_LIBRARIES}") | |||
| else () | |||
| else() | |||
| find_python_package(py_inc py_lib) | |||
| set(PYTHON_INCLUDE_DIRS "${py_inc}") | |||
| set(PYTHON_LIBRARIES "${py_lib}") | |||
| endif () | |||
| endif() | |||
| include_directories(${PYTHON_INCLUDE_DIRS}) | |||
| set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/mindspore_serving) | |||
| pybind11_add_module(_mindspore_serving ${PY_SRC_LIST} ${UT_SERVING_COMMON}) | |||
| pybind11_add_module(_mindspore_serving ${PY_SRC_LIST}) | |||
| target_link_libraries(_mindspore_serving PRIVATE -Wl,--whole-archive serving_ut_common -Wl,--no-whole-archive) | |||
| target_link_libraries(_mindspore_serving PRIVATE "${PYTHON_LIBRARIES}") | |||
| target_include_directories(_mindspore_serving PRIVATE ${pybind11_INCLUDE_DIRS}) | |||
| target_link_libraries(_mindspore_serving PRIVATE mindspore_serving::event mindspore_serving::event_pthreads) | |||
| target_link_libraries(_mindspore_serving PRIVATE ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF} pthread mindspore::glog) | |||
| target_link_libraries(_mindspore_serving PRIVATE ${SECUREC_LIBRARY}) | |||
| # disable auto rpath | |||
| set_target_properties(_mindspore_serving PROPERTIES SKIP_BUILD_RPATH TRUE RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||
| # copy libevent lib | |||
| file(GLOB_RECURSE LIBEVENT_LIB_LIST ${libevent_LIBPATH}/libevent* libevent_LIBPATH}/libevent_pthreads*) | |||
| file(COPY ${LIBEVENT_LIB_LIST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) | |||
| # copy glog lib | |||
| file(GLOB_RECURSE GLOG_LIB_LIST ${glog_LIBPATH}/libglog*) | |||
| file(COPY ${GLOG_LIB_LIST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) | |||
| set_target_properties(_mindspore_serving PROPERTIES SKIP_BUILD_RPATH TRUE) | |||
| @@ -1 +0,0 @@ | |||
| ../../../../mindspore_serving/proto/ | |||
| @@ -14,17 +14,21 @@ | |||
| # limitations under the License. | |||
| # ============================================================================ | |||
| set -e | |||
| BASEPATH=$(cd "$(dirname "$0")"; pwd) | |||
| BASEPATH=$( | |||
| cd "$(dirname "$0")" | |||
| pwd | |||
| ) | |||
| PROJECT_PATH=${BASEPATH}/../../.. | |||
| if [ $BUILD_PATH ];then | |||
| if [ $BUILD_PATH ]; then | |||
| echo "BUILD_PATH = $BUILD_PATH" | |||
| else | |||
| BUILD_PATH=${PROJECT_PATH}/build | |||
| echo "BUILD_PATH = $BUILD_PATH" | |||
| fi | |||
| cd ${BUILD_PATH}/mindspore_serving/tests/ut/python | |||
| mkdir -p mindspore_serving | |||
| rm -rf mindspore_serving/master mindspore_serving/worker mindspore_serving/client mindspore_serving/*.py | |||
| rm -rf mindspore_serving | |||
| mkdir -p mindspore_serving/proto | |||
| cp ../mindspore_serving/proto/ms_service*.py mindspore_serving/proto/ | |||
| cp _mindspore_serving*.so mindspore_serving/ | |||
| cp -r ${PROJECT_PATH}/mindspore_serving/master mindspore_serving/ | |||
| cp -r ${PROJECT_PATH}/mindspore_serving/worker mindspore_serving/ | |||
| @@ -32,6 +36,7 @@ cp -r ${PROJECT_PATH}/mindspore_serving/client mindspore_serving/ | |||
| cp ${PROJECT_PATH}/mindspore_serving/*.py mindspore_serving/ | |||
| export PYTHONPATH=${BUILD_PATH}/mindspore_serving/tests/ut/python:${PROJECT_PATH}/tests/ut/python:$PYTHONPATH | |||
| export LD_LIBRARY_PATH=${BUILD_PATH}/mindspore_serving/tests/ut/lib:${LD_LIBRARY_PATH} | |||
| export LD_LIBRARY_PATH=${BUILD_PATH}/mindspore_serving/tests/ut/python:${LD_LIBRARY_PATH} | |||
| echo "PYTHONPATH=$PYTHONPATH" | |||
| @@ -40,7 +45,7 @@ unset http_proxy | |||
| unset https_proxy | |||
| if [ $# -gt 0 ]; then | |||
| pytest -v ${PROJECT_PATH}/tests/ut/python/tests/$1 | |||
| pytest -v ${PROJECT_PATH}/tests/ut/python/tests/ -k $1 | |||
| else | |||
| pytest -v ${PROJECT_PATH}/tests/ut/python/tests | |||
| fi | |||
| @@ -50,11 +50,98 @@ def test_master_worker_client_success(): | |||
| instance_count = 3 | |||
| instances, y_data_list = create_multi_instances_fp32(instance_count) | |||
| result = client.infer(instances) | |||
| client.close() # avoid affecting the next use case | |||
| print(result) | |||
| check_result(result, y_data_list) | |||
| @serving_test | |||
| def test_master_worker_client_multi_times_success(): | |||
| base = ServingTestBase() | |||
| base.init_servable(1, "add_servable_config.py") | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name, 0) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_common") as client: | |||
| for instance_count in range(1, 5): | |||
| instances, y_data_list = create_multi_instances_fp32(instance_count) | |||
| result = client.infer(instances) | |||
| check_result(result, y_data_list) | |||
| @serving_test | |||
| def test_master_worker_client_async_success(): | |||
| base = ServingTestBase() | |||
| base.init_servable(1, "add_servable_config.py") | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name, 0) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| client = Client("localhost", 5500, base.servable_name, "add_common") | |||
| instance_count = 3 | |||
| instances, y_data_list = create_multi_instances_fp32(instance_count) | |||
| result_future = client.infer_async(instances) | |||
| result = result_future.result() | |||
| client.close() # avoid affecting the next use case | |||
| print(result) | |||
| check_result(result, y_data_list) | |||
| @serving_test | |||
| def test_master_worker_client_async_multi_times_success(): | |||
| base = ServingTestBase() | |||
| base.init_servable(1, "add_servable_config.py") | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name, 0) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_common") as client: | |||
| for instance_count in range(1, 5): | |||
| instances, y_data_list = create_multi_instances_fp32(instance_count) | |||
| result_future = client.infer_async(instances) | |||
| result = result_future.result() | |||
| check_result(result, y_data_list) | |||
| @serving_test | |||
| def test_master_worker_client_start_grpc_twice_failed(): | |||
| base = ServingTestBase() | |||
| base.init_servable(1, "add_servable_config.py") | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name, 0) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| try: | |||
| master.start_grpc_server("0.0.0.0", 4500) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert "Serving Error: Serving gRPC server is already running" in str(e) | |||
| @serving_test | |||
| def test_master_worker_client_start_master_grpc_twice_failed(): | |||
| base = ServingTestBase() | |||
| base.init_servable(1, "add_servable_config.py") | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name, 0) | |||
| master.start_master_server("0.0.0.0", 5500) | |||
| try: | |||
| master.start_master_server("0.0.0.0", 4500) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert "Serving Error: Master server is already running" in str(e) | |||
| @serving_test | |||
| def test_master_worker_client_start_restful_server_twice_failed(): | |||
| base = ServingTestBase() | |||
| base.init_servable(1, "add_servable_config.py") | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name, 0) | |||
| master.start_restful_server("0.0.0.0", 5500) | |||
| try: | |||
| master.start_restful_server("0.0.0.0", 4500) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert "Serving Error: RESTful server is already running" in str(e) | |||
| # test servable_config.py with client | |||
| servable_config_import = r""" | |||
| import numpy as np | |||
| @@ -87,7 +174,7 @@ def add_cast(x1, x2): | |||
| @serving_test | |||
| def no_test_master_worker_client_servable_content_success(): | |||
| def test_master_worker_client_servable_content_success(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| @@ -99,22 +186,21 @@ def no_test_master_worker_client_servable_content_success(): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| client = Client("localhost", 5500, base.servable_name, "add_common") | |||
| instance_count = 3 | |||
| instances, y_data_list = create_multi_instances_fp32(instance_count) | |||
| result = client.infer(instances) | |||
| with Client("localhost", 5500, base.servable_name, "add_common") as client: | |||
| result = client.infer(instances) | |||
| print(result) | |||
| check_result(result, y_data_list) | |||
| @serving_test | |||
| def no_test_master_worker_client_preprocess_outputs_count_not_match_failed(): | |||
| def test_master_worker_client_preprocess_outputs_count_not_match_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += r""" | |||
| def add_trans_datatype(x1, x2): | |||
| return x1.astype(np.float32) | |||
| @@ -124,14 +210,178 @@ def add_cast(x1, x2): | |||
| y = register.call_servable(x1, x2) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| instance_count = 3 | |||
| instances, _ = create_multi_instances_fp32(instance_count) | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_cast") as client: | |||
| result = client.infer(instances) | |||
| print(result) | |||
| assert "Preprocess Failed" in str(result[0]["error"]) | |||
| @serving_test | |||
| def test_master_worker_client_postprocess_outputs_count_not_match_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += r""" | |||
| def add_trans_datatype(x1, x2): | |||
| return x1.astype(np.float32) | |||
| @register.register_method(output_names=["y"]) | |||
| def add_cast(x1, x2): | |||
| y = register.call_servable(x1, x2) | |||
| y, y2 = register.call_postprocess(add_trans_datatype, y, x2) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| client = Client("localhost", 5500, base.servable_name, "add_cast") | |||
| instance_count = 3 | |||
| instances, _ = create_multi_instances_fp32(instance_count) | |||
| result = client.infer(instances) | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_cast") as client: | |||
| result = client.infer(instances) | |||
| print(result) | |||
| assert "Servable stopped" in str(result[0]["error"]) | |||
| assert "Postprocess Failed" in str(result[0]["error"]) | |||
| @serving_test | |||
| def test_master_worker_client_str_input_output_success(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += r""" | |||
| index = 0 | |||
| list_str = ["123", "456", "789"] | |||
| def postprocess(y, label): | |||
| global index | |||
| text = list_str[index] | |||
| index = (index + 1) if index + 1 < len(list_str) else 0 | |||
| return y.astype(np.int32), label + text | |||
| @register.register_method(output_names=["y", "text"]) | |||
| def add_cast(x1, x2, label): | |||
| y = register.call_servable(x1, x2) | |||
| y, text = register.call_postprocess(postprocess, y, label) | |||
| return y, text | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| instance_count = 3 | |||
| instances, _ = create_multi_instances_fp32(instance_count) | |||
| list_str = ["ABC", "DEF", "HIJ"] | |||
| for i, instance in enumerate(instances): | |||
| instance["label"] = list_str[i] | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_cast") as client: | |||
| result = client.infer(instances) | |||
| assert result[0]["text"] == "ABC123" | |||
| assert result[1]["text"] == "DEF456" | |||
| assert result[2]["text"] == "HIJ789" | |||
| @serving_test | |||
| def test_master_worker_client_bool_input_output_success(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += r""" | |||
| def postprocess(y, bool_val): | |||
| return y.astype(np.int32), not bool_val | |||
| @register.register_method(output_names=["y", "value"]) | |||
| def add_cast(x1, x2, bool_val): | |||
| y = register.call_servable(x1, x2) | |||
| y, value = register.call_postprocess(postprocess, y, bool_val) | |||
| return y, value | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| instance_count = 3 | |||
| instances, _ = create_multi_instances_fp32(instance_count) | |||
| for i, instance in enumerate(instances): | |||
| instance["bool_val"] = (i % 2 == 0) | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_cast") as client: | |||
| result = client.infer(instances) | |||
| assert not result[0]["value"] | |||
| assert result[1]["value"] | |||
| assert not result[2]["value"] | |||
| @serving_test | |||
| def test_master_worker_client_int_input_output_success(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += r""" | |||
| def postprocess(y, int_val): | |||
| return y.astype(np.int32), int_val + 1 | |||
| @register.register_method(output_names=["y", "value"]) | |||
| def add_cast(x1, x2, int_val): | |||
| y = register.call_servable(x1, x2) | |||
| y, value = register.call_postprocess(postprocess, y, int_val) | |||
| return y, value | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| instance_count = 3 | |||
| instances, _ = create_multi_instances_fp32(instance_count) | |||
| for i, instance in enumerate(instances): | |||
| instance["int_val"] = i * 2 | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_cast") as client: | |||
| result = client.infer(instances) | |||
| assert result[0]["value"] == 1 | |||
| assert result[1]["value"] == 3 | |||
| assert result[2]["value"] == 5 | |||
| @serving_test | |||
| def test_master_worker_client_float_input_output_success(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += r""" | |||
| def postprocess(y, float_val): | |||
| return y.astype(np.int32), float_val + 1 | |||
| @register.register_method(output_names=["y", "value"]) | |||
| def add_cast(x1, x2, float_val): | |||
| y = register.call_servable(x1, x2) | |||
| y, value = register.call_postprocess(postprocess, y, float_val) | |||
| return y, value | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| master.start_grpc_server("0.0.0.0", 5500) | |||
| # Client | |||
| instance_count = 3 | |||
| instances, _ = create_multi_instances_fp32(instance_count) | |||
| for i, instance in enumerate(instances): | |||
| instance["float_val"] = i * 2.2 | |||
| # Client, use with avoid affecting the next use case | |||
| with Client("localhost", 5500, base.servable_name, "add_cast") as client: | |||
| result = client.infer(instances) | |||
| assert result[0]["value"] == 1 | |||
| assert result[1]["value"] == (2.2 + 1) | |||
| assert result[2]["value"] == (4.4 + 1) | |||
| @@ -129,7 +129,7 @@ def add_trans_datatype(x1, x2, x3): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"function add_trans_datatype input args count 3 not match registered in method count 2" in str(e) | |||
| assert "function add_trans_datatype input args count 3 not match registered in method count 2" in str(e) | |||
| @serving_test | |||
| @@ -149,7 +149,7 @@ def add_trans_datatype(x1): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"function add_trans_datatype input args count 1 not match registered in method count 2" in str(e) | |||
| assert "function add_trans_datatype input args count 1 not match registered in method count 2" in str(e) | |||
| @serving_test | |||
| @@ -174,7 +174,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"function add_trans_datatype_back input args count 2 not match registered in method count 1" in str(e) | |||
| assert "function add_trans_datatype_back input args count 2 not match registered in method count 1" in str(e) | |||
| # preprocess order error | |||
| @@ -196,7 +196,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_servable should be invoked after call_preprocess" in str(e) | |||
| assert "call_servable should be invoked after call_preprocess" in str(e) | |||
| @serving_test | |||
| @@ -218,7 +218,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess" in str(e) | |||
| assert "call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess" in str(e) | |||
| @serving_test | |||
| @@ -240,7 +240,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess" in str(e) | |||
| assert "call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess" in str(e) | |||
| # preprocess_pipeline order error | |||
| @@ -262,7 +262,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_servable should be invoked after call_preprocess_pipeline" in str(e) | |||
| assert "call_servable should be invoked after call_preprocess_pipeline" in str(e) | |||
| @serving_test | |||
| @@ -284,7 +284,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess_pipeline" \ | |||
| assert "call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess_pipeline" \ | |||
| in str(e) | |||
| @@ -307,7 +307,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess_pipeline" \ | |||
| assert "call_postprocess or call_postprocess_pipeline should be invoked after call_preprocess_pipeline" \ | |||
| in str(e) | |||
| @@ -331,7 +331,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_preprocess or call_preprocess_pipeline should not be invoked more than once" in str(e) | |||
| assert "call_preprocess or call_preprocess_pipeline should not be invoked more than once" in str(e) | |||
| @serving_test | |||
| @@ -353,7 +353,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_preprocess or call_preprocess_pipeline should not be invoked more than once" in str(e) | |||
| assert "call_preprocess or call_preprocess_pipeline should not be invoked more than once" in str(e) | |||
| @serving_test | |||
| @@ -375,7 +375,80 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_preprocess or call_preprocess_pipeline should not be invoked more than once" in str(e) | |||
| assert "call_preprocess or call_preprocess_pipeline should not be invoked more than once" in str(e) | |||
| # repeat postprocess | |||
| @serving_test | |||
| def test_register_method_postprocess_twice_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += servable_config_preprocess_cast | |||
| servable_content += r""" | |||
| def postprocess(y): | |||
| return y.astype(np.int32) | |||
| @register.register_method(output_names=["y"]) | |||
| def add_cast(x1, x2): | |||
| y = register.call_servable(x1, x2) | |||
| y = register.call_postprocess(postprocess, y) | |||
| y = register.call_postprocess(postprocess, y) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| try: | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert "call_postprocess or call_postprocess_pipeline should not be invoked more than once" in str(e) | |||
| @serving_test | |||
| def test_register_method_postprocess_twice2_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += servable_config_preprocess_cast | |||
| servable_content += r""" | |||
| def postprocess(y): | |||
| return y.astype(np.int32) | |||
| @register.register_method(output_names=["y"]) | |||
| def add_cast(x1, x2): | |||
| y = register.call_servable(x1, x2) | |||
| y = register.call_postprocess_pipeline(postprocess, y) | |||
| y = register.call_postprocess(postprocess, y) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| try: | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert "call_postprocess or call_postprocess_pipeline should not be invoked more than once" in str(e) | |||
| @serving_test | |||
| def test_register_method_postprocess_pipeline_twice_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += servable_config_preprocess_cast | |||
| servable_content += r""" | |||
| def postprocess(y): | |||
| return y.astype(np.int32) | |||
| @register.register_method(output_names=["y"]) | |||
| def add_cast(x1, x2): | |||
| y = register.call_servable(x1, x2) | |||
| y = register.call_postprocess_pipeline(postprocess, y) | |||
| y = register.call_postprocess_pipeline(postprocess, y) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| try: | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert "call_postprocess or call_postprocess_pipeline should not be invoked more than once" in str(e) | |||
| # call servable repeat | |||
| @@ -398,7 +471,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_servable should not be invoked more than once" in str(e) | |||
| assert "call_servable should not be invoked more than once" in str(e) | |||
| @serving_test | |||
| @@ -419,7 +492,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_postprocess or call_postprocess_pipeline should be invoked after call_servable" in str(e) | |||
| assert "call_postprocess or call_postprocess_pipeline should be invoked after call_servable" in str(e) | |||
| @serving_test | |||
| @@ -440,7 +513,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"call_postprocess or call_postprocess_pipeline should be invoked after call_servable" in str(e) | |||
| assert "call_postprocess or call_postprocess_pipeline should be invoked after call_servable" in str(e) | |||
| @serving_test | |||
| @@ -687,7 +760,7 @@ def add_cast(x1, x2): | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert f"Method add_cast has been registered more than once." in str(e) | |||
| assert "Method add_cast has been registered more than once." in str(e) | |||
| @serving_test | |||
| @@ -728,3 +801,68 @@ def add_cast(x1, *x2): | |||
| assert False | |||
| except RuntimeError as e: | |||
| assert "'add_cast' input x2 cannot be VAR_POSITIONAL !" in str(e) | |||
| @serving_test | |||
| def test_register_method_call_preprocess_invalid_input_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += servable_config_preprocess_cast | |||
| servable_content += r""" | |||
| @register.register_method(output_names=["y"]) | |||
| def add_cast(x1, x2): | |||
| x1, x2 = register.call_preprocess(add_trans_datatype, x1, np.ones([2,2])) | |||
| y = register.call_servable(x1, x2) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| try: | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except AttributeError as e: | |||
| assert "'numpy.ndarray' object has no attribute 'as_pair'" in str(e) | |||
| @serving_test | |||
| def test_register_method_call_servable_invalid_input_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += servable_config_preprocess_cast | |||
| servable_content += r""" | |||
| @register.register_method(output_names=["y"]) | |||
| def add_cast(x1, x2): | |||
| y = register.call_servable(x1, np.ones([2,2])) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| try: | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except AttributeError as e: | |||
| assert "'numpy.ndarray' object has no attribute 'as_pair'" in str(e) | |||
| @serving_test | |||
| def test_register_method_call_postprocess_invalid_input_failed(): | |||
| base = ServingTestBase() | |||
| servable_content = servable_config_import | |||
| servable_content += servable_config_declare_servable | |||
| servable_content += servable_config_preprocess_cast | |||
| servable_content += r""" | |||
| def postprocess(y, data): | |||
| return y.astype(np.int32) | |||
| @register.register_method(output_names=["y"]) | |||
| def add_cast(x1, x2): | |||
| y = register.call_servable(x1, x2) | |||
| y = register.call_postprocess(postprocess, y, np.ones([2,2])) | |||
| return y | |||
| """ | |||
| base.init_servable_with_servable_config(1, servable_content) | |||
| try: | |||
| worker.start_servable_in_master(base.servable_dir, base.servable_name) | |||
| assert False | |||
| except AttributeError as e: | |||
| assert "'numpy.ndarray' object has no attribute 'as_pair'" in str(e) | |||