From d669c164525d8e2053e30e8e14de59d66e6a87be Mon Sep 17 00:00:00 2001 From: Matthijs Douze Date: Thu, 29 Aug 2024 23:00:05 -0700 Subject: [PATCH] group SWIG tests into one file (#3807) Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/3807 This groups tests related to SWIG into a single file removes a dep on platform.Version that does not exist on some envs Differential Revision: D61959750 --- faiss/python/loader.py | 4 +- faiss/python/swigfaiss.swig | 13 ++-- tests/test_build_blocks.py | 76 -------------------- tests/test_documentation.py | 1 - tests/test_doxygen_documentation.py | 17 ----- tests/test_swig_wrapper.py | 105 ++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 100 deletions(-) delete mode 100644 tests/test_doxygen_documentation.py create mode 100644 tests/test_swig_wrapper.py diff --git a/faiss/python/loader.py b/faiss/python/loader.py index fa75edb468..977ada1d9f 100644 --- a/faiss/python/loader.py +++ b/faiss/python/loader.py @@ -3,13 +3,15 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from packaging.version import Version import platform import subprocess import logging import os +def Version(v): + return [int(x) for x in v.split('.')] + def supported_instruction_sets(): """ Returns the set of supported CPU features, see diff --git a/faiss/python/swigfaiss.swig b/faiss/python/swigfaiss.swig index 752b64b55b..4d44fb650b 100644 --- a/faiss/python/swigfaiss.swig +++ b/faiss/python/swigfaiss.swig @@ -1245,10 +1245,13 @@ void * cast_integer_to_void_ptr (int64_t x) { %} %inline %{ - void wait() { - // in gdb, use return to get out of this function - for(int i = 0; i == 0; i += 0); - } - %} + +// the SWIG version is a 6-digit hex string, eg. version 3.2.1 is encoded as +// 0x030201 +uint64_t swig_version() { + return SWIG_VERSION; +} + +%} // End of file... diff --git a/tests/test_build_blocks.py b/tests/test_build_blocks.py index fdf9ad8bd7..061462abb8 100644 --- a/tests/test_build_blocks.py +++ b/tests/test_build_blocks.py @@ -418,82 +418,6 @@ def test_IP(self): dis[i], np.dot(x[ix[i]], y[iy[i]])) -class TestSWIGWrap(unittest.TestCase): - """ various regressions with the SWIG wrapper """ - - def test_size_t_ptr(self): - # issue 1064 - index = faiss.IndexHNSWFlat(10, 32) - - hnsw = index.hnsw - index.add(np.random.rand(100, 10).astype('float32')) - be = np.empty(2, 'uint64') - hnsw.neighbor_range(23, 0, faiss.swig_ptr(be), faiss.swig_ptr(be[1:])) - - def test_id_map_at(self): - # issue 1020 - n_features = 100 - feature_dims = 10 - - features = np.random.random((n_features, feature_dims)).astype(np.float32) - idx = np.arange(n_features).astype(np.int64) - - index = faiss.IndexFlatL2(feature_dims) - index = faiss.IndexIDMap2(index) - index.add_with_ids(features, idx) - - [index.id_map.at(int(i)) for i in range(index.ntotal)] - - def test_downcast_Refine(self): - - index = faiss.IndexRefineFlat( - faiss.IndexScalarQuantizer(10, faiss.ScalarQuantizer.QT_8bit) - ) - - # serialize and deserialize - index2 = faiss.deserialize_index( - faiss.serialize_index(index) - ) - - assert isinstance(index2, faiss.IndexRefineFlat) - - def do_test_array_type(self, dtype): - """ tests swig_ptr and rev_swig_ptr for this type of array """ - a = np.arange(12).astype(dtype) - ptr = faiss.swig_ptr(a) - a2 = faiss.rev_swig_ptr(ptr, 12) - np.testing.assert_array_equal(a, a2) - - def test_all_array_types(self): - self.do_test_array_type('float32') - self.do_test_array_type('float64') - self.do_test_array_type('int8') - self.do_test_array_type('uint8') - self.do_test_array_type('int16') - self.do_test_array_type('uint16') - self.do_test_array_type('int32') - self.do_test_array_type('uint32') - self.do_test_array_type('int64') - self.do_test_array_type('uint64') - - def test_int64(self): - # see https://github.com/facebookresearch/faiss/issues/1529 - v = faiss.Int64Vector() - - for i in range(10): - v.push_back(i) - a = faiss.vector_to_array(v) - assert a.dtype == 'int64' - np.testing.assert_array_equal(a, np.arange(10, dtype='int64')) - - # check if it works in an IDMap - idx = faiss.IndexIDMap(faiss.IndexFlatL2(32)) - idx.add_with_ids( - np.random.rand(10, 32).astype('float32'), - np.random.randint(1000, size=10, dtype='int64') - ) - faiss.vector_to_array(idx.id_map) - class TestNNDescentKNNG(unittest.TestCase): diff --git a/tests/test_documentation.py b/tests/test_documentation.py index c55f162a9b..2a0e189281 100644 --- a/tests/test_documentation.py +++ b/tests/test_documentation.py @@ -4,7 +4,6 @@ # LICENSE file in the root directory of this source tree. import unittest - import faiss diff --git a/tests/test_doxygen_documentation.py b/tests/test_doxygen_documentation.py deleted file mode 100644 index e6b7c1006b..0000000000 --- a/tests/test_doxygen_documentation.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -import unittest - -import faiss - - -class TestDocumentation(unittest.TestCase): - - def test_doxygen_comments(self): - maxheap_array = faiss.float_maxheap_array_t() - - self.assertTrue("a template structure for a set of [min|max]-heaps" - in maxheap_array.__doc__) diff --git a/tests/test_swig_wrapper.py b/tests/test_swig_wrapper.py new file mode 100644 index 0000000000..b3cab42ef0 --- /dev/null +++ b/tests/test_swig_wrapper.py @@ -0,0 +1,105 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# a few tests of the swig wrapper + +import unittest +import faiss +import numpy as np + + +class TestSWIGWrap(unittest.TestCase): + """ various regressions with the SWIG wrapper """ + + def test_size_t_ptr(self): + # issue 1064 + index = faiss.IndexHNSWFlat(10, 32) + + hnsw = index.hnsw + index.add(np.random.rand(100, 10).astype('float32')) + be = np.empty(2, 'uint64') + hnsw.neighbor_range(23, 0, faiss.swig_ptr(be), faiss.swig_ptr(be[1:])) + + def test_id_map_at(self): + # issue 1020 + n_features = 100 + feature_dims = 10 + + features = np.random.random((n_features, feature_dims)).astype(np.float32) + idx = np.arange(n_features).astype(np.int64) + + index = faiss.IndexFlatL2(feature_dims) + index = faiss.IndexIDMap2(index) + index.add_with_ids(features, idx) + + [index.id_map.at(int(i)) for i in range(index.ntotal)] + + def test_downcast_Refine(self): + + index = faiss.IndexRefineFlat( + faiss.IndexScalarQuantizer(10, faiss.ScalarQuantizer.QT_8bit) + ) + + # serialize and deserialize + index2 = faiss.deserialize_index( + faiss.serialize_index(index) + ) + + assert isinstance(index2, faiss.IndexRefineFlat) + + def do_test_array_type(self, dtype): + """ tests swig_ptr and rev_swig_ptr for this type of array """ + a = np.arange(12).astype(dtype) + ptr = faiss.swig_ptr(a) + a2 = faiss.rev_swig_ptr(ptr, 12) + np.testing.assert_array_equal(a, a2) + + def test_all_array_types(self): + self.do_test_array_type('float32') + self.do_test_array_type('float64') + self.do_test_array_type('int8') + self.do_test_array_type('uint8') + self.do_test_array_type('int16') + self.do_test_array_type('uint16') + self.do_test_array_type('int32') + self.do_test_array_type('uint32') + self.do_test_array_type('int64') + self.do_test_array_type('uint64') + + def test_int64(self): + # see https://github.com/facebookresearch/faiss/issues/1529 + v = faiss.Int64Vector() + + for i in range(10): + v.push_back(i) + a = faiss.vector_to_array(v) + assert a.dtype == 'int64' + np.testing.assert_array_equal(a, np.arange(10, dtype='int64')) + + # check if it works in an IDMap + idx = faiss.IndexIDMap(faiss.IndexFlatL2(32)) + idx.add_with_ids( + np.random.rand(10, 32).astype('float32'), + np.random.randint(1000, size=10, dtype='int64') + ) + faiss.vector_to_array(idx.id_map) + + def test_asan(self): + # this test should fail with ASAN + index = faiss.IndexFlatL2(32) + index.this.own(False) # this is a mem leak, should be catched by ASAN + + def test_SWIG_version(self): + self.assertLess(faiss.swig_version(), 0x050000) + + +@unittest.skipIf(faiss.swig_version() < 0x040000, "swig < 4 does not support Doxygen comments") +class TestDoxygen(unittest.TestCase): + + def test_doxygen_comments(self): + maxheap_array = faiss.float_maxheap_array_t() + + self.assertTrue("a template structure for a set of [min|max]-heaps" + in maxheap_array.__doc__)