This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch refactor-s0
in repository https://gitbox.apache.org/repos/asf/tvm.git

commit f29e76f9f43d0eb73408404afaf82726df36be12
Author: tqchen <[email protected]>
AuthorDate: Sat Sep 14 17:28:11 2024 -0400

    [FFI] Formalize SafeCall handling
    
    Move all dll calls into c api.
    Leverage the TLS for safecall exception propagation
    so it works better for codegen.
---
 ffi/CMakeLists.txt                                |  12 +-
 ffi/include/tvm/ffi/base_details.h                |  18 +
 ffi/include/tvm/ffi/c_api.h                       | 111 ++-
 ffi/include/tvm/ffi/container/optional.h          |   2 +
 ffi/include/tvm/ffi/error.h                       |  38 +-
 ffi/include/tvm/ffi/function.h                    |  78 ++-
 ffi/include/tvm/ffi/object.h                      |  57 +-
 ffi/include/tvm/ffi/string.h                      |   2 +-
 ffi/include/tvm/ffi/type_traits.h                 |   6 +-
 ffi/scripts/run_tests.sh                          |   5 +-
 ffi/src/ffi/function.cc                           |  63 ++
 ffi/src/ffi/object.cc                             |  25 +-
 ffi/src/ffi/traceback.cc                          |  20 +-
 ffi/tests/{example => backup_cpp}/CMakeLists.txt  |   5 +-
 ffi/tests/{cpp => backup_cpp}/test_any.cc         | 157 ++---
 ffi/tests/{cpp => backup_cpp}/test_any_view.cc    | 163 ++---
 ffi/tests/{cpp => backup_cpp}/test_dict.cc        |  21 +-
 ffi/tests/{cpp => backup_cpp}/test_func.cc        |  58 +-
 ffi/tests/{cpp => backup_cpp}/test_list.cc        |  69 +-
 ffi/tests/{cpp => backup_cpp}/test_ref.cc         |  63 +-
 ffi/tests/{cpp => backup_cpp}/test_str.cc         |  12 +-
 ffi/tests/{cpp => backup_cpp}/test_type_dyn.cc    |  15 +-
 ffi/tests/{cpp => backup_cpp}/test_type_static.cc |  17 +-
 ffi/tests/cpp/CMakeLists.txt                      |   4 +-
 ffi/tests/cpp/test_any.cc                         | 794 +++++-----------------
 ffi/tests/{example => cpp}/test_array.cc          |   0
 ffi/tests/{example => cpp}/test_c_ffi_abi.cc      |   0
 ffi/tests/{example => cpp}/test_error.cc          |   0
 ffi/tests/{example => cpp}/test_function.cc       |   0
 ffi/tests/{example => cpp}/test_map.cc            |   0
 ffi/tests/{example => cpp}/test_object.cc         |   2 +-
 ffi/tests/{example => cpp}/test_optional.cc       |   0
 ffi/tests/{example => cpp}/test_string.cc         |   0
 ffi/tests/{example => cpp}/testing_object.h       |   0
 ffi/tests/example/test_any.cc                     | 166 -----
 35 files changed, 739 insertions(+), 1244 deletions(-)

diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt
index 89429d253b..b327c6667a 100644
--- a/ffi/CMakeLists.txt
+++ b/ffi/CMakeLists.txt
@@ -20,7 +20,6 @@ option(TVM_FFI_BUILD_REGISTRY
 )
 option(TVM_FFI_USE_LIBBRACKTRACE "Enable libbacktrace" ON)
 option(TVM_FFI_BACKTRACE_ON_SEGFAULT "Set signal handler to print traceback on 
segfault" ON)
-option(TVM_FFI_ALLOW_DYN_TYPE "Wehthert to allow dynamic features" ON)
 
 include(cmake/Utils/CxxWarning.cmake)
 include(cmake/Utils/Sanitizer.cmake)
@@ -39,20 +38,13 @@ target_link_libraries(tvm_ffi INTERFACE dlpack_header)
 target_compile_features(tvm_ffi INTERFACE cxx_std_17)
 target_include_directories(tvm_ffi INTERFACE 
"${CMAKE_CURRENT_SOURCE_DIR}/include")
 
-if (TVM_FFI_ALLOW_DYN_TYPE)
-  message(STATUS "Setting C++ macro TVM_FFI_ALLOW_DYN_TYPE - 1")
-  target_compile_definitions(tvm_ffi INTERFACE TVM_FFI_ALLOW_DYN_TYPE=1)
-else()
-  message(STATUS "Setting C++ macro TVM_FFI_ALLOW_DYN_TYPES - 0")
-  target_compile_definitions(tvm_ffi INTERFACE TVM_FFI_ALLOW_DYN_TYPE=0)
-endif()
-
 ########## Target: `tvm_ffi_registry` ##########
 
 if (TVM_FFI_BUILD_REGISTRY)
   add_library(tvm_ffi_registry_objs OBJECT
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/traceback.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/object.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/function.cc"
   )
   set_target_properties(
     tvm_ffi_registry_objs PROPERTIES
@@ -101,6 +93,6 @@ if (${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
     enable_testing()
     message(STATUS "Enable Testing")
     include(cmake/Utils/AddGoogleTest.cmake)
-    add_subdirectory(tests/example/)
+    add_subdirectory(tests/cpp/)
   endif()
 endif ()
diff --git a/ffi/include/tvm/ffi/base_details.h 
b/ffi/include/tvm/ffi/base_details.h
index cf825fdea7..a779eb89ea 100644
--- a/ffi/include/tvm/ffi/base_details.h
+++ b/ffi/include/tvm/ffi/base_details.h
@@ -82,6 +82,23 @@
   TypeName& operator=(const TypeName& other) = default;       \
   TypeName& operator=(TypeName&& other) = default;
 
+/**
+ * \brief marks the begining of a C call that logs exception
+ */
+#define TVM_FFI_LOG_EXCEPTION_CALL_BEGIN() \
+  try {                                    \
+  (void)0
+
+/*!
+ * \brief Marks the end of a C call that logs exception
+ */
+#define TVM_FFI_LOG_EXCEPTION_CALL_END(Name)                                   
           \
+  }                                                                            
           \
+  catch (const std::exception& err) {                                          
           \
+    std::cout << "Exception caught during " << #Name << ":\n" << err.what() << 
std::endl; \
+    throw err;                                                                 
           \
+  }
+
 namespace tvm {
 namespace ffi {
 namespace details {
@@ -221,6 +238,7 @@ TVM_FFI_INLINE uint64_t StableHashBytes(const char* data, 
size_t size) {
   }
   return result;
 }
+
 }  // namespace details
 }  // namespace ffi
 }  // namespace tvm
diff --git a/ffi/include/tvm/ffi/c_api.h b/ffi/include/tvm/ffi/c_api.h
index 20579bbe06..e6d3449ac3 100644
--- a/ffi/include/tvm/ffi/c_api.h
+++ b/ffi/include/tvm/ffi/c_api.h
@@ -20,8 +20,6 @@
 /*
  * \file tvm/ffi/c_api.h
  * \brief This file defines the C convention of the FFI convention
- *
- *  Only use the APIs when TVM_FFI_ALLOW_DYN_TYPE is set to true
  */
 #ifndef TVM_FFI_C_API_H_
 #define TVM_FFI_C_API_H_
@@ -29,14 +27,6 @@
 #include <dlpack/dlpack.h>
 #include <stdint.h>
 
-/*!
- * \brief Macro defines whether we enable dynamic runtime features.
- * \note Turning this one would mean that we need to link 
tvm_ffi_registry_shared
- */
-#ifndef TVM_FFI_ALLOW_DYN_TYPE
-#define TVM_FFI_ALLOW_DYN_TYPE 1
-#endif
-
 #if !defined(TVM_FFI_DLL) && defined(__EMSCRIPTEN__)
 #include <emscripten/emscripten.h>
 #define TVM_FFI_DLL EMSCRIPTEN_KEEPALIVE
@@ -92,9 +82,12 @@ typedef enum {
 } TVMFFITypeIndex;
 #endif
 
+/*! \brief Handle to Object from C API's pov */
+typedef void* TVMFFIObjectHandle;
+
 /*!
  * \brief C-based type of all FFI object types that allocates on heap.
- * \note TVMFFIObject and TVMFFIAny share the common type_index_ header
+ * \note TVMFFIObject and TVMFFIAny share the common type_index header
  */
 typedef struct TVMFFIObject {
   /*!
@@ -164,6 +157,9 @@ typedef struct {
   const int32_t* type_acenstors;
 } TVMFFITypeInfo;
 
+//------------------------------------------------------------
+// Section: User APIs to interact with the FFI
+//------------------------------------------------------------
 /*!
  * \brief Type that defines C-style safe call convention
  *
@@ -176,11 +172,102 @@ typedef struct {
  *
  * \return The call return 0 if call is successful.
  *  It returns non-zero value if there is an error.
- *  When error happens, the exception object will be stored in result.
+ *
+ *  Possible return error of the API functions:
+ *  * 0: success
+ *  * -1: error happens, can be retrieved by TVMFFIGetLastError
+ *  * -2: a frontend error occurred and recorded in the frontend.
+ *
+ * \note We decided to leverage TVMFFIGetLastError and TVMFFISetLastError
+ *  for C function error propagation. This design choice, while
+ *  introducing a dependency for TLS runtime, simplifies error
+ *  propgation in chains of calls in compiler codegen.
+ *  As we do not need to propagate error through argument but simply
+ *  set them in the runtime environment.
  */
 typedef int (*TVMFFISafeCallType)(void* func, int32_t num_args, const 
TVMFFIAny* args,
                                   TVMFFIAny* result);
 
+/*!
+ * \brief Free an object handle by decreasing reference
+ * \param obj The object handle.
+ * \note Internally we decrease the reference counter of the object.
+ *       The object will be freed when every reference to the object are 
removed.
+ * \return 0 when success, nonzero when failure happens
+ */
+TVM_FFI_DLL int TVMFFIObjectFree(TVMFFIObjectHandle obj);
+
+/*!
+ * \brief Move the last error from the environment to result.
+ *
+ * \param result The result error.
+ *
+ * \note This function clears the error stored in the TLS.
+ */
+TVM_FFI_DLL void TVMFFIMoveFromLastError(TVMFFIAny* result);
+
+/*!
+ * \brief Set the last error in TLS, which can be fetched by 
TVMFFIGetLastError.
+ *
+ * \param error_view The error in format of any view.
+ *        It can be an object, or simply a raw c_str.
+ * \note
+ */
+TVM_FFI_DLL void TVMFFISetLastError(const TVMFFIAny* error_view);
+
+//------------------------------------------------------------
+// Section: Backend noexcept functions for internal use
+//
+// These functions are used internally and do not throw error
+// instead the error will be logged and abort the process
+// These are function are being called in startup or exit time
+// so exception handling do not apply
+//------------------------------------------------------------
+/*!
+ * \brief Get stack traceback in a string.
+ * \param filaname The current file name.
+ * \param func The current function
+ * \param lineno The current line number
+ * \return The traceback string
+ *
+ * \note filename func and lino are only used as a backup info, most cases 
they are not needed.
+ *  The return value is set to const char* to be more compatible across dll 
boundaries.
+ */
+TVM_FFI_DLL const char* TVMFFITraceback(const char* filename, const char* 
func, int lineno);
+
+/*!
+ * \brief Initialize the type info during runtime.
+ *
+ *  When the function is first time called for a type,
+ *  it will register the type to the type table in the runtime.
+ *
+ *  If the static_tindex is non-negative, the function will
+ *  allocate a runtime type index.
+ *  Otherwise, we will populate the type table and return the static index.
+ *
+ * \param type_key The type key.
+ * \param static_type_index Static type index if any, can be -1, which means 
this is a dynamic index
+ * \param num_child_slots Number of slots reserved for its children.
+ * \param child_slots_can_overflow Whether to allow child to overflow the 
slots.
+ * \param parent_type_index Parent type index, pass in -1 if it is root.
+ * \param result The output type index
+ *
+ * \return 0 if success, -1 if error occured
+ */
+TVM_FFI_DLL int32_t TVMFFIGetOrAllocTypeIndex(const char* type_key, int32_t 
static_type_index,
+                                              int32_t type_depth, int32_t 
num_child_slots,
+                                              int32_t child_slots_can_overflow,
+                                              int32_t parent_type_index);
+/*!
+ * \brief Get dynamic type info by type index.
+ *
+ * \param type_index The type index
+ * \param result The output type information
+ *
+ * \return 0 when success, nonzero when failure happens
+ */
+TVM_FFI_DLL const TVMFFITypeInfo* TVMFFIGetTypeInfo(int32_t type_index);
+
 #ifdef __cplusplus
 }  // TVM_FFI_EXTERN_C
 #endif
diff --git a/ffi/include/tvm/ffi/container/optional.h 
b/ffi/include/tvm/ffi/container/optional.h
index 5f08db0a5b..a35d4f8ae2 100644
--- a/ffi/include/tvm/ffi/container/optional.h
+++ b/ffi/include/tvm/ffi/container/optional.h
@@ -28,6 +28,8 @@
 #include <tvm/ffi/object.h>
 
 #include <optional>
+#include <string>
+#include <utility>
 
 namespace tvm {
 namespace ffi {
diff --git a/ffi/include/tvm/ffi/error.h b/ffi/include/tvm/ffi/error.h
index 1f703f1fac..aeed40f243 100644
--- a/ffi/include/tvm/ffi/error.h
+++ b/ffi/include/tvm/ffi/error.h
@@ -53,6 +53,17 @@
 namespace tvm {
 namespace ffi {
 
+/*!
+ * \brief Error already set in frontend env.
+ *
+ *  This error can be thrown by EnvCheckSignals to indicate
+ *  that there is an error set in the frontend environment(e.g.
+ *  python interpreter). The TVM FFI should catch this error
+ *  and return a proper code tell the frontend caller about
+ *  this fact.
+ */
+struct EnvErrorAlreadySet : public std::exception {};
+
 /*!
  * \brief Error object class.
  */
@@ -128,33 +139,8 @@ class ErrorBuilder {
   bool log_before_throw_;
 };
 
-// Code section that depends on dynamic components that requires linking
-#if TVM_FFI_ALLOW_DYN_TYPE
-/*!
- * \brief Get stack traceback in a string.
- * \param filaname The current file name.
- * \param func The current function
- * \param lineno The current line number
- * \return The traceback string
- *
- * \note filename func and lino are only used as a backup info, most cases 
they are not needed.
- *  The return value is set to const char* to be more compatible across dll 
boundaries.
- */
-TVM_FFI_DLL const char* Traceback(const char* filename, const char* func, int 
lineno);
 // define traceback here as call into traceback function
-#define TVM_FFI_TRACEBACK_HERE ::tvm::ffi::details::Traceback(__FILE__, 
TVM_FFI_FUNC_SIG, __LINE__)
-
-#else
-// simple traceback when allow dyn type is set to false
-inline std::string SimpleTraceback(const char* filename, const char* func, int 
lineno) {
-  std::ostringstream traceback;
-  // python style backtrace
-  traceback << "  " << filename << ", line " << lineno << ", in " << func << 
'\n';
-  return traceback.str();
-}
-#define TVM_FFI_TRACEBACK_HERE \
-  ::tvm::ffi::details::SimpleTraceback(__FILE__, TVM_FFI_FUNC_SIG, __LINE__)
-#endif  // TVM_FFI_ALLOW_DYN_TYPE
+#define TVM_FFI_TRACEBACK_HERE TVMFFITraceback(__FILE__, TVM_FFI_FUNC_SIG, 
__LINE__)
 }  // namespace details
 
 /*!
diff --git a/ffi/include/tvm/ffi/function.h b/ffi/include/tvm/ffi/function.h
index e2adee03c0..cb4cb2b937 100644
--- a/ffi/include/tvm/ffi/function.h
+++ b/ffi/include/tvm/ffi/function.h
@@ -29,12 +29,61 @@
 #include <tvm/ffi/error.h>
 #include <tvm/ffi/function_details.h>
 
+#include <functional>
 #include <string>
 #include <utility>
 
 namespace tvm {
 namespace ffi {
 
+/**
+ * Helper macro to construct a safe call
+ *
+ * \brief Marks the begining of the safe call that catches exception explicitly
+ *
+ */
+#define TVM_FFI_SAFE_CALL_BEGIN() \
+  try {                           \
+  (void)0
+
+/*!
+ * \brief Marks the end of safe call.
+ */
+#define TVM_FFI_SAFE_CALL_END()                                                
     \
+  return 0;                                                                    
     \
+  }                                                                            
     \
+  catch (const ::tvm::ffi::Error& err) {                                       
     \
+    ::tvm::ffi::AnyView error_as_any(err);                                     
     \
+    TVMFFISetLastError(reinterpret_cast<TVMFFIAny*>(&error_as_any));           
     \
+    return -1;                                                                 
     \
+  }                                                                            
     \
+  catch (const ::tvm::ffi::EnvErrorAlreadySet&) {                              
     \
+    return -2;                                                                 
     \
+  }                                                                            
     \
+  catch (const std::exception& err) {                                          
     \
+    ::tvm::ffi::Any error_as_any(tvm::ffi::Error("InternalError", err.what(), 
"")); \
+    TVMFFISetLastError(reinterpret_cast<TVMFFIAny*>(&error_as_any));           
     \
+    return -1;                                                                 
     \
+  }                                                                            
     \
+  TVM_FFI_UNREACHABLE()
+
+#define TVM_FFI_CHECK_SAFE_CALL(func)                                          
        \
+  {                                                                            
        \
+    int ret_code = (func);                                                     
        \
+    if (ret_code != 0) {                                                       
        \
+      if (ret_code == -2) {                                                    
        \
+        throw ::tvm::ffi::EnvErrorAlreadySet();                                
        \
+      }                                                                        
        \
+      Any error_any;                                                           
        \
+      TVMFFIMoveFromLastError(reinterpret_cast<TVMFFIAny*>(&error_any));       
        \
+      if (std::optional<tvm::ffi::Error> error = 
error_any.TryAs<tvm::ffi::Error>()) { \
+        throw std::move(*error);                                               
        \
+      } else {                                                                 
        \
+        TVM_FFI_THROW(RuntimeError) << "Error encountered";                    
        \
+      }                                                                        
        \
+    }                                                                          
        \
+  }
+
 /*!
  * \brief Object container class that backs ffi::Function
  * \note Do not use this function directly, use ffi::Function
@@ -61,20 +110,12 @@ class FunctionObj : public Object {
   FunctionObj() {}
 
   // Implementing safe call style
-  static int32_t SafeCall(void* func, int32_t num_args, const TVMFFIAny* args, 
TVMFFIAny* result) {
+  static int SafeCall(void* func, int32_t num_args, const TVMFFIAny* args, 
TVMFFIAny* result) {
+    TVM_FFI_SAFE_CALL_BEGIN();
     FunctionObj* self = static_cast<FunctionObj*>(func);
-    try {
-      self->call(self, num_args, reinterpret_cast<const AnyView*>(args),
-                 reinterpret_cast<Any*>(result));
-      return 0;
-    } catch (const tvm::ffi::Error& err) {
-      Any(std::move(err)).MoveToTVMFFIAny(result);
-      return 1;
-    } catch (const std::runtime_error& err) {
-      Any(tvm::ffi::Error("RuntimeError", err.what(), 
"")).MoveToTVMFFIAny(result);
-      return 1;
-    }
-    TVM_FFI_UNREACHABLE();
+    self->call(self, num_args, reinterpret_cast<const AnyView*>(args),
+               reinterpret_cast<Any*>(result));
+    TVM_FFI_SAFE_CALL_END();
   }
 
   friend class Function;
@@ -119,15 +160,8 @@ template <typename Derived>
 struct RedirectCallToSafeCall {
   static void Call(const FunctionObj* func, int32_t num_args, const AnyView* 
args, Any* rv) {
     Derived* self = static_cast<Derived*>(const_cast<FunctionObj*>(func));
-    int ret_code = self->RedirectSafeCall(num_args, reinterpret_cast<const 
TVMFFIAny*>(args),
-                                          reinterpret_cast<TVMFFIAny*>(rv));
-    if (ret_code != 0) {
-      if (std::optional<tvm::ffi::Error> err = rv->TryAs<tvm::ffi::Error>()) {
-        throw std::move(*err);
-      } else {
-        TVM_FFI_THROW(RuntimeError) << "Error encountered when calling a 
tvm::ffi::Function";
-      }
-    }
+    TVM_FFI_CHECK_SAFE_CALL(self->RedirectSafeCall(
+        num_args, reinterpret_cast<const TVMFFIAny*>(args), 
reinterpret_cast<TVMFFIAny*>(rv)));
   }
 
   static int32_t SafeCall(void* func, int32_t num_args, const TVMFFIAny* args, 
TVMFFIAny* rv) {
diff --git a/ffi/include/tvm/ffi/object.h b/ffi/include/tvm/ffi/object.h
index 07170dce8f..dbb940ab45 100644
--- a/ffi/include/tvm/ffi/object.h
+++ b/ffi/include/tvm/ffi/object.h
@@ -41,39 +41,6 @@ namespace details {
 // unsafe operations related to object
 struct ObjectUnsafe;
 
-// Code section that depends on dynamic components
-#if TVM_FFI_ALLOW_DYN_TYPE
-/*!
- * \brief Initialize the type info during runtime.
- *
- *  When the function is first time called for a type,
- *  it will register the type to the type table in the runtime.
- *
- *  If the static_tindex is non-negative, the function will
- *  allocate a runtime type index.
- *  Otherwise, we will populate the type table and return the static index.
- *
- * \param type_key The type key.
- * \param static_type_index Static type index if any, can be -1, which means 
this is a dynamic index
- * \param num_child_slots Number of slots reserved for its children.
- * \param child_slots_can_overflow Whether to allow child to overflow the 
slots.
- * \param parent_type_index Parent type index, pass in -1 if it is root.
- *
- * \return The allocated type index
- */
-TVM_FFI_DLL int32_t ObjectGetOrAllocTypeIndex(const char* type_key, int32_t 
static_type_index,
-                                              int32_t type_depth, int32_t 
num_child_slots,
-                                              bool child_slots_can_overflow,
-                                              int32_t parent_type_index);
-
-/*!
- * \brief Get Type information from type index.
- * \param type_index The type index
- * \return The type information
- */
-TVM_FFI_DLL const TypeInfo* ObjectGetTypeInfo(int32_t type_index);
-#endif  // TVM_FFI_ALLOW_DYN_TYPE
-
 /*!
  * Check if the type_index is an instance of TargetObjectType.
  *
@@ -153,13 +120,9 @@ class Object {
    * \note this operation is expensive, can be used for error reporting.
    */
   std::string GetTypeKey() const {
-#if TVM_FFI_ALLOW_DYN_TYPE
     // the function checks that the info exists
-    const TypeInfo* type_info = details::ObjectGetTypeInfo(header_.type_index);
+    const TypeInfo* type_info = TVMFFIGetTypeInfo(header_.type_index);
     return type_info->type_key;
-#else
-    return "<unknown>";
-#endif
   }
 
   // Information about the object
@@ -462,19 +425,15 @@ inline ObjectPtr<BaseType> GetObjectPtr(ObjectType* ptr);
                 "Need to set _type_child_slots when parent specifies it.")
 
 // If dynamic type is enabled, we still need to register the runtime type of 
parent
-#if TVM_FFI_ALLOW_DYN_TYPE
 #define TVM_FFI_REGISTER_STATIC_TYPE_INFO(TypeName, ParentType)                
\
   static int32_t _GetOrAllocRuntimeTypeIndex() {                               
\
-    static int32_t tindex = ::tvm::ffi::details::ObjectGetOrAllocTypeIndex(    
\
+    static int32_t tindex = TVMFFIGetOrAllocTypeIndex(                         
\
         TypeName::_type_key, TypeName::_type_index, TypeName::_type_depth,     
\
         TypeName::_type_child_slots, TypeName::_type_child_slots_can_overflow, 
\
         ParentType::_GetOrAllocRuntimeTypeIndex());                            
\
     return tindex;                                                             
\
   }                                                                            
\
   static inline int32_t _register_type_index = _GetOrAllocRuntimeTypeIndex()
-#else
-#define TVM_FFI_REGISTER_STATIC_TYPE_INFO(TypeName, ParentType)
-#endif
 
 /*!
  * \brief Helper macro to declare a object that comes with static type index.
@@ -492,11 +451,9 @@ inline ObjectPtr<BaseType> GetObjectPtr(ObjectType* ptr);
  * \param ParentType The name of the ParentType
  */
 #define TVM_FFI_DECLARE_BASE_OBJECT_INFO(TypeName, ParentType)                 
               \
-  static_assert(TVM_FFI_ALLOW_DYN_TYPE,                                        
               \
-                "Dynamic object depend on TVM_FFI_ALLOW_DYN_TYPE cd set to 
1");               \
   TVM_FFI_OBJECT_STATIC_DEFS(TypeName, ParentType);                            
               \
   static int32_t _GetOrAllocRuntimeTypeIndex() {                               
               \
-    static int32_t tindex = ::tvm::ffi::details::ObjectGetOrAllocTypeIndex(    
               \
+    static int32_t tindex = TVMFFIGetOrAllocTypeIndex(                         
               \
         TypeName::_type_key, -1, TypeName::_type_depth, 
TypeName::_type_child_slots,          \
         TypeName::_type_child_slots_can_overflow, 
ParentType::_GetOrAllocRuntimeTypeIndex()); \
     return tindex;                                                             
               \
@@ -571,15 +528,11 @@ TVM_FFI_INLINE bool IsObjectInstance(int32_t 
object_type_index) {
   if (!TargetType::_type_child_slots_can_overflow) return false;
   // Invariance: parent index is always smaller than the child.
   if (object_type_index < target_type_index) return false;
-    // Do a runtime lookup of type information
-#if TVM_FFI_ALLOW_DYN_TYPE
+  // Do a runtime lookup of type information
   // the function checks that the info exists
-  const TypeInfo* type_info = details::ObjectGetTypeInfo(object_type_index);
+  const TypeInfo* type_info = TVMFFIGetTypeInfo(object_type_index);
   return (type_info->type_depth > TargetType::_type_depth &&
           type_info->type_acenstors[TargetType::_type_depth] == 
target_type_index);
-#else
-  return false;
-#endif
 }
 /*!
  * \brief Namespace to internally manipulate object class.
diff --git a/ffi/include/tvm/ffi/string.h b/ffi/include/tvm/ffi/string.h
index 6b43829ff8..7cbed2f7e8 100644
--- a/ffi/include/tvm/ffi/string.h
+++ b/ffi/include/tvm/ffi/string.h
@@ -165,7 +165,7 @@ class String : public ObjectRef {
   template <typename T>
   String& operator=(T&& other) {
     // copy-and-swap idiom
-    String(std::forward<T>(other)).swap(*this);
+    String(std::forward<T>(other)).swap(*this);  // NOLINT(*)
     return *this;
   }
 
diff --git a/ffi/include/tvm/ffi/type_traits.h 
b/ffi/include/tvm/ffi/type_traits.h
index 68c83bc0df..a46d04ad83 100644
--- a/ffi/include/tvm/ffi/type_traits.h
+++ b/ffi/include/tvm/ffi/type_traits.h
@@ -59,12 +59,8 @@ inline std::string TypeIndex2TypeKey(int32_t type_index) {
     default: {
       TVM_FFI_ICHECK_GE(type_index, TypeIndex::kTVMFFIStaticObjectBegin)
           << "Uknown type_index=" << type_index;
-#if TVM_FFI_ALLOW_DYN_TYPE
-      const TypeInfo* type_info = details::ObjectGetTypeInfo(type_index);
+      const TypeInfo* type_info = TVMFFIGetTypeInfo(type_index);
       return type_info->type_key;
-#else
-      return "object.Object";
-#endif
     }
   }
 }
diff --git a/ffi/scripts/run_tests.sh b/ffi/scripts/run_tests.sh
index 8219afc90d..dc7e6cdc71 100755
--- a/ffi/scripts/run_tests.sh
+++ b/ffi/scripts/run_tests.sh
@@ -1,11 +1,10 @@
 #!/bin/bash
 set -euxo pipefail
 
-TVM_FFI_ALLOW_DYN_TYPE=ON
-BUILD_TYPE=Release
+BUILD_TYPE=RelWithDebugInfo
 
 rm -rf build/CMakeFiles build/CMakeCache.txt
-cmake -G Ninja -S . -B build 
-DTVM_FFI_ALLOW_DYN_TYPE=${TVM_FFI_ALLOW_DYN_TYPE} -DTVM_FFI_BUILD_TESTS=ON 
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
+cmake -G Ninja -S . -B build  -DTVM_FFI_BUILD_TESTS=ON 
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
   -DTVM_FFI_BUILD_REGISTRY=ON \
   -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
 cmake --build build --parallel 16 --clean-first --config ${BUILD_TYPE} 
--target tvm_ffi_tests
diff --git a/ffi/src/ffi/function.cc b/ffi/src/ffi/function.cc
new file mode 100644
index 0000000000..5da4e0178b
--- /dev/null
+++ b/ffi/src/ffi/function.cc
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * \file src/ffi/function.cc
+ * \brief Function call registry and safecall context
+ */
+#include <tvm/ffi/any.h>
+#include <tvm/ffi/c_api.h>
+#include <tvm/ffi/error.h>
+#include <tvm/ffi/string.h>
+
+namespace tvm {
+namespace ffi {
+
+class SafeCallContext {
+ public:
+  void SetLastError(const TVMFFIAny* error_view) {
+    last_error_ = Any(AnyView::CopyFromTVMFFIAny(error_view[0]));
+    // turn string into formal error.
+    if (std::optional<String> opt_str = last_error_.TryAs<String>()) {
+      last_error_ = ::tvm::ffi::Error("RuntimeError", *opt_str, "");
+    }
+  }
+
+  void MoveFromLastError(TVMFFIAny* result) { 
last_error_.MoveToTVMFFIAny(result); }
+
+  static SafeCallContext* ThreadLocal() {
+    static thread_local SafeCallContext ctx;
+    return &ctx;
+  }
+
+ private:
+  Any last_error_;
+};
+
+}  // namespace ffi
+}  // namespace tvm
+
+extern "C" {
+void TVMFFISetLastError(const TVMFFIAny* error_view) {
+  tvm::ffi::SafeCallContext::ThreadLocal()->SetLastError(error_view);
+}
+
+void TVMFFIMoveFromLastError(TVMFFIAny* result) {
+  tvm::ffi::SafeCallContext::ThreadLocal()->MoveFromLastError(result);
+}
+}
diff --git a/ffi/src/ffi/object.cc b/ffi/src/ffi/object.cc
index f4e2ff3e30..d0782d1b50 100644
--- a/ffi/src/ffi/object.cc
+++ b/ffi/src/ffi/object.cc
@@ -22,6 +22,7 @@
  */
 #include <tvm/ffi/c_api.h>
 #include <tvm/ffi/error.h>
+#include <tvm/ffi/function.h>
 
 #include <memory>
 #include <string>
@@ -219,20 +220,24 @@ class TypeTable {
   std::vector<std::unique_ptr<Entry>> type_table_;
   std::unordered_map<std::string, int32_t> type_key2index_;
 };
+}  // namespace ffi
+}  // namespace tvm
 
-namespace details {
+extern "C" {
 
-int32_t ObjectGetOrAllocTypeIndex(const char* type_key, int32_t 
static_type_index,
+int32_t TVMFFIGetOrAllocTypeIndex(const char* type_key, int32_t 
static_type_index,
                                   int32_t type_depth, int32_t num_child_slots,
-                                  bool child_slots_can_overflow, int32_t 
parent_index) {
-  return tvm::ffi::TypeTable::Global()->GetOrAllocTypeIndex(type_key, 
static_type_index, type_depth,
-                                                            num_child_slots,
-                                                            
child_slots_can_overflow, parent_index);
+                                  int32_t child_slots_can_overflow, int32_t 
parent_type_index) {
+  TVM_FFI_LOG_EXCEPTION_CALL_BEGIN();
+  return tvm::ffi::TypeTable::Global()->GetOrAllocTypeIndex(
+      type_key, static_type_index, type_depth, num_child_slots, 
child_slots_can_overflow,
+      parent_type_index);
+  TVM_FFI_LOG_EXCEPTION_CALL_END(TVMFFIGetOrAllocTypeIndex);
 }
 
-const TypeInfo* ObjectGetTypeInfo(int32_t type_index) {
+const TVMFFITypeInfo* TVMFFIGetTypeInfo(int32_t type_index) {
+  TVM_FFI_LOG_EXCEPTION_CALL_BEGIN();
   return tvm::ffi::TypeTable::Global()->GetTypeInfo(type_index);
+  TVM_FFI_LOG_EXCEPTION_CALL_END(TVMFFIGetTypeInfo);
 }
-}  // namespace details
-}  // namespace ffi
-}  // namespace tvm
+}  // extern "C"
diff --git a/ffi/src/ffi/traceback.cc b/ffi/src/ffi/traceback.cc
index f2826957a2..70de055719 100644
--- a/ffi/src/ffi/traceback.cc
+++ b/ffi/src/ffi/traceback.cc
@@ -146,22 +146,20 @@ __attribute__((constructor)) void 
install_signal_handler(void) {
 }
 #endif  // TVM_FFI_BACKTRACE_ON_SEGFAULT
 }  // namespace
+}  // namespace ffi
+}  // namespace tvm
 
-namespace details {
-const char* Traceback(const char*, const char*, int) {
+extern "C" {
+const char* TVMFFITraceback(const char*, const char*, int) {
   static thread_local std::string traceback_str;
   traceback_str = ::tvm::ffi::Traceback();
   return traceback_str.c_str();
 }
-}  // namespace details
-}  // namespace ffi
-}  // namespace tvm
+}  // extern "C"
 #else
-namespace tvm {
-namespace ffi {
-namespace details {
+extern "C" {
 // fallback implementation simply print out the last trace
-const char* Traceback(const char* filename, const char* func, int lineno) {
+const char* TVMFFITraceback(const char* filename, const char* func, int 
lineno) {
   static thread_local std::string traceback_str;
   std::ostringstream traceback_stream;
   // python style backtrace
@@ -169,8 +167,6 @@ const char* Traceback(const char* filename, const char* 
func, int lineno) {
   traceback_str = traceback_stream.str();
   return traceback_str.c_str();
 }
-}  // namespace details
-}  // namespace ffi
-}  // namespace tvm
+}  // extern "C"
 #endif  // TVM_FFI_USE_LIBBACKTRACE
 #endif  // _MSC_VER
diff --git a/ffi/tests/example/CMakeLists.txt 
b/ffi/tests/backup_cpp/CMakeLists.txt
similarity index 84%
rename from ffi/tests/example/CMakeLists.txt
rename to ffi/tests/backup_cpp/CMakeLists.txt
index 62543756b9..cb17040090 100644
--- a/ffi/tests/example/CMakeLists.txt
+++ b/ffi/tests/backup_cpp/CMakeLists.txt
@@ -17,9 +17,8 @@ set_target_properties(
 add_cxx_warning(tvm_ffi_tests)
 add_sanitizer_address(tvm_ffi_tests)
 target_link_libraries(tvm_ffi_tests PRIVATE tvm_ffi)
+add_sanitizer_address(tvm_ffi_registry_shared)
+target_link_libraries(tvm_ffi_tests PRIVATE tvm_ffi_registry_shared)
 
-if (TVM_FFI_BUILD_REGISTRY)
-  target_link_libraries(tvm_ffi_tests PRIVATE tvm_ffi_registry_shared)
-endif()
 
 add_googletest(tvm_ffi_tests)
diff --git a/ffi/tests/cpp/test_any.cc b/ffi/tests/backup_cpp/test_any.cc
similarity index 84%
copy from ffi/tests/cpp/test_any.cc
copy to ffi/tests/backup_cpp/test_any.cc
index a57829bd0a..d3c1e17002 100644
--- a/ffi/tests/cpp/test_any.cc
+++ b/ffi/tests/backup_cpp/test_any.cc
@@ -1,11 +1,12 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 
 namespace {
 using namespace tvm::ffi;
 
 template <typename SrcType, typename Checker>
-void TestAnyConstructor(Checker check, TVMFFITypeIndex expected_type_index, 
const SrcType &source) {
+void TestAnyConstructor(Checker check, TVMFFITypeIndex expected_type_index, 
const SrcType& source) {
   Any v(source);
   EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
   EXPECT_EQ(v.ref_cnt, 0);
@@ -19,7 +20,7 @@ std::vector<Any> AnyArrayFactory() {
       Any(nullptr),
       Any(1),
       Any(2.5),
-      Any(reinterpret_cast<void *>(FuncCall)),
+      Any(reinterpret_cast<void*>(FuncCall)),
       Any(DLDevice{kDLCPU, 0}),
       Any(DLDataType{kDLInt, 32, 1}),
       Any("Hello (raw str)"),
@@ -31,22 +32,22 @@ std::vector<Any> AnyArrayFactory() {
 }
 
 template <typename SrcType>
-void TestAnyStringify(const SrcType &source, TVMFFITypeIndex 
expected_type_index,
-                      const std::string &expected) {
+void TestAnyStringify(const SrcType& source, TVMFFITypeIndex 
expected_type_index,
+                      const std::string& expected) {
   Any v(source);
   EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
   EXPECT_EQ(v.str()->c_str(), expected);
 }
 
 template <typename SrcType, typename Checker>
-void TestAnyStringifyChecker(const SrcType &source, TVMFFITypeIndex 
expected_type_index,
+void TestAnyStringifyChecker(const SrcType& source, TVMFFITypeIndex 
expected_type_index,
                              Checker check) {
   Any v(source);
   EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
   check(v);
 }
 
-void CheckAnyRefCnt(const TVMFFIAny *v) {
+void CheckAnyRefCnt(const TVMFFIAny* v) {
   if (v->type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
     EXPECT_EQ(v->v_obj->ref_cnt, 1);
   }
@@ -98,17 +99,17 @@ TEST(Any_Constructor_2_AnyView, Move) {
 TEST(Any_Constructor_3_Ref, Copy) {
   Ref<Object> obj = Ref<Object>::New();
   Any v(obj);
-  const TVMFFIAny *v_obj = v.v_obj;
+  const TVMFFIAny* v_obj = v.v_obj;
   EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
   EXPECT_EQ(v.ref_cnt, 0);
-  EXPECT_EQ(v_obj, static_cast<const void *>(obj.get()));
+  EXPECT_EQ(v_obj, static_cast<const void*>(obj.get()));
   EXPECT_EQ(v_obj->ref_cnt, 2);
 }
 
 TEST(Any_Constructor_3_Ref, Move) {
   Ref<Object> obj = Ref<Object>::New();
   Any v(std::move(obj));
-  const TVMFFIAny *v_obj = v.v_obj;
+  const TVMFFIAny* v_obj = v.v_obj;
   EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
   EXPECT_EQ(v.ref_cnt, 0);
   EXPECT_EQ(v_obj->ref_cnt, 1);
@@ -116,7 +117,7 @@ TEST(Any_Constructor_3_Ref, Move) {
 }
 
 TEST(Any_Constructor_4_TypeTraits, Integer) {
-  auto check = [](TVMFFIAny *v, int64_t source) -> void { 
EXPECT_EQ(v->v_int64, source); };
+  auto check = [](TVMFFIAny* v, int64_t source) -> void { 
EXPECT_EQ(v->v_int64, source); };
   TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int8_t>(1));
   TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int16_t>(2));
   TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int32_t>(3));
@@ -128,20 +129,20 @@ TEST(Any_Constructor_4_TypeTraits, Integer) {
 }
 
 TEST(Any_Constructor_4_TypeTraits, Float) {
-  auto check = [](TVMFFIAny *v, double source) -> void { 
EXPECT_EQ(v->v_float64, source); };
+  auto check = [](TVMFFIAny* v, double source) -> void { 
EXPECT_EQ(v->v_float64, source); };
   TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIFloat, 
static_cast<float>(3));
   TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIFloat, 
static_cast<float>(4));
 }
 
 TEST(Any_Constructor_4_TypeTraits, Ptr) {
   int p = 4;
-  auto check = [](TVMFFIAny *v, void *source) -> void { EXPECT_EQ(v->v_ptr, 
source); };
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFINone, static_cast<void 
*>(nullptr));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIPtr, static_cast<void 
*>(&p));
+  auto check = [](TVMFFIAny* v, void* source) -> void { EXPECT_EQ(v->v_ptr, 
source); };
+  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFINone, 
static_cast<void*>(nullptr));
+  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIPtr, 
static_cast<void*>(&p));
 }
 
 TEST(Any_Constructor_4_TypeTraits, Device) {
-  auto check = [](TVMFFIAny *v, const DLDevice &source) -> void {
+  auto check = [](TVMFFIAny* v, const DLDevice& source) -> void {
     EXPECT_EQ(v->v_device.device_type, source.device_type);
     EXPECT_EQ(v->v_device.device_id, source.device_id);
   };
@@ -150,7 +151,7 @@ TEST(Any_Constructor_4_TypeTraits, Device) {
 }
 
 TEST(Any_Constructor_4_TypeTraits, DataType) {
-  auto check = [](TVMFFIAny *v, const DLDataType &source) -> void {
+  auto check = [](TVMFFIAny* v, const DLDataType& source) -> void {
     EXPECT_EQ(v->v_dtype.code, source.code);
     EXPECT_EQ(v->v_dtype.bits, source.bits);
     EXPECT_EQ(v->v_dtype.lanes, source.lanes);
@@ -160,19 +161,19 @@ TEST(Any_Constructor_4_TypeTraits, DataType) {
 }
 
 TEST(Any_Constructor_4_TypeTraits, RawStr) {
-  auto check = [](TVMFFIAny *v, const char *source) -> void {
-    Str *str = static_cast<Str *>(v->v_ptr);
+  auto check = [](TVMFFIAny* v, const char* source) -> void {
+    Str* str = static_cast<Str*>(v->v_ptr);
     EXPECT_STREQ(str->c_str(), source);
   };
-  const char *empty = "";
-  const char *hello = "hello";
+  const char* empty = "";
+  const char* hello = "hello";
   TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, empty);
   TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, hello);
 }
 
 TEST(Any_Constructor_4_TypeTraits, CharArray) {
-  auto check = [](TVMFFIAny *v, const char *source) -> void {
-    Str *str = static_cast<Str *>(v->v_ptr);
+  auto check = [](TVMFFIAny* v, const char* source) -> void {
+    Str* str = static_cast<Str*>(v->v_ptr);
     EXPECT_STREQ(str->c_str(), source);
   };
   const char empty[] = "";
@@ -182,8 +183,8 @@ TEST(Any_Constructor_4_TypeTraits, CharArray) {
 }
 
 TEST(Any_Constructor_4_TypeTraits, StdString) {
-  auto check = [](TVMFFIAny *v, const std::string &source) -> void {
-    Str *str = static_cast<Str *>(v->v_ptr);
+  auto check = [](TVMFFIAny* v, const std::string& source) -> void {
+    Str* str = static_cast<Str*>(v->v_ptr);
     EXPECT_EQ(str->c_str(), source);
   };
   std::string empty = "";
@@ -194,7 +195,7 @@ TEST(Any_Constructor_4_TypeTraits, StdString) {
 
 TEST(Any_Constructor_5_Object_Ptr, Object) {
   Ref<Object> obj = Ref<Object>::New();
-  TVMFFIAny *ptr = reinterpret_cast<TVMFFIAny *>(obj.get());
+  TVMFFIAny* ptr = reinterpret_cast<TVMFFIAny*>(obj.get());
   {
     Any v(obj.get());
     EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
@@ -206,7 +207,7 @@ TEST(Any_Constructor_5_Object_Ptr, Object) {
 
 TEST(Any_Constructor_5_Object_Ptr, Func) {
   Ref<Func> func = Ref<Func>::New(FuncCall);
-  TVMFFIAny *ptr = reinterpret_cast<TVMFFIAny *>(func.get());
+  TVMFFIAny* ptr = reinterpret_cast<TVMFFIAny*>(func.get());
   {
     Any v(func.get());
     EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc));
@@ -218,7 +219,7 @@ TEST(Any_Constructor_5_Object_Ptr, Func) {
 
 TEST(Any_Constructor_5_Object_Ptr, Str) {
   Ref<Str> str = Ref<Str>::New("hello");
-  TVMFFIAny *ptr = reinterpret_cast<TVMFFIAny *>(str.get());
+  TVMFFIAny* ptr = reinterpret_cast<TVMFFIAny*>(str.get());
   {
     Any v(str.get());
     EXPECT_EQ(v.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
@@ -230,7 +231,7 @@ TEST(Any_Constructor_5_Object_Ptr, Str) {
 
 TEST(Any_Converter_0_TypeTraits, Integer) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
+  for (const Any& v : vs) {
     auto convert = [&]() -> int64_t { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt)) {
       EXPECT_EQ(convert(), 1);
@@ -238,7 +239,7 @@ TEST(Any_Converter_0_TypeTraits, Integer) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `int`";
         EXPECT_EQ(ex.what(), os.str());
@@ -250,7 +251,7 @@ TEST(Any_Converter_0_TypeTraits, Integer) {
 
 TEST(Any_Converter_0_TypeTraits, Float) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
+  for (const Any& v : vs) {
     auto convert = [&]() -> double { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt)) {
       EXPECT_EQ(convert(), 1.0);
@@ -260,7 +261,7 @@ TEST(Any_Converter_0_TypeTraits, Float) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `float`";
         EXPECT_EQ(ex.what(), os.str());
@@ -272,19 +273,19 @@ TEST(Any_Converter_0_TypeTraits, Float) {
 
 TEST(Any_Converter_0_TypeTraits, Ptr) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> void * { return v; };
+  for (const Any& v : vs) {
+    auto convert = [&]() -> void* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       EXPECT_EQ(convert(), nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIPtr)) {
-      EXPECT_EQ(convert(), reinterpret_cast<void *>(&FuncCall));
+      EXPECT_EQ(convert(), reinterpret_cast<void*>(&FuncCall));
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIRawStr)) {
       EXPECT_EQ(convert(), v.v_str);
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `Ptr`";
         EXPECT_EQ(ex.what(), os.str());
@@ -296,7 +297,7 @@ TEST(Any_Converter_0_TypeTraits, Ptr) {
 
 TEST(Any_Converter_0_TypeTraits, Device) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
+  for (const Any& v : vs) {
     auto convert = [&]() -> DLDevice { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDevice)) {
       EXPECT_EQ(convert().device_type, kDLCPU);
@@ -305,7 +306,7 @@ TEST(Any_Converter_0_TypeTraits, Device) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `Device`";
         EXPECT_EQ(ex.what(), os.str());
@@ -317,7 +318,7 @@ TEST(Any_Converter_0_TypeTraits, Device) {
 
 TEST(Any_Converter_0_TypeTraits, DataType) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
+  for (const Any& v : vs) {
     auto convert = [&]() -> DLDataType { return v; };
     if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDataType)) {
       EXPECT_EQ(convert().code, kDLInt);
@@ -327,7 +328,7 @@ TEST(Any_Converter_0_TypeTraits, DataType) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `dtype`";
         EXPECT_EQ(ex.what(), os.str());
@@ -340,8 +341,8 @@ TEST(Any_Converter_0_TypeTraits, DataType) {
 TEST(Any_Converter_0_TypeTraits, RawStr) {
   std::vector<Any> vs = AnyArrayFactory();
   int counter = 0;
-  for (const Any &v : vs) {
-    auto convert = [&]() -> const char * { return v; };
+  for (const Any& v : vs) {
+    auto convert = [&]() -> const char* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr)) {
       ++counter;
       EXPECT_LE(counter, 3);
@@ -356,7 +357,7 @@ TEST(Any_Converter_0_TypeTraits, RawStr) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `const char *`";
@@ -369,7 +370,7 @@ TEST(Any_Converter_0_TypeTraits, RawStr) {
 
 TEST(Any_Converter_1_AnyView, Any) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
+  for (const Any& v : vs) {
     auto convert = [&]() -> AnyView { return v; };
     {
       AnyView ret = convert();
@@ -384,20 +385,20 @@ TEST(Any_Converter_1_AnyView, Any) {
 
 TEST(Any_Converter_2_Ref, Object) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
+  for (const Any& v : vs) {
     auto convert = [&]() -> Ref<Object> { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       Ref<Object> ret = convert();
       EXPECT_EQ(ret.get(), nullptr);
     } else if (v.type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
       Ref<Object> ret = convert();
-      EXPECT_EQ(ret.get(), static_cast<void *>(v.v_obj));
+      EXPECT_EQ(ret.get(), static_cast<void*>(v.v_obj));
       EXPECT_EQ(v.v_obj->ref_cnt, 2);
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Object`";
@@ -410,19 +411,19 @@ TEST(Any_Converter_2_Ref, Object) {
 
 TEST(Any_Converter_2_Ref, Func) {
   std::vector<Any> views = AnyArrayFactory();
-  for (const Any &v : views) {
+  for (const Any& v : views) {
     auto convert = [&]() -> Ref<Func> { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       Ref<Func> ret = convert();
       EXPECT_EQ(ret.get(), nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc)) {
       Ref<Func> ret = convert();
-      EXPECT_EQ(ret.get(), static_cast<void *>(v.v_obj));
+      EXPECT_EQ(ret.get(), static_cast<void*>(v.v_obj));
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Func`";
@@ -436,7 +437,7 @@ TEST(Any_Converter_2_Ref, Func) {
 TEST(Any_Converter_2_Ref, Str) {
   int counter = 0;
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
+  for (const Any& v : vs) {
     auto convert = [&]() -> Ref<Str> { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       Ref<Str> ret = convert();
@@ -456,7 +457,7 @@ TEST(Any_Converter_2_Ref, Str) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Str`";
@@ -469,20 +470,20 @@ TEST(Any_Converter_2_Ref, Str) {
 
 TEST(Any_Converter_3_Object_Ptr, Object) {
   std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> Object * { return v; };
+  for (const Any& v : vs) {
+    auto convert = [&]() -> Object* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Object *ret = convert();
+      Object* ret = convert();
       EXPECT_EQ(ret, nullptr);
     } else if (v.type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
-      Object *ret = convert();
-      EXPECT_EQ(ret, static_cast<void *>(v.v_obj));
+      Object* ret = convert();
+      EXPECT_EQ(ret, static_cast<void*>(v.v_obj));
       EXPECT_EQ(v.v_obj->ref_cnt, 1);
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Object *`";
@@ -495,19 +496,19 @@ TEST(Any_Converter_3_Object_Ptr, Object) {
 
 TEST(Any_Converter_3_Object_Ptr, Func) {
   std::vector<Any> views = AnyArrayFactory();
-  for (const Any &v : views) {
-    auto convert = [&]() -> Func * { return v; };
+  for (const Any& v : views) {
+    auto convert = [&]() -> Func* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Func *ret = convert();
+      Func* ret = convert();
       EXPECT_EQ(ret, nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc)) {
-      Func *ret = convert();
-      EXPECT_EQ(ret, reinterpret_cast<Func *>(v.v_ptr));
+      Func* ret = convert();
+      EXPECT_EQ(ret, reinterpret_cast<Func*>(v.v_ptr));
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Func *`";
@@ -521,13 +522,13 @@ TEST(Any_Converter_3_Object_Ptr, Func) {
 TEST(Any_Converter_3_Object_Ptr, Str) {
   std::vector<Any> vs = AnyArrayFactory();
   int counter = 0;
-  for (const Any &v : vs) {
-    auto convert = [&]() -> Str * { return v; };
+  for (const Any& v : vs) {
+    auto convert = [&]() -> Str* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Str *ret = convert();
+      Str* ret = convert();
       EXPECT_EQ(ret, nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr)) {
-      Str *ret = convert();
+      Str* ret = convert();
       ++counter;
       EXPECT_LE(counter, 3);
       if (counter == 1) {
@@ -541,7 +542,7 @@ TEST(Any_Converter_3_Object_Ptr, Str) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Str *`";
@@ -560,7 +561,7 @@ TEST(Any_Stringify, Integer) {
 }
 
 TEST(Any_Stringify, Float) {
-  auto check = [](const Any &v) -> void {
+  auto check = [](const Any& v) -> void {
     std::string str = v.str()->c_str();
     double f_str = std::stod(str);
     double f_src = v.v_float64;
@@ -571,13 +572,13 @@ TEST(Any_Stringify, Float) {
 }
 
 TEST(Any_Stringify, Ptr) {
-  auto check = [](const Any &v) -> void {
+  auto check = [](const Any& v) -> void {
     std::string str = v.str()->c_str();
     EXPECT_GT(str.size(), 2);
   };
-  TestAnyStringify<void *>(nullptr, TVMFFITypeIndex::kTVMFFINone, "None");
-  TestAnyStringifyChecker<void *>(reinterpret_cast<void *>(FuncCall), 
TVMFFITypeIndex::kTVMFFIPtr,
-                                  check);
+  TestAnyStringify<void*>(nullptr, TVMFFITypeIndex::kTVMFFINone, "None");
+  TestAnyStringifyChecker<void*>(reinterpret_cast<void*>(FuncCall), 
TVMFFITypeIndex::kTVMFFIPtr,
+                                 check);
 }
 
 TEST(Any_Stringify, Device) {
@@ -596,13 +597,13 @@ TEST(Any_Stringify, DataType) {
 }
 
 TEST(Any_Stringify, RawStr) {
-  TestAnyStringify<const char *>("Hello", TVMFFITypeIndex::kTVMFFIStr, 
"\"Hello\"");
+  TestAnyStringify<const char*>("Hello", TVMFFITypeIndex::kTVMFFIStr, 
"\"Hello\"");
   TestAnyStringify<char[6]>("Hello", TVMFFITypeIndex::kTVMFFIStr, "\"Hello\"");
   TestAnyStringify<const char[6]>("Hello", TVMFFITypeIndex::kTVMFFIStr, 
"\"Hello\"");
 }
 
 TEST(Any_Stringify, Object) {
-  auto check = [](const Any &v) -> void {
+  auto check = [](const Any& v) -> void {
     std::string expected_prefix = "object.Object@0";
     int n = static_cast<int>(expected_prefix.size());
     std::string str = v.str()->c_str();
@@ -613,7 +614,7 @@ TEST(Any_Stringify, Object) {
 }
 
 TEST(Any_Stringify, Func) {
-  auto check = [](const Any &v) -> void {
+  auto check = [](const Any& v) -> void {
     std::string expected_prefix = "object.Func@0";
     int n = static_cast<int>(expected_prefix.size());
     std::string str = v.str()->c_str();
@@ -624,7 +625,7 @@ TEST(Any_Stringify, Func) {
 }
 
 TEST(Any_Stringify, Str) {
-  auto check = [](const Any &v) -> void {
+  auto check = [](const Any& v) -> void {
     std::string str = v.str()->c_str();
     EXPECT_EQ(str, "\"Hello World\"");
   };
@@ -632,4 +633,4 @@ TEST(Any_Stringify, Str) {
                                     check);
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/test_any_view.cc 
b/ffi/tests/backup_cpp/test_any_view.cc
similarity index 84%
rename from ffi/tests/cpp/test_any_view.cc
rename to ffi/tests/backup_cpp/test_any_view.cc
index 67aaa9de3a..122c9ec368 100644
--- a/ffi/tests/cpp/test_any_view.cc
+++ b/ffi/tests/backup_cpp/test_any_view.cc
@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 
 namespace {
@@ -6,7 +7,7 @@ using namespace tvm::ffi;
 
 template <typename SrcType, typename Checker>
 void TestAnyViewConstructor(Checker check, TVMFFITypeIndex expected_type_index,
-                            const SrcType &source) {
+                            const SrcType& source) {
   AnyView v(source);
   EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
   EXPECT_EQ(v.ref_cnt, 0);
@@ -16,7 +17,7 @@ void TestAnyViewConstructor(Checker check, TVMFFITypeIndex 
expected_type_index,
 int64_t FuncCall(int64_t x) { return x + 1; }
 
 std::vector<AnyView> AnyViewArrayFactory() {
-  static const char *raw_str = "Hello (raw str)";
+  static const char* raw_str = "Hello (raw str)";
   static std::string std_str = "World (std::string)";
   static std::string ref_str = "Hello World (Ref<Str>)";
   static Ref<Object> obj = Ref<Object>::New();
@@ -26,34 +27,34 @@ std::vector<AnyView> AnyViewArrayFactory() {
       AnyView(nullptr),
       AnyView(1),
       AnyView(2.5),
-      AnyView(reinterpret_cast<void *>(FuncCall)),
+      AnyView(reinterpret_cast<void*>(FuncCall)),
       AnyView(DLDevice{kDLCPU, 0}),
       AnyView(DLDataType{kDLInt, 32, 1}),
       AnyView(raw_str),
       AnyView(obj),
       AnyView(func),
-      AnyView(std_str), // TODO: disable AnyView(std::string&&)
+      AnyView(std_str),  // TODO: disable AnyView(std::string&&)
       AnyView(str),
   };
 }
 
 template <typename SrcType>
-void TestAnyViewStringify(const SrcType &source, TVMFFITypeIndex 
expected_type_index,
-                          const std::string &expected) {
+void TestAnyViewStringify(const SrcType& source, TVMFFITypeIndex 
expected_type_index,
+                          const std::string& expected) {
   AnyView v(source);
   EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
   EXPECT_EQ(v.str()->c_str(), expected);
 }
 
 template <typename SrcType, typename Checker>
-void TestAnyViewStringifyChecker(const SrcType &source, TVMFFITypeIndex 
expected_type_index,
+void TestAnyViewStringifyChecker(const SrcType& source, TVMFFITypeIndex 
expected_type_index,
                                  Checker check) {
   AnyView v(source);
   EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
   check(v);
 }
 
-void CheckAnyViewRefCnt(const TVMFFIAny *v) {
+void CheckAnyViewRefCnt(const TVMFFIAny* v) {
   if (v->type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
     EXPECT_EQ(v->v_obj->ref_cnt, 1);
   }
@@ -102,10 +103,10 @@ TEST(AnyView_Constructor_2_Any, Move) {
 TEST(AnyView_Constructor_3_Ref, Copy) {
   Ref<Object> obj = Ref<Object>::New();
   AnyView v(obj);
-  const TVMFFIAny *v_obj = v.v_obj;
+  const TVMFFIAny* v_obj = v.v_obj;
   EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
   EXPECT_EQ(v.ref_cnt, 0);
-  EXPECT_EQ(v_obj, static_cast<const void *>(obj.get()));
+  EXPECT_EQ(v_obj, static_cast<const void*>(obj.get()));
   EXPECT_EQ(v_obj->ref_cnt, 1);
 }
 
@@ -116,7 +117,7 @@ TEST(AnyView_Constructor_3_Ref, Move) {
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, Integer) {
-  auto check = [](TVMFFIAny *v, int64_t source) -> void { 
EXPECT_EQ(v->v_int64, source); };
+  auto check = [](TVMFFIAny* v, int64_t source) -> void { 
EXPECT_EQ(v->v_int64, source); };
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int8_t>(1));
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int16_t>(2));
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int32_t>(3));
@@ -128,20 +129,20 @@ TEST(AnyView_Constructor_4_TypeTraits, Integer) {
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, Float) {
-  auto check = [](TVMFFIAny *v, double source) -> void { 
EXPECT_EQ(v->v_float64, source); };
+  auto check = [](TVMFFIAny* v, double source) -> void { 
EXPECT_EQ(v->v_float64, source); };
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIFloat, 
static_cast<float>(3));
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIFloat, 
static_cast<float>(4));
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, Ptr) {
   int p = 4;
-  auto check = [](TVMFFIAny *v, void *source) -> void { EXPECT_EQ(v->v_ptr, 
source); };
-  TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFINone, static_cast<void 
*>(nullptr));
-  TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIPtr, static_cast<void 
*>(&p));
+  auto check = [](TVMFFIAny* v, void* source) -> void { EXPECT_EQ(v->v_ptr, 
source); };
+  TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFINone, 
static_cast<void*>(nullptr));
+  TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIPtr, 
static_cast<void*>(&p));
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, Device) {
-  auto check = [](TVMFFIAny *v, const DLDevice &source) -> void {
+  auto check = [](TVMFFIAny* v, const DLDevice& source) -> void {
     EXPECT_EQ(v->v_device.device_type, source.device_type);
     EXPECT_EQ(v->v_device.device_id, source.device_id);
   };
@@ -150,7 +151,7 @@ TEST(AnyView_Constructor_4_TypeTraits, Device) {
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, DataType) {
-  auto check = [](TVMFFIAny *v, const DLDataType &source) -> void {
+  auto check = [](TVMFFIAny* v, const DLDataType& source) -> void {
     EXPECT_EQ(v->v_dtype.code, source.code);
     EXPECT_EQ(v->v_dtype.bits, source.bits);
     EXPECT_EQ(v->v_dtype.lanes, source.lanes);
@@ -160,15 +161,15 @@ TEST(AnyView_Constructor_4_TypeTraits, DataType) {
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, RawStr) {
-  auto check = [](TVMFFIAny *v, const char *source) -> void { 
EXPECT_EQ(v->v_str, source); };
-  const char *empty = "";
-  const char *hello = "hello";
+  auto check = [](TVMFFIAny* v, const char* source) -> void { 
EXPECT_EQ(v->v_str, source); };
+  const char* empty = "";
+  const char* hello = "hello";
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIRawStr, empty);
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIRawStr, hello);
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, CharArray) {
-  auto check = [](TVMFFIAny *v, const char *source) -> void { 
EXPECT_EQ(v->v_str, source); };
+  auto check = [](TVMFFIAny* v, const char* source) -> void { 
EXPECT_EQ(v->v_str, source); };
   const char empty[] = "";
   const char hello[] = "hello";
   TestAnyViewConstructor(check, TVMFFITypeIndex::kTVMFFIRawStr, empty);
@@ -176,7 +177,7 @@ TEST(AnyView_Constructor_4_TypeTraits, CharArray) {
 }
 
 TEST(AnyView_Constructor_4_TypeTraits, StdString) {
-  auto check = [](TVMFFIAny *v, const std::string &source) -> void {
+  auto check = [](TVMFFIAny* v, const std::string& source) -> void {
     EXPECT_EQ(v->v_str, source.data());
   };
   std::string empty = "";
@@ -190,7 +191,7 @@ TEST(AnyView_Constructor_5_Object_Ptr, Object) {
   AnyView v(obj.get());
   EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
   EXPECT_EQ(v.v_obj->ref_cnt, 1);
-  EXPECT_EQ(v.v_obj, static_cast<void *>(obj.get()));
+  EXPECT_EQ(v.v_obj, static_cast<void*>(obj.get()));
 }
 
 TEST(AnyView_Constructor_5_Object_Ptr, Func) {
@@ -198,7 +199,7 @@ TEST(AnyView_Constructor_5_Object_Ptr, Func) {
   AnyView v(func.get());
   EXPECT_EQ(v.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc));
   EXPECT_EQ(v.v_obj->ref_cnt, 1);
-  EXPECT_EQ(v.v_ptr, static_cast<void *>(func.get()));
+  EXPECT_EQ(v.v_ptr, static_cast<void*>(func.get()));
 }
 
 TEST(AnyView_Constructor_5_Object_Ptr, Str) {
@@ -206,12 +207,12 @@ TEST(AnyView_Constructor_5_Object_Ptr, Str) {
   AnyView v(str.get());
   EXPECT_EQ(v.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
   EXPECT_EQ(v.v_obj->ref_cnt, 1);
-  EXPECT_EQ(v.v_obj, static_cast<void *>(str.get()));
+  EXPECT_EQ(v.v_obj, static_cast<void*>(str.get()));
 }
 
 TEST(AnyView_Converter_0_TypeTraits, Integer) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
+  for (const AnyView& v : views) {
     auto convert = [&]() -> int64_t { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt)) {
       EXPECT_EQ(convert(), 1);
@@ -219,7 +220,7 @@ TEST(AnyView_Converter_0_TypeTraits, Integer) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `int`";
         EXPECT_EQ(ex.what(), os.str());
@@ -231,7 +232,7 @@ TEST(AnyView_Converter_0_TypeTraits, Integer) {
 
 TEST(AnyView_Converter_0_TypeTraits, Float) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
+  for (const AnyView& v : views) {
     auto convert = [&]() -> double { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt)) {
       EXPECT_EQ(convert(), 1.0);
@@ -241,7 +242,7 @@ TEST(AnyView_Converter_0_TypeTraits, Float) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `float`";
         EXPECT_EQ(ex.what(), os.str());
@@ -253,19 +254,19 @@ TEST(AnyView_Converter_0_TypeTraits, Float) {
 
 TEST(AnyView_Converter_0_TypeTraits, Ptr) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
-    auto convert = [&]() -> void * { return v; };
+  for (const AnyView& v : views) {
+    auto convert = [&]() -> void* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       EXPECT_EQ(convert(), nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIPtr)) {
-      EXPECT_EQ(convert(), reinterpret_cast<void *>(&FuncCall));
+      EXPECT_EQ(convert(), reinterpret_cast<void*>(&FuncCall));
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIRawStr)) {
       EXPECT_EQ(convert(), v.v_str);
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `Ptr`";
         EXPECT_EQ(ex.what(), os.str());
@@ -277,7 +278,7 @@ TEST(AnyView_Converter_0_TypeTraits, Ptr) {
 
 TEST(AnyView_Converter_0_TypeTraits, Device) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
+  for (const AnyView& v : views) {
     auto convert = [&]() -> DLDevice { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDevice)) {
       EXPECT_EQ(convert().device_type, kDLCPU);
@@ -286,7 +287,7 @@ TEST(AnyView_Converter_0_TypeTraits, Device) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `Device`";
         EXPECT_EQ(ex.what(), os.str());
@@ -298,7 +299,7 @@ TEST(AnyView_Converter_0_TypeTraits, Device) {
 
 TEST(AnyView_Converter_0_TypeTraits, DataType) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
+  for (const AnyView& v : views) {
     auto convert = [&]() -> DLDataType { return v; };
     if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDataType)) {
       EXPECT_EQ(convert().code, kDLInt);
@@ -308,7 +309,7 @@ TEST(AnyView_Converter_0_TypeTraits, DataType) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `dtype`";
         EXPECT_EQ(ex.what(), os.str());
@@ -321,8 +322,8 @@ TEST(AnyView_Converter_0_TypeTraits, DataType) {
 TEST(AnyView_Converter_0_TypeTraits, RawStr) {
   std::vector<AnyView> views = AnyViewArrayFactory();
   int counter = 0;
-  for (const AnyView &v : views) {
-    auto convert = [&]() -> const char * { return v; };
+  for (const AnyView& v : views) {
+    auto convert = [&]() -> const char* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIRawStr)) {
       counter += 1;
       EXPECT_LT(counter, 3);
@@ -337,7 +338,7 @@ TEST(AnyView_Converter_0_TypeTraits, RawStr) {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `const char *`";
@@ -351,10 +352,10 @@ TEST(AnyView_Converter_0_TypeTraits, RawStr) {
 TEST(AnyView_Converter_0_TypeTraits, RawStrToStrStar_Fail) {
   AnyView v = "Hello";
   try {
-    Str *v_str = v;
+    Str* v_str = v;
     (void)v_str;
     FAIL() << "No exception thrown";
-  } catch (TVMError &ex) {
+  } catch (TVMError& ex) {
     EXPECT_STREQ(ex.what(), "Cannot convert from type `const char *` to 
`object.Str *`");
   }
 }
@@ -362,19 +363,19 @@ TEST(AnyView_Converter_0_TypeTraits, 
RawStrToStrStar_Fail) {
 TEST(AnyView_Converter_0_TypeTraits, RawStrToStrStar_WrithStorage) {
   Any storage;
   AnyView v = "Hello";
-  Str *v_str = v.CastWithStorage<Str *>(&storage);
+  Str* v_str = v.CastWithStorage<Str*>(&storage);
   EXPECT_STREQ(v_str->c_str(), "Hello");
 }
 
 TEST(AnyView_Converter_1_Any, Any) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &view : views) {
+  for (const AnyView& view : views) {
     auto convert = [&]() -> Any { return view; };
     {
       Any ret = convert();
       EXPECT_EQ(view.ref_cnt, 0);
       if (view.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIRawStr)) {
-        Str *str = ret;
+        Str* str = ret;
         EXPECT_EQ(ret.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
         EXPECT_STREQ(str->c_str(), view.v_str);
         EXPECT_EQ(ret.ref_cnt, 0);
@@ -390,20 +391,20 @@ TEST(AnyView_Converter_1_Any, Any) {
 
 TEST(AnyView_Converter_2_Ref, Object) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
+  for (const AnyView& v : views) {
     auto convert = [&]() -> Ref<Object> { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       Ref<Object> ret = convert();
       EXPECT_EQ(ret.get(), nullptr);
     } else if (v.type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
       Ref<Object> ret = convert();
-      EXPECT_EQ(ret.get(), static_cast<void *>(v.v_obj));
+      EXPECT_EQ(ret.get(), static_cast<void*>(v.v_obj));
       EXPECT_EQ(v.v_obj->ref_cnt, 2);
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Object`";
@@ -416,19 +417,19 @@ TEST(AnyView_Converter_2_Ref, Object) {
 
 TEST(AnyView_Converter_2_Ref, Func) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
+  for (const AnyView& v : views) {
     auto convert = [&]() -> Ref<Func> { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       Ref<Func> ret = convert();
       EXPECT_EQ(ret.get(), nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc)) {
       Ref<Func> ret = convert();
-      EXPECT_EQ(ret.get(), static_cast<void *>(v.v_obj));
+      EXPECT_EQ(ret.get(), static_cast<void*>(v.v_obj));
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Func`";
@@ -441,7 +442,7 @@ TEST(AnyView_Converter_2_Ref, Func) {
 
 TEST(AnyView_Converter_2_Ref, Str) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
+  for (const AnyView& v : views) {
     auto convert = [&]() -> Ref<Str> { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
       Ref<Str> ret = convert();
@@ -451,13 +452,13 @@ TEST(AnyView_Converter_2_Ref, Str) {
       EXPECT_STREQ(ret->c_str(), "Hello World (Ref<Str>)");
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIRawStr)) {
       Ref<Str> ret = convert();
-      EXPECT_EQ(reinterpret_cast<TVMFFIStr *>(ret.get())->ref_cnt, 1);
+      EXPECT_EQ(reinterpret_cast<TVMFFIStr*>(ret.get())->ref_cnt, 1);
       EXPECT_STREQ(ret->c_str(), v.v_str);
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Str`";
@@ -470,20 +471,20 @@ TEST(AnyView_Converter_2_Ref, Str) {
 
 TEST(AnyView_Converter_3_Object_Ptr, Object) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
-    auto convert = [&]() -> Object * { return v; };
+  for (const AnyView& v : views) {
+    auto convert = [&]() -> Object* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Object *ret = convert();
+      Object* ret = convert();
       EXPECT_EQ(ret, nullptr);
     } else if (v.type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
-      Object *ret = convert();
-      EXPECT_EQ(ret, static_cast<void *>(v.v_obj));
+      Object* ret = convert();
+      EXPECT_EQ(ret, static_cast<void*>(v.v_obj));
       EXPECT_EQ(v.v_obj->ref_cnt, 1);
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Object *`";
@@ -496,19 +497,19 @@ TEST(AnyView_Converter_3_Object_Ptr, Object) {
 
 TEST(AnyView_Converter_3_Object_Ptr, Func) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
-    auto convert = [&]() -> Func * { return v; };
+  for (const AnyView& v : views) {
+    auto convert = [&]() -> Func* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Func *ret = convert();
+      Func* ret = convert();
       EXPECT_EQ(ret, nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc)) {
-      Func *ret = convert();
-      EXPECT_EQ(ret, reinterpret_cast<Func *>(v.v_ptr));
+      Func* ret = convert();
+      EXPECT_EQ(ret, reinterpret_cast<Func*>(v.v_ptr));
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Func *`";
@@ -521,19 +522,19 @@ TEST(AnyView_Converter_3_Object_Ptr, Func) {
 
 TEST(AnyView_Converter_3_Object_Ptr, Str) {
   std::vector<AnyView> views = AnyViewArrayFactory();
-  for (const AnyView &v : views) {
-    auto convert = [&]() -> Str * { return v; };
+  for (const AnyView& v : views) {
+    auto convert = [&]() -> Str* { return v; };
     if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Str *ret = convert();
+      Str* ret = convert();
       EXPECT_EQ(ret, nullptr);
     } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr)) {
-      Str *ret = convert();
+      Str* ret = convert();
       EXPECT_STREQ(ret->c_str(), "Hello World (Ref<Str>)");
     } else {
       try {
         convert();
         FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
+      } catch (TVMError& ex) {
         std::ostringstream os;
         os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
            << "` to `object.Str *`";
@@ -552,7 +553,7 @@ TEST(AnyView_Stringify, Integer) {
 }
 
 TEST(AnyView_Stringify, Float) {
-  auto check = [](const AnyView &v) -> void {
+  auto check = [](const AnyView& v) -> void {
     std::string str = v.str()->c_str();
     double f_str = std::stod(str);
     double f_src = v.v_float64;
@@ -563,13 +564,13 @@ TEST(AnyView_Stringify, Float) {
 }
 
 TEST(AnyView_Stringify, Ptr) {
-  auto check = [](const AnyView &v) -> void {
+  auto check = [](const AnyView& v) -> void {
     std::string str = v.str()->c_str();
     EXPECT_GT(str.size(), 2);
   };
-  TestAnyViewStringify<void *>(nullptr, TVMFFITypeIndex::kTVMFFINone, "None");
-  TestAnyViewStringifyChecker<void *>(reinterpret_cast<void *>(FuncCall),
-                                      TVMFFITypeIndex::kTVMFFIPtr, check);
+  TestAnyViewStringify<void*>(nullptr, TVMFFITypeIndex::kTVMFFINone, "None");
+  TestAnyViewStringifyChecker<void*>(reinterpret_cast<void*>(FuncCall), 
TVMFFITypeIndex::kTVMFFIPtr,
+                                     check);
 }
 
 TEST(AnyView_Stringify, Device) {
@@ -589,13 +590,13 @@ TEST(AnyView_Stringify, DataType) {
 }
 
 TEST(AnyView_Stringify, RawStr) {
-  TestAnyViewStringify<const char *>("Hello", TVMFFITypeIndex::kTVMFFIRawStr, 
"\"Hello\"");
+  TestAnyViewStringify<const char*>("Hello", TVMFFITypeIndex::kTVMFFIRawStr, 
"\"Hello\"");
   TestAnyViewStringify<char[6]>("Hello", TVMFFITypeIndex::kTVMFFIRawStr, 
"\"Hello\"");
   TestAnyViewStringify<const char[6]>("Hello", TVMFFITypeIndex::kTVMFFIRawStr, 
"\"Hello\"");
 }
 
 TEST(AnyView_Stringify, Object) {
-  auto check = [](const AnyView &v) -> void {
+  auto check = [](const AnyView& v) -> void {
     std::string expected_prefix = "object.Object@0";
     int n = static_cast<int>(expected_prefix.size());
     std::string str = v.str()->c_str();
@@ -607,7 +608,7 @@ TEST(AnyView_Stringify, Object) {
 }
 
 TEST(AnyView_Stringify, Func) {
-  auto check = [](const AnyView &v) -> void {
+  auto check = [](const AnyView& v) -> void {
     std::string expected_prefix = "object.Func@0";
     int n = static_cast<int>(expected_prefix.size());
     std::string str = v.str()->c_str();
@@ -619,7 +620,7 @@ TEST(AnyView_Stringify, Func) {
 }
 
 TEST(AnyView_Stringify, Str) {
-  auto check = [](const AnyView &v) -> void {
+  auto check = [](const AnyView& v) -> void {
     std::string str = v.str()->c_str();
     EXPECT_EQ(str, "\"Hello World\"");
   };
@@ -627,4 +628,4 @@ TEST(AnyView_Stringify, Str) {
                                         check);
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/test_dict.cc b/ffi/tests/backup_cpp/test_dict.cc
similarity index 92%
rename from ffi/tests/cpp/test_dict.cc
rename to ffi/tests/backup_cpp/test_dict.cc
index 04d5a2854f..53c4452401 100644
--- a/ffi/tests/cpp/test_dict.cc
+++ b/ffi/tests/backup_cpp/test_dict.cc
@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 #include <unordered_set>
 
@@ -16,7 +17,7 @@ bool DTypeEqual(DLDataType a, DLDataType b) {
 TEST(Dict_Construtor, Default) {
   Ref<Dict> dict;
   ASSERT_EQ(dict.size(), 0);
-  TVMFFIDict *dict_ptr = reinterpret_cast<TVMFFIDict *>(dict.get());
+  TVMFFIDict* dict_ptr = reinterpret_cast<TVMFFIDict*>(dict.get());
   EXPECT_EQ(dict_ptr->type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDict));
   EXPECT_EQ(dict_ptr->ref_cnt, 1);
   EXPECT_NE(dict_ptr->deleter, nullptr);
@@ -32,7 +33,7 @@ TEST(Dict_Construtor, InitializerList) {
   EXPECT_EQ(int(dict[3]), 4);
 
   bool found[3] = {false, false, false};
-  for (const auto &kv : dict) {
+  for (const auto& kv : dict) {
     if (AnyEqual()(kv.first, Any("key1"))) {
       found[0] = true;
       EXPECT_EQ(int(kv.second), 1);
@@ -65,7 +66,7 @@ TEST(Dict_Insert, New) {
   EXPECT_DOUBLE_EQ(double(dict[integer]), fp);
   EXPECT_PRED2(DTypeEqual, DLDataType(dict[str]), dtype);
   EXPECT_EQ(int(dict[null_obj]), 0);
-  EXPECT_EQ((Object *)(dict[device]), nullptr);
+  EXPECT_EQ((Object*)(dict[device]), nullptr);
 }
 
 TEST(Dict_Insert, Override) {
@@ -98,7 +99,7 @@ TEST(Dict_At, NotFound) {
   try {
     dict.at("key3");
     FAIL() << "Expected TVMError";
-  } catch (const TVMError &e) {
+  } catch (const TVMError& e) {
   }
 }
 
@@ -109,7 +110,7 @@ TEST(Dict_ReHash, POD) {
   }
   EXPECT_EQ(dict.size(), 1000);
   std::unordered_set<int64_t> keys;
-  for (auto &kv : dict) {
+  for (auto& kv : dict) {
     int64_t key = kv.first;
     int64_t value = kv.second;
     EXPECT_EQ(key, value);
@@ -122,7 +123,7 @@ TEST(Dict_ReHash, POD) {
 
 TEST(Dict_ReHash, Object) {
   std::vector<Ref<Object>> objs;
-  std::unordered_map<Object *, int64_t> obj_map;
+  std::unordered_map<Object*, int64_t> obj_map;
   for (int j = 0; j < 1000; ++j) {
     objs.push_back(Ref<Object>::New());
     obj_map[objs[j].get()] = j;
@@ -132,8 +133,8 @@ TEST(Dict_ReHash, Object) {
     dict[objs[j]] = j;
   }
   EXPECT_EQ(dict.size(), 1000);
-  std::unordered_set<Object *> keys;
-  for (auto &kv : dict) {
+  std::unordered_set<Object*> keys;
+  for (auto& kv : dict) {
     Ref<Object> key = kv.first;
     int64_t value = kv.second;
     keys.insert(key.get());
@@ -160,7 +161,7 @@ TEST(Dict_Erase, POD) {
 
 TEST(Dict_Erase, Object) {
   std::vector<Ref<Object>> objs;
-  std::unordered_map<Object *, int64_t> obj_map;
+  std::unordered_map<Object*, int64_t> obj_map;
   for (int j = 0; j < 1000; ++j) {
     objs.push_back(Ref<Object>::New());
     obj_map[objs[j].get()] = j;
@@ -180,4 +181,4 @@ TEST(Dict_Erase, Object) {
   }
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/test_func.cc b/ffi/tests/backup_cpp/test_func.cc
similarity index 77%
rename from ffi/tests/cpp/test_func.cc
rename to ffi/tests/backup_cpp/test_func.cc
index 32512d3dcf..0790692bb9 100644
--- a/ffi/tests/cpp/test_func.cc
+++ b/ffi/tests/backup_cpp/test_func.cc
@@ -1,12 +1,13 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 
 namespace {
 using namespace tvm::ffi;
 
-const char *c_str_raw = "Hello";
+const char* c_str_raw = "Hello";
 
-double func_unpacked_0(int64_t a, double b, const char *c, const double &d) {
+double func_unpacked_0(int64_t a, double b, const char* c, const double& d) {
   EXPECT_STREQ(c, c_str_raw);
   return a + b + d;
 }
@@ -17,7 +18,7 @@ void func_unpacked_1(DLDataType dtype, DLDevice device, 
std::string str) {
   (void)str;
 }
 
-void func_packed_0(int num_args, const AnyView *, Any *ret) { *ret = num_args; 
}
+void func_packed_0(int num_args, const AnyView*, Any* ret) { *ret = num_args; }
 
 template <enum TVMFFITypeIndex type_index>
 void func_unpacked_anyview_arg(AnyView a) {
@@ -30,8 +31,8 @@ void func_unpacked_any_arg(Any a) {
 AnyView func_unpacked_anyview_ret() { return AnyView(1); }
 Any func_unpacked_any_ret() { return Any(1); }
 
-std::string func_unpacked_str_obj(Str *str, const char *str_2) {
-  EXPECT_EQ(reinterpret_cast<TVMFFIStr *>(str)->ref_cnt, 1);
+std::string func_unpacked_str_obj(Str* str, const char* str_2) {
+  EXPECT_EQ(reinterpret_cast<TVMFFIStr*>(str)->ref_cnt, 1);
   EXPECT_STREQ(str->c_str(), str_2);
   return str->c_str();
 }
@@ -47,26 +48,23 @@ TEST(Func_Signature, 1) {
 }
 
 TEST(Func_Signature, AnyView_Arg) {
-  EXPECT_EQ(details::FuncFunctor<decltype(func_unpacked_anyview_arg<
-                                          
TVMFFITypeIndex::kTVMFFIInt>)>::Sig(),
-            "(0: AnyView) -> void");
+  EXPECT_EQ(
+      
details::FuncFunctor<decltype(func_unpacked_anyview_arg<TVMFFITypeIndex::kTVMFFIInt>)>::Sig(),
+      "(0: AnyView) -> void");
 }
 
 TEST(Func_Signature, AnyView_Ret) {
-  EXPECT_EQ(details::FuncFunctor<decltype(func_unpacked_anyview_ret)>::Sig(),
-            "() -> AnyView");
+  EXPECT_EQ(details::FuncFunctor<decltype(func_unpacked_anyview_ret)>::Sig(), 
"() -> AnyView");
 }
 
 TEST(Func_Signature, Any_Arg) {
   EXPECT_EQ(
-      details::FuncFunctor<
-          decltype(func_unpacked_any_arg<TVMFFITypeIndex::kTVMFFIInt>)>::Sig(),
+      
details::FuncFunctor<decltype(func_unpacked_any_arg<TVMFFITypeIndex::kTVMFFIInt>)>::Sig(),
       "(0: Any) -> void");
 }
 
 TEST(Func_Signature, Any_Ret) {
-  EXPECT_EQ(details::FuncFunctor<decltype(func_unpacked_any_ret)>::Sig(),
-            "() -> Any");
+  EXPECT_EQ(details::FuncFunctor<decltype(func_unpacked_any_ret)>::Sig(), "() 
-> Any");
 }
 
 TEST(Func_Unpacked_Invoke, Func0_RawStr) {
@@ -98,8 +96,7 @@ TEST(Func_Unpacked_Invoke, Func1) {
 }
 
 TEST(Func_Unpacked_Invoke, AnyView_Arg) {
-  Ref<Func> func =
-      Ref<Func>::New(func_unpacked_anyview_arg<TVMFFITypeIndex::kTVMFFIInt>);
+  Ref<Func> func = 
Ref<Func>::New(func_unpacked_anyview_arg<TVMFFITypeIndex::kTVMFFIInt>);
   func(1);
 }
 
@@ -110,8 +107,7 @@ TEST(Func_Unpacked_Invoke, AnyView_Ret) {
 }
 
 TEST(Func_Unpacked_Invoke, Any_Arg) {
-  Ref<Func> func =
-      Ref<Func>::New(func_unpacked_any_arg<TVMFFITypeIndex::kTVMFFIInt>);
+  Ref<Func> func = 
Ref<Func>::New(func_unpacked_any_arg<TVMFFITypeIndex::kTVMFFIInt>);
   func(1);
 }
 
@@ -156,7 +152,7 @@ TEST(Func_Unpacked_Invoke_TypeError, TypeMismatch_0) {
   try {
     func(1.0, 2, c_str_raw, 4);
     FAIL() << "No execption thrown";
-  } catch (TVMError &ex) {
+  } catch (TVMError& ex) {
     EXPECT_STREQ(ex.what(),
                  "Mismatched type on argument #0 when calling: "
                  "`(0: int, 1: float, 2: const char *, 3: float) -> float`. "
@@ -169,10 +165,11 @@ TEST(Func_Unpacked_Invoke_TypeError, TypeMismatch_1) {
   try {
     func(DLDataType{kDLInt, 32, 1}, DLDevice{kDLCPU, 0}, 1);
     FAIL() << "No execption thrown";
-  } catch (TVMError &ex) {
-    EXPECT_STREQ(ex.what(), "Mismatched type on argument #2 when calling: "
-                            "`(0: dtype, 1: Device, 2: str) -> void`. "
-                            "Expected `str` but got `int`");
+  } catch (TVMError& ex) {
+    EXPECT_STREQ(ex.what(),
+                 "Mismatched type on argument #2 when calling: "
+                 "`(0: dtype, 1: Device, 2: str) -> void`. "
+                 "Expected `str` but got `int`");
   }
 }
 
@@ -181,7 +178,7 @@ TEST(Func_Unpacked_Invoke_TypeError, ArgCountMismatch_0) {
   try {
     func(1, 2, c_str_raw);
     FAIL() << "No execption thrown";
-  } catch (TVMError &ex) {
+  } catch (TVMError& ex) {
     EXPECT_STREQ(ex.what(),
                  "Mismatched number of arguments when calling: "
                  "`(0: int, 1: float, 2: const char *, 3: float) -> float`. "
@@ -194,10 +191,11 @@ TEST(Func_Unpacked_Invoke_TypeError, ArgCountMismatch_1) {
   try {
     func(DLDataType{kDLInt, 32, 1}, DLDevice{kDLCPU, 0});
     FAIL() << "No execption thrown";
-  } catch (TVMError &ex) {
-    EXPECT_STREQ(ex.what(), "Mismatched number of arguments when calling: "
-                            "`(0: dtype, 1: Device, 2: str) -> void`. "
-                            "Expected 3 but got 2 arguments");
+  } catch (TVMError& ex) {
+    EXPECT_STREQ(ex.what(),
+                 "Mismatched number of arguments when calling: "
+                 "`(0: dtype, 1: Device, 2: str) -> void`. "
+                 "Expected 3 but got 2 arguments");
   }
 }
 
@@ -207,9 +205,9 @@ TEST(Func_Unpacked_Invoke_TypeError, ReturnTypeMismatch_0) {
     int ret = func(DLDataType{kDLInt, 32, 1}, DLDevice{kDLCPU, 0}, "Hello");
     (void)ret;
     FAIL() << "No execption thrown";
-  } catch (TVMError &ex) {
+  } catch (TVMError& ex) {
     EXPECT_STREQ(ex.what(), "Cannot convert from type `None` to `int`");
   }
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/test_list.cc b/ffi/tests/backup_cpp/test_list.cc
similarity index 88%
rename from ffi/tests/cpp/test_list.cc
rename to ffi/tests/backup_cpp/test_list.cc
index 53fd727af6..06b9d6a483 100644
--- a/ffi/tests/cpp/test_list.cc
+++ b/ffi/tests/backup_cpp/test_list.cc
@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 
 namespace {
@@ -12,7 +13,7 @@ bool DeviceEqual(DLDevice a, DLDevice b) {
   return a.device_type == b.device_type && a.device_id == b.device_id;
 }
 
-void TestSizeCapacityClear(Ref<List> *list, int64_t size, int64_t capacity) {
+void TestSizeCapacityClear(Ref<List>* list, int64_t size, int64_t capacity) {
   EXPECT_EQ(list->size(), size);
   EXPECT_EQ(list->capacity(), capacity);
   EXPECT_EQ(list->empty(), size == 0);
@@ -24,7 +25,7 @@ void TestSizeCapacityClear(Ref<List> *list, int64_t size, 
int64_t capacity) {
 
 TEST(List_Constructor, Default) {
   Ref<List> list = Ref<List>::New();
-  TVMFFIList *list_ptr = reinterpret_cast<TVMFFIList *>(list.get());
+  TVMFFIList* list_ptr = reinterpret_cast<TVMFFIList*>(list.get());
   ASSERT_NE(list_ptr, nullptr);
   EXPECT_EQ(list_ptr->type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIList));
   EXPECT_EQ(list_ptr->ref_cnt, 1);
@@ -44,8 +45,8 @@ TEST(List_Constructor, InitializerList) {
       100,          1.0f, "Hi", DLDataType{kDLInt, 32, 1}, DLDevice{kDLCPU, 
0}, Ref<Object>::New(),
       Ref<Object>()};
 
-  auto test = [](Ref<List> *src) {
-    auto *list_ptr = reinterpret_cast<const TVMFFIList *>(src->get());
+  auto test = [](Ref<List>* src) {
+    auto* list_ptr = reinterpret_cast<const TVMFFIList*>(src->get());
     ASSERT_NE(list_ptr, nullptr);
     EXPECT_EQ(list_ptr->type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIList));
     EXPECT_EQ(list_ptr->ref_cnt, 1);
@@ -53,7 +54,7 @@ TEST(List_Constructor, InitializerList) {
     EXPECT_EQ(list_ptr->list_capacity, 7);
     EXPECT_EQ(list_ptr->list_length, 7);
     EXPECT_EQ(list_ptr->pool_capacity, 7);
-    EXPECT_EQ(list_ptr->pool_length, 4); // string is not in the POD pool
+    EXPECT_EQ(list_ptr->pool_length, 4);  // string is not in the POD pool
     EXPECT_EQ(src->size(), 7);
     EXPECT_EQ(src->capacity(), 7);
     EXPECT_EQ(src->empty(), false);
@@ -68,7 +69,7 @@ TEST(List_PushBack, POD) {
   ASSERT_NE(list.get(), nullptr);
   list.push_back(100);
   list.push_back(1.0f);
-  TVMFFIList *list_ptr = reinterpret_cast<TVMFFIList *>(list.get());
+  TVMFFIList* list_ptr = reinterpret_cast<TVMFFIList*>(list.get());
   ASSERT_NE(list_ptr, nullptr);
   EXPECT_EQ(list_ptr->type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIList));
   EXPECT_EQ(list_ptr->ref_cnt, 1);
@@ -88,7 +89,7 @@ TEST(List_PushBack, Obj) {
   Ref<Object> obj2 = Ref<Object>::New();
   list.push_back(obj1);
   list.push_back(obj2);
-  TVMFFIList *list_ptr = reinterpret_cast<TVMFFIList *>(list.get());
+  TVMFFIList* list_ptr = reinterpret_cast<TVMFFIList*>(list.get());
   ASSERT_NE(list_ptr, nullptr);
   EXPECT_EQ(list_ptr->type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIList));
   EXPECT_EQ(list_ptr->ref_cnt, 1);
@@ -97,8 +98,8 @@ TEST(List_PushBack, Obj) {
   EXPECT_EQ(list_ptr->list_length, 2);
   EXPECT_EQ(list_ptr->pool_capacity, 0);
   EXPECT_EQ(list_ptr->pool_length, 0);
-  EXPECT_EQ((Object *)(list[0]), obj1.get());
-  EXPECT_EQ((Object *)(list[1]), obj2.get());
+  EXPECT_EQ((Object*)(list[0]), obj1.get());
+  EXPECT_EQ((Object*)(list[1]), obj2.get());
   TestSizeCapacityClear(&list, 2, List::kMinCapacity);
 }
 
@@ -138,9 +139,9 @@ TEST(List_PushBack, Heterogeneous) {
     std::string i_2 = list[i * k + 2];
     DLDataType i_3 = list[i * k + 3];
     DLDevice i_4 = list[i * k + 4];
-    Object *i_5 = list[i * k + 5];
-    Object *i_6 = list[i * k + 6];
-    const char *i_7 = list[i * k + 7];
+    Object* i_5 = list[i * k + 5];
+    Object* i_6 = list[i * k + 6];
+    const char* i_7 = list[i * k + 7];
     EXPECT_EQ(i_0, integer);
     EXPECT_DOUBLE_EQ(i_1, fp);
     EXPECT_EQ(i_2, str);
@@ -150,7 +151,7 @@ TEST(List_PushBack, Heterogeneous) {
     EXPECT_EQ(i_6, nullptr);
     EXPECT_STREQ(i_7, long_str.c_str());
   }
-  auto *list_ptr = reinterpret_cast<const TVMFFIList *>(list.get());
+  auto* list_ptr = reinterpret_cast<const TVMFFIList*>(list.get());
   EXPECT_EQ(list_ptr->list_capacity, expected_capacity);
   EXPECT_EQ(list_ptr->list_length, expected_size);
   EXPECT_EQ(list_ptr->pool_capacity, expected_pool_capacity);
@@ -160,7 +161,7 @@ TEST(List_PushBack, Heterogeneous) {
 TEST(List_Insert, Once) {
   Ref<List> values = {100,
                       1.0,
-                      "Hi", //
+                      "Hi",  //
                       DLDataType{kDLInt, 32, 1},
                       DLDevice{kDLCPU, 0},
                       Ref<Object>::New(),
@@ -192,7 +193,7 @@ TEST(List_Insert, Error_0) {
   try {
     list.insert(-1, 1.0);
     FAIL() << "No exception thrown";
-  } catch (TVMError &ex) {
+  } catch (TVMError& ex) {
     EXPECT_STREQ(ex.what(), "Indexing `-1` of a list of size 3");
   }
 }
@@ -202,7 +203,7 @@ TEST(List_Insert, Error_1) {
   try {
     list.insert(4, 1.0);
     FAIL() << "No exception thrown";
-  } catch (TVMError &ex) {
+  } catch (TVMError& ex) {
     EXPECT_STREQ(ex.what(), "Indexing `4` of a list of size 3");
   }
 }
@@ -224,7 +225,7 @@ TEST(List_Resize, Expand) {
   EXPECT_EQ(int32_t(list[0]), 100);
   EXPECT_DOUBLE_EQ(double(list[1]), 1.0);
   EXPECT_STREQ(list[2], "Hi");
-  EXPECT_EQ(list[3].operator void *(), nullptr);
+  EXPECT_EQ(list[3].operator void*(), nullptr);
 }
 
 TEST(List_Reserve, Shrink) {
@@ -259,7 +260,7 @@ TEST(List_SetItem, PodToPod) {
   }
   EXPECT_EQ(list.size(), 3);
   EXPECT_EQ(list.capacity(), 3);
-  TVMFFIList *list_ptr = reinterpret_cast<TVMFFIList *>(list.get());
+  TVMFFIList* list_ptr = reinterpret_cast<TVMFFIList*>(list.get());
   EXPECT_EQ(list_ptr->list_capacity, 3);
   EXPECT_EQ(list_ptr->list_length, 3);
   EXPECT_EQ(list_ptr->pool_capacity, 24);
@@ -267,7 +268,7 @@ TEST(List_SetItem, PodToPod) {
 }
 
 TEST(List_SetItem, ObjToPod) {
-  Ref<List> list = {100, 1.0, "Hi"}; //
+  Ref<List> list = {100, 1.0, "Hi"};  //
   for (int i = 0; i < 16; ++i) {
     list[2] = i;
     EXPECT_EQ(list.size(), 3);
@@ -278,7 +279,7 @@ TEST(List_SetItem, ObjToPod) {
   }
   EXPECT_EQ(list.size(), 3);
   EXPECT_EQ(list.capacity(), 3);
-  TVMFFIList *list_ptr = reinterpret_cast<TVMFFIList *>(list.get());
+  TVMFFIList* list_ptr = reinterpret_cast<TVMFFIList*>(list.get());
   EXPECT_EQ(list_ptr->list_capacity, 3);
   EXPECT_EQ(list_ptr->list_length, 3);
   EXPECT_EQ(list_ptr->pool_capacity, 24);
@@ -292,13 +293,13 @@ TEST(List_SetItem, PodToObj) {
     list[0] = obj;
     EXPECT_EQ(list.size(), 3);
     EXPECT_EQ(list.capacity(), 3);
-    EXPECT_EQ((Object *)(list[0]), obj.get());
+    EXPECT_EQ((Object*)(list[0]), obj.get());
     EXPECT_DOUBLE_EQ(double(list[1]), 1.0);
     EXPECT_STREQ(list[2], "Hi");
   }
   EXPECT_EQ(list.size(), 3);
   EXPECT_EQ(list.capacity(), 3);
-  TVMFFIList *list_ptr = reinterpret_cast<TVMFFIList *>(list.get());
+  TVMFFIList* list_ptr = reinterpret_cast<TVMFFIList*>(list.get());
   EXPECT_EQ(list_ptr->list_capacity, 3);
   EXPECT_EQ(list_ptr->list_length, 3);
   EXPECT_EQ(list_ptr->pool_capacity, 3);
@@ -314,11 +315,11 @@ TEST(List_SetItem, ObjToObj) {
     EXPECT_EQ(list.capacity(), 3);
     EXPECT_EQ(int32_t(list[0]), 100);
     EXPECT_DOUBLE_EQ(double(list[1]), 1.0);
-    EXPECT_EQ((Object *)(list[2]), obj.get());
+    EXPECT_EQ((Object*)(list[2]), obj.get());
   }
   EXPECT_EQ(list.size(), 3);
   EXPECT_EQ(list.capacity(), 3);
-  TVMFFIList *list_ptr = reinterpret_cast<TVMFFIList *>(list.get());
+  TVMFFIList* list_ptr = reinterpret_cast<TVMFFIList*>(list.get());
   EXPECT_EQ(list_ptr->list_capacity, 3);
   EXPECT_EQ(list_ptr->list_length, 3);
   EXPECT_EQ(list_ptr->pool_capacity, 3);
@@ -356,10 +357,10 @@ TEST(List_PopBack, Heterogeneous) {
       EXPECT_PRED2(DeviceEqual, DLDevice(list[4]), device);
     }
     if (m > 5) {
-      EXPECT_EQ((Object *)(list[5]), obj.get());
+      EXPECT_EQ((Object*)(list[5]), obj.get());
     }
     if (m > 6) {
-      EXPECT_EQ((Object *)(list[6]), nullptr);
+      EXPECT_EQ((Object*)(list[6]), nullptr);
     }
   }
   EXPECT_EQ(list.size(), 0);
@@ -369,7 +370,7 @@ TEST(List_PopBack, Heterogeneous) {
   try {
     list.pop_back();
     FAIL() << "No exception thrown";
-  } catch (TVMError &ex) {
+  } catch (TVMError& ex) {
     EXPECT_STREQ(ex.what(), "Indexing `-1` of a list of size 0");
   }
 }
@@ -390,8 +391,8 @@ TEST(List_Erase, Front) {
   EXPECT_STREQ(list[1], "Hi");
   EXPECT_PRED2(DTypeEqual, DLDataType(list[2]), dtype);
   EXPECT_PRED2(DeviceEqual, DLDevice(list[3]), device);
-  EXPECT_EQ((Object *)(list[4]), obj.get());
-  EXPECT_EQ((Object *)(list[5]), nullptr);
+  EXPECT_EQ((Object*)(list[4]), obj.get());
+  EXPECT_EQ((Object*)(list[5]), nullptr);
 }
 
 TEST(List_Erase, Back) {
@@ -410,8 +411,8 @@ TEST(List_Erase, Back) {
   EXPECT_STREQ(list[1], "Hi");
   EXPECT_PRED2(DTypeEqual, DLDataType(list[2]), dtype);
   EXPECT_PRED2(DeviceEqual, DLDevice(list[3]), device);
-  EXPECT_EQ((Object *)(list[4]), obj.get());
-  EXPECT_EQ((Object *)(list[5]), nullptr);
+  EXPECT_EQ((Object*)(list[4]), obj.get());
+  EXPECT_EQ((Object*)(list[5]), nullptr);
 }
 
 TEST(List_Erase, Mid) {
@@ -430,8 +431,8 @@ TEST(List_Erase, Mid) {
   EXPECT_DOUBLE_EQ(double(list[1]), 1.0);
   EXPECT_STREQ(list[2], "Hi");
   EXPECT_PRED2(DeviceEqual, DLDevice(list[3]), device);
-  EXPECT_EQ((Object *)(list[4]), obj.get());
-  EXPECT_EQ((Object *)(list[5]), nullptr);
+  EXPECT_EQ((Object*)(list[4]), obj.get());
+  EXPECT_EQ((Object*)(list[5]), nullptr);
 }
 
 TEST(List_Iter, Test) {
@@ -458,4 +459,4 @@ TEST(List_RevIter, Test) {
   }
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/test_ref.cc b/ffi/tests/backup_cpp/test_ref.cc
similarity index 80%
rename from ffi/tests/cpp/test_ref.cc
rename to ffi/tests/backup_cpp/test_ref.cc
index 3c9dc0561d..197f2def88 100644
--- a/ffi/tests/cpp/test_ref.cc
+++ b/ffi/tests/backup_cpp/test_ref.cc
@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 #include <unordered_map>
 
@@ -7,30 +8,30 @@ using namespace tvm::ffi;
 using tvm::ffi::details::StrPad;
 using tvm::ffi::details::StrStd;
 
-using ObjDeleter = void (*)(void *);
+using ObjDeleter = void (*)(void*);
 
 struct AllocRecorder {
-  std::unordered_map<void *, ObjDeleter> deleters;
+  std::unordered_map<void*, ObjDeleter> deleters;
 
-  void Alloc(void *ptr) {
-    deleters[ptr] = reinterpret_cast<TVMFFIAny *>(ptr)->deleter;
-    reinterpret_cast<TVMFFIAny *>(ptr)->deleter = AllocRecorder::Deleter;
+  void Alloc(void* ptr) {
+    deleters[ptr] = reinterpret_cast<TVMFFIAny*>(ptr)->deleter;
+    reinterpret_cast<TVMFFIAny*>(ptr)->deleter = AllocRecorder::Deleter;
   }
 
-  void Delete(void *ptr) {
+  void Delete(void* ptr) {
     ASSERT_EQ(deleters.count(ptr), 1);
     ObjDeleter d = this->deleters[ptr];
     d(ptr);
     deleters.erase(ptr);
   }
 
-  bool IsDeletedImpl(void *ptr) { return deleters.count(ptr) == 0; }
+  bool IsDeletedImpl(void* ptr) { return deleters.count(ptr) == 0; }
 
-  static void Deleter(void *ptr) { AllocRecorder::Global()->Delete(ptr); }
+  static void Deleter(void* ptr) { AllocRecorder::Global()->Delete(ptr); }
 
-  static bool IsDeleted(void *ptr) { return 
AllocRecorder::Global()->IsDeletedImpl(ptr); }
+  static bool IsDeleted(void* ptr) { return 
AllocRecorder::Global()->IsDeletedImpl(ptr); }
 
-  static AllocRecorder *Global() {
+  static AllocRecorder* Global() {
     static AllocRecorder inst;
     return &inst;
   }
@@ -41,15 +42,15 @@ struct TestAllocator {
   using Allocator = typename ::tvm::ffi::GetAllocator<ObjectType>::Type;
 
   template <typename... Args>
-  TVM_FFI_INLINE static ObjectType *New(Args &&...args) {
-    ObjectType *ret = Allocator::New(std::forward<Args>(args)...);
+  TVM_FFI_INLINE static ObjectType* New(Args&&... args) {
+    ObjectType* ret = Allocator::New(std::forward<Args>(args)...);
     AllocRecorder::Global()->Alloc(ret);
     return ret;
   }
 
   template <typename PadType, typename... Args>
-  TVM_FFI_INLINE static ObjectType *NewWithPad(size_t pad_size, Args 
&&...args) {
-    ObjectType *ret =
+  TVM_FFI_INLINE static ObjectType* NewWithPad(size_t pad_size, Args&&... 
args) {
+    ObjectType* ret =
         Allocator::template NewWithPad<PadType>(pad_size, 
std::forward<Args>(args)...);
     AllocRecorder::Global()->Alloc(ret);
     return ret;
@@ -58,11 +59,11 @@ struct TestAllocator {
 
 int64_t FuncCall(int64_t x) { return x + 1; }
 
-int32_t GetRefCount(void *obj) { return reinterpret_cast<TVMFFIAny 
*>(obj)->ref_cnt; }
+int32_t GetRefCount(void* obj) { return 
reinterpret_cast<TVMFFIAny*>(obj)->ref_cnt; }
 
-int32_t GetTypeIndex(void *obj) { return reinterpret_cast<TVMFFIAny 
*>(obj)->type_index; }
+int32_t GetTypeIndex(void* obj) { return 
reinterpret_cast<TVMFFIAny*>(obj)->type_index; }
 
-ObjDeleter GetDeleter(void *obj) { return reinterpret_cast<TVMFFIAny 
*>(obj)->deleter; }
+ObjDeleter GetDeleter(void* obj) { return 
reinterpret_cast<TVMFFIAny*>(obj)->deleter; }
 
 TEST(Ref_Constructor_0_Default, Default) {
   Ref<Object> ref;
@@ -70,7 +71,7 @@ TEST(Ref_Constructor_0_Default, Default) {
 }
 
 TEST(Ref_Constructor_1_Ptr, SameType) {
-  Object *obj = TestAllocator<Object>::New();
+  Object* obj = TestAllocator<Object>::New();
   {
     Ref<Object> ref(obj);
     EXPECT_EQ(ref.get(), obj);
@@ -80,17 +81,17 @@ TEST(Ref_Constructor_1_Ptr, SameType) {
 }
 
 TEST(Ref_Constructor_1_Ptr, SubType) {
-  Str *obj = TestAllocator<Str>::New("Hello world");
+  Str* obj = TestAllocator<Str>::New("Hello world");
   {
     Ref<Object> ref(obj);
-    EXPECT_EQ(ref.get(), static_cast<void *>(obj));
+    EXPECT_EQ(ref.get(), static_cast<void*>(obj));
     EXPECT_EQ(GetRefCount(obj), 1);
   }
   EXPECT_TRUE(AllocRecorder::IsDeleted(obj));
 }
 
 TEST(Ref_Constructor_2_Ref, SameType_Copy) {
-  Object *obj = TestAllocator<Object>::New();
+  Object* obj = TestAllocator<Object>::New();
   {
     Ref<Object> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -104,7 +105,7 @@ TEST(Ref_Constructor_2_Ref, SameType_Copy) {
 }
 
 TEST(Ref_Constructor_2_Ref, SameType_Move) {
-  Object *obj = TestAllocator<Object>::New();
+  Object* obj = TestAllocator<Object>::New();
   {
     Ref<Object> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -118,7 +119,7 @@ TEST(Ref_Constructor_2_Ref, SameType_Move) {
 }
 
 TEST(Ref_Constructor_2_Ref, SubType_Copy) {
-  Str *obj = TestAllocator<Str>::New("Hello world");
+  Str* obj = TestAllocator<Str>::New("Hello world");
   {
     Ref<Str> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -132,7 +133,7 @@ TEST(Ref_Constructor_2_Ref, SubType_Copy) {
 }
 
 TEST(Ref_Constructor_2_Ref, SubType_Move) {
-  Str *obj = TestAllocator<Str>::New("Hello world");
+  Str* obj = TestAllocator<Str>::New("Hello world");
   {
     Ref<Str> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -146,7 +147,7 @@ TEST(Ref_Constructor_2_Ref, SubType_Move) {
 }
 
 TEST(Ref_Constructor_3_AnyView, Copy) {
-  Object *obj = TestAllocator<Object>::New();
+  Object* obj = TestAllocator<Object>::New();
   {
     Ref<Object> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -161,7 +162,7 @@ TEST(Ref_Constructor_3_AnyView, Copy) {
 }
 
 TEST(Ref_Constructor_3_AnyView, Move) {
-  Object *obj = TestAllocator<Object>::New();
+  Object* obj = TestAllocator<Object>::New();
   {
     Ref<Object> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -182,7 +183,7 @@ TEST(Ref_Constructor_3_AnyView, Move) {
 }
 
 TEST(Ref_Constructor_4_Any, Copy) {
-  Object *obj = TestAllocator<Object>::New();
+  Object* obj = TestAllocator<Object>::New();
   {
     Ref<Object> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -198,7 +199,7 @@ TEST(Ref_Constructor_4_Any, Copy) {
 }
 
 TEST(Ref_Constructor_4_Any, Move) {
-  Object *obj = TestAllocator<Object>::New();
+  Object* obj = TestAllocator<Object>::New();
   {
     Ref<Object> ref1(obj);
     EXPECT_EQ(GetRefCount(obj), 1);
@@ -231,7 +232,7 @@ TEST(Ref_New, Func) {
 }
 
 TEST(Ref_New, RawStr) {
-  const char *str = "Hello world";
+  const char* str = "Hello world";
   Ref<Str> ref = Ref<Str>::New(str);
   EXPECT_EQ(GetTypeIndex(ref.get()), 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
   EXPECT_EQ(GetRefCount(ref.get()), 1);
@@ -283,11 +284,11 @@ TEST(Ref_Stringify, Str) {
 }
 
 TEST(Ref_Misc, MoveToRaw) {
-  TVMFFIAny *str = reinterpret_cast<TVMFFIAny *>(Ref<Str>::New("Hello 
world").MoveToRawObjPtr());
+  TVMFFIAny* str = reinterpret_cast<TVMFFIAny*>(Ref<Str>::New("Hello 
world").MoveToRawObjPtr());
   EXPECT_EQ(GetTypeIndex(str), 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
   EXPECT_EQ(GetRefCount(str), 1);
   EXPECT_EQ(GetDeleter(str), DefaultObjectAllocator<StrPad>::Deleter);
   str->deleter(str);
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/test_str.cc b/ffi/tests/backup_cpp/test_str.cc
similarity index 81%
rename from ffi/tests/cpp/test_str.cc
rename to ffi/tests/backup_cpp/test_str.cc
index bd91f241f6..c0b38c2935 100644
--- a/ffi/tests/cpp/test_str.cc
+++ b/ffi/tests/backup_cpp/test_str.cc
@@ -1,11 +1,13 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 
 namespace {
 using namespace tvm::ffi;
 
-const char c_str_long[] = "Hello, World! This is an extremely long string to "
-                          "avoid any on-stack optimization.";
+const char c_str_long[] =
+    "Hello, World! This is an extremely long string to "
+    "avoid any on-stack optimization.";
 
 TEST(Str, CopyFromStdString) {
   std::string std_str = "Hello, World!";
@@ -17,9 +19,9 @@ TEST(Str, CopyFromStdString) {
 
 TEST(Str, MoveFromStdString_0) {
   std::string std_str = c_str_long;
-  const void *data = std_str.data();
+  const void* data = std_str.data();
   Ref<Str> str = Ref<Str>::New(std::move(std_str));
-  EXPECT_EQ(static_cast<const void *>(str->data()), data);
+  EXPECT_EQ(static_cast<const void*>(str->data()), data);
   EXPECT_STREQ(str->c_str(), c_str_long);
 }
 
@@ -44,4 +46,4 @@ TEST(Str, CopyFromCharArray) {
   EXPECT_EQ(str->size(), 17);
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/test_type_dyn.cc 
b/ffi/tests/backup_cpp/test_type_dyn.cc
similarity index 82%
rename from ffi/tests/cpp/test_type_dyn.cc
rename to ffi/tests/backup_cpp/test_type_dyn.cc
index 45910528b3..b93595dc3b 100644
--- a/ffi/tests/cpp/test_type_dyn.cc
+++ b/ffi/tests/backup_cpp/test_type_dyn.cc
@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 
 #if TVM_FFI_ALLOW_DYN_TYPE == 1
@@ -18,8 +19,7 @@ struct SubTestObj : public TestObj {
   TVM_FFI_DEF_DYN_TYPE(SubTestObj, TestObj, "test.SubTestObj");
 };
 
-void CheckAncestor(int32_t num, const int32_t *ancestors,
-                   std::vector<int32_t> expected) {
+void CheckAncestor(int32_t num, const int32_t* ancestors, std::vector<int32_t> 
expected) {
   EXPECT_EQ(num, expected.size());
   for (int i = 0; i < num; ++i) {
     EXPECT_EQ(ancestors[i], expected[i]);
@@ -27,8 +27,7 @@ void CheckAncestor(int32_t num, const int32_t *ancestors,
 }
 
 TEST(DynTypeInfo, TestObj) {
-  EXPECT_GE(TestObj::_type_index,
-            static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDynObjectBegin));
+  EXPECT_GE(TestObj::_type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDynObjectBegin));
   EXPECT_STRCASEEQ(TestObj::_type_key, "test.TestObj");
   EXPECT_EQ(TestObj::_type_depth, 1);
   CheckAncestor(TestObj::_type_depth, TestObj::_type_ancestors.data(),
@@ -36,14 +35,12 @@ TEST(DynTypeInfo, TestObj) {
 }
 
 TEST(DynTypeInfo, SubTestObj) {
-  EXPECT_GE(SubTestObj::_type_index,
-            static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDynObjectBegin));
+  EXPECT_GE(SubTestObj::_type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDynObjectBegin));
   EXPECT_NE(SubTestObj::_type_index, TestObj::_type_index);
   EXPECT_STRCASEEQ(SubTestObj::_type_key, "test.SubTestObj");
   EXPECT_EQ(SubTestObj::_type_depth, 2);
   CheckAncestor(SubTestObj::_type_depth, SubTestObj::_type_ancestors.data(),
-                {static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject),
-                 TestObj::_type_index});
+                {static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject), 
TestObj::_type_index});
 }
 
 TEST(DynTypeInheritance, TestObj) {
@@ -66,6 +63,6 @@ TEST(DynTypeInheritance, SubTestObj) {
   EXPECT_FALSE(obj->IsInstance<Str>());
 }
 
-} // namespace
+}  // namespace
 
 #endif
diff --git a/ffi/tests/cpp/test_type_static.cc 
b/ffi/tests/backup_cpp/test_type_static.cc
similarity index 87%
rename from ffi/tests/cpp/test_type_static.cc
rename to ffi/tests/backup_cpp/test_type_static.cc
index aebeba7c3e..abb21af2f5 100644
--- a/ffi/tests/cpp/test_type_static.cc
+++ b/ffi/tests/backup_cpp/test_type_static.cc
@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+
 #include <tvm/ffi/ffi.hpp>
 
 namespace {
@@ -15,8 +16,7 @@ struct SubType : public Object {
 
 int64_t FuncCall(int64_t x) { return x + 1; }
 
-void CheckAncestor(int32_t num, const int32_t *ancestors,
-                   std::vector<int32_t> expected) {
+void CheckAncestor(int32_t num, const int32_t* ancestors, std::vector<int32_t> 
expected) {
   EXPECT_EQ(num, expected.size());
   for (int i = 0; i < num; ++i) {
     EXPECT_EQ(ancestors[i], expected[i]);
@@ -28,16 +28,14 @@ static_assert(IsObject<Func>, "IsObject<Func> == true");
 static_assert(IsObject<Str>, "IsObject<Str> == true");
 
 TEST(StaticTypeInfo, Object) {
-  EXPECT_EQ(Object::_type_index,
-            static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
+  EXPECT_EQ(Object::_type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
   EXPECT_STRCASEEQ(Object::_type_key, "object.Object");
   EXPECT_EQ(Object::_type_depth, 0);
   CheckAncestor(Object::_type_depth, Object::_type_ancestors.data(), {});
 }
 
 TEST(StaticTypeInfo, Func) {
-  EXPECT_EQ(Func::_type_index,
-            static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc));
+  EXPECT_EQ(Func::_type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc));
   EXPECT_STRCASEEQ(Func::_type_key, "object.Func");
   EXPECT_EQ(Func::_type_depth, 1);
   CheckAncestor(Func::_type_depth, Func::_type_ancestors.data(),
@@ -45,8 +43,7 @@ TEST(StaticTypeInfo, Func) {
 }
 
 TEST(StaticTypeInfo, Str) {
-  EXPECT_EQ(Str::_type_index,
-            static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
+  EXPECT_EQ(Str::_type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
   EXPECT_STRCASEEQ(Str::_type_key, "object.Str");
   EXPECT_EQ(Str::_type_depth, 1);
   CheckAncestor(Str::_type_depth, Str::_type_ancestors.data(),
@@ -111,9 +108,9 @@ TEST(StaticTypeSubclass, Exception) {
   try {
     Ref<SubType>::New(1);
     FAIL() << "No exception thrown";
-  } catch (std::runtime_error &ex) {
+  } catch (std::runtime_error& ex) {
     EXPECT_STREQ(ex.what(), "New Error");
   }
 }
 
-} // namespace
+}  // namespace
diff --git a/ffi/tests/cpp/CMakeLists.txt b/ffi/tests/cpp/CMakeLists.txt
index 539115f24d..62543756b9 100644
--- a/ffi/tests/cpp/CMakeLists.txt
+++ b/ffi/tests/cpp/CMakeLists.txt
@@ -17,8 +17,8 @@ set_target_properties(
 add_cxx_warning(tvm_ffi_tests)
 add_sanitizer_address(tvm_ffi_tests)
 target_link_libraries(tvm_ffi_tests PRIVATE tvm_ffi)
-if (TVM_FFI_ALLOW_DYN_TYPE)
-  add_sanitizer_address(tvm_ffi_registry_shared)
+
+if (TVM_FFI_BUILD_REGISTRY)
   target_link_libraries(tvm_ffi_tests PRIVATE tvm_ffi_registry_shared)
 endif()
 
diff --git a/ffi/tests/cpp/test_any.cc b/ffi/tests/cpp/test_any.cc
index a57829bd0a..2cb3e8b95b 100644
--- a/ffi/tests/cpp/test_any.cc
+++ b/ffi/tests/cpp/test_any.cc
@@ -1,635 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 #include <gtest/gtest.h>
-#include <tvm/ffi/ffi.hpp>
+#include <tvm/ffi/any.h>
+#include <tvm/ffi/memory.h>
 
-namespace {
-using namespace tvm::ffi;
-
-template <typename SrcType, typename Checker>
-void TestAnyConstructor(Checker check, TVMFFITypeIndex expected_type_index, 
const SrcType &source) {
-  Any v(source);
-  EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
-  EXPECT_EQ(v.ref_cnt, 0);
-  check(&v, source);
-};
-
-int64_t FuncCall(int64_t x) { return x + 1; }
-
-std::vector<Any> AnyArrayFactory() {
-  return std::vector<Any>{
-      Any(nullptr),
-      Any(1),
-      Any(2.5),
-      Any(reinterpret_cast<void *>(FuncCall)),
-      Any(DLDevice{kDLCPU, 0}),
-      Any(DLDataType{kDLInt, 32, 1}),
-      Any("Hello (raw str)"),
-      Any(Ref<Object>::New()),
-      Any(Ref<Func>::New(FuncCall)),
-      Any(std::string("World (std::string)")),
-      Any(Ref<Str>::New("Hello World (Ref<Str>)")),
-  };
-}
-
-template <typename SrcType>
-void TestAnyStringify(const SrcType &source, TVMFFITypeIndex 
expected_type_index,
-                      const std::string &expected) {
-  Any v(source);
-  EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
-  EXPECT_EQ(v.str()->c_str(), expected);
-}
-
-template <typename SrcType, typename Checker>
-void TestAnyStringifyChecker(const SrcType &source, TVMFFITypeIndex 
expected_type_index,
-                             Checker check) {
-  Any v(source);
-  EXPECT_EQ(v.type_index, static_cast<int32_t>(expected_type_index));
-  check(v);
-}
-
-void CheckAnyRefCnt(const TVMFFIAny *v) {
-  if (v->type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
-    EXPECT_EQ(v->v_obj->ref_cnt, 1);
-  }
-}
-
-TEST(Any_Constructor_0_Default, Default) {
-  Any v;
-  EXPECT_EQ(v.type_index, 0);
-  EXPECT_EQ(v.ref_cnt, 0);
-  EXPECT_EQ(v.v_int64, 0);
-}
-
-TEST(Any_Constructor_1_Any, Copy) {
-  Any v1(1);
-  Any v2(v1);
-  EXPECT_EQ(v1.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt));
-  EXPECT_EQ(v1.v_int64, 1);
-  EXPECT_EQ(v2.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt));
-  EXPECT_EQ(v2.v_int64, 1);
-}
-
-TEST(Any_Constructor_1_Any, Move) {
-  Any v1(1);
-  Any v2(std::move(v1));
-  EXPECT_EQ(v1.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone));
-  EXPECT_EQ(v1.v_int64, 0);
-  EXPECT_EQ(v2.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt));
-  EXPECT_EQ(v2.v_int64, 1);
-}
-
-TEST(Any_Constructor_2_AnyView, Copy) {
-  AnyView v1(1);
-  Any v2(v1);
-  EXPECT_EQ(v1.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt));
-  EXPECT_EQ(v1.v_int64, 1);
-  EXPECT_EQ(v2.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt));
-  EXPECT_EQ(v2.v_int64, 1);
-}
-
-TEST(Any_Constructor_2_AnyView, Move) {
-  AnyView v1(1);
-  Any v2(std::move(v1));
-  EXPECT_EQ(v1.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone));
-  EXPECT_EQ(v1.v_int64, 0);
-  EXPECT_EQ(v2.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt));
-  EXPECT_EQ(v2.v_int64, 1);
-}
-
-TEST(Any_Constructor_3_Ref, Copy) {
-  Ref<Object> obj = Ref<Object>::New();
-  Any v(obj);
-  const TVMFFIAny *v_obj = v.v_obj;
-  EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
-  EXPECT_EQ(v.ref_cnt, 0);
-  EXPECT_EQ(v_obj, static_cast<const void *>(obj.get()));
-  EXPECT_EQ(v_obj->ref_cnt, 2);
-}
+#include "./testing_object.h"
 
-TEST(Any_Constructor_3_Ref, Move) {
-  Ref<Object> obj = Ref<Object>::New();
-  Any v(std::move(obj));
-  const TVMFFIAny *v_obj = v.v_obj;
-  EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
-  EXPECT_EQ(v.ref_cnt, 0);
-  EXPECT_EQ(v_obj->ref_cnt, 1);
-  EXPECT_EQ(obj.get(), nullptr);
-}
-
-TEST(Any_Constructor_4_TypeTraits, Integer) {
-  auto check = [](TVMFFIAny *v, int64_t source) -> void { 
EXPECT_EQ(v->v_int64, source); };
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int8_t>(1));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int16_t>(2));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int32_t>(3));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<int64_t>(4));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<uint8_t>(1));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<uint16_t>(2));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<uint32_t>(3));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIInt, 
static_cast<uint64_t>(4));
-}
-
-TEST(Any_Constructor_4_TypeTraits, Float) {
-  auto check = [](TVMFFIAny *v, double source) -> void { 
EXPECT_EQ(v->v_float64, source); };
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIFloat, 
static_cast<float>(3));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIFloat, 
static_cast<float>(4));
-}
-
-TEST(Any_Constructor_4_TypeTraits, Ptr) {
-  int p = 4;
-  auto check = [](TVMFFIAny *v, void *source) -> void { EXPECT_EQ(v->v_ptr, 
source); };
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFINone, static_cast<void 
*>(nullptr));
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIPtr, static_cast<void 
*>(&p));
-}
-
-TEST(Any_Constructor_4_TypeTraits, Device) {
-  auto check = [](TVMFFIAny *v, const DLDevice &source) -> void {
-    EXPECT_EQ(v->v_device.device_type, source.device_type);
-    EXPECT_EQ(v->v_device.device_id, source.device_id);
-  };
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIDevice, DLDevice{kDLCPU, 
0});
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIDevice, DLDevice{kDLCUDA, 
1});
-}
-
-TEST(Any_Constructor_4_TypeTraits, DataType) {
-  auto check = [](TVMFFIAny *v, const DLDataType &source) -> void {
-    EXPECT_EQ(v->v_dtype.code, source.code);
-    EXPECT_EQ(v->v_dtype.bits, source.bits);
-    EXPECT_EQ(v->v_dtype.lanes, source.lanes);
-  };
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIDataType, 
DLDataType{kDLInt, 32, 1});
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIDataType, 
DLDataType{kDLUInt, 0, 0});
-}
-
-TEST(Any_Constructor_4_TypeTraits, RawStr) {
-  auto check = [](TVMFFIAny *v, const char *source) -> void {
-    Str *str = static_cast<Str *>(v->v_ptr);
-    EXPECT_STREQ(str->c_str(), source);
-  };
-  const char *empty = "";
-  const char *hello = "hello";
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, empty);
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, hello);
-}
-
-TEST(Any_Constructor_4_TypeTraits, CharArray) {
-  auto check = [](TVMFFIAny *v, const char *source) -> void {
-    Str *str = static_cast<Str *>(v->v_ptr);
-    EXPECT_STREQ(str->c_str(), source);
-  };
-  const char empty[] = "";
-  const char hello[] = "hello";
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, empty);
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, hello);
-}
-
-TEST(Any_Constructor_4_TypeTraits, StdString) {
-  auto check = [](TVMFFIAny *v, const std::string &source) -> void {
-    Str *str = static_cast<Str *>(v->v_ptr);
-    EXPECT_EQ(str->c_str(), source);
-  };
-  std::string empty = "";
-  std::string hello = "hello";
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, hello);
-  TestAnyConstructor(check, TVMFFITypeIndex::kTVMFFIStr, empty);
-}
-
-TEST(Any_Constructor_5_Object_Ptr, Object) {
-  Ref<Object> obj = Ref<Object>::New();
-  TVMFFIAny *ptr = reinterpret_cast<TVMFFIAny *>(obj.get());
-  {
-    Any v(obj.get());
-    EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIObject));
-    EXPECT_EQ(v.v_obj->ref_cnt, 2);
-    EXPECT_EQ(v.v_obj, ptr);
-  }
-  EXPECT_EQ(ptr->ref_cnt, 1);
-}
-
-TEST(Any_Constructor_5_Object_Ptr, Func) {
-  Ref<Func> func = Ref<Func>::New(FuncCall);
-  TVMFFIAny *ptr = reinterpret_cast<TVMFFIAny *>(func.get());
-  {
-    Any v(func.get());
-    EXPECT_EQ(v.type_index, 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc));
-    EXPECT_EQ(v.v_obj->ref_cnt, 2);
-    EXPECT_EQ(v.v_obj, ptr);
-  }
-  EXPECT_EQ(ptr->ref_cnt, 1);
-}
-
-TEST(Any_Constructor_5_Object_Ptr, Str) {
-  Ref<Str> str = Ref<Str>::New("hello");
-  TVMFFIAny *ptr = reinterpret_cast<TVMFFIAny *>(str.get());
-  {
-    Any v(str.get());
-    EXPECT_EQ(v.type_index, static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr));
-    EXPECT_EQ(v.v_obj->ref_cnt, 2);
-    EXPECT_EQ(v.v_obj, ptr);
-  }
-  EXPECT_EQ(ptr->ref_cnt, 1);
-}
-
-TEST(Any_Converter_0_TypeTraits, Integer) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> int64_t { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt)) {
-      EXPECT_EQ(convert(), 1);
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `int`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_0_TypeTraits, Float) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> double { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIInt)) {
-      EXPECT_EQ(convert(), 1.0);
-    } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFloat)) {
-      EXPECT_EQ(convert(), 2.5);
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `float`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_0_TypeTraits, Ptr) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> void * { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      EXPECT_EQ(convert(), nullptr);
-    } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIPtr)) {
-      EXPECT_EQ(convert(), reinterpret_cast<void *>(&FuncCall));
-    } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIRawStr)) {
-      EXPECT_EQ(convert(), v.v_str);
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `Ptr`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_0_TypeTraits, Device) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> DLDevice { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDevice)) {
-      EXPECT_EQ(convert().device_type, kDLCPU);
-      EXPECT_EQ(convert().device_id, 0);
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `Device`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_0_TypeTraits, DataType) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> DLDataType { return v; };
-    if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIDataType)) {
-      EXPECT_EQ(convert().code, kDLInt);
-      EXPECT_EQ(convert().bits, 32);
-      EXPECT_EQ(convert().lanes, 1);
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index) 
<< "` to `dtype`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_0_TypeTraits, RawStr) {
-  std::vector<Any> vs = AnyArrayFactory();
-  int counter = 0;
-  for (const Any &v : vs) {
-    auto convert = [&]() -> const char * { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr)) {
-      ++counter;
-      EXPECT_LE(counter, 3);
-      if (counter == 1) {
-        EXPECT_STREQ(convert(), "Hello (raw str)");
-      } else if (counter == 2) {
-        EXPECT_STREQ(convert(), "World (std::string)");
-      } else if (counter == 3) {
-        EXPECT_STREQ(convert(), "Hello World (Ref<Str>)");
-      }
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
-           << "` to `const char *`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_1_AnyView, Any) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> AnyView { return v; };
-    {
-      AnyView ret = convert();
-      EXPECT_EQ(ret.type_index, v.type_index);
-      EXPECT_EQ(ret.ref_cnt, 0);
-      EXPECT_EQ(v.ref_cnt, 0);
-      EXPECT_EQ(ret.v_obj, v.v_obj);
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_2_Ref, Object) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> Ref<Object> { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Ref<Object> ret = convert();
-      EXPECT_EQ(ret.get(), nullptr);
-    } else if (v.type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
-      Ref<Object> ret = convert();
-      EXPECT_EQ(ret.get(), static_cast<void *>(v.v_obj));
-      EXPECT_EQ(v.v_obj->ref_cnt, 2);
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
-           << "` to `object.Object`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_2_Ref, Func) {
-  std::vector<Any> views = AnyArrayFactory();
-  for (const Any &v : views) {
-    auto convert = [&]() -> Ref<Func> { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Ref<Func> ret = convert();
-      EXPECT_EQ(ret.get(), nullptr);
-    } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc)) {
-      Ref<Func> ret = convert();
-      EXPECT_EQ(ret.get(), static_cast<void *>(v.v_obj));
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
-           << "` to `object.Func`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_2_Ref, Str) {
-  int counter = 0;
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> Ref<Str> { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Ref<Str> ret = convert();
-      EXPECT_EQ(ret.get(), nullptr);
-    } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr)) {
-      Ref<Str> ret = convert();
-      ++counter;
-      EXPECT_LE(counter, 3);
-      if (counter == 1) {
-        EXPECT_STREQ(ret->c_str(), "Hello (raw str)");
-      } else if (counter == 2) {
-        EXPECT_STREQ(ret->c_str(), "World (std::string)");
-      } else {
-        EXPECT_STREQ(ret->c_str(), "Hello World (Ref<Str>)");
-      }
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
-           << "` to `object.Str`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_3_Object_Ptr, Object) {
-  std::vector<Any> vs = AnyArrayFactory();
-  for (const Any &v : vs) {
-    auto convert = [&]() -> Object * { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Object *ret = convert();
-      EXPECT_EQ(ret, nullptr);
-    } else if (v.type_index >= 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStaticObjectBegin)) {
-      Object *ret = convert();
-      EXPECT_EQ(ret, static_cast<void *>(v.v_obj));
-      EXPECT_EQ(v.v_obj->ref_cnt, 1);
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
-           << "` to `object.Object *`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_3_Object_Ptr, Func) {
-  std::vector<Any> views = AnyArrayFactory();
-  for (const Any &v : views) {
-    auto convert = [&]() -> Func * { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Func *ret = convert();
-      EXPECT_EQ(ret, nullptr);
-    } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIFunc)) {
-      Func *ret = convert();
-      EXPECT_EQ(ret, reinterpret_cast<Func *>(v.v_ptr));
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
-           << "` to `object.Func *`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Converter_3_Object_Ptr, Str) {
-  std::vector<Any> vs = AnyArrayFactory();
-  int counter = 0;
-  for (const Any &v : vs) {
-    auto convert = [&]() -> Str * { return v; };
-    if (v.type_index == static_cast<int32_t>(TVMFFITypeIndex::kTVMFFINone)) {
-      Str *ret = convert();
-      EXPECT_EQ(ret, nullptr);
-    } else if (v.type_index == 
static_cast<int32_t>(TVMFFITypeIndex::kTVMFFIStr)) {
-      Str *ret = convert();
-      ++counter;
-      EXPECT_LE(counter, 3);
-      if (counter == 1) {
-        EXPECT_STREQ(ret->c_str(), "Hello (raw str)");
-      } else if (counter == 2) {
-        EXPECT_STREQ(ret->c_str(), "World (std::string)");
-      } else {
-        EXPECT_STREQ(ret->c_str(), "Hello World (Ref<Str>)");
-      }
-    } else {
-      try {
-        convert();
-        FAIL() << "No exception thrown";
-      } catch (TVMError &ex) {
-        std::ostringstream os;
-        os << "Cannot convert from type `" << TypeIndex2TypeKey(v.type_index)
-           << "` to `object.Str *`";
-        EXPECT_EQ(ex.what(), os.str());
-      }
-    }
-    CheckAnyRefCnt(&v);
-  }
-}
-
-TEST(Any_Stringify, Integer) {
-  TestAnyStringify<int8_t>(-13, TVMFFITypeIndex::kTVMFFIInt, "-13");
-  TestAnyStringify<int16_t>(-5, TVMFFITypeIndex::kTVMFFIInt, "-5");
-  TestAnyStringify<int32_t>(0, TVMFFITypeIndex::kTVMFFIInt, "0");
-  TestAnyStringify<int64_t>(1, TVMFFITypeIndex::kTVMFFIInt, "1");
-}
-
-TEST(Any_Stringify, Float) {
-  auto check = [](const Any &v) -> void {
-    std::string str = v.str()->c_str();
-    double f_str = std::stod(str);
-    double f_src = v.v_float64;
-    EXPECT_NEAR(f_src, f_str, 1e-5);
-  };
-  TestAnyStringifyChecker<float>(float(-3.14), TVMFFITypeIndex::kTVMFFIFloat, 
check);
-  TestAnyStringifyChecker<double>(0.0, TVMFFITypeIndex::kTVMFFIFloat, check);
-}
-
-TEST(Any_Stringify, Ptr) {
-  auto check = [](const Any &v) -> void {
-    std::string str = v.str()->c_str();
-    EXPECT_GT(str.size(), 2);
-  };
-  TestAnyStringify<void *>(nullptr, TVMFFITypeIndex::kTVMFFINone, "None");
-  TestAnyStringifyChecker<void *>(reinterpret_cast<void *>(FuncCall), 
TVMFFITypeIndex::kTVMFFIPtr,
-                                  check);
-}
-
-TEST(Any_Stringify, Device) {
-  TestAnyStringify<DLDevice>(DLDevice{kDLCPU, 0}, 
TVMFFITypeIndex::kTVMFFIDevice, "cpu:0");
-  TestAnyStringify<DLDevice>(DLDevice{kDLCUDA, 1}, 
TVMFFITypeIndex::kTVMFFIDevice, "cuda:1");
-}
-
-TEST(Any_Stringify, DataType) {
-  TestAnyStringify<DLDataType>(DLDataType{kDLInt, 32, 1}, 
TVMFFITypeIndex::kTVMFFIDataType,
-                               "int32");
-  TestAnyStringify<DLDataType>(DLDataType{kDLUInt, 1, 1}, 
TVMFFITypeIndex::kTVMFFIDataType, "bool");
-  TestAnyStringify<DLDataType>(DLDataType{kDLOpaqueHandle, 0, 0}, 
TVMFFITypeIndex::kTVMFFIDataType,
-                               "void");
-  TestAnyStringify<DLDataType>(DLDataType{kDLFloat, 8, 4}, 
TVMFFITypeIndex::kTVMFFIDataType,
-                               "float8x4");
-}
-
-TEST(Any_Stringify, RawStr) {
-  TestAnyStringify<const char *>("Hello", TVMFFITypeIndex::kTVMFFIStr, 
"\"Hello\"");
-  TestAnyStringify<char[6]>("Hello", TVMFFITypeIndex::kTVMFFIStr, "\"Hello\"");
-  TestAnyStringify<const char[6]>("Hello", TVMFFITypeIndex::kTVMFFIStr, 
"\"Hello\"");
-}
-
-TEST(Any_Stringify, Object) {
-  auto check = [](const Any &v) -> void {
-    std::string expected_prefix = "object.Object@0";
-    int n = static_cast<int>(expected_prefix.size());
-    std::string str = v.str()->c_str();
-    EXPECT_GT(str.size(), n);
-    EXPECT_EQ(str.substr(0, n), expected_prefix);
-  };
-  TestAnyStringifyChecker<Ref<Object>>(Ref<Object>::New(), 
TVMFFITypeIndex::kTVMFFIObject, check);
-}
-
-TEST(Any_Stringify, Func) {
-  auto check = [](const Any &v) -> void {
-    std::string expected_prefix = "object.Func@0";
-    int n = static_cast<int>(expected_prefix.size());
-    std::string str = v.str()->c_str();
-    EXPECT_GT(str.size(), n);
-    EXPECT_EQ(str.substr(0, n), expected_prefix);
-  };
-  TestAnyStringifyChecker<Ref<Func>>(Ref<Func>::New(FuncCall), 
TVMFFITypeIndex::kTVMFFIFunc, check);
-}
-
-TEST(Any_Stringify, Str) {
-  auto check = [](const Any &v) -> void {
-    std::string str = v.str()->c_str();
-    EXPECT_EQ(str, "\"Hello World\"");
-  };
-  TestAnyStringifyChecker<Ref<Str>>(Ref<Str>::New("Hello World"), 
TVMFFITypeIndex::kTVMFFIStr,
-                                    check);
-}
+namespace {
 
-} // namespace
+using namespace tvm::ffi;
+using namespace tvm::ffi::testing;
+
+TEST(Any, Int) {
+  AnyView view0;
+  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFINone);
+
+  std::optional<int64_t> opt_v0 = view0.TryAs<int64_t>();
+  EXPECT_TRUE(!opt_v0.has_value());
+
+  EXPECT_THROW(
+      {
+        try {
+          [[maybe_unused]] int64_t v0 = view0;
+        } catch (const Error& error) {
+          EXPECT_EQ(error->kind, "TypeError");
+          std::string what = error.what();
+          EXPECT_NE(what.find("Cannot convert from type `None` to `int`"), 
std::string::npos);
+          throw;
+        }
+      },
+      ::tvm::ffi::Error);
+
+  AnyView view1 = 1;
+  EXPECT_EQ(view1.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIInt);
+  EXPECT_EQ(view1.CopyToTVMFFIAny().v_int64, 1);
+
+  int32_t int_v1 = view1;
+  EXPECT_EQ(int_v1, 1);
+
+  int64_t v1 = 2;
+  view0 = v1;
+  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIInt);
+  EXPECT_EQ(view0.CopyToTVMFFIAny().v_int64, 2);
+}
+
+TEST(Any, Float) {
+  AnyView view0;
+  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFINone);
+
+  std::optional<double> opt_v0 = view0.TryAs<double>();
+  EXPECT_TRUE(!opt_v0.has_value());
+
+  EXPECT_THROW(
+      {
+        try {
+          [[maybe_unused]] double v0 = view0;
+        } catch (const Error& error) {
+          EXPECT_EQ(error->kind, "TypeError");
+          std::string what = error.what();
+          EXPECT_NE(what.find("Cannot convert from type `None` to `float`"), 
std::string::npos);
+          throw;
+        }
+      },
+      ::tvm::ffi::Error);
+
+  AnyView view1_int = 1;
+  float float_v1 = view1_int;
+  EXPECT_EQ(float_v1, 1);
+
+  AnyView view2 = 2.2;
+  EXPECT_EQ(view2.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIFloat);
+  EXPECT_EQ(view2.CopyToTVMFFIAny().v_float64, 2.2);
+
+  float v1 = 2;
+  view0 = v1;
+  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIFloat);
+  EXPECT_EQ(view0.CopyToTVMFFIAny().v_float64, 2);
+}
+
+TEST(Any, Object) {
+  AnyView view0;
+  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFINone);
+
+  // int object is not nullable
+  std::optional<TInt> opt_v0 = view0.TryAs<TInt>();
+  EXPECT_TRUE(!opt_v0.has_value());
+
+  TInt v1(11);
+  EXPECT_EQ(v1.use_count(), 1);
+  // view won't increase refcount
+  AnyView view1 = v1;
+  EXPECT_EQ(v1.use_count(), 1);
+  // any will trigger ref count increase
+  Any any1 = v1;
+  EXPECT_EQ(v1.use_count(), 2);
+  // copy to another view
+  AnyView view2 = any1;
+  EXPECT_EQ(v1.use_count(), 2);
+
+  // convert to weak raw object ptr
+  const TIntObj* v1_ptr = view2;
+  EXPECT_EQ(v1.use_count(), 2);
+  EXPECT_EQ(v1_ptr->value, 11);
+  Any any2 = v1_ptr;
+  EXPECT_EQ(v1.use_count(), 3);
+  EXPECT_TRUE(any2.TryAs<TInt>().has_value());
+
+  // convert to raw opaque ptr
+  void* raw_v1_ptr = const_cast<TIntObj*>(v1_ptr);
+  any2 = raw_v1_ptr;
+  EXPECT_TRUE(any2.TryAs<void*>().value() == v1_ptr);
+
+  // convert to ObjectPtr
+  ObjectPtr<TNumberObj> v1_obj_ptr = view2;
+  EXPECT_EQ(v1.use_count(), 3);
+  any2 = v1_obj_ptr;
+  EXPECT_EQ(v1.use_count(), 4);
+  EXPECT_TRUE(any2.TryAs<TInt>().has_value());
+  any2.reset();
+  v1_obj_ptr.reset();
+
+  // convert that triggers error
+  EXPECT_THROW(
+      {
+        try {
+          [[maybe_unused]] TFloat v0 = view1;
+        } catch (const Error& error) {
+          EXPECT_EQ(error->kind, "TypeError");
+          std::string what = error.what();
+          std::cout << what;
+          EXPECT_NE(what.find("Cannot convert from type `test.Int` to 
`test.Float`"),
+                    std::string::npos);
+          throw;
+        }
+      },
+      ::tvm::ffi::Error);
+  // Try to convert to number
+  TNumber number0 = any1;
+  EXPECT_EQ(v1.use_count(), 3);
+  EXPECT_TRUE(number0.as<TIntObj>());
+  EXPECT_EQ(number0.as<TIntObj>()->value, 11);
+  EXPECT_TRUE(!any1.TryAs<int>().has_value());
+
+  TInt int1 = view2;
+  EXPECT_EQ(v1.use_count(), 4);
+  any1.reset();
+  EXPECT_EQ(v1.use_count(), 3);
+}
+
+}  // namespace
diff --git a/ffi/tests/example/test_array.cc b/ffi/tests/cpp/test_array.cc
similarity index 100%
rename from ffi/tests/example/test_array.cc
rename to ffi/tests/cpp/test_array.cc
diff --git a/ffi/tests/example/test_c_ffi_abi.cc 
b/ffi/tests/cpp/test_c_ffi_abi.cc
similarity index 100%
rename from ffi/tests/example/test_c_ffi_abi.cc
rename to ffi/tests/cpp/test_c_ffi_abi.cc
diff --git a/ffi/tests/example/test_error.cc b/ffi/tests/cpp/test_error.cc
similarity index 100%
rename from ffi/tests/example/test_error.cc
rename to ffi/tests/cpp/test_error.cc
diff --git a/ffi/tests/example/test_function.cc b/ffi/tests/cpp/test_function.cc
similarity index 100%
rename from ffi/tests/example/test_function.cc
rename to ffi/tests/cpp/test_function.cc
diff --git a/ffi/tests/example/test_map.cc b/ffi/tests/cpp/test_map.cc
similarity index 100%
rename from ffi/tests/example/test_map.cc
rename to ffi/tests/cpp/test_map.cc
diff --git a/ffi/tests/example/test_object.cc b/ffi/tests/cpp/test_object.cc
similarity index 96%
rename from ffi/tests/example/test_object.cc
rename to ffi/tests/cpp/test_object.cc
index f931c99419..ed3361a0ba 100644
--- a/ffi/tests/example/test_object.cc
+++ b/ffi/tests/cpp/test_object.cc
@@ -47,7 +47,7 @@ TEST(Object, RefCounter) {
 }
 
 TEST(Object, TypeInfo) {
-  const TypeInfo* info = 
tvm::ffi::details::ObjectGetTypeInfo(TIntObj::RuntimeTypeIndex());
+  const TypeInfo* info = TVMFFIGetTypeInfo(TIntObj::RuntimeTypeIndex());
   EXPECT_TRUE(info != nullptr);
   EXPECT_EQ(info->type_index, TIntObj::RuntimeTypeIndex());
   EXPECT_EQ(info->type_depth, 2);
diff --git a/ffi/tests/example/test_optional.cc b/ffi/tests/cpp/test_optional.cc
similarity index 100%
rename from ffi/tests/example/test_optional.cc
rename to ffi/tests/cpp/test_optional.cc
diff --git a/ffi/tests/example/test_string.cc b/ffi/tests/cpp/test_string.cc
similarity index 100%
rename from ffi/tests/example/test_string.cc
rename to ffi/tests/cpp/test_string.cc
diff --git a/ffi/tests/example/testing_object.h b/ffi/tests/cpp/testing_object.h
similarity index 100%
rename from ffi/tests/example/testing_object.h
rename to ffi/tests/cpp/testing_object.h
diff --git a/ffi/tests/example/test_any.cc b/ffi/tests/example/test_any.cc
deleted file mode 100644
index 36d4783dc5..0000000000
--- a/ffi/tests/example/test_any.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-#include <gtest/gtest.h>
-#include <tvm/ffi/any.h>
-#include <tvm/ffi/memory.h>
-
-#include "./testing_object.h"
-
-namespace {
-
-using namespace tvm::ffi;
-using namespace tvm::ffi::testing;
-
-TEST(Any, Int) {
-  AnyView view0;
-  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFINone);
-
-  std::optional<int64_t> opt_v0 = view0.TryAs<int64_t>();
-  EXPECT_TRUE(!opt_v0.has_value());
-
-  EXPECT_THROW(
-      {
-        try {
-          [[maybe_unused]] int64_t v0 = view0;
-        } catch (const Error& error) {
-          EXPECT_EQ(error->kind, "TypeError");
-          std::string what = error.what();
-          EXPECT_NE(what.find("Cannot convert from type `None` to `int`"), 
std::string::npos);
-          throw;
-        }
-      },
-      ::tvm::ffi::Error);
-
-  AnyView view1 = 1;
-  EXPECT_EQ(view1.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIInt);
-  EXPECT_EQ(view1.CopyToTVMFFIAny().v_int64, 1);
-
-  int32_t int_v1 = view1;
-  EXPECT_EQ(int_v1, 1);
-
-  int64_t v1 = 2;
-  view0 = v1;
-  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIInt);
-  EXPECT_EQ(view0.CopyToTVMFFIAny().v_int64, 2);
-}
-
-TEST(Any, Float) {
-  AnyView view0;
-  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFINone);
-
-  std::optional<double> opt_v0 = view0.TryAs<double>();
-  EXPECT_TRUE(!opt_v0.has_value());
-
-  EXPECT_THROW(
-      {
-        try {
-          [[maybe_unused]] double v0 = view0;
-        } catch (const Error& error) {
-          EXPECT_EQ(error->kind, "TypeError");
-          std::string what = error.what();
-          EXPECT_NE(what.find("Cannot convert from type `None` to `float`"), 
std::string::npos);
-          throw;
-        }
-      },
-      ::tvm::ffi::Error);
-
-  AnyView view1_int = 1;
-  float float_v1 = view1_int;
-  EXPECT_EQ(float_v1, 1);
-
-  AnyView view2 = 2.2;
-  EXPECT_EQ(view2.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIFloat);
-  EXPECT_EQ(view2.CopyToTVMFFIAny().v_float64, 2.2);
-
-  float v1 = 2;
-  view0 = v1;
-  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFIFloat);
-  EXPECT_EQ(view0.CopyToTVMFFIAny().v_float64, 2);
-}
-
-TEST(Any, Object) {
-  AnyView view0;
-  EXPECT_EQ(view0.CopyToTVMFFIAny().type_index, TypeIndex::kTVMFFINone);
-
-  // int object is not nullable
-  std::optional<TInt> opt_v0 = view0.TryAs<TInt>();
-  EXPECT_TRUE(!opt_v0.has_value());
-
-  TInt v1(11);
-  EXPECT_EQ(v1.use_count(), 1);
-  // view won't increase refcount
-  AnyView view1 = v1;
-  EXPECT_EQ(v1.use_count(), 1);
-  // any will trigger ref count increase
-  Any any1 = v1;
-  EXPECT_EQ(v1.use_count(), 2);
-  // copy to another view
-  AnyView view2 = any1;
-  EXPECT_EQ(v1.use_count(), 2);
-
-  // convert to weak raw object ptr
-  const TIntObj* v1_ptr = view2;
-  EXPECT_EQ(v1.use_count(), 2);
-  EXPECT_EQ(v1_ptr->value, 11);
-  Any any2 = v1_ptr;
-  EXPECT_EQ(v1.use_count(), 3);
-  EXPECT_TRUE(any2.TryAs<TInt>().has_value());
-
-  // convert to raw opaque ptr
-  void* raw_v1_ptr = const_cast<TIntObj*>(v1_ptr);
-  any2 = raw_v1_ptr;
-  EXPECT_TRUE(any2.TryAs<void*>().value() == v1_ptr);
-
-  // convert to ObjectPtr
-  ObjectPtr<TNumberObj> v1_obj_ptr = view2;
-  EXPECT_EQ(v1.use_count(), 3);
-  any2 = v1_obj_ptr;
-  EXPECT_EQ(v1.use_count(), 4);
-  EXPECT_TRUE(any2.TryAs<TInt>().has_value());
-  any2.reset();
-  v1_obj_ptr.reset();
-
-  // convert that triggers error
-  EXPECT_THROW(
-      {
-        try {
-          [[maybe_unused]] TFloat v0 = view1;
-        } catch (const Error& error) {
-          EXPECT_EQ(error->kind, "TypeError");
-          std::string what = error.what();
-          EXPECT_NE(what.find("Cannot convert from type `test.Int` to 
`test.Float`"),
-                    std::string::npos);
-          throw;
-        }
-      },
-      ::tvm::ffi::Error);
-  // Try to convert to number
-  TNumber number0 = any1;
-  EXPECT_EQ(v1.use_count(), 3);
-  EXPECT_TRUE(number0.as<TIntObj>());
-  EXPECT_EQ(number0.as<TIntObj>()->value, 11);
-  EXPECT_TRUE(!any1.TryAs<int>().has_value());
-
-  TInt int1 = view2;
-  EXPECT_EQ(v1.use_count(), 4);
-  any1.reset();
-  EXPECT_EQ(v1.use_count(), 3);
-}
-
-}  // namespace


Reply via email to