test_server.py 11.8 KB
Newer Older
P
peng.xu 已提交
1 2 3 4 5 6 7 8 9
import logging
import pytest
import mock
import datetime
import random
import faker
import inspect
from milvus import Milvus
from milvus.client.types import Status, IndexType, MetricType
J
Jin Hai 已提交
10
from milvus.client.abstract import IndexParam, CollectionSchema
P
peng.xu 已提交
11 12 13 14 15
from milvus.grpc_gen import status_pb2, milvus_pb2
from mishards import db, create_app, settings
from mishards.service_handler import ServiceHandler
from mishards.grpc_utils.grpc_args_parser import GrpcArgsParser as Parser
from mishards.factories import TableFilesFactory, TablesFactory, TableFiles, Tables
P
peng.xu 已提交
16
from mishards.router import RouterMixin
17 18
from mishards.connections import (ConnectionMgr, Connection,
        ConnectionPool, ConnectionTopology, ConnectionGroup)
P
peng.xu 已提交
19 20 21 22 23 24 25 26 27

logger = logging.getLogger(__name__)

OK = Status(code=Status.SUCCESS, message='Success')
BAD = Status(code=Status.PERMISSION_DENIED, message='Fail')


@pytest.mark.usefixtures('started_app')
class TestServer:
28

P
peng.xu 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
    @property
    def client(self):
        m = Milvus()
        m.connect(host='localhost', port=settings.SERVER_TEST_PORT)
        return m

    def test_cmd(self, started_app):
        ServiceHandler._get_server_version = mock.MagicMock(return_value=(OK,
                                                                          ''))
        status, _ = self.client.server_version()
        assert status.OK()

        Parser.parse_proto_Command = mock.MagicMock(return_value=(BAD, 'cmd'))
        status, _ = self.client.server_version()
        assert not status.OK()

    def test_drop_index(self, started_app):
J
Jin Hai 已提交
46
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
47
        ServiceHandler._drop_index = mock.MagicMock(return_value=OK)
J
Jin Hai 已提交
48
        status = self.client.drop_index(collection_name)
P
peng.xu 已提交
49 50
        assert status.OK()

J
Jin Hai 已提交
51 52 53
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(BAD, collection_name))
        status = self.client.drop_index(collection_name)
P
peng.xu 已提交
54 55 56
        assert not status.OK()

    def test_describe_index(self, started_app):
J
Jin Hai 已提交
57
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
58
        index_type = IndexType.FLAT
J
Jin Hai 已提交
59 60
        params = {'nlist': 1}
        index_param = IndexParam(collection_name=collection_name,
P
peng.xu 已提交
61
                                 index_type=index_type,
J
Jin Hai 已提交
62 63 64
                                 params=params)
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(OK, collection_name))
P
peng.xu 已提交
65 66
        ServiceHandler._describe_index = mock.MagicMock(
            return_value=(OK, index_param))
J
Jin Hai 已提交
67
        status, ret = self.client.describe_index(collection_name)
P
peng.xu 已提交
68
        assert status.OK()
J
Jin Hai 已提交
69
        assert ret._collection_name == index_param._collection_name
P
peng.xu 已提交
70

J
Jin Hai 已提交
71 72 73
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(BAD, collection_name))
        status, _ = self.client.describe_index(collection_name)
P
peng.xu 已提交
74 75 76
        assert not status.OK()

    def test_preload(self, started_app):
J
Jin Hai 已提交
77
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
78

J
Jin Hai 已提交
79 80 81 82
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(OK, collection_name))
        ServiceHandler._preload_collection = mock.MagicMock(return_value=OK)
        status = self.client.preload_collection(collection_name)
P
peng.xu 已提交
83 84
        assert status.OK()

J
Jin Hai 已提交
85 86 87
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(BAD, collection_name))
        status = self.client.preload_collection(collection_name)
P
peng.xu 已提交
88 89 90 91
        assert not status.OK()

    @pytest.mark.skip
    def test_delete_by_range(self, started_app):
J
Jin Hai 已提交
92
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
93

J
Jin Hai 已提交
94
        unpacked = collection_name, datetime.datetime.today(
P
peng.xu 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
        ), datetime.datetime.today()

        Parser.parse_proto_DeleteByRangeParam = mock.MagicMock(
            return_value=(OK, unpacked))
        ServiceHandler._delete_by_range = mock.MagicMock(return_value=OK)
        status = self.client.delete_vectors_by_range(
            *unpacked)
        assert status.OK()

        Parser.parse_proto_DeleteByRangeParam = mock.MagicMock(
            return_value=(BAD, unpacked))
        status = self.client.delete_vectors_by_range(
            *unpacked)
        assert not status.OK()

J
Jin Hai 已提交
110 111
    def test_count_collection(self, started_app):
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
112 113
        count = random.randint(100, 200)

J
Jin Hai 已提交
114 115 116 117
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(OK, collection_name))
        ServiceHandler._count_collection = mock.MagicMock(return_value=(OK, count))
        status, ret = self.client.count_collection(collection_name)
P
peng.xu 已提交
118 119 120
        assert status.OK()
        assert ret == count

J
Jin Hai 已提交
121 122 123
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(BAD, collection_name))
        status, _ = self.client.count_collection(collection_name)
P
peng.xu 已提交
124 125
        assert not status.OK()

J
Jin Hai 已提交
126 127 128 129
    def test_show_collections(self, started_app):
        collections = ['t1', 't2']
        ServiceHandler._show_collections = mock.MagicMock(return_value=(OK, collections))
        status, ret = self.client.show_collections()
P
peng.xu 已提交
130
        assert status.OK()
J
Jin Hai 已提交
131
        assert ret == collections
P
peng.xu 已提交
132

J
Jin Hai 已提交
133 134
    def test_describe_collection(self, started_app):
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
135 136
        dimension = 128
        nlist = 1
J
Jin Hai 已提交
137
        collection_schema = CollectionSchema(collection_name=collection_name,
P
peng.xu 已提交
138 139 140
                                   index_file_size=100,
                                   metric_type=MetricType.L2,
                                   dimension=dimension)
J
Jin Hai 已提交
141 142 143 144 145
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(OK, collection_schema.collection_name))
        ServiceHandler._describe_collection = mock.MagicMock(
            return_value=(OK, collection_schema))
        status, _ = self.client.describe_collection(collection_name)
P
peng.xu 已提交
146 147
        assert status.OK()

J
Jin Hai 已提交
148 149 150
        ServiceHandler._describe_collection = mock.MagicMock(
            return_value=(BAD, collection_schema))
        status, _ = self.client.describe_collection(collection_name)
P
peng.xu 已提交
151 152
        assert not status.OK()

J
Jin Hai 已提交
153
        Parser.parse_proto_CollectionName = mock.MagicMock(return_value=(BAD,
P
peng.xu 已提交
154
                                                                    'cmd'))
J
Jin Hai 已提交
155
        status, ret = self.client.describe_collection(collection_name)
P
peng.xu 已提交
156 157 158
        assert not status.OK()

    def test_insert(self, started_app):
J
Jin Hai 已提交
159
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
160 161 162 163
        vectors = [[random.random() for _ in range(16)] for _ in range(10)]
        ids = [random.randint(1000000, 20000000) for _ in range(10)]
        ServiceHandler._add_vectors = mock.MagicMock(return_value=(OK, ids))
        status, ret = self.client.add_vectors(
J
Jin Hai 已提交
164
            collection_name=collection_name, records=vectors)
P
peng.xu 已提交
165 166 167 168
        assert status.OK()
        assert ids == ret

    def test_create_index(self, started_app):
J
Jin Hai 已提交
169 170
        collection_name = inspect.currentframe().f_code.co_name
        unpacks = collection_name, None
P
peng.xu 已提交
171 172 173
        Parser.parse_proto_IndexParam = mock.MagicMock(return_value=(OK,
                                                                     unpacks))
        ServiceHandler._create_index = mock.MagicMock(return_value=OK)
J
Jin Hai 已提交
174
        status = self.client.create_index(collection_name=collection_name)
P
peng.xu 已提交
175 176 177 178
        assert status.OK()

        Parser.parse_proto_IndexParam = mock.MagicMock(return_value=(BAD,
                                                                     None))
J
Jin Hai 已提交
179
        status = self.client.create_index(collection_name=collection_name)
P
peng.xu 已提交
180 181
        assert not status.OK()

J
Jin Hai 已提交
182 183
    def test_drop_collection(self, started_app):
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
184

J
Jin Hai 已提交
185 186 187 188
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(OK, collection_name))
        ServiceHandler._drop_collection = mock.MagicMock(return_value=OK)
        status = self.client.drop_collection(collection_name=collection_name)
P
peng.xu 已提交
189 190
        assert status.OK()

J
Jin Hai 已提交
191 192 193
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(BAD, collection_name))
        status = self.client.drop_collection(collection_name=collection_name)
P
peng.xu 已提交
194 195
        assert not status.OK()

J
Jin Hai 已提交
196 197
    def test_has_collection(self, started_app):
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
198

J
Jin Hai 已提交
199 200 201 202
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(OK, collection_name))
        ServiceHandler._has_collection = mock.MagicMock(return_value=(OK, True))
        has = self.client.has_collection(collection_name=collection_name)
P
peng.xu 已提交
203 204
        assert has

J
Jin Hai 已提交
205 206 207
        Parser.parse_proto_CollectionName = mock.MagicMock(
            return_value=(BAD, collection_name))
        status, has = self.client.has_collection(collection_name=collection_name)
P
peng.xu 已提交
208 209 210
        assert not status.OK()
        assert not has

J
Jin Hai 已提交
211 212
    def test_create_collection(self, started_app):
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
213
        dimension = 128
J
Jin Hai 已提交
214
        collection_schema = dict(collection_name=collection_name,
P
peng.xu 已提交
215 216 217 218
                            index_file_size=100,
                            metric_type=MetricType.L2,
                            dimension=dimension)

J
Jin Hai 已提交
219 220
        ServiceHandler._create_collection = mock.MagicMock(return_value=OK)
        status = self.client.create_collection(collection_schema)
P
peng.xu 已提交
221 222
        assert status.OK()

J
Jin Hai 已提交
223
        Parser.parse_proto_CollectionSchema = mock.MagicMock(return_value=(BAD,
P
peng.xu 已提交
224
                                                                      None))
J
Jin Hai 已提交
225
        status = self.client.create_collection(collection_schema)
P
peng.xu 已提交
226 227 228 229 230
        assert not status.OK()

    def random_data(self, n, dimension):
        return [[random.random() for _ in range(dimension)] for _ in range(n)]

231
    @pytest.mark.skip
P
peng.xu 已提交
232
    def test_search(self, started_app):
J
Jin Hai 已提交
233
        collection_name = inspect.currentframe().f_code.co_name
P
peng.xu 已提交
234
        to_index_cnt = random.randint(10, 20)
J
Jin Hai 已提交
235
        collection = TablesFactory(collection_id=collection_name, state=Tables.NORMAL)
P
peng.xu 已提交
236
        to_index_files = TableFilesFactory.create_batch(
J
Jin Hai 已提交
237
            to_index_cnt, collection=collection, file_type=TableFiles.FILE_TYPE_TO_INDEX)
P
peng.xu 已提交
238 239 240
        topk = random.randint(5, 10)
        nq = random.randint(5, 10)
        param = {
J
Jin Hai 已提交
241 242
            'collection_name': collection_name,
            'query_records': self.random_data(nq, collection.dimension),
P
peng.xu 已提交
243
            'top_k': topk,
J
Jin Hai 已提交
244
            'params': {'nprobe': 2049}
P
peng.xu 已提交
245 246 247 248 249 250 251 252 253 254 255 256 257
        }

        result = [
            milvus_pb2.TopKQueryResult(query_result_arrays=[
                milvus_pb2.QueryResult(id=i, distance=random.random())
                for i in range(topk)
            ]) for i in range(nq)
        ]

        mock_results = milvus_pb2.TopKQueryResultList(status=status_pb2.Status(
            error_code=status_pb2.SUCCESS, reason="Success"),
            topk_query_result=result)

J
Jin Hai 已提交
258 259 260 261
        collection_schema = CollectionSchema(collection_name=collection_name,
                                   index_file_size=collection.index_file_size,
                                   metric_type=collection.metric_type,
                                   dimension=collection.dimension)
P
peng.xu 已提交
262 263 264 265

        status, _ = self.client.search_vectors(**param)
        assert status.code == Status.ILLEGAL_ARGUMENT

J
Jin Hai 已提交
266
        param['params']['nprobe'] = 2048
P
peng.xu 已提交
267
        RouterMixin.connection = mock.MagicMock(return_value=Milvus())
268
        RouterMixin.query_conn.conn = mock.MagicMock(return_value=Milvus())
J
Jin Hai 已提交
269 270
        Milvus.describe_collection = mock.MagicMock(return_value=(BAD,
                                                             collection_schema))
P
peng.xu 已提交
271
        status, ret = self.client.search_vectors(**param)
J
Jin Hai 已提交
272
        assert status.code == Status.COLLECTION_NOT_EXISTS
P
peng.xu 已提交
273

J
Jin Hai 已提交
274
        Milvus.describe_collection = mock.MagicMock(return_value=(OK, collection_schema))
P
peng.xu 已提交
275 276 277 278 279 280
        Milvus.search_vectors_in_files = mock.MagicMock(
            return_value=mock_results)

        status, ret = self.client.search_vectors(**param)
        assert status.OK()
        assert len(ret) == nq