Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / quotaholder / test / simpletests.py @ c6ef66ba

History | View | Annotate | Download (19.2 kB)

1
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from config import QHTestCase
35
from config import run_test_case
36
from config import printf
37

    
38
from astakos.quotaholder.exception import (
39
                            QuotaholderError,
40
                            InvalidDataError,
41
                            NoQuantityError, NoCapacityError,
42
                            ExportLimitError, ImportLimitError,
43
                            CommissionValueException,
44
                            DuplicateError)
45

    
46
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE
47
from astakos.quotaholder.utils.rand import random_int, random_nat, random_name
48

    
49
DEFAULT_HOLDING = (0, 0, 0, 0)
50

    
51
class QHAPITest(QHTestCase):
52

    
53
    @classmethod
54
    def setUpClass(self):
55
        QHTestCase.setUpClass()
56
        self.client = self.rand_holder()
57

    
58
    @classmethod
59
    def rand_name(self, exclude=None):
60
        for i in range(1,100):
61
            r = random_name()
62
            if exclude is not None and r not in exclude:
63
                exclude.append(r)
64
                return r
65
        else:
66
            m = 'Could not make a unique random name'
67
            raise Exception(m)
68

    
69
    used_entities = ['system']
70

    
71
    @classmethod
72
    def rand_holder(self):
73
        return self.rand_name(self.used_entities)
74

    
75
    used_policies = []
76

    
77
    @classmethod
78
    def rand_policy(self):
79
        return self.rand_name(self.used_policies)
80

    
81
    used_resources = []
82

    
83
    @classmethod
84
    def rand_resource(self):
85
        return self.rand_name(self.used_resources)
86

    
87
    def rand_limits(self):
88
        q = random_nat()
89
        c = random_nat()
90
        il = random_nat()
91
        el = random_nat()
92
        return q, c, il, el
93

    
94
    def rand_policy_limits(self):
95
        p = self.rand_policy()
96
        limits = self.rand_limits()
97
        return p, limits
98

    
99
    def rand_flags(self):
100
        return random_nat()
101

    
102
    def rand_counters(self):
103
        return tuple(random_nat() for i in range(4))
104

    
105
    def new_policy(self):
106
        p, limits = self.rand_policy_limits()
107
        self.qh.set_limits(set_limits=[(p,) + limits])
108
        return p, limits
109

    
110
    @transaction.commit_on_success
111
    def test_006_get_set_limits(self):
112

    
113
        p1, limits1 = self.rand_policy_limits()
114
        limits2 = self.rand_limits()
115
        r = self.qh.set_limits(set_limits=[(p1,) + limits1,
116
                                           (p1,) + limits2])
117

    
118
        p2, _ = self.rand_policy_limits()
119
        r = self.qh.get_limits(get_limits=[p1, p2])
120
        self.assertEqual(r, [(p1,) + limits2])
121

    
122
    @transaction.commit_on_success
123
    def test_007_get_set_holding(self):
124
        e = self.rand_holder()
125
        resource = self.rand_resource()
126

    
127
        p0 = self.rand_policy()
128
        f0 = self.rand_flags()
129
        p1, _ = self.new_policy()
130
        f1 = self.rand_flags()
131
        p2, _ = self.new_policy()
132
        f2 = self.rand_flags()
133

    
134
        with self.assertRaises(QuotaholderError) as cm:
135
            self.qh.set_holding(set_holding=[(e, resource, p0, f0),
136
                                             (e, resource, p1, f1),
137
                                             (e, resource, p2, f2)])
138

    
139
        # Python people consider this a legal use
140
        # It's even in the library docs... whatever
141
        err = cm.exception
142
        self.assertEqual(err.message, [(e, resource, p0)])
143

    
144
        self.qh.get_holding(get_holding=[(e, resource)])
145

    
146
        self.qh.set_holding(set_holding=[(e, resource, p1, f1),
147
                                         (e, resource, p2, f2)])
148

    
149
        resource1 = self.rand_resource()
150
        r = self.qh.get_holding(get_holding=[(e, resource),
151
                                             (e, resource1)])
152
        self.assertEqual(r, [(e, resource, p2) + DEFAULT_HOLDING + (f2,)])
153

    
154
    @transaction.commit_on_success
155
    def test_0080_get_set_quota(self):
156
        e = self.rand_holder()
157
        resource = self.rand_resource()
158
        limits = self.rand_limits()
159
        limits1 = self.rand_limits()
160
        f = self.rand_flags()
161
        self.qh.set_quota(set_quota=[(e, resource) + limits + (f,),
162
                                     (e, resource) + limits1 + (f,)])
163

    
164
        resource2 = self.rand_resource()
165
        r = self.qh.get_quota(get_quota=[(e, resource),
166
                                         (e, resource2)])
167
        self.assertEqual(r, [(e, resource) + limits1 +
168
                             DEFAULT_HOLDING + (f,)])
169

    
170
    def new_quota(self, holder, resource, limits=None):
171
        if limits is None:
172
            limits = self.rand_limits()
173
        f = self.rand_flags()
174
        self.qh.set_quota(
175
            set_quota=[(holder, resource) + limits + (f,)])
176
        return limits
177

    
178
    @transaction.commit_on_success
179
    def test_0081_add_quota(self):
180
        e0 = self.rand_holder()
181
        e1 = self.rand_holder()
182
        resource0 = self.rand_resource()
183
        resource1 = self.rand_resource()
184

    
185
        self.qh.set_quota(
186
            set_quota=[(e0, resource0) + (5, QH_PRACTICALLY_INFINITE, 5, 6) + (0,),
187
                       (e1, resource0) + (5, 5, 5, 5) + (0,)])
188

    
189
        self.qh.add_quota(sub_quota=[(e0, resource0,
190
                                      0, QH_PRACTICALLY_INFINITE, 1, 1)],
191
                          add_quota=[(e0, resource0,
192
                                      0, 3, QH_PRACTICALLY_INFINITE, 0),
193
                                     # new holding
194
                                     (e0, resource1,
195
                                      0, QH_PRACTICALLY_INFINITE, 5, 5)])
196

    
197
        r = self.qh.get_quota(get_quota=[(e0, resource0),
198
                                         (e0, resource1)])
199
        self.assertEqual(r, [(e0, resource0, 5, 3, QH_PRACTICALLY_INFINITE+4, 5)
200
                             + DEFAULT_HOLDING + (0,),
201
                             (e0, resource1, 0, QH_PRACTICALLY_INFINITE, 5, 5)
202
                             + DEFAULT_HOLDING + (0,)])
203

    
204
        with self.assertRaises(QuotaholderError) as cm:
205
            self.qh.add_quota(add_quota=[(e1, resource0,
206
                                          0, (-10), QH_PRACTICALLY_INFINITE, 0),
207
                                         (e0, resource1, 1, 0, 0, 0)])
208

    
209
        err = cm.exception
210
        self.assertEqual(err.message, [(e1, resource0)])
211

    
212
        # r = self.qh.get_quota(get_quota=[(e1, resource0),
213
        #                                  (e0, resource1)])
214
        # self.assertEqual(r, [(e1, resource0, 5, 5 , 5, 5)
215
        #                      + DEFAULT_HOLDING + (0,),
216
        #                      (e0, resource1, 0, QH_PRACTICALLY_INFINITE, 5, 5)
217
        #                      + DEFAULT_HOLDING + (0,)])
218

    
219
    @transaction.commit_on_success
220
    def test_0082_max_quota(self):
221
        e0 = self.rand_holder()
222
        e1 = self.rand_holder()
223
        resource0 = self.rand_resource()
224
        resource1 = self.rand_resource()
225

    
226
        self.qh.set_quota(
227
            set_quota=[(e0, resource0) +
228
                       (5, QH_PRACTICALLY_INFINITE, 5, 6) + (0,)])
229

    
230
        self.qh.add_quota(add_quota=[(e0, resource0,
231
                                      0, QH_PRACTICALLY_INFINITE, 0, 0)])
232

    
233
        r = self.qh.get_quota(get_quota=[(e0, resource0)])
234
        self.assertEqual(r, [(e0, resource0, 5, 2*QH_PRACTICALLY_INFINITE, 5, 6)
235
                             + DEFAULT_HOLDING + (0,)])
236

    
237
    @transaction.commit_on_success
238
    def test_0090_commissions(self):
239
        e0 = self.rand_holder()
240
        e1 = self.rand_holder()
241
        resource = self.rand_resource()
242
        q0, c0, il0, el0 = self.new_quota(e0, resource)
243
        q1, c1, il1, el1 = self.new_quota(e1, resource)
244

    
245
        most = min(c0, il0, q1, el1)
246
        if most < 0:
247
            raise AssertionError("%s <= 0" % most)
248

    
249
        @transaction.commit_on_success
250
        def f():
251
            return self.qh.issue_commission(clientkey=self.client, target=e0,
252
                                            name='something',
253
                                            provisions=[(e1, resource, most)])
254

    
255
        r = f()
256
        self.assertEqual(r, 1)
257

    
258
        @transaction.commit_on_success
259
        def f():
260
            self.qh.issue_commission(clientkey=self.client, target=e0,
261
                                     name='something',
262
                                     provisions=[(e1, resource, 1)])
263

    
264
        with self.assertRaises(CommissionValueException):
265
            f()
266

    
267
        r = self.qh.get_pending_commissions(clientkey=self.client)
268
        self.assertEqual(list(r), [1])
269
        r = self.qh.resolve_pending_commissions(clientkey=self.client,
270
                                                max_serial=1, accept_set=[1])
271
        r = self.qh.get_pending_commissions(clientkey=self.client)
272
        self.assertEqual(list(r), [])
273

    
274
    @transaction.commit_on_success
275
    def test_0091_commissions_exceptions(self):
276
        es1 = self.rand_holder()
277
        es2 = self.rand_holder()
278
        et1 = self.rand_holder()
279
        et2 = self.rand_holder()
280
        resource = self.rand_resource()
281
        self.new_quota(es1, resource, (10, 5, 5, 15))
282
        self.new_quota(es2, resource, (10, 5, 5, 10))
283
        self.new_quota(et1, resource, (0, 15, 3, 20))
284
        self.new_quota(et2, resource, (0, 15, 20, 20))
285

    
286
        with self.assertRaises(NoQuantityError) as cm:
287
            self.qh.issue_commission(clientkey=self.client, target=et1,
288
                                     name='something',
289
                                     provisions=[(es1, resource, 12)])
290
        e = cm.exception
291
        self.assertEqual(e.source, es1)
292
        self.assertEqual(e.target, et1)
293
        self.assertEqual(e.resource, resource)
294
        self.assertEqual(int(e.limit), 10)
295
        self.assertEqual(int(e.requested), 12)
296
        self.assertEqual(int(e.current), 0)
297

    
298
        r = self.qh.issue_commission(clientkey=self.client, target=et1,
299
                                     name='something',
300
                                     provisions=[(es1, resource, 2)])
301
        self.assertGreater(r, 0)
302

    
303
        with self.assertRaises(ImportLimitError) as cm:
304
            self.qh.issue_commission(clientkey=self.client, target=et1,
305
                                     name='something',
306
                                     provisions=[(es1, resource, 2)])
307
        e = cm.exception
308
        self.assertEqual(e.source, es1)
309
        self.assertEqual(e.target, et1)
310
        self.assertEqual(e.resource, resource)
311
        self.assertEqual(int(e.limit), 3)
312
        self.assertEqual(int(e.requested), 2)
313
        self.assertEqual(int(e.current), 2)
314

    
315
        r = self.qh.issue_commission(clientkey=self.client, target=et2,
316
                                     name='something',
317
                                     provisions=[(es2, resource, 9)])
318
        self.assertGreater(r, 0)
319

    
320
        with self.assertRaises(NoCapacityError) as cm:
321
            self.qh.issue_commission(clientkey=self.client, target=et2,
322
                                     name='something',
323
                                     provisions=[(es2, resource, 1),
324
                                                 (es1, resource, 6)])
325
        e = cm.exception
326
        self.assertEqual(e.source, es1)
327
        self.assertEqual(e.target, et2)
328
        self.assertEqual(e.resource, resource)
329
        self.assertEqual(int(e.limit), 15)
330
        self.assertEqual(int(e.requested), 6)
331
        # 9 actual + 1 from the first provision
332
        self.assertEqual(int(e.current), 10)
333

    
334
    @transaction.commit_on_success
335
    def test_010_list_holdings(self):
336
        e0 = 'list_holdings_one'
337
        e1 = 'list_holdings_two'
338
        resource = 'list_holdings_resource'
339
        sys = 'system'
340

    
341
        self.qh.set_quota(set_quota=[(sys, resource, 10, 0,
342
                                      QH_PRACTICALLY_INFINITE,
343
                                      QH_PRACTICALLY_INFINITE, 0),
344
                                     (e0, resource, 0, 10,
345
                                      QH_PRACTICALLY_INFINITE,
346
                                      QH_PRACTICALLY_INFINITE, 0),
347
                                     (e1, resource, 0, 10,
348
                                      QH_PRACTICALLY_INFINITE,
349
                                      QH_PRACTICALLY_INFINITE, 0)])
350

    
351
        s0 = self.qh.issue_commission(clientkey=self.client, target=e0,
352
                                      name='a commission',
353
                                      provisions=[('system', resource, 3)])
354

    
355
        s1 = self.qh.issue_commission(clientkey=self.client, target=e1,
356
                                      name='a commission',
357
                                      provisions=[('system', resource, 4)])
358

    
359
        self.qh.accept_commission(clientkey=self.client, serials=[s0, s1])
360

    
361
        holdings_list, rejected = self.qh.list_holdings(
362
            list_holdings=[e0, e1, e0+e1])
363

    
364
        self.assertEqual(rejected, [e0+e1])
365
        self.assertEqual(holdings_list, [[(e0, resource, 3, 0, 0, 0)],
366
                                         [(e1, resource, 4, 0, 0, 0)]])
367

    
368

    
369
    @transaction.commit_on_success
370
    def test_0130_release_holding(self):
371
        e = self.rand_holder()
372
        resource = self.rand_resource()
373
        limits = self.new_quota(e, resource, (1, 2, 3, 4))
374

    
375
        with self.assertRaises(QuotaholderError) as cm:
376
            self.qh.release_holding(release_holding=[(e, resource)])
377

    
378
        err = cm.exception
379
        self.assertEqual(err.message, [0])
380

    
381
    @transaction.commit_on_success
382
    def test_0131_release_holding(self):
383
        e = self.rand_holder()
384
        resource = self.rand_resource()
385
        limits = self.new_quota(e, resource, (0, 2, 3, 4))
386

    
387
        self.qh.release_holding(release_holding=[(e, resource)])
388

    
389
    @transaction.commit_on_success
390
    def test_0132_release_holding(self):
391
        resource = self.rand_resource()
392

    
393
        es = self.rand_holder()
394
        limits_s = self.new_quota(es, resource, (3, 3, 3, 3))
395
        e = self.rand_holder()
396
        limits = self.new_quota(e, resource, (0, 2, 3, 4))
397

    
398
        r = self.qh.issue_commission(clientkey=self.client, target=e,
399
                                     name='something',
400
                                     provisions=[(es, resource, 1)])
401
        self.assertGreater(r, 0)
402

    
403
        with self.assertRaises(QuotaholderError) as cm:
404
            self.qh.release_holding(release_holding=[(e, resource)])
405

    
406
        err = cm.exception
407
        self.assertEqual(err.message, [0])
408

    
409
    @transaction.commit_on_success
410
    def test_014_reset_holding(self):
411
        e0 = self.rand_holder()
412
        e1 = self.rand_holder()
413
        resource = self.rand_resource()
414
        p, _ = self.new_policy()
415
        f = self.rand_flags()
416
        r = self.qh.set_holding(set_holding=[(e1, resource, p, f)])
417

    
418
        counters = self.rand_counters()
419

    
420
        with self.assertRaises(QuotaholderError) as cm:
421
            self.qh.reset_holding(
422
                reset_holding=[(e0, resource) + counters,
423
                               (e1, resource) + counters])
424

    
425
        err = cm.exception
426
        self.assertEqual(err.message, [0])
427

    
428
        r = self.qh.get_holding(get_holding=[(e1, resource)])
429
        self.assertEqual(r, [(e1, resource, p) + counters + (f,)])
430

    
431
    @transaction.commit_on_success
432
    def test_015_release_nocapacity(self):
433
        qh = self.qh
434
        owner = "system"
435
        source = "test_015_release_nocapacity_source"
436
        resource = "resource"
437
        target = "test_015_release_nocapacity_target"
438
        flags = 0
439
        source_limits  = [source, 6, 0, 1000, 1000]
440
        source_holding = [source, resource, source, flags]
441
        target_limits  = [target, 0, 5, 1000, 1000]
442
        target_holding = [target, resource, target, flags]
443

    
444
        failed = AssertionError("Quotaholder call failed")
445
        if qh.set_limits(set_limits=[source_limits, target_limits]):
446
            raise failed
447
        if qh.set_holding(set_holding=[source_holding, target_holding]):
448
            raise failed
449

    
450
        serial = qh.issue_commission(clientkey=self.client, target=target,
451
                                     name="something",
452
                                     provisions=[(source, resource, 5)])
453
        qh.accept_commission(clientkey=self.client, serials=[serial])
454

    
455
        holding = qh.get_holding(get_holding=[[source, resource]])
456
        self.assertEqual(tuple(holding[0]),
457
                         (source, resource, source, 0, 5, 0, 0, flags))
458
        holding = qh.get_holding(get_holding=[[target, resource]])
459
        self.assertEqual(tuple(holding[0]),
460
                         (target, resource, target, 5, 0, 0, 0, flags))
461

    
462
        if qh.reset_holding(reset_holding=[[target, resource, 10, 0, 0, 0]]):
463
            raise failed
464

    
465
        with self.assertRaises(NoCapacityError):
466
            qh.issue_commission(clientkey=self.client, target=target,
467
                                name="something",
468
                                provisions=[(source, resource, 1)])
469

    
470
        with self.assertRaises(NoQuantityError):
471
            qh.issue_commission(clientkey=self.client, target=target,
472
                                name="something",
473
                                provisions=[(source, resource, -7)])
474

    
475
        source_limits  = [source, 6, 10, 1000, 1000]
476
        if qh.set_limits(set_limits=[source_limits]):
477
            raise failed
478

    
479
        serial = qh.issue_commission(clientkey=self.client, target=target,
480
                                     name="something",
481
                                     provisions=[(source, resource, -1)])
482
        qh.accept_commission(clientkey=self.client, serials=[serial])
483

    
484
        holding = qh.get_holding(get_holding=[[source, resource]])
485
        self.assertEqual(tuple(holding[0]),
486
                         (source, resource, source, 0, 5, 1, 0, flags))
487
        holding = qh.get_holding(get_holding=[[target, resource]])
488
        self.assertEqual(tuple(holding[0]),
489
                         (target, resource, target, 10, 0, 0, 1, flags))
490

    
491
        with self.assertRaises(NoCapacityError):
492
            qh.issue_commission(clientkey=self.client, target=target,
493
                                name="something",
494
                                provisions=[(source, resource, -10)])
495

    
496

    
497
if __name__ == "__main__":
498
    import sys
499
    printf("Using {0}", sys.executable)
500
    run_test_case(QHAPITest)