Passed
Push — master ( 64d748...d0b3c7 )
by
unknown
01:48
created

TestDeleteBase.test_create_index_after_delete()   A

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nop 4
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
import time
2
import random
3
import pdb
4
import copy
5
import threading
6
import logging
7
from multiprocessing import Pool, Process
8
import pytest
9
from utils import *
10
11
12
dim = 128
13
segment_row_count = 5000
14
collection_id = "test_delete"
15
DELETE_TIMEOUT = 60
16
tag = "1970-01-01"
17
nb = 6000
18
field_name = "float_vector"
19
entity = gen_entities(1)
20
raw_vector, binary_entity = gen_binary_entities(1)
21
entities = gen_entities(nb)
22
raw_vectors, binary_entities = gen_binary_entities(nb)
23
default_single_query = {
24
    "bool": {
25
        "must": [
26
            {"vector": {field_name: {"topk": 10, "query": gen_vectors(1, dim), "params": {"nprobe": 10}}}}
27
        ]
28
    }
29
}
30
31
class TestDeleteBase:
32
    """
33
    ******************************************************************
34
      The following cases are used to test `delete_entity_by_id` function
35
    ******************************************************************
36
    """
37 View Code Duplication
    @pytest.fixture(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
38
        scope="function",
39
        params=gen_simple_index()
40
    )
41
    def get_simple_index(self, request, connect):
42
        if str(connect._cmd("mode")) == "GPU":
43
            if not request.param["index_type"] not in ivf():
44
                pytest.skip("Only support index_type: idmap/ivf")
45
        if str(connect._cmd("mode")) == "CPU":
46
            if request.param["index_type"] in index_cpu_not_support():
47
                pytest.skip("CPU not support index_type: ivf_sq8h")
48
        return request.param
49
50
    @pytest.fixture(
51
        scope="function",
52
        params=[
53
            1,
54
            6000
55
        ],
56
    )
57
    def insert_count(self, request):
58
        yield request.param
59
60
    def test_delete_entity_id_not_exised(self, connect, collection):
61
        '''
62
        target: test delete entity, params entity_id not existed
63
        method: add entity and delete
64
        expected: status DELETED
65
        '''
66
        ids = connect.insert(collection, entity)
67
        connect.flush([collection])
68
        status = connect.delete_entity_by_id(collection, [0])
69
        assert status
70
71
    # TODO
72
    def test_delete_empty_collection(self, connect, collection):
73
        '''
74
        target: test delete entity, params collection_name not existed
75
        method: add entity and delete
76
        expected: status DELETED
77
        '''
78
        status = connect.delete_entity_by_id(collection, [0])
79
        assert status
80
81
    def test_delete_entity_collection_not_existed(self, connect, collection):
82
        '''
83
        target: test delete entity, params collection_name not existed
84
        method: add entity and delete
85
        expected: error raised
86
        '''
87
        collection_new = gen_unique_str()
88
        with pytest.raises(Exception) as e:
89
            status = connect.delete_entity_by_id(collection_new, [0])
90
91
    def test_delete_entity_collection_not_existed(self, connect, collection):
92
        '''
93
        target: test delete entity, params collection_name not existed
94
        method: add entity and delete
95
        expected: error raised
96
        '''
97
        ids = connect.insert(collection, entity)
98
        connect.flush([collection])
99
        collection_new = gen_unique_str()
100
        with pytest.raises(Exception) as e:
101
            status = connect.delete_entity_by_id(collection_new, [0])
102
103
    # TODO:
104
    def test_insert_delete(self, connect, collection, insert_count):
105
        '''
106
        target: test delete entity
107
        method: add entities and delete
108
        expected: no error raised
109
        '''
110
        entities = gen_entities(insert_count)
111
        ids = connect.insert(collection, entities)
112
        connect.flush([collection])
113
        delete_ids = [ids[0]]
114
        status = connect.delete_entity_by_id(collection, delete_ids)
115
        assert status
116
117 View Code Duplication
    @pytest.mark.level(2)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
118
    def test_insert_delete_A(self, connect, collection):
119
        '''
120
        target: test delete entity
121
        method: add entities and delete one in collection, and one not in collection
122
        expected: no error raised
123
        '''
124
        ids = connect.insert(collection, entities)
125
        connect.flush([collection])
126
        delete_ids = [ids[0], 1]
127
        status = connect.delete_entity_by_id(collection, delete_ids)
128
        assert status
129
        connect.flush([collection])
130
        res_count = connect.count_entities(collection)
131
        assert res_count == nb - 1
132
133
    @pytest.mark.level(2)
134
    def test_insert_delete_B(self, connect, collection):
135
        '''
136
        target: test delete entity
137
        method: add entities with the same ids, and delete the id in collection
138
        expected: no error raised, all entities deleted
139
        '''
140
        ids = [1 for i in range(nb)]
141
        res_ids = connect.insert(collection, entities, ids)
142
        connect.flush([collection])
143
        delete_ids = [1]
144
        status = connect.delete_entity_by_id(collection, delete_ids)
145
        assert status
146
        connect.flush([collection])
147
        res_count = connect.count_entities(collection)
148
        assert res_count == 0
149
150
    @pytest.mark.level(2)
151
    def test_delete_exceed_limit(self, connect, collection):
152
        '''
153
        target: test delete entity
154
        method: add one entity and delete two ids
155
        expected: error raised
156
        '''        
157
        ids = connect.insert(collection, entity)
158
        connect.flush([collection])
159
        delete_ids = [ids[0], 1]
160
        status = connect.delete_entity_by_id(collection, delete_ids)
161
        connect.flush([collection])
162
        res_count = connect.count_entities(collection)
163
        assert res_count == 0
164
165
    # TODO
166 View Code Duplication
    @pytest.mark.level(2)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
167
    def test_flush_after_delete(self, connect, collection):
168
        '''
169
        target: test delete entity
170
        method: add entities and delete, then flush
171
        expected: entity deleted and no error raised
172
        '''
173
        ids = connect.insert(collection, entities)
174
        connect.flush([collection])
175
        delete_ids = [ids[0], ids[-1]]
176
        status = connect.delete_entity_by_id(collection, delete_ids)
177
        assert status
178
        connect.flush([collection])
179
        res_count = connect.count_entities(collection)
180
        assert res_count == nb - len(delete_ids)
181
182
    # TODO
183
    @pytest.mark.level(2)
184
    def test_flush_after_delete_ip(self, connect, ip_collection):
185
        '''
186
        target: test delete entity
187
        method: add entities and delete, then flush
188
        expected: entity deleted and no error raised
189
        '''
190
        ids = connect.insert(ip_collection, entities)
191
        connect.flush([ip_collection])
192
        delete_ids = [ids[0], ids[-1]]
193
        status = connect.delete_entity_by_id(ip_collection, delete_ids)
194
        assert status
195
        connect.flush([ip_collection])
196
        res_count = connect.count_entities(ip_collection)
197
        assert res_count == nb - len(delete_ids)
198
199
    # TODO
200
    @pytest.mark.level(2)
201
    def test_flush_after_delete_jac(self, connect, jac_collection):
202
        '''
203
        target: test delete entity
204
        method: add entities and delete, then flush
205
        expected: entity deleted and no error raised
206
        '''
207
        ids = connect.insert(jac_collection, binary_entities)
208
        connect.flush([jac_collection])
209
        delete_ids = [ids[0], ids[-1]]
210
        status = connect.delete_entity_by_id(jac_collection, delete_ids)
211
        assert status
212
        connect.flush([jac_collection])
213
        res_count = connect.count_entities(jac_collection)
214
        assert res_count == nb - len(delete_ids)
215
216
    # TODO
217 View Code Duplication
    @pytest.mark.level(2)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
218
    def test_insert_same_ids_after_delete(self, connect, collection):
219
        '''
220
        method: add entities and delete
221
        expected: status DELETED
222
        '''
223
        insert_ids = [i for i in range(nb)]
224
        ids = connect.insert(collection, entities, insert_ids)
225
        connect.flush([collection])
226
        delete_ids = [ids[0], ids[-1]]
227
        status = connect.delete_entity_by_id(collection, delete_ids)
228
        assert status
229
        new_ids = connect.insert(collection, entity, [ids[0]])
230
        assert new_ids == [ids[0]]
231
        connect.flush([collection])
232
        res_count = connect.count_entities(collection)
233
        assert res_count == nb - 1
234
235
    # TODO
236 View Code Duplication
    @pytest.mark.level(2)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
237
    def test_insert_same_ids_after_delete_ip(self, connect, ip_collection):
238
        '''
239
        method: add entities and delete
240
        expected: status DELETED
241
        '''
242
        insert_ids = [i for i in range(nb)]
243
        ids = connect.insert(ip_collection, entities, insert_ids)
244
        connect.flush([ip_collection])
245
        delete_ids = [ids[0], ids[-1]]
246
        status = connect.delete_entity_by_id(ip_collection, delete_ids)
247
        assert status
248
        new_ids = connect.insert(ip_collection, entity, [ids[0]])
249
        assert new_ids == [ids[0]]
250
        connect.flush([ip_collection])
251
        res_count = connect.count_entities(ip_collection)
252
        assert res_count == nb - 1
253
254
    # TODO
255
    @pytest.mark.level(2)
256
    def test_insert_same_ids_after_delete_jac(self, connect, jac_collection):
257
        '''
258
        method: add entities, with the same id and delete the ids
259
        expected: status DELETED, all id deleted
260
        '''
261
        insert_ids = [i for i in range(nb)]
262
        ids = connect.insert(jac_collection, binary_entities, insert_ids)
263
        connect.flush([jac_collection])
264
        delete_ids = [ids[0], ids[-1]]
265
        status = connect.delete_entity_by_id(jac_collection, delete_ids)
266
        assert status
267
        new_ids = connect.insert(jac_collection, binary_entity, [ids[0]])
268
        assert new_ids == [ids[0]]
269
        connect.flush([jac_collection])
270
        res_count = connect.count_entities(jac_collection)
271
        assert res_count == nb - 1
272
273
    # TODO:
274
    @pytest.mark.level(2)
275
    def test_search_after_delete(self, connect, collection):
276
        '''
277
        target: test delete entity
278
        method: add entities and delete, then search
279
        expected: entity deleted and no error raised
280
        '''
281
        ids = connect.insert(collection, entities)
282
        connect.flush([collection])
283
        delete_ids = [ids[0], ids[-1]]
284
        status = connect.delete_entity_by_id(collection, delete_ids)
285
        assert status
286
        query = copy.deepcopy(default_single_query)
287
        query["bool"]["must"][0]["vector"][field_name]["query"] = [entity[-1]["values"][0], entities[-1]["values"][0], entities[-1]["values"][-1]]
288
        res = connect.search(collection, query)
289
        logging.getLogger().debug(res)
290
        assert len(res) == len(query["bool"]["must"][0]["vector"][field_name]["query"])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable field_name does not seem to be defined.
Loading history...
291
        assert res[0]._distances[0] > epsilon
292
        assert res[1]._distances[0] < epsilon
293
        assert res[2]._distances[0] < epsilon
294
295
    # TODO
296
    @pytest.mark.level(2)
297
    def test_create_index_after_delete(self, connect, collection, get_simple_index):
298
        '''
299
        method: add entitys and delete, then create index
300
        expected: vectors deleted, index created
301
        '''
302
        ids = connect.insert(collection, entities)
303
        connect.flush([collection])
304
        delete_ids = [ids[0], ids[-1]]
305
        status = connect.delete_entity_by_id(collection, delete_ids)
306
        connect.create_index(collection, field_name, get_simple_index)
307
        # assert index info
308
309
    # TODO
310
    def test_delete_multiable_times(self, connect, collection):
311
        '''
312
        method: add entities and delete id serveral times
313
        expected: entities deleted
314
        '''
315
        ids = connect.insert(collection, entities)
316
        connect.flush([collection])
317
        delete_ids = [ids[0], ids[-1]]
318
        status = connect.delete_entity_by_id(collection, delete_ids)
319
        assert status
320
        connect.flush([collection])
321
        for i in range(10):
322
            status = connect.delete_entity_by_id(collection, delete_ids)
323
            assert status
324
325
    # TODO
326
    @pytest.mark.level(2)
327
    def test_index_insert_batch_delete_get(self, connect, collection, get_simple_index):
328
        '''
329
        method: create index, insert entities, and delete
330
        expected: entities deleted
331
        '''
332
        connect.create_index(collection, field_name, get_simple_index)
333
        ids = connect.insert(collection, entities)
334
        connect.flush([collection])
335
        delete_ids = [ids[0], ids[-1]]
336
        status = connect.delete_entity_by_id(collection, delete_ids)
337
        assert status
338
        connect.flush([collection])
339
        res_count = connect.count_entities(collection)
340
        assert res_count == nb - len(delete_ids)
341
        res_get = connect.get_entity_by_id(collection, delete_ids)
342
        assert res_get[0] is None
343
344
    # TODO
345
    @pytest.mark.level(2)
346
    def test_index_insert_single_delete_get(self, connect, collection, get_simple_index):
347
        '''
348
        method: create index, insert entities, and delete
349
        expected: entities deleted
350
        '''
351
        ids = [i for i in range(nb)]
352
        connect.create_index(collection, field_name, get_simple_index)
353
        for i in range(nb):
354
            connect.insert(collection, entity, [ids[i]])
355
        connect.flush([collection])
356
        delete_ids = [ids[0], ids[-1]]
357
        status = connect.delete_entity_by_id(collection, delete_ids)
358
        assert status
359
        connect.flush([collection])
360
        res_count = connect.count_entities(collection)
361
        assert res_count == nb - len(delete_ids)
362
363
    """
364
    ******************************************************************
365
      The following cases are used to test `delete_entity_by_id` function, with tags
366
    ******************************************************************
367
    """
368
    # TODO:
369
    def test_insert_tag_delete(self, connect, collection):
370
        '''
371
        method: add entitys with given tag, delete entities with the return ids
372
        expected: entities deleted
373
        '''
374
        connect.create_partition(collection, tag)
375
        ids = connect.insert(collection, entities, partition_tag=tag)
376
        connect.flush([collection])
377
        delete_ids = [ids[0], ids[-1]]
378
        status = connect.delete_entity_by_id(collection, delete_ids)
379
        assert status
380
381
    # TODO:
382
    def test_insert_default_tag_delete(self, connect, collection):
383
        '''
384
        method: add entitys, delete entities with the return ids
385
        expected: entities deleted
386
        '''
387
        connect.create_partition(collection, tag)
388
        ids = connect.insert(collection, entities)
389
        connect.flush([collection])
390
        delete_ids = [ids[0], ids[-1]]
391
        status = connect.delete_entity_by_id(collection, delete_ids)
392
        assert status
393
394
    # TODO:
395 View Code Duplication
    @pytest.mark.level(2)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
396
    def test_insert_tags_delete(self, connect, collection):
397
        '''
398
        method: add entitys with given two tags, delete entities with the return ids
399
        expected: entities deleted
400
        '''
401
        tag_new = "tag_new"
402
        connect.create_partition(collection, tag)
403
        connect.create_partition(collection, tag_new)
404
        ids = connect.insert(collection, entities, partition_tag=tag)
405
        ids_new = connect.insert(collection, entities, partition_tag=tag_new)
406
        connect.flush([collection])
407
        delete_ids = [ids[0], ids_new[0]]
408
        status = connect.delete_entity_by_id(collection, delete_ids)
409
        assert status
410
        connect.flush([collection])
411
        res_count = connect.count_entities(collection)
412
        assert res_count == 2 * (nb - 1)
413
414
    # TODO:
415 View Code Duplication
    @pytest.mark.level(2)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
416
    def test_insert_tags_index_delete(self, connect, collection, get_simple_index):
417
        '''
418
        method: add entitys with given tag, create index, delete entities with the return ids
419
        expected: entities deleted
420
        '''
421
        tag_new = "tag_new"
422
        connect.create_partition(collection, tag)
423
        connect.create_partition(collection, tag_new)
424
        ids = connect.insert(collection, entities, partition_tag=tag)
425
        ids_new = connect.insert(collection, entities, partition_tag=tag_new)
426
        connect.flush([collection])
427
        connect.create_index(collection, field_name, get_simple_index)
428
        delete_ids = [ids[0], ids_new[0]]
429
        status = connect.delete_entity_by_id(collection, delete_ids)
430
        assert status
431
        connect.flush([collection])
432
        res_count = connect.count_entities(collection)
433
        assert res_count == 2 * (nb - 1)
434
435
436
class TestDeleteInvalid(object):
437
438
    """
439
    Test adding vectors with invalid vectors
440
    """
441
    @pytest.fixture(
442
        scope="function",
443
        params=gen_invalid_ints()
444
    )
445
    def gen_entity_id(self, request):
446
        yield request.param
447
448
    @pytest.fixture(
449
        scope="function",
450
        params=gen_invalid_strs()
451
    )
452
    def get_collection_name(self, request):
453
        yield request.param
454
455
    @pytest.mark.level(1)
456
    def test_delete_entity_id_invalid(self, connect, collection, gen_entity_id):
457
        invalid_id = gen_entity_id
458
        with pytest.raises(Exception) as e:
459
            status = connect.delete_entity_by_id(collection, [invalid_id])
460
461
    @pytest.mark.level(2)
462
    def test_delete_entity_ids_invalid(self, connect, collection, gen_entity_id):
463
        invalid_id = gen_entity_id
464
        with pytest.raises(Exception) as e:
465
            status = connect.delete_entity_by_id(collection, [1, invalid_id])
466
467
    @pytest.mark.level(2)
468
    def test_delete_entity_with_invalid_collection_name(self, connect, get_collection_name):
469
        collection_name = get_collection_name
470
        with pytest.raises(Exception) as e:
471
            status = connect.delete_entity_by_id(collection_name, [1])
472
473
    # def test_insert_same_ids_after_delete_jac(self, connect, jac_collection):
474
    #     '''
475
    #     method: add entities and delete
476
    #     expected: status DELETED
477
    #     '''
478
    #     insert_ids = [i for i in range(nb)]
479
    #     ids = connect.insert(jac_collection, binary_entities, insert_ids)
480
    #     connect.flush([jac_collection])
481
    #     delete_ids = [ids[0], ids[-1]]
482
    #     with pytest.raises(Exception) as e:
483
    #         status = connect.delete_entity_by_id(jac_collection, delete_ids)
484