@@ -6,7 +6,7 @@ const P = require('../../../util/promise');
6
6
const fs_utils = require ( '../../../util/fs_utils' ) ;
7
7
const NamespaceFS = require ( '../../../sdk/namespace_fs' ) ;
8
8
const buffer_utils = require ( '../../../util/buffer_utils' ) ;
9
- const { TMP_PATH } = require ( '../../system_tests/test_utils' ) ;
9
+ const { TMP_PATH , TEST_TIMEOUT } = require ( '../../system_tests/test_utils' ) ;
10
10
const { crypto_random_string } = require ( '../../../util/string_utils' ) ;
11
11
const endpoint_stats_collector = require ( '../../../sdk/endpoint_stats_collector' ) ;
12
12
@@ -27,18 +27,20 @@ function make_dummy_object_sdk(nsfs_config, uid, gid) {
27
27
}
28
28
29
29
const DUMMY_OBJECT_SDK = make_dummy_object_sdk ( true ) ;
30
+
31
+ const tmp_fs_path = path . join ( TMP_PATH , 'test_nsfs_concurrency' ) ;
32
+
33
+ const nsfs = new NamespaceFS ( {
34
+ bucket_path : tmp_fs_path ,
35
+ bucket_id : '1' ,
36
+ namespace_resource_id : undefined ,
37
+ access_mode : undefined ,
38
+ versioning : 'DISABLED' ,
39
+ force_md5_etag : false ,
40
+ stats : endpoint_stats_collector . instance ( ) ,
41
+ } ) ;
42
+
30
43
describe ( 'test nsfs concurrency' , ( ) => {
31
- const tmp_fs_path = path . join ( TMP_PATH , 'test_nsfs_concurrency' ) ;
32
-
33
- const nsfs = new NamespaceFS ( {
34
- bucket_path : tmp_fs_path ,
35
- bucket_id : '1' ,
36
- namespace_resource_id : undefined ,
37
- access_mode : undefined ,
38
- versioning : 'DISABLED' ,
39
- force_md5_etag : false ,
40
- stats : endpoint_stats_collector . instance ( ) ,
41
- } ) ;
42
44
43
45
beforeEach ( async ( ) => {
44
46
await fs_utils . create_fresh_path ( tmp_fs_path ) ;
@@ -68,5 +70,101 @@ describe('test nsfs concurrency', () => {
68
70
}
69
71
await P . delay ( 5000 ) ;
70
72
expect ( res_etags ) . toHaveLength ( 15 ) ;
71
- } , 6000 ) ;
73
+ } , TEST_TIMEOUT ) ;
74
+
75
+ test_list_and_delete ( {
76
+ test_name : 'list objects and delete an object during it - random deletion' ,
77
+ bucket_name : 'bucket1' ,
78
+ num_of_objects_to_upload : 5 ,
79
+ expected_num_of_object_in_list : 4 ,
80
+ key_to_delete : `my-key-${ random_integer ( 1 , 5 ) } ` ,
81
+ iterations : 5 ,
82
+ } ) ;
83
+
84
+ test_list_and_delete ( {
85
+ test_name : 'list objects and delete an object during it - delete the last object' ,
86
+ bucket_name : 'bucket2' ,
87
+ num_of_objects_to_upload : 1000 ,
88
+ expected_num_of_object_in_list : 999 ,
89
+ key_to_delete : `my-key-1000` ,
90
+ iterations : 1
91
+ } ) ;
72
92
} ) ;
93
+
94
+ /**
95
+ * @param {{
96
+ * test_name: string,
97
+ * bucket_name: string,
98
+ * num_of_objects_to_upload: number,
99
+ * expected_num_of_object_in_list: number,
100
+ * key_to_delete?: string,
101
+ * iterations?: number,
102
+ * }} params
103
+ */
104
+ function test_list_and_delete ( {
105
+ test_name,
106
+ bucket_name,
107
+ num_of_objects_to_upload,
108
+ expected_num_of_object_in_list,
109
+ key_to_delete,
110
+ iterations = 1
111
+ } ) {
112
+
113
+ it ( test_name , async ( ) => {
114
+ await _upload_objects ( bucket_name , num_of_objects_to_upload ) ;
115
+ if ( key_to_delete === undefined ) {
116
+ key_to_delete = `my-key-${ random_integer ( 1 , expected_num_of_object_in_list ) } ` ;
117
+ console . log ( 'test_list_and_delete: key_to_delete' , key_to_delete ) ;
118
+ }
119
+
120
+ console . log ( `test_list_and_delete: ${ test_name } ${ bucket_name } num_of_objects_to_upload: ${ num_of_objects_to_upload } ,
121
+ expected_num_of_object_in_list ${ expected_num_of_object_in_list } key_to_delete ${ key_to_delete } ` ) ;
122
+
123
+ for ( let i = 0 ; i < iterations ; ++ i ) {
124
+ nsfs . list_objects ( { bucket : bucket_name } , DUMMY_OBJECT_SDK )
125
+ . catch ( err => {
126
+ console . log ( 'error during list_objects' , err ) ;
127
+ throw err ;
128
+ } ) . then ( res => {
129
+ console . log ( 'list was successful' ) ;
130
+ } ) ;
131
+ nsfs . delete_object ( { bucket : bucket_name , key : key_to_delete } , DUMMY_OBJECT_SDK )
132
+ . catch ( err => {
133
+ console . log ( 'delete_object got an error' , err ) ;
134
+ throw err ;
135
+ } ) . then ( res => {
136
+ console . log ( 'delete_object during list objects was successful' ) ;
137
+ } ) ;
138
+ await P . delay ( 5000 ) ;
139
+ // up to this point if it was successful, the race between the delete object and list object went fine.
140
+ }
141
+ } , TEST_TIMEOUT ) ;
142
+ }
143
+
144
+ /**
145
+ * _upload_objects uploads number_of_versions of objects in bucket
146
+ * note: this function is not concurrent, it's a helper function for preparing a bucket with a couple of objects
147
+ * @param {string } bucket
148
+ * @param {number } number_of_objects
149
+ */
150
+ async function _upload_objects ( bucket , number_of_objects ) {
151
+ const keys_names = [ ] ;
152
+ for ( let i = 0 ; i < number_of_objects ; i ++ ) {
153
+ const key_name = `my-key-${ i + 1 } ` ;
154
+ const random_data = Buffer . from ( String ( crypto_random_string ( 7 ) ) ) ;
155
+ const body = buffer_utils . buffer_to_read_stream ( random_data ) ;
156
+ await nsfs . upload_object ( { bucket : bucket , key : key_name , source_stream : body } , DUMMY_OBJECT_SDK ) ;
157
+ keys_names . push ( key_name ) ;
158
+ }
159
+ return keys_names ;
160
+ }
161
+
162
+ /**
163
+ * randomInteger between min (included) and max (included)
164
+ * // copied from: https://stackoverflow.com/questions/4959975/generate-random-number-between-two-numbers-in-javascript
165
+ * @param {number } min
166
+ * @param {number } max
167
+ */
168
+ function random_integer ( min , max ) {
169
+ return Math . floor ( Math . random ( ) * ( max - min + 1 ) ) + min ;
170
+ }
0 commit comments