Skip to content

Commit

Permalink
Add coverage tests for IndexErrors, fix one bug, clean up two checks
Browse files Browse the repository at this point in the history
Adds numpy/core/tests/test_indexerrors.py with tests to cover failure cases in indexing not covered
by other tests.

Added a missing check for invalid index in multiarray/iterators.c:iter_ass_sub_int().
Used the new checking code in multiarray/iterators.c:iter_ass_subscript().
Changed a ValueError to an IndexError in multiarray/mapping.c:PyArray_MapIterBind().
  • Loading branch information
thouis committed Jun 6, 2012
1 parent 56f8659 commit 330468f
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 6 deletions.
3 changes: 2 additions & 1 deletion numpy/core/src/multiarray/arraytypes.c.src
Expand Up @@ -3527,7 +3527,8 @@ static int
for (i = 0; i < n_outer; i++) {
for (j = 0; j < m_middle; j++) {
tmp = indarray[j];
if (check_and_adjust_index(&tmp, nindarray, (int) j) < 0)
/* We don't know what axis we're operating on, so don't report it in case of an error. */
if (check_and_adjust_index(&tmp, nindarray, -1) < 0)
return 1;
if (nelem == 1) {
*dest++ = *(src + tmp);
Expand Down
8 changes: 4 additions & 4 deletions numpy/core/src/multiarray/iterators.c
Expand Up @@ -975,6 +975,9 @@ iter_ass_sub_int(PyArrayIterObject *self, PyArrayObject *ind,
copyswap = PyArray_DESCR(self->ao)->f->copyswap;
if (PyArray_NDIM(ind) == 0) {
num = *((npy_intp *)PyArray_DATA(ind));
if (check_and_adjust_index(&num, self->size, -1) < 0) {
return -1;
}
PyArray_ITER_GOTO1D(self, num);
copyswap(self->dataptr, val->dataptr, swap, self->ao);
return 0;
Expand Down Expand Up @@ -1060,10 +1063,7 @@ iter_ass_subscript(PyArrayIterObject *self, PyObject *ind, PyObject *val)
PyErr_Clear();
}
else {
if (start < -self->size || start >= self->size) {
PyErr_Format(PyExc_ValueError,
"index (%" NPY_INTP_FMT \
") out of range", start);
if (check_and_adjust_index(&start, self->size, -1) < 0) {
goto finish;
}
retval = 0;
Expand Down
2 changes: 1 addition & 1 deletion numpy/core/src/multiarray/mapping.c
Expand Up @@ -2203,7 +2203,7 @@ PyArray_MapIterBind(PyArrayMapIterObject *mit, PyArrayObject *arr)
goto fail;
}
if (mit->ait->size == 0 && mit->size != 0) {
PyErr_SetString(PyExc_ValueError,
PyErr_SetString(PyExc_IndexError,
"invalid index into a 0-size array");
goto fail;
}
Expand Down
149 changes: 149 additions & 0 deletions numpy/core/tests/test_indexerrors.py
@@ -0,0 +1,149 @@
import numpy as np
from numpy.testing import TestCase, run_module_suite, assert_raises, assert_equal, assert_
import sys

class TestIndexErrors(TestCase):
'''Tests to exercise indexerrors not covered by other tests.'''

def test_arraytypes_fasttake(self):
'take from a 0-length dimension'
x = np.empty((2, 3, 0, 4))
assert_raises(IndexError, x.take, [0], axis=2)
assert_raises(IndexError, x.take, [1], axis=2)

def test_maskna_take_1D(self):
# Check exception taking from masked array
a = np.array([1, np.NA, 2, np.NA], maskna=True)
assert_raises(IndexError, a.take, [6])
a = np.array(np.NA, maskna=True)
assert_raises(IndexError, a.take, [6])

# Check exception taking from masked 0-d array
d = np.empty((5, 0), maskna=True)
assert_raises(IndexError, d.take, [1], axis=1)
assert_raises(IndexError, d.take, [0], axis=1)
assert_raises(IndexError, d.take, [0])

def test_take_from_object(self):
# Check exception taking from object array
d = np.zeros(5, dtype=object)
assert_raises(IndexError, d.take, [6])

# Check exception taking from 0-d array
d = np.zeros((5, 0), dtype=object)
assert_raises(IndexError, d.take, [1], axis=1)
assert_raises(IndexError, d.take, [0], axis=1)
assert_raises(IndexError, d.take, [0])

def test_multiindex_exceptions(self):
a = np.empty(5, dtype=object)
assert_raises(IndexError, a.item, 20)
a = np.empty((5, 0), dtype=object)
assert_raises(IndexError, a.item, (0, 0))
a = np.empty(5, dtype=object, maskna=True)
assert_raises(IndexError, a.item, 20)
a = np.empty((5, 0), dtype=object, maskna=True)
assert_raises(IndexError, a.item, (0, 0))

a = np.empty(5, dtype=object)
assert_raises(IndexError, a.itemset, 20, 0)
a = np.empty((5, 0), dtype=object)
assert_raises(IndexError, a.itemset, (0, 0), 0)
a = np.empty(5, dtype=object, maskna=True)
assert_raises(IndexError, a.itemset, 20, 0)
a = np.empty((5, 0), dtype=object, maskna=True)
assert_raises(IndexError, a.itemset, (0, 0), 0)

def test_put_exceptions(self):
a = np.zeros((5, 5))
assert_raises(IndexError, a.put, 100, 0)
a = np.zeros((5, 5), dtype=object)
assert_raises(IndexError, a.put, 100, 0)
a = np.zeros((5, 5, 0))
assert_raises(IndexError, a.put, 100, 0)
a = np.zeros((5, 5, 0), dtype=object)
assert_raises(IndexError, a.put, 100, 0)

def test_iterators_exceptions(self):
"cases in iterators.c"
def assign(obj, ind, val):
obj[ind] = val

a = np.zeros([1,2,3])
assert_raises(IndexError, lambda: a[0,5,None,2])
assert_raises(IndexError, lambda: a[0,5,0,2])
assert_raises(IndexError, lambda: assign(a, (0,5,None,2), 1))
assert_raises(IndexError, lambda: assign(a, (0,5,0,2), 1))

a = np.zeros([1,0,3])
assert_raises(IndexError, lambda: a[0,0,None,2])
assert_raises(IndexError, lambda: assign(a, (0,0,None,2), 1))

a = np.zeros([1,2,3])
assert_raises(IndexError, lambda: a.flat[10])
assert_raises(IndexError, lambda: assign(a.flat, 10, 5))
a = np.zeros([1,0,3])
assert_raises(IndexError, lambda: a.flat[10])
assert_raises(IndexError, lambda: assign(a.flat, 10, 5))

a = np.zeros([1,2,3])
assert_raises(IndexError, lambda: a.flat[np.array(10)])
assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5))
a = np.zeros([1,0,3])
assert_raises(IndexError, lambda: a.flat[np.array(10)])
assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5))

a = np.zeros([1,2,3])
assert_raises(IndexError, lambda: a.flat[np.array([10])])
assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5))
a = np.zeros([1,0,3])
assert_raises(IndexError, lambda: a.flat[np.array([10])])
assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5))

def test_mapping(self):
"cases from mapping.c"

def assign(obj, ind, val):
obj[ind] = val

a = np.zeros((0, 10))
assert_raises(IndexError, lambda: a[12])

a = np.zeros((3,5))
assert_raises(IndexError, lambda: a[(10, 20)])
assert_raises(IndexError, lambda: assign(a, (10, 20), 1))
a = np.zeros((3,0))
assert_raises(IndexError, lambda: a[(1, 0)])
assert_raises(IndexError, lambda: assign(a, (1, 0), 1))

a = np.zeros((3,5), maskna=True)
assert_raises(IndexError, lambda: a[(10, 20)])
assert_raises(IndexError, lambda: assign(a, (10, 20), 1))
a = np.zeros((3,0), maskna=True)
assert_raises(IndexError, lambda: a[(1, 0)])
assert_raises(IndexError, lambda: assign(a, (1, 0), 1))

a = np.zeros((10,))
assert_raises(IndexError, lambda: assign(a, 10, 1))
a = np.zeros((0,))
assert_raises(IndexError, lambda: assign(a, 10, 1))

a = np.zeros((3,5))
assert_raises(IndexError, lambda: a[(1, [1, 20])])
assert_raises(IndexError, lambda: assign(a, (1, [1, 20]), 1))
a = np.zeros((3,0))
assert_raises(IndexError, lambda: a[(1, [0, 1])])
assert_raises(IndexError, lambda: assign(a, (1, [0, 1]), 1))

def test_methods(self):
"cases from methods.c"

a = np.zeros((3, 3))
assert_raises(IndexError, lambda: a.item(100))
assert_raises(IndexError, lambda: a.itemset(100, 1))
a = np.zeros((0, 3))
assert_raises(IndexError, lambda: a.item(100))
assert_raises(IndexError, lambda: a.itemset(100, 1))

if __name__ == "__main__":
run_module_suite()

0 comments on commit 330468f

Please sign in to comment.