ai-content-maker/.venv/Lib/site-packages/numba/tests/test_boundscheck.py

269 lines
7.9 KiB
Python

import numpy as np
from numba.cuda.testing import SerialMixin
from numba import typeof, cuda, njit
from numba.core.types import float64
from numba.tests.support import TestCase, MemoryLeakMixin
from numba.core import config
import unittest
def basic_array_access(a):
return a[10]
def slice_array_access(a):
# The first index (slice) is not bounds checked
return a[10:, 10]
def fancy_array_access(x):
a = np.array([1, 2, 3])
return x[a]
def fancy_array_modify(x):
a = np.array([1, 2, 3])
x[a] = 0
return x
class TestBoundsCheckNoError(MemoryLeakMixin, TestCase):
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_basic_array_boundscheck(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.arange(5)
# Check the numpy behavior to make sure the test is correct
with self.assertRaises(IndexError):
# TODO: When we raise the same error message as numpy, test that
# they are the same
basic_array_access(a)
at = typeof(a)
noboundscheck = njit((at,))(basic_array_access)
# Check that the default flag doesn't raise
noboundscheck(a)
# boundscheck(a) is tested in TestBoundsCheckError below
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_slice_array_boundscheck(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.ones((5, 5))
b = np.ones((5, 20))
with self.assertRaises(IndexError):
# TODO: When we raise the same error message as numpy, test that
# they are the same
slice_array_access(a)
# Out of bounds on a slice doesn't raise
slice_array_access(b)
at = typeof(a)
rt = float64[:]
noboundscheck = njit(rt(at))(slice_array_access)
boundscheck = njit(rt(at), boundscheck=True)(slice_array_access)
# Check that the default flag doesn't raise
noboundscheck(a)
noboundscheck(b)
# boundscheck(a) is tested in TestBoundsCheckError below
# Doesn't raise
boundscheck(b)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_fancy_indexing_boundscheck(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.arange(3)
b = np.arange(4)
# Check the numpy behavior to ensure the test is correct.
with self.assertRaises(IndexError):
# TODO: When we raise the same error message as numpy, test that
# they are the same
fancy_array_access(a)
fancy_array_access(b)
at = typeof(a)
rt = at.dtype[:]
noboundscheck = njit(rt(at))(fancy_array_access)
boundscheck = njit(rt(at), boundscheck=True)(fancy_array_access)
# Check that the default flag doesn't raise
noboundscheck(a)
noboundscheck(b)
# boundscheck(a) is tested in TestBoundsCheckError below
# Doesn't raise
boundscheck(b)
class TestNoCudaBoundsCheck(SerialMixin, TestCase):
@unittest.skipIf(not cuda.is_available(), "NO CUDA")
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '1'})
def test_no_cuda_boundscheck(self):
self.assertTrue(config.BOUNDSCHECK)
with self.assertRaises(NotImplementedError):
@cuda.jit(boundscheck=True)
def func():
pass
# Make sure we aren't raising "not supported" error if we aren't
# requesting bounds checking anyway. Related pull request: #5257
@cuda.jit(boundscheck=False)
def func3():
pass
@cuda.jit
def func2(x, a):
a[1] = x[1]
a = np.ones((1,))
x = np.zeros((1,))
# Out of bounds but doesn't raise (it does raise in the simulator,
# so skip there)
if not config.ENABLE_CUDASIM:
func2[1, 1](x, a)
# This is a separate test because the jitted functions that raise exceptions
# have memory leaks.
class TestBoundsCheckError(TestCase):
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_basic_array_boundscheck(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.arange(5)
# Check the numpy behavior to make sure the test is correct
with self.assertRaises(IndexError):
# TODO: When we raise the same error message as numpy, test that
# they are the same
basic_array_access(a)
at = typeof(a)
boundscheck = njit((at,), boundscheck=True)(basic_array_access)
with self.assertRaises(IndexError):
boundscheck(a)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_slice_array_boundscheck(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.ones((5, 5))
b = np.ones((5, 20))
with self.assertRaises(IndexError):
# TODO: When we raise the same error message as numpy, test that
# they are the same
slice_array_access(a)
# Out of bounds on a slice doesn't raise
slice_array_access(b)
at = typeof(a)
rt = float64[:]
boundscheck = njit(rt(at), boundscheck=True)(slice_array_access)
with self.assertRaises(IndexError):
boundscheck(a)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_fancy_indexing_boundscheck(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.arange(3)
b = np.arange(4)
# Check the numpy behavior to ensure the test is correct.
with self.assertRaises(IndexError):
# TODO: When we raise the same error message as numpy, test that
# they are the same
fancy_array_access(a)
fancy_array_access(b)
at = typeof(a)
rt = at.dtype[:]
boundscheck = njit(rt(at), boundscheck=True)(fancy_array_access)
with self.assertRaises(IndexError):
boundscheck(a)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_fancy_indexing_with_modification_boundscheck(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.arange(3)
b = np.arange(4)
# Check the numpy behavior to ensure the test is correct.
with self.assertRaises(IndexError):
# TODO: When we raise the same error message as numpy, test that
# they are the same
fancy_array_modify(a)
fancy_array_modify(b)
at = typeof(a)
rt = at.dtype[:]
boundscheck = njit(rt(at), boundscheck=True)(fancy_array_modify)
with self.assertRaises(IndexError):
boundscheck(a)
class TestBoundsEnvironmentVariable(TestCase):
def setUp(self):
@njit
def default(x):
return x[1]
@njit(boundscheck=False)
def off(x):
return x[1]
@njit(boundscheck=True)
def on(x):
return x[1]
self.default = default
self.off = off
self.on = on
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''})
def test_boundscheck_unset(self):
self.assertIsNone(config.BOUNDSCHECK)
a = np.array([1])
# Doesn't raise
self.default(a)
self.off(a)
with self.assertRaises(IndexError):
self.on(a)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '1'})
def test_boundscheck_enabled(self):
self.assertTrue(config.BOUNDSCHECK)
a = np.array([1])
with self.assertRaises(IndexError):
self.default(a)
self.off(a)
self.on(a)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '0'})
def test_boundscheck_disabled(self):
self.assertFalse(config.BOUNDSCHECK)
a = np.array([1])
# Doesn't raise
self.default(a)
self.off(a)
self.on(a)
if __name__ == '__main__':
unittest.main()