This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 410b4cf931 [REFACTOR] Phase out src/support/ffi_testing.cc (#19459)
410b4cf931 is described below
commit 410b4cf93125d696c68116a54c8f0bdc56be5aee
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Apr 27 16:40:44 2026 -0400
[REFACTOR] Phase out src/support/ffi_testing.cc (#19459)
Deletes src/support/ffi_testing.cc (271 lines) and removes TVM-only
testing symbols (TestAttrs, FrontendTestModule, TestingEventLogger,
ErrorTest). The duplicated testing.echo, testing.nop,
testing.object_use_count, and testing.run_check_signal symbols continue
to resolve through tvm-ffi which already registers them. Removes test
files that depend exclusively on deleted symbols.
**Test plan**: 185 passed / 77 skipped / 0 failed across covered suites
(tests/python/all-platform-minimal-test/, tests/python/ir/,
tests/python/runtime/test_runtime_error.py, tests/python/tirx-base/,
tests/python/contrib/). Build clean (cmake + ninja); pre-commit clean.
---
python/tvm/support.py | 24 --
python/tvm/testing/__init__.py | 18 --
python/tvm/testing/attrs.py | 30 ---
python/tvm/testing/popen_pool.py | 43 ++--
src/runtime/rpc/testing.cc | 5 +-
src/support/ffi_testing.cc | 271 ---------------------
.../test_runtime_packed_func.py | 159 ------------
tests/python/contrib/test_popen_pool.py | 12 +-
tests/python/ir/test_ir_attrs.py | 24 --
tests/python/ir/test_ir_container.py | 25 --
tests/python/ir/test_node_reflection.py | 24 --
tests/python/runtime/test_runtime_container.py | 175 -------------
tests/python/runtime/test_runtime_error.py | 124 ----------
.../tirx-base/test_tir_structural_equal_hash.py | 14 --
14 files changed, 31 insertions(+), 917 deletions(-)
diff --git a/python/tvm/support.py b/python/tvm/support.py
index 1734c7572f..7943abf7be 100644
--- a/python/tvm/support.py
+++ b/python/tvm/support.py
@@ -16,7 +16,6 @@
# under the License.
"""Support infra of TVM."""
-import ctypes
import json
import os
import sys
@@ -27,7 +26,6 @@ import tvm_ffi
import tvm
from . import get_global_func
-from .runtime.module import Module
tvm_ffi.init_ffi_api("support", __name__)
@@ -68,25 +66,3 @@ def describe():
print(textwrap.indent("\n".join(lines), prefix=" "))
print("CMake Options:")
print(textwrap.indent(json.dumps(info, indent=2), prefix=" "))
-
-
-class FrontendTestModule(Module):
- """A tvm.runtime.Module whose member functions are PackedFunc."""
-
- def __init__(self, entry_name=None):
- underlying_mod = get_global_func("testing.FrontendTestModule")()
- handle = underlying_mod.handle
-
- # Set handle to NULL to avoid cleanup in c++ runtime, transferring
ownership.
- # Both cython and ctypes FFI use c_void_p, so this is safe to assign
here.
- underlying_mod.handle = ctypes.c_void_p(0)
-
- super().__init__(handle)
- if entry_name is not None:
- self.entry_name = entry_name
-
- def add_function(self, name, func):
- self.get_function("__add_function")(name, func)
-
- def __setitem__(self, key, value):
- self.add_function(key, value)
diff --git a/python/tvm/testing/__init__.py b/python/tvm/testing/__init__.py
index 1ab85590c5..cca9843700 100644
--- a/python/tvm/testing/__init__.py
+++ b/python/tvm/testing/__init__.py
@@ -20,29 +20,11 @@
"""Utility Python functions for TVM testing"""
from ._ffi_api import (
- ErrorTest,
- FrontendTestModule,
- device_test,
echo,
- identity_cpp,
nop,
object_use_count,
run_check_signal,
- test_check_eq_callback,
test_raise_error,
- test_wrap_callback,
-)
-from .popen_pool import (
- after_initializer,
- call_cpp_ffi,
- call_cpp_py_ffi,
- call_py_ffi,
- fast_summation,
- initializer,
- register_ffi,
- slow_summation,
- timeout_job,
)
from .runner import local_run, rpc_run
from .utils import *
-from .attrs import *
diff --git a/python/tvm/testing/attrs.py b/python/tvm/testing/attrs.py
deleted file mode 100644
index 674ae8755b..0000000000
--- a/python/tvm/testing/attrs.py
+++ /dev/null
@@ -1,30 +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.
-# pylint: disable=invalid-name, import-outside-toplevel, unused-variable
-"""Testing utilities for attrs"""
-
-from tvm_ffi import register_object
-
-from ..ir import Attrs
-
-
-@register_object("attrs.TestAttrs")
-class TestAttrs(Attrs):
- """Attrs used for testing purposes"""
-
-
-__all__ = ["TestAttrs"]
diff --git a/python/tvm/testing/popen_pool.py b/python/tvm/testing/popen_pool.py
index 1e943867f3..8887f63b46 100644
--- a/python/tvm/testing/popen_pool.py
+++ b/python/tvm/testing/popen_pool.py
@@ -15,12 +15,18 @@
# specific language governing permissions and limitations
# under the License.
# pylint: disable=invalid-name, missing-function-docstring
-# ruff: noqa: F821
-"""Common functions for popen_pool test cases"""
+"""Helper functions for popen_pool test cases.
-import tvm_ffi
+These functions run inside PopenWorker subprocesses and must live in an
+importable module (cloudpickle resolves them by module + qualname). The
+previous version used FFI helpers (testing.sleep_in_ffi, testing.identity_cpp,
+etc.) that were removed with ffi_testing.cc. This version is pure-Python and
+uses time.sleep for any blocking needed by the timeout test.
+"""
+
+import time
-from . import _ffi_api
+import tvm_ffi
TEST_GLOBAL_STATE_1 = 0
TEST_GLOBAL_STATE_2 = 0
@@ -39,13 +45,13 @@ def after_initializer():
return TEST_GLOBAL_STATE_1, TEST_GLOBAL_STATE_2, TEST_GLOBAL_STATE_3
-@tvm_ffi.register_global_func("testing.identity_py")
+@tvm_ffi.register_global_func("testing.identity_py", override=True)
def identity_py(arg):
return arg
def register_ffi():
- @tvm_ffi.register_global_func("testing.nested_identity_py")
+ @tvm_ffi.register_global_func("testing.nested_identity_py", override=True)
def _identity_py(arg): # pylint: disable=unused-variable
return arg
@@ -56,23 +62,20 @@ def call_py_ffi(arg):
def call_cpp_ffi(arg):
+ import tvm # pylint: disable=import-outside-toplevel
+
return tvm.testing.echo(arg)
def call_cpp_py_ffi(arg):
- return tvm.testing.identity_cpp(arg)
-
-
-def fast_summation(n):
- return n * (n + 1) // 2
-
-
-def slow_summation(n):
- r = 0
- for i in range(0, n + 1):
- r += i
- return r
+ # Call the Python-registered identity function through the FFI registry,
+ # exercising the same cross-language dispatch path that identity_cpp
covered.
+ _identity = tvm_ffi.get_global_func("testing.identity_py")
+ return _identity(arg)
-def timeout_job(n):
- _ffi_api.sleep_in_ffi(n * 1.5)
+def timeout_job(seconds):
+ # Previously called testing.sleep_in_ffi (C++ FFI helper, now removed).
+ # Plain time.sleep is sufficient — the PopenPoolExecutor timeout mechanism
+ # watches wall-clock time and terminates the process just the same.
+ time.sleep(seconds)
diff --git a/src/runtime/rpc/testing.cc b/src/runtime/rpc/testing.cc
index 332606effb..3513b4c9c1 100644
--- a/src/runtime/rpc/testing.cc
+++ b/src/runtime/rpc/testing.cc
@@ -19,9 +19,8 @@
/*!
* Runtime-side test helpers used by the RPC test suite.
- * Registered here (rather than in ``src/support/ffi_testing.cc``) so the
- * ``minrpc`` server binary — which links only against ``libtvm_runtime``
- * — can resolve them.
+ * Registered here so the ``minrpc`` server binary — which links only
+ * against ``libtvm_runtime`` — can resolve them.
* \file runtime/rpc/testing.cc
*/
#include <tvm/ffi/container/shape.h>
diff --git a/src/support/ffi_testing.cc b/src/support/ffi_testing.cc
deleted file mode 100644
index da11ce586e..0000000000
--- a/src/support/ffi_testing.cc
+++ /dev/null
@@ -1,271 +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.
- */
-
-/*!
- * FFI registration code used for frontend testing purposes.
- * \file ffi_testing.cc
- */
-#include <tvm/ffi/container/variant.h>
-#include <tvm/ffi/extra/module.h>
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/attrs.h>
-#include <tvm/ir/env_func.h>
-#include <tvm/runtime/device_api.h>
-#include <tvm/te/tensor.h>
-#include <tvm/tirx/expr.h>
-
-#include <chrono>
-#include <thread>
-
-namespace tvm {
-// Attrs used to python API
-struct TestAttrs : public AttrsNodeReflAdapter<TestAttrs> {
- int axis;
- ffi::String name;
- ffi::Array<PrimExpr> padding;
- TypedEnvFunc<int(int)> func;
-
- static void RegisterReflection() {
- namespace refl = tvm::ffi::reflection;
- refl::ObjectDef<TestAttrs>()
- .def_ro("axis", &TestAttrs::axis, "axis field", refl::DefaultValue(10))
- .def_ro("name", &TestAttrs::name, "name")
- .def_ro("padding", &TestAttrs::padding, "padding of input",
- refl::DefaultValue(ffi::Array<PrimExpr>({0, 0})))
- .def_ro("func", &TestAttrs::func, "some random env function",
- refl::DefaultValue(TypedEnvFunc<int(int)>(nullptr)));
- }
- TVM_FFI_DECLARE_OBJECT_INFO_FINAL("attrs.TestAttrs", TestAttrs,
BaseAttrsNode);
-};
-
-TVM_FFI_STATIC_INIT_BLOCK() { TestAttrs::RegisterReflection(); }
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- refl::GlobalDef()
- .def_packed("testing.test_wrap_callback",
- [](ffi::PackedArgs args, ffi::Any* ret) {
- ffi::Function pf = args[0].cast<ffi::Function>();
- *ret = ffi::TypedFunction<void()>([pf]() { pf(); });
- })
- .def_packed("testing.test_wrap_callback_suppress_err",
- [](ffi::PackedArgs args, ffi::Any* ret) {
- ffi::Function pf = args[0].cast<ffi::Function>();
- auto result = ffi::TypedFunction<void()>([pf]() {
- try {
- pf();
- } catch (std::exception& err) {
- }
- });
- *ret = result;
- })
- .def_packed("testing.test_check_eq_callback",
- [](ffi::PackedArgs args, ffi::Any* ret) {
- auto msg = args[0].cast<std::string>();
- *ret = ffi::TypedFunction<void(int x, int y)>(
- [msg](int x, int y) { TVM_FFI_ICHECK_EQ(x, y) << msg;
});
- })
- .def_packed("testing.device_test",
- [](ffi::PackedArgs args, ffi::Any* ret) {
- auto dev = args[0].cast<Device>();
- int dtype = args[1].cast<int>();
- int did = args[2].cast<int>();
- TVM_FFI_ICHECK_EQ(static_cast<int>(dev.device_type),
dtype);
- TVM_FFI_ICHECK_EQ(static_cast<int>(dev.device_id), did);
- *ret = dev;
- })
- .def_packed("testing.identity_cpp", [](ffi::PackedArgs args, ffi::Any*
ret) {
- const auto identity_func =
tvm::ffi::Function::GetGlobal("testing.identity_py");
- TVM_FFI_CHECK(identity_func.has_value(), AttributeError)
- << "\"testing.identity_py\" is not registered. Please check "
- "if the python module is properly loaded";
- *ret = (*identity_func)(args[0]);
- });
-}
-
-// in src/api_test.cc
-void ErrorTest(int x, int y) {
- // raise ValueError
- TVM_FFI_CHECK_EQ(x, y, ValueError) << "expect x and y to be equal.";
- if (x == 1) {
- // raise InternalError.
- TVM_FFI_THROW(InternalError) << "cannot reach here";
- }
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- refl::GlobalDef().def("testing.ErrorTest", ErrorTest);
-}
-
-class FrontendTestModuleNode : public ffi::ModuleObj {
- public:
- const char* kind() const final { return "frontend_test"; }
-
- static constexpr const char* kAddFunctionName = "__add_function";
-
- virtual ffi::Optional<ffi::Function> GetFunction(const ffi::String& name);
-
- private:
- std::unordered_map<std::string, ffi::Function> functions_;
-};
-
-constexpr const char* FrontendTestModuleNode::kAddFunctionName;
-
-ffi::Optional<ffi::Function> FrontendTestModuleNode::GetFunction(const
ffi::String& name) {
- ffi::Module self_strong_ref = ffi::GetRef<ffi::Module>(this);
- if (name == kAddFunctionName) {
- return ffi::Function::FromTyped(
- [this, self_strong_ref](std::string func_name, ffi::Function pf) {
- TVM_FFI_ICHECK_NE(func_name, kAddFunctionName)
- << "func_name: cannot be special function " << kAddFunctionName;
- functions_[func_name] = pf;
- });
- }
-
- auto it = functions_.find(name);
- if (it == functions_.end()) {
- return std::nullopt;
- }
-
- return it->second;
-}
-
-ffi::Module NewFrontendTestModule() {
- auto n = ffi::make_object<FrontendTestModuleNode>();
- return ffi::Module(n);
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- refl::GlobalDef()
- .def("testing.FrontendTestModule", NewFrontendTestModule)
- .def(
- "testing.sleep_in_ffi",
- [](double timeout) {
- std::chrono::duration<int64_t, std::nano>
duration(static_cast<int64_t>(timeout * 1e9));
- std::this_thread::sleep_for(duration);
- })
- .def("testing.ReturnsVariant",
- [](int x) -> ffi::Variant<ffi::String, IntImm> {
- if (x % 2 == 0) {
- return IntImm(DataType::Int(64), x / 2);
- } else {
- return ffi::String("argument was odd");
- }
- })
- .def("testing.AcceptsVariant",
- [](ffi::Variant<ffi::String, Integer> arg) -> ffi::String {
- if (auto opt_str = arg.as<ffi::String>()) {
- return ffi::StaticTypeKey::kTVMFFIStr;
- } else {
- return arg.get<Integer>().GetTypeKey();
- }
- })
- .def("testing.AcceptsBool", [](bool arg) -> bool { return arg; })
- .def("testing.AcceptsInt", [](int arg) -> int { return arg; })
- .def("testing.AcceptsObjectRefArray", [](ffi::Array<Any> arg) -> Any {
return arg[0]; })
- .def("testing.AcceptsMapReturnsValue",
- [](ffi::Map<Any, Any> map, Any key) -> Any { return map[key]; })
- .def("testing.AcceptsMapReturnsMap", [](ffi::Map<Any, Any> map) ->
ObjectRef { return map; })
- .def("testing.AcceptsPrimExpr", [](PrimExpr expr) -> ObjectRef { return
expr; })
- .def("testing.AcceptsArrayOfPrimExpr",
- [](ffi::Array<PrimExpr> arr) -> ObjectRef {
- for (ObjectRef item : arr) {
- TVM_FFI_ICHECK(item->IsInstance<PrimExprNode>())
- << "Array contained " << item->GetTypeKey()
- << " when it should contain PrimExpr";
- }
- return arr;
- })
- .def("testing.AcceptsArrayOfVariant",
- [](ffi::Array<ffi::Variant<ffi::Function, PrimExpr>> arr) ->
ObjectRef {
- for (auto item : arr) {
- TVM_FFI_ICHECK(item.as<PrimExpr>() || item.as<ffi::Function>())
- << "Array should contain either PrimExpr or ffi::Function";
- }
- return arr;
- })
- .def("testing.AcceptsMapOfPrimExpr", [](ffi::Map<Any, PrimExpr> map) ->
ObjectRef {
- for (const auto& kv : map) {
- ObjectRef value = kv.second;
- TVM_FFI_ICHECK(value->IsInstance<PrimExprNode>())
- << "Map contained " << value->GetTypeKey() << " when it should
contain PrimExpr";
- }
- return map;
- });
-}
-
-/**
- * Simple event logger that can be used for testing purposes
- */
-class TestingEventLogger {
- public:
- struct Entry {
- ffi::String event;
- double time_us;
- };
-
- TestingEventLogger() {
- entries_.reserve(1024);
- start_ = std::chrono::high_resolution_clock::now();
- }
-
- void Record(ffi::String event) {
- auto tend = std::chrono::high_resolution_clock::now();
- double time_us = static_cast<double>((tend - start_).count()) / 1e3;
- entries_.emplace_back(Entry{event, time_us});
- }
-
- void Reset() { entries_.clear(); }
-
- void Dump() const {
- for (const Entry& e : entries_) {
- LOG(INFO) << e.event << "\t" << e.time_us << " us";
- }
- }
-
- static TestingEventLogger* ThreadLocal() {
- thread_local TestingEventLogger inst;
- return &inst;
- }
-
- private:
- std::chrono::high_resolution_clock::time_point start_;
- std::vector<Entry> entries_;
-};
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- refl::GlobalDef()
- .def_packed("testing.record_event",
- [](ffi::PackedArgs args, ffi::Any* rv) {
- if (args.size() != 0 && args[0].try_cast<ffi::String>()) {
-
TestingEventLogger::ThreadLocal()->Record(args[0].cast<ffi::String>());
- } else {
- TestingEventLogger::ThreadLocal()->Record("X");
- }
- })
- .def_packed(
- "testing.reset_events",
- [](ffi::PackedArgs args, ffi::Any* rv) {
TestingEventLogger::ThreadLocal()->Reset(); })
- .def("testing.dump_events", []() {
TestingEventLogger::ThreadLocal()->Dump(); });
-}
-} // namespace tvm
diff --git a/tests/python/all-platform-minimal-test/test_runtime_packed_func.py
b/tests/python/all-platform-minimal-test/test_runtime_packed_func.py
deleted file mode 100644
index 51128c8b5b..0000000000
--- a/tests/python/all-platform-minimal-test/test_runtime_packed_func.py
+++ /dev/null
@@ -1,159 +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.
-# ruff: noqa: F401, F821
-"""Test packed function FFI."""
-
-import gc
-
-import numpy as np
-import tvm_ffi
-
-import tvm
-import tvm.testing
-from tvm.script import tirx as T
-
-
-def test_get_global():
- targs = (10, 10.0, "hello")
-
- # register into global function table
- @tvm.register_global_func
- def my_packed_func(*args):
- assert tuple(args) == targs
- return 10
-
- # get it out from global function table
- f = tvm.get_global_func("my_packed_func")
- assert isinstance(f, tvm_ffi.Function)
- y = f(*targs)
- assert y == 10
-
-
-def test_get_callback_with_node():
- x = T.int32(10)
-
- def test(y):
- return y
-
- f2 = tvm.runtime.convert(test)
-
- # register into global function table
- @tvm.register_global_func
- def my_callback_with_node(y, f):
- assert y == x
- return f(y)
-
- # get it out from global function table
- f = tvm.get_global_func("my_callback_with_node")
- assert isinstance(f, tvm_ffi.Function)
- y = f(x, f2)
- assert y.value == 10
-
-
-def test_return_func():
- def addy(y):
- def add(x):
- return tvm.runtime.convert(x + y)
-
- return add
-
- myf = tvm.runtime.convert(addy)
- f = myf(10)
- assert f(11) == 21
-
-
-def test_convert():
- # convert a function to tvm function
- targs = (10, 10.0, "hello", 10)
-
- def myfunc(*args):
- assert tuple(args) == targs
-
- f = tvm.runtime.convert(myfunc)
- assert isinstance(f, tvm_ffi.Function)
-
-
-def test_byte_array():
- s = "hello"
- a = bytearray(s, encoding="ascii")
-
- def myfunc(ss):
- assert ss == a
-
- f = tvm.runtime.convert(myfunc)
- f(a)
-
-
-def test_empty_array():
- def myfunc(ss):
- assert tuple(ss) == ()
-
- x = tvm.runtime.convert(())
- tvm.runtime.convert(myfunc)(x)
-
-
-def test_device():
- def test_device_func(dev):
- assert tvm.cuda(7) == dev
- return tvm.cpu(0)
-
- x = test_device_func(tvm.cuda(7))
- assert x == tvm.cpu(0)
- x = tvm.opencl(10)
- x = tvm.testing.device_test(x, x.dlpack_device_type(), x.index)
- assert x == tvm.opencl(10)
-
-
-def test_numpy_scalar():
- maxint = (1 << 63) - 1
- assert tvm.testing.echo(np.int64(maxint)) == maxint
-
-
-def test_tensor_args():
- def check(arr):
- assert tvm.testing.object_use_count(arr) == 2
-
- fcheck = tvm.runtime.convert(check)
- x = tvm.runtime.tensor([1, 2, 3])
- fcheck(x)
- assert tvm.testing.object_use_count(x) == 1
-
-
-def test_dict_function_value_type():
- from tvm import tirx # pylint: disable=import-outside-toplevel
-
- te_func_dict = {"add": lambda a, b: a + b}
-
- converted_dict = tvm.runtime.convert(te_func_dict)
- f = converted_dict["add"]
- a = tirx.Var("a", "float32")
- b = tirx.Var("b", "float32")
- tvm.ir.assert_structural_equal(f(a, b), tirx.Add(a, b))
-
-
-if __name__ == "__main__":
- test_tensor_args()
- test_numpy_scalar()
- test_rvalue_ref()
- test_empty_array()
- test_get_global()
- test_get_callback_with_node()
- test_convert()
- test_return_func()
- test_byte_array()
- test_device()
- test_dict_function_value_type()
diff --git a/tests/python/contrib/test_popen_pool.py
b/tests/python/contrib/test_popen_pool.py
index 355954caf9..6ac5970f3b 100644
--- a/tests/python/contrib/test_popen_pool.py
+++ b/tests/python/contrib/test_popen_pool.py
@@ -25,16 +25,16 @@ import pytest
from tvm.contrib.popen_pool import PopenPoolExecutor, PopenWorker
from tvm.testing import (
+ identity_after,
+ terminate_self,
+)
+from tvm.testing.popen_pool import (
after_initializer,
call_cpp_ffi,
call_cpp_py_ffi,
call_py_ffi,
- fast_summation,
- identity_after,
initializer,
register_ffi,
- slow_summation,
- terminate_self,
timeout_job,
)
@@ -151,12 +151,12 @@ def test_popen_ffi():
proc.send(call_py_ffi, initargs)
assert proc.recv() == initargs[0]
- # call cpp function via ffi
+ # call cpp function (testing.echo) via ffi
initargs = [1]
proc.send(call_cpp_ffi, initargs)
assert proc.recv() == initargs[0]
- # call python function from cpp function via ffi
+ # call python function from ffi registry via cross-language dispatch
initargs = [2]
proc.send(call_cpp_py_ffi, initargs)
assert proc.recv() == initargs[0]
diff --git a/tests/python/ir/test_ir_attrs.py b/tests/python/ir/test_ir_attrs.py
index 0d4fdcfb38..7074215505 100644
--- a/tests/python/ir/test_ir_attrs.py
+++ b/tests/python/ir/test_ir_attrs.py
@@ -15,31 +15,8 @@
# specific language governing permissions and limitations
# under the License.
# ruff: noqa: F841
-import pytest
-
import tvm
-# needed for attrs
-import tvm.testing
-
-
-def test_make_attrs():
- with pytest.raises(TypeError):
- x = tvm.ir.make_node("attrs.TestAttrs", unknown_key=1, name="xx")
-
- x = tvm.ir.make_node("attrs.TestAttrs", name="xx", padding=(3, 4))
- assert x.name == "xx"
- assert x.padding[0].value == 3
- assert x.padding[1].value == 4
- assert x.axis == 10
-
- x = tvm.ir.make_node("attrs.TestAttrs", name="xx", padding=(3, 4))
- y = tvm.ir.make_node("attrs.TestAttrs", name="xx", padding=(3, 5))
- z = tvm.ir.make_node("attrs.TestAttrs", name="xx", padding=(3, 5))
- assert not tvm.ir.structural_equal(x, y)
- assert tvm.ir.structural_equal(x, x)
- assert tvm.ir.structural_equal(y, z)
-
def test_dict_attrs():
dattr = tvm.ir.make_node("ir.DictAttrs", x=1, y=10, name="xyz",
padding=(0, 0))
@@ -65,6 +42,5 @@ def test_attrs_equal():
if __name__ == "__main__":
- test_make_attrs()
test_dict_attrs()
test_attrs_equal()
diff --git a/tests/python/ir/test_ir_container.py
b/tests/python/ir/test_ir_container.py
index 67a6e857f5..3180e980ed 100644
--- a/tests/python/ir/test_ir_container.py
+++ b/tests/python/ir/test_ir_container.py
@@ -109,30 +109,5 @@ def test_tensor_container():
assert isinstance(arr[0], tvm.runtime.Tensor)
-def test_return_variant_type():
- func = tvm.get_global_func("testing.ReturnsVariant")
- res_even = func(42)
- assert isinstance(res_even, tvm.tirx.IntImm)
- assert res_even == 21
-
- res_odd = func(17)
- assert res_odd == "argument was odd"
-
-
-def test_pass_variant_type():
- func = tvm.get_global_func("testing.AcceptsVariant")
-
- assert func("string arg") == "ffi.String"
- assert func(17) == "ir.IntImm"
-
-
-def test_pass_incorrect_variant_type():
- func = tvm.get_global_func("testing.AcceptsVariant")
- float_arg = tvm.tirx.FloatImm("float32", 0.5)
-
- with pytest.raises(Exception):
- func(float_arg)
-
-
if __name__ == "__main__":
tvm.testing.main()
diff --git a/tests/python/ir/test_node_reflection.py
b/tests/python/ir/test_node_reflection.py
index 111efa5696..6cfff9d184 100644
--- a/tests/python/ir/test_node_reflection.py
+++ b/tests/python/ir/test_node_reflection.py
@@ -97,30 +97,6 @@ def test_make_sum():
assert BB.op.body[0].combiner is not None
-def test_env_func():
- @tvm.register_global_func("test.env_func")
- def test(x):
- return x + 1
-
- f = tvm.get_global_func("test.env_func")
- x = tvm.ir.EnvFunc.get("test.env_func")
- assert x.name == "test.env_func"
- json_str = tvm.ir.save_json([x])
- y = tvm.ir.load_json(json_str)[0]
- assert y.name == x.name
- assert y(1) == 2
- assert y.func(1) == 2
-
- x = tvm.ir.make_node("attrs.TestAttrs", name="xx", padding=(3, 4), func=y)
- assert x.name == "xx"
- assert x.padding[0].value == 3
- assert x.padding[1].value == 4
- assert x.axis == 10
- x = tvm.ir.load_json(tvm.ir.save_json(x))
- assert isinstance(x.func, tvm.ir.EnvFunc)
- assert x.func(10) == 11
-
-
def test_string():
# non printable str, need to store by b64
s1 = tvm_ffi.core.String("xy\x01z")
diff --git a/tests/python/runtime/test_runtime_container.py
b/tests/python/runtime/test_runtime_container.py
deleted file mode 100644
index 43809fb00f..0000000000
--- a/tests/python/runtime/test_runtime_container.py
+++ /dev/null
@@ -1,175 +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.
-# ruff: noqa: E712, F401
-
-import pickle
-import random
-
-import numpy as np
-import tvm_ffi
-
-import tvm
-import tvm.runtime
-import tvm.testing
-
-
-def test_string():
- s = tvm_ffi.core.String("xyz")
-
- assert isinstance(s, str)
- assert s.startswith("xy")
- assert s + "1" == "xyz1"
- y = tvm.testing.echo(s)
- assert isinstance(y, str)
- assert s == y
-
- x = tvm.ir.load_json(tvm.ir.save_json(y))
- assert x == y
-
- # test pickle
- z = pickle.loads(pickle.dumps(s))
- assert s == z
-
-
-def test_shape_tuple():
- shape = [random.randint(-10, 10) for _ in range(5)]
- stuple = tvm_ffi.Shape(shape)
- len(stuple) == len(shape)
- for a, b in zip(stuple, shape):
- assert a == b
- # ShapleTuple vs. tuple
- assert stuple == tuple(shape)
- # ShapleTuple vs. ShapeTuple
- assert stuple == tvm_ffi.Shape(shape)
-
- # test pickle
- z = pickle.loads(pickle.dumps(stuple))
- assert isinstance(z, tvm_ffi.Shape)
- assert stuple == z
-
-
-def test_bool_argument():
- """Boolean objects are currently stored as int"""
- func = tvm.get_global_func("testing.AcceptsBool")
-
- assert isinstance(func(True), bool)
- assert isinstance(func(1), bool)
- assert isinstance(func(0), bool)
-
-
-def test_int_argument():
- func = tvm.get_global_func("testing.AcceptsInt")
-
- assert isinstance(func(True), int)
- assert isinstance(func(1), int)
- assert isinstance(func(0), int)
-
-
-def test_object_ref_array_argument():
- func = tvm.get_global_func("testing.AcceptsObjectRefArray")
-
- assert isinstance(func([True, 17, "hello"]), bool)
- assert isinstance(func([True]), bool)
- assert isinstance(func([17]), int)
- assert isinstance(func(["hello"]), str)
-
-
-def test_map_argument_returns_value():
- func = tvm.get_global_func("testing.AcceptsMapReturnsValue")
-
- res = func({"a": 1, "b": 2}, "a")
- assert isinstance(res, int)
- assert res == 1
-
- res = func({"a": True, "b": False}, "a")
- assert isinstance(res, bool)
- assert res == True
-
-
-def test_map_argument_returns_map():
- func = tvm.get_global_func("testing.AcceptsMapReturnsMap")
-
- res = func({"a": 1, "b": 2})
- for key, value in res.items():
- assert isinstance(key, str)
- assert isinstance(value, int)
-
- res = func({"a": False, "b": True})
- for key, value in res.items():
- assert isinstance(key, str)
- assert isinstance(value, bool)
-
-
-def test_conversion_of_arg():
- """Arguments may be converted
-
- The calling side of the FFI converts to types that are available
- at runtime. However, there may be additional type conversions
- required, that must be performed on the callee-side of the FFI.
- """
-
- func = tvm.get_global_func("testing.AcceptsPrimExpr")
-
- res = func(1)
- assert isinstance(res, tvm.tirx.IntImm)
- assert res.dtype == "int32"
-
- res = func(True)
- assert isinstance(res, tvm.tirx.IntImm)
- assert res.dtype == "bool"
-
-
-def test_conversion_of_array_elements():
- """Elements of an array may require conversion from FFI to param type
-
- Like `test_conversion_of_arg`, but conversions must be applied
- recursively to array elements. Here, the Python-side of the FFI
- converts the array `[1,2]` to `Array{runtime::Int(1),
- runtime::Int(2)}`, and the C++ side of the FFI converts to
- `Array{IntImm(1), IntImm(2)}`.
- """
-
- func = tvm.get_global_func("testing.AcceptsArrayOfPrimExpr")
-
- res = func([1, False])
- assert isinstance(res[0], tvm.tirx.IntImm)
- assert res[0].dtype == "int32"
- assert isinstance(res[1], tvm.tirx.IntImm)
- assert res[1].dtype == "bool"
-
-
-def test_conversion_of_map_values():
- """Elements of a map may require conversion from FFI to param type
-
- Like `test_conversion_of_arg`, but conversions must be applied
- recursively to map elements. Here, the Python-side of the FFI
- converts the map `{'a':1, 'b':2}` to `Map{{"a", runtime::Int(1)},
- {"b", runtime::Int(2)}}`, and the C++ side of the FFI converts to
- `Map{{"a", IntImm(1)}, {"b", IntImm(2)}}`.
- """
-
- func = tvm.get_global_func("testing.AcceptsMapOfPrimExpr")
-
- res = func({"a": 1, "b": False})
- assert isinstance(res["a"], tvm.tirx.IntImm)
- assert res["a"].dtype == "int32"
- assert isinstance(res["b"], tvm.tirx.IntImm)
- assert res["b"].dtype == "bool"
-
-
-if __name__ == "__main__":
- tvm.testing.main()
diff --git a/tests/python/runtime/test_runtime_error.py
b/tests/python/runtime/test_runtime_error.py
index f65f0fe006..2a23a04ffe 100644
--- a/tests/python/runtime/test_runtime_error.py
+++ b/tests/python/runtime/test_runtime_error.py
@@ -14,16 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-# ruff: noqa: F841
"""Test runtime error handling"""
-import functools
-import platform
-import subprocess
-import traceback
-
-import pytest
-
import tvm
import tvm.testing
@@ -36,121 +28,5 @@ def test_op_translation_to_not_implemented():
assert isinstance(e, NotImplementedError)
-def test_op_translation_to_internal_error():
- fchk_eq = tvm.testing.test_check_eq_callback("InternalError: myop")
- try:
- fchk_eq(0, 1)
- assert False
- except tvm.error.InternalError as e:
- pass
-
-
-def test_op_translation_to_value_error():
- try:
- tvm.testing.ErrorTest(0, 1)
- assert False
- except ValueError as e:
- pass
-
-
-def test_deep_callback():
- """Propagate python errors through API calls
-
- If a Python exception is raised, and that exception is caught in
- Python, the original exception should be propagated so that the
- traceback contains all intermediate python frames.
-
- Stack
- - test_deep_callback
- - test
-
- """
-
- def error_callback():
- raise ValueError("callback error")
-
- wrap1 = tvm.testing.test_wrap_callback(error_callback)
-
- def flevel2():
- wrap1()
-
- wrap2 = tvm.testing.test_wrap_callback(flevel2)
-
- def flevel3():
- wrap2()
-
- wrap3 = tvm.testing.test_wrap_callback(flevel3)
-
- try:
- wrap3()
- assert False
- except ValueError as err:
- frames = traceback.extract_tb(err.__traceback__)
-
- local_frames = [frame.name for frame in frames if frame.filename ==
__file__]
- assert local_frames == ["test_deep_callback", "flevel3", "flevel2",
"error_callback"]
-
-
[email protected]_cache
-def _has_debug_symbols():
- lib = tvm.base._LIB
- headers = subprocess.check_output(["objdump", "--section-headers",
lib._name], encoding="utf-8")
- return ".debug" in headers
-
-
[email protected](
- not _has_debug_symbols() or platform.machine != "x86_64",
- reason="C++ stack frames require debug symbols, only implemented for x86",
-)
-def test_cpp_frames_in_stack_trace_from_python_error():
- """A python exception crossing C++ boundaries should have C++ stack
frames"""
-
- def error_callback():
- raise ValueError("callback error")
-
- wrapped = tvm.testing.test_wrap_callback(error_callback)
-
- try:
- wrapped()
- assert False
- except ValueError as err:
- frames = traceback.extract_tb(err.__traceback__)
-
- cpp_frames = [
- frame
- for frame in frames
- if frame.filename.endswith(".cc") or frame.filename.endswith(".c")
- ]
- assert len(cpp_frames) >= 1, (
- f"Traceback through files '{[frame.filename for frame in frames]}'"
- f" expected to contain C/C++ frames, "
- f" but instead caught exception {err}"
- )
-
-
[email protected](
- not _has_debug_symbols() or platform.machine != "x86_64",
- reason="C++ stack frames require debug symbols, only implemented for x86",
-)
-def test_stack_trace_from_cpp_error():
- """A python exception originating in C++ should have C++ stack frames"""
- try:
- tvm.testing.ErrorTest(0, 1)
- assert False
- except ValueError as err:
- frames = traceback.extract_tb(err.__traceback__)
-
- cpp_frames = [
- frame
- for frame in frames
- if frame.filename.endswith(".cc") or frame.filename.endswith(".c")
- ]
- assert len(cpp_frames) >= 1, (
- f"Traceback through files '{[frame.filename for frame in frames]}'"
- f" expected to contain C/C++ frames, "
- f" but instead caught exception {err}"
- )
-
-
if __name__ == "__main__":
tvm.testing.main()
diff --git a/tests/python/tirx-base/test_tir_structural_equal_hash.py
b/tests/python/tirx-base/test_tir_structural_equal_hash.py
index 86fccad482..545243a4d8 100644
--- a/tests/python/tirx-base/test_tir_structural_equal_hash.py
+++ b/tests/python/tirx-base/test_tir_structural_equal_hash.py
@@ -186,20 +186,6 @@ def test_env_func():
assert consistent_equal(y, x)
-def test_attrs():
- x = tvm.ir.make_node("attrs.TestAttrs", axis=1, name="xx")
- y = tvm.ir.make_node("attrs.TestAttrs", axis=1, name="xx")
- z = tvm.ir.make_node("attrs.TestAttrs", axis=2, name="xx")
- tvm.ir.assert_structural_equal(y, x)
- assert not consistent_equal(y, z)
-
- x = tvm.runtime.convert({"x": [1, 2, 3], "y": 2})
- y = tvm.runtime.convert({"y": 2, "x": [1, 2, 3]})
- z = tvm.runtime.convert({"y": 2, "x": [1, 2, 3, 4]})
- assert consistent_equal(y, x)
- assert not consistent_equal(y, z)
-
-
def test_stmt():
@T.prim_func(private=True, check_well_formed=False)
def func2(A: T.handle, n_param: T.int32):