test_httpclientpool.py 18.3 KB
Newer Older
1
# -*- coding: utf-8 -*-
tearsyu's avatar
tearsyu committed
2

3
from test_pal import backup_restore
4
from serv.test_httppool import getPayload, check_response
tearsyu's avatar
tearsyu committed
5
6

from fdi.dataset.product import Product
7
8
from fdi.dataset.numericparameter import NumericParameter
from fdi.dataset.stringparameter import StringParameter
mh001's avatar
mh001 committed
9
from fdi.dataset.eq import deepcmp
M. Huang's avatar
M. Huang committed
10

11
from fdi.dataset.deserialize import serialize_args, deserialize_args
M. Huang's avatar
M. Huang committed
12
from fdi.dataset.testproducts import get_demo_product, get_related_product
13
from fdi.pal.productstorage import ProductStorage
M. Huang's avatar
M. Huang committed
14
from fdi.pal.productref import ProductRef
tearsyu's avatar
tearsyu committed
15
from fdi.pal.query import MetaQuery
16
from fdi.pal.poolmanager import PoolManager, DEFAULT_MEM_POOL, PM_S
17
from fdi.pal.httpclientpool import HttpClientPool
M. Huang's avatar
M. Huang committed
18
from fdi.pns.fdi_requests import safe_client, urn2fdiurl, parse_poolurl
19
from fdi.utils.common import fullname, trbk
tearsyu's avatar
tearsyu committed
20

21
22
import networkx as nx

23
24
from flask_httpauth import HTTPBasicAuth
# from requests.auth import HTTPBasicAuth
25
from requests.exceptions import ConnectionError
26
import pytest
27
import time
28
import urllib
29
import copy
30

tearsyu's avatar
tearsyu committed
31

M. Huang's avatar
M. Huang committed
32
33
def setuplogging():
    import logging
34
    import logging.config
35
    from . import logdict1
M. Huang's avatar
M. Huang committed
36

tearsyu's avatar
tearsyu committed
37
    # create logger
38
    logging.config.dictConfig(logdict1.logdict)
M. Huang's avatar
M. Huang committed
39
40
41
42
43
44
    logging.getLogger("requests").setLevel(logging.WARN)
    logging.getLogger("urllib3").setLevel(logging.WARN)
    logging.getLogger("filelock").setLevel(logging.WARN)
    return logging


M. Huang's avatar
M. Huang committed
45
46
logging = setuplogging()
logger = logging.getLogger()
M. Huang's avatar
M. Huang committed
47

48
logger.setLevel(logging.INFO)
M. Huang's avatar
M. Huang committed
49
50
logger.debug('logging level %d' % (logger.getEffectiveLevel()))

51
SHORT = 'function'
tearsyu's avatar
tearsyu committed
52
53
54
55
56
57

@pytest.fixture(scope="module")
def init_test():
    pass


58
def chksa(a, k):
59
    p = 0
M. Huang's avatar
M. Huang committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    for not_quoted in [False, True]:
        s = serialize_args(*a, **k)
        if p:
            print('s= ', s)
        code, a1, k1 = deserialize_args(s, not_quoted=False)
        assert code == 200
        assert a == a1
        assert k == k1
        s = urllib.parse.unquote(s)
        if p:
            print('S= ', s)
        code, a1, k1 = deserialize_args(s, not_quoted=True)
        assert code == 200
        assert a == a1
        assert k == k1
75
76
77


def test_serialize_args():
M. Huang's avatar
M. Huang committed
78
79
80
81
    a = ['__foo__', 1, 2, -3, 4.0, 'a', 'b c__d', b'\xde\xad',
         True, None, NumericParameter(42)]
    k = {'__f__': '__g__', 'a': 'r', 'f': 0, 'b': True,
         'k': None, 's': StringParameter('4..2')}
82
83
84
85
    chksa(a, k)
    a = [[1]]
    k = {}
    chksa(a, k)
86
87
    a = []
    k = {'s': 2}
88
    chksa(a, k)
M. Huang's avatar
M. Huang committed
89
90
    a, k = ['__foo', {'3': 4}], dict(d=6)
    chksa(a, k)
91
92


93
def test_gen_url(server, set_ids):
tearsyu's avatar
tearsyu committed
94
95
    """ Makesure that request create corrent url
    """
96
97
    csdb_pool_id, http_pool_id, PTYPES = set_ids
    
mh001's avatar
mh001 committed
98
    aburl, client, auth, pool, poolurl, pstore, server_type = server
99
    samplepoolname = 'sample_' + http_pool_id
100
    samplepoolurl = aburl + '/' + samplepoolname
M. Huang's avatar
M. Huang committed
101
    sampleurn = 'urn:' + samplepoolname + ':fdi.dataset.product.Product:10'
tearsyu's avatar
tearsyu committed
102
103

    logger.info('Test GET HK')
M. Huang's avatar
M. Huang committed
104
    got_hk_url = urn2fdiurl(
M. Huang's avatar
M. Huang committed
105
        urn=sampleurn, poolurl=samplepoolurl, contents='housekeeping', method='GET')
106
    hk_url = aburl + '/' + samplepoolname + '/hk/'
tearsyu's avatar
tearsyu committed
107
108
    assert got_hk_url == hk_url, 'Housekeeping url error: ' + got_hk_url + ':' + hk_url

M. Huang's avatar
M. Huang committed
109
    logger.info('Test GET classes, urns, tags, webapi url')
M. Huang's avatar
M. Huang committed
110
    got_classes_url = urn2fdiurl(
M. Huang's avatar
M. Huang committed
111
        urn=sampleurn, poolurl=samplepoolurl, contents='classes', method='GET')
M. Huang's avatar
M. Huang committed
112
    classes_url = aburl + '/' + samplepoolname + '/hk/classes'
tearsyu's avatar
tearsyu committed
113
114
    assert got_classes_url == classes_url, 'Classes url error: ' + got_classes_url

M. Huang's avatar
M. Huang committed
115
116
    got_urns_url = urn2fdiurl(
        urn=sampleurn, poolurl=samplepoolurl, contents='urns', method='GET')
M. Huang's avatar
M. Huang committed
117
    urns_url = aburl + '/' + samplepoolname + '/hk/urns'
tearsyu's avatar
tearsyu committed
118
119
    assert got_urns_url == urns_url, 'Urns url error: ' + got_urns_url

M. Huang's avatar
M. Huang committed
120
121
    got_tags_url = urn2fdiurl(
        urn=sampleurn, poolurl=samplepoolurl, contents='tags', method='GET')
M. Huang's avatar
M. Huang committed
122
    tags_url = aburl + '/' + samplepoolname + '/hk/tags'
tearsyu's avatar
tearsyu committed
123
124
125
    assert got_tags_url == tags_url, 'Housekeeping url error: ' + got_tags_url

    logger.info('Get product url')
M. Huang's avatar
M. Huang committed
126
    got_product_url = urn2fdiurl(
M. Huang's avatar
M. Huang committed
127
        urn=sampleurn, poolurl=samplepoolurl, contents='product', method='GET')
YuxinSHI's avatar
YuxinSHI committed
128
    product_url = aburl + '/' + samplepoolname + '/fdi.dataset.product.Product/10'
tearsyu's avatar
tearsyu committed
129
130
    assert got_product_url == product_url, 'Get product url error: ' + got_product_url

M. Huang's avatar
M. Huang committed
131
    logger.info('GET WebAPI  url')
M. Huang's avatar
M. Huang committed
132
    call = 'tagExists__foo'
M. Huang's avatar
M. Huang committed
133
134
    got_webapi_url = urn2fdiurl(
        urn=sampleurn, poolurl=samplepoolurl, contents=call, method='GET')
M. Huang's avatar
M. Huang committed
135
    webapi_url = aburl + '/' + samplepoolname + '/' + 'api/' + call
M. Huang's avatar
M. Huang committed
136
    # '/'
137
138
    assert got_webapi_url == webapi_url + \
        '/', 'Get WebAPI url error: ' + got_webapi_url
M. Huang's avatar
M. Huang committed
139

140
141
142
143
144
145
146
147
    logger.info('Post WebAPI url')
    call = 'tagExists__foo'
    got_post_api_url = urn2fdiurl(
        urn=sampleurn, poolurl=samplepoolurl, contents=call, method='POST')
    post_api_url = aburl + '/' + samplepoolname+'/' + 'api/' + 'tagExists/'
    assert got_post_api_url == post_api_url, 'Post WebAPI url error: ' + \
        got_post_api_url

tearsyu's avatar
tearsyu committed
148
    logger.info('Post product url')
M. Huang's avatar
M. Huang committed
149
    got_post_product_url = urn2fdiurl(
M. Huang's avatar
M. Huang committed
150
        urn=sampleurn, poolurl=samplepoolurl, contents='product', method='POST')
YuxinSHI's avatar
YuxinSHI committed
151
    post_product_url = aburl + '/' + samplepoolname + '/'
M. Huang's avatar
M. Huang committed
152
    assert got_post_product_url == post_product_url, 'Post product url error: ' + \
YuxinSHI's avatar
YuxinSHI committed
153
                                                     got_post_product_url
tearsyu's avatar
tearsyu committed
154
155

    logger.info('Delete product url')
M. Huang's avatar
M. Huang committed
156
    got_del_product_url = urn2fdiurl(
M. Huang's avatar
M. Huang committed
157
        urn=sampleurn, poolurl=samplepoolurl, contents='product', method='DELETE')
158
    del_product_url = aburl + '/urn' + sampleurn
M. Huang's avatar
M. Huang committed
159
    assert got_del_product_url == del_product_url, 'Delete product url error: ' + \
YuxinSHI's avatar
YuxinSHI committed
160
                                                   got_del_product_url
tearsyu's avatar
tearsyu committed
161
162

    logger.info('Delete pool url')
M. Huang's avatar
M. Huang committed
163
    got_del_pool_url = urn2fdiurl(
164
165
        urn=sampleurn, poolurl=samplepoolurl, contents='wipe_pool', method='DELETE')
    del_pool_url = aburl + '/' + samplepoolname + '/wipe'
tearsyu's avatar
tearsyu committed
166
167
168
169
    assert got_del_pool_url == del_pool_url, 'Delete product url error: ' + got_del_pool_url

    logger.info('Test corrupt request url')
    with pytest.raises(ValueError) as exc:
M. Huang's avatar
M. Huang committed
170
        err_url = urn2fdiurl(
171
            urn=sampleurn, poolurl=samplepoolurl, contents='pool', method ='GET')
tearsyu's avatar
tearsyu committed
172
173
        exc_msg = exc.value.args[0]
        assert exc_msg == 'No such method and contents composition: GET/pool'
174
175
        
num = 0
176
def test_foo(tmp_remote_storage_no_wipe, set_ids):
177
    ps, pool  = tmp_remote_storage_no_wipe
178
    csdb_pool_id, http_pool_id, PTYPES = set_ids
179
    assert http_pool_id in ps
180
181
182
183
184
185
186
187
188
    wtb = ps.getWritablePool()
    pw = ps._pools[wtb]
    pw.removeAll()
    global num
    num = pw.getCount()
    p = Product('fffoooo')
    ref = ps.save(p)
    assert pw.getCount() == num + 1
          
189
190
def test_foo1(set_ids, tmp_remote_storage_no_wipe):
    csdb_pool_id, http_pool_id, PTYPES = set_ids
191
    ps, pool  = tmp_remote_storage_no_wipe
192
    assert http_pool_id  in ps
193
194
195
196
197
198
199
200
    wtb = ps.getWritablePool()
    pw = ps._pools[wtb]
    assert pw.getCount() == num + 1
          

def test_tmp_remote_storage_no_wipe(tmp_remote_storage_no_wipe, tmp_prods):

    ps, pool = tmp_remote_storage_no_wipe
201
    # lit of poolnames
202
203
    plst = list(ps._pools)
    assert len(plst) > 0
204

205
    # empty
M. Huang's avatar
M. Huang committed
206
207
    inicnt = pool.getCount()
    assert inicnt > 0
208
    assert not pool.isEmpty()
209
210
211
    prod_lst = tmp_prods
    refs = []
    for i, p in enumerate(prod_lst):
212
        ts = 'saved at %d' % time.time_ns()
213
        refs.append(ps.save(p, tag=ts))
M. Huang's avatar
M. Huang committed
214
    
215
216
217
218
219
    retrd = []
    for r in refs:
        p = r.product
        retrd.append(p)
        assert p.description.startswith('test-product-')
M. Huang's avatar
M. Huang committed
220
    assert len(prod_lst) == len(retrd) == pool.getCount() - inicnt
221
    
222

223
224
225
226
227
228
229
230
231
# def est_CRUD_product_by_client(server, local_pools_dir, auth):
#     """Client http product storage READ, CREATE, DELETE products in remote
#     """
#     aburl, headers = server
#     client = None
#     poolid = http_pool_id
#     poolurl = aburl + '/' + poolid
#     pool = HttpClientPool(poolname=poolid, poolurl=poolurl)
#     crud_t(poolid, poolurl, pool, auth, client)
232
233


234
@ pytest.fixture(scope="function")
mh001's avatar
mh001 committed
235
def get_PS_for_CRUD(server, tmp_remote_storage):
236
237
238

    logger.info('Init a pstore')

mh001's avatar
mh001 committed
239
    aburl, client, auth, pool, poolurl, pstore, server_type = server
240
241
    ps_remote = tmp_remote_storage

mh001's avatar
mh001 committed
242
243
244
245
246
    poolid = pool.poolname
    
    # poolid = ps_remote.getPools()[0]
    # pool = ps_remote.getPool(poolid)
    # poolurl = pool.poolurl
247
248
249
    if 1:
        if PoolManager.isLoaded(DEFAULT_MEM_POOL):
            PoolManager.getPool(DEFAULT_MEM_POOL).removeAll()
mh001's avatar
mh001 committed
250
251
252
    # # this will also register the server side
    # pstore = ProductStorage(pool=pool, auth=auth, client=client)
    # pstore.register(poolid)
253
254
    pool.removeAll()

M. Huang's avatar
M. Huang committed
255
    assert len(pstore.getPools()) == 1, 'product storage size error: ' + \
YuxinSHI's avatar
YuxinSHI committed
256
                                        str(pstore.getPools())
257
    assert pstore.getPool(poolid) is not None, 'Pool ' + \
YuxinSHI's avatar
YuxinSHI committed
258
                                               poolid + ' is None.'
259
260
261
262
263
264
    return poolid, poolurl, pool, auth, client, pstore


def test_CRUD_product_by_client(get_PS_for_CRUD):
    """Client http product storage READ, CREATE, DELETE products in remote
    """
M. Huang's avatar
M. Huang committed
265
    logger.info('start CRUD test')
266
267

    poolid, poolurl, pool, auth, client, pstore = get_PS_for_CRUD
M. Huang's avatar
M. Huang committed
268
269

    cnt = pool.getCount('fdi.dataset.product.Product')
M. Huang's avatar
M. Huang committed
270
    assert cnt == 0, 'Local metadata file size is 0'
M. Huang's avatar
M. Huang committed
271
    assert pool.count == 0
M. Huang's avatar
M. Huang committed
272
273

    logger.info('Save data by ' + pool.__class__.__name__)
tearsyu's avatar
tearsyu committed
274
    x = Product(description='desc test')
275
276
    x0 = x.copy()
    
tearsyu's avatar
tearsyu committed
277
    urn = pstore.save(x, geturnobjs=True)
M. Huang's avatar
M. Huang committed
278
    x.creator = 'httpclient'
279

M. Huang's avatar
M. Huang committed
280
    urn2 = pstore.save(x, geturnobjs=True)
M. Huang's avatar
M. Huang committed
281
    typenm = fullname(x)
282
    expected_urn = 'urn:' + poolid + ':' + fullname(x)
283
284
    assert urn.urn.rsplit(':', 1)[0] == expected_urn, \
        'Urn error: ' + expected_urn
M. Huang's avatar
M. Huang committed
285
286
    logger.info('Saved two products.')

M. Huang's avatar
M. Huang committed
287
    poolpath, scheme, place, pn, un, pw = parse_poolurl(
288
        poolurl, poolhint=poolid)
289
    # import http
M. Huang's avatar
M. Huang committed
290
291
    # http.client.HTTPConnection.debuglevel = 1

M. Huang's avatar
M. Huang committed
292
    cnt = pool.getCount(typenm)
M. Huang's avatar
M. Huang committed
293
    assert cnt == pool.getCount()
294

M. Huang's avatar
M. Huang committed
295
    assert cnt == 2 == pool.count
tearsyu's avatar
tearsyu committed
296
297

    logger.info('Load product from httpclientpool')
M. Huang's avatar
M. Huang committed
298
    res = pstore.getPool(poolid).loadProduct(urn2.urn)
tearsyu's avatar
tearsyu committed
299
    assert res.creator == 'httpclient', 'Load product error: ' + str(res)
M. Huang's avatar
M. Huang committed
300
    diff = deepcmp(x, res)
mh001's avatar
mh001 committed
301
    assert diff is None, diff
tearsyu's avatar
tearsyu committed
302

303
304
305
306
    logger.info('Search metadata')
    q = MetaQuery(Product, 'm["creator"] == "httpclient"')
    res = pstore.select(q)
    assert len(res) == 1, 'Select from metadata error: ' + str(res)
tearsyu's avatar
tearsyu committed
307

308
309
310
311
312
313
    # save two in one go
    p2 = [x0, x]
    urns  = pstore.save(p2, geturnobjs=True)
    assert all(expected_urn==u.urn.rsplit(':',1)[0] for u in urns)
    assert x == pstore.getPool(poolid).loadProduct(urns[1].urn)

tearsyu's avatar
tearsyu committed
314
    logger.info('Delete a product from httpclientpool')
315
    pstore.getPool(poolid).remove(urn.urn)
M. Huang's avatar
M. Huang committed
316
    lsn = pstore.getPool(poolid).getCount('fdi.dataset.product.Product')
317
    assert lsn == 3, 'Delete product local error, len sn : ' + lsn
M. Huang's avatar
M. Huang committed
318
    logger.info('A load exception message is expected')
319

320
    with pytest.raises(NameError):
321
        res = pstore.getPool(poolid).loadProduct(urn.urn)
322
323
324
    with pytest.raises(NameError):
        res = pstore.getPool(poolid).loadProduct(
            urn.urn.replace('Product', 'this_and_the_last_errors.are.expected'))
tearsyu's avatar
tearsyu committed
325

M. Huang's avatar
M. Huang committed
326
    logger.info('Wipe a pool')
327

328
    pstore.getPool(poolid).removeAll()
329
330
331
332
    try:
        assert pool.isEmpty()
        assert pool.count == 0
    except ConnectionError:
M. Huang's avatar
M. Huang committed
333
        logger.info('Unregistered Pool raises connectionError.')
M. Huang's avatar
M. Huang committed
334
    tag = '==== Demo Product ===='
YuxinSHI's avatar
YuxinSHI committed
335
    logger.info('test sample demo prod with tag: ' + tag)
336
    sp = get_demo_product()
M. Huang's avatar
M. Huang committed
337
338
    sp.refs['a_ref'] = ProductRef(get_related_product())

M. Huang's avatar
M. Huang committed
339
340
341
342
    urn = pstore.save(sp, tag=tag)
    print('Sample Prod saved with tag "%s" %s to %s' %
          (tag, urn.urn, pool.poolname))

M. Huang's avatar
M. Huang committed
343
344
    logger.info('unregister a pool')
    assert len(pstore.getPools()) == 1, 'product storage size error: ' + \
YuxinSHI's avatar
YuxinSHI committed
345
                                        str(pstore.getPools())
M. Huang's avatar
M. Huang committed
346
347
348
    # unregister locally and remotely
    pstore.unregister(poolid)
    assert len(pstore.getPools()) == 0, 'product storage size error: ' + \
YuxinSHI's avatar
YuxinSHI committed
349
                                        str(pstore.getPools())
M. Huang's avatar
M. Huang committed
350

351
    logger.info('Access a non-existing pool and trigger an Error.')
352
353
354
355
356
357
358
359
360
361
    return
    if 0:
        with pytest.raises(NameError):
            pstore.getPool(poolid + '_NON_EXISTS') is None
    else:
        try:
            pstore.getPool(poolid + '_NON_EXISTS') is None
        except Exception as e:
            print(f"Expected exception from server: {e}, traceback {trbk(e)}")
            assert 'not found' in str(e)
M. Huang's avatar
M. Huang committed
362

363
def est_webapi_backup_restore(server):
M. Huang's avatar
M. Huang committed
364
365
    """
    """
M. Huang's avatar
wip    
M. Huang committed
366
    aburl, headers = server
M. Huang's avatar
M. Huang committed
367
368

    logger.info('Create pools on the server.')
369
    poolid = http_pool_id
M. Huang's avatar
M. Huang committed
370
371
372
    poolurl = aburl + '/' + poolid
    pool = HttpClientPool(poolname=poolid, poolurl=poolurl)

M. Huang's avatar
M. Huang committed
373
374
    logger.info('Bacckup/restore a pool on the server.')

M. Huang's avatar
M. Huang committed
375
376
377
378
    if PoolManager.isLoaded(DEFAULT_MEM_POOL):
        PoolManager.getPool(DEFAULT_MEM_POOL).removeAll()
    # this will also register the server side
    pstore = ProductStorage(pool=pool)
M. Huang's avatar
M. Huang committed
379
    backup_restore(pstore)
M. Huang's avatar
M. Huang committed
380

YuxinSHI's avatar
YuxinSHI committed
381

mh001's avatar
mh001 committed
382
def test_webapi_backup_restore(server):
383
384
385
    """
    """
    logger.info('Create pools on the server.')
mh001's avatar
mh001 committed
386
387
    #pstore = tmp_remote_storage
    aburl, client, auth, pool, poolurl, pstore, server_type = server
388
    logger.info('Bacckup/restore a pool on the server.')
mh001's avatar
mh001 committed
389

390
    backup_restore(pstore, client, auth)
391
392


mh001's avatar
mh001 committed
393
394
def test_flask_fmt(tmp_pools, server):
    aburl, client, auth, pool, poolurl, pstore, server_type = server
395
396
397
398
399
400
401
402
    pool, prd, ref, tag = tmp_pools[0]
    prd_urn = ref.urn

    #### /{pool}  /{pool}/  GET  ####

    # server url without slash
    aburl_no_slash = aburl.rstrip('/')
    # get poolname
M. Huang's avatar
M. Huang committed
403
    x = safe_client(client.get, aburl_no_slash, auth=auth)
404
405
406
407
408
409
    o, code = getPayload(x)
    # check to see if the pool url is malformed
    check_response(o, code=code, failed_case=False)
    # should be a list of names
    poolnames = o['result']
    assert isinstance(poolnames, dict)
410
    assert any(pool._poolname in x for x in poolnames)
411
412
413
414
415
416

    # check to see if the pool url is malformed by checking if
    # the pool's url can be used to retrieve the pool
    from fdi.pal.urn import Urn, parseUrn
    p_pname, p_type, p_index = parseUrn(prd_urn)

417
    received_poolurls_no_slash = PoolManager.getMap()[pool._poolname]._poolurl.rstrip('/')
418
419
    # get pool with products and their urls

M. Huang's avatar
M. Huang committed
420
    x = safe_client(client.get, received_poolurls_no_slash, auth=auth)
421
422
423
424
425
426
427
    o, code = getPayload(x)
    # check to see if the pool url is malformed
    check_response(o, code=code, failed_case=False)
    # The product under the correct type and sn has the right tag
    # tags are a string to make btter display.

    # the url is right
428
    assert o['result']['DataTypes'][p_type.rsplit('.', 1)[1]][p_index]['url'] == '/'.join(
429
        (received_poolurls_no_slash, p_type, str(p_index)))
430
431
    assert o['result']['DataTypes'][p_type.rsplit(
        '.', 1)[1]][p_index]['tags'] == str([tag])
432
433
434
    # pool aburl with slash
    # get the pool using url with slash
    received_poolurls_slash = received_poolurls_no_slash+'/'
M. Huang's avatar
M. Huang committed
435
    x1 = safe_client(client.get, received_poolurls_slash, auth=auth)
436
437
438
439
    o1, code = getPayload(x1)
    assert o['result'] == o1['result']

    aburl_slash = aburl_no_slash+'/'
M. Huang's avatar
M. Huang committed
440
    x = safe_client(client.get, aburl_slash, auth=auth)
441
442
443
444
    o, code = getPayload(x)
    check_response(o, code=code, failed_case=False)
    # should be a list of names
    poolnames = o['result']
445
    assert isinstance(poolnames, dict)
446
447
    assert any(pool._poolname in x for x in poolnames)

448

449

450
def test_slash(tmp_remote_storage_no_wipe, tmp_prods):
451
    # add urn
452
    ps, pool = tmp_remote_storage_no_wipe
453
454
455
456
    p0_, p11_, p12_, p121, p122, p1221, p12211 = tmp_prods
    urn12211 = ps.save(p12211).urn


457
def test_hist(tmp_remote_storage_no_wipe, tmp_prods):
458
    # add urn
459
    ps, pool = tmp_remote_storage_no_wipe
460
461
462
463
464
465
466
467
468
469
470
    p0_, p11_, p12_, p121, p122, p1221, p12211 = tmp_prods
    urn12211 = ps.save(p12211).urn
    p1221.history.add_input(refs={'p1-2-2-1-1': urn12211})
    assert p1221.history.rowCount == 1
    assert p12211.history.rowCount == 0

    urn1221 = ps.save(p1221).urn
    p122.history.add_input(refs={'p1-2-2-1': urn1221})
    assert p121.history.rowCount == 0
    assert p122.history.rowCount == 1

M. Huang's avatar
M. Huang committed
471
    # get fresh p0, p11, p12 in case they used for something else
472
473
    p11 = copy.deepcopy(p11_)
    p12 = copy.deepcopy(p12_)
M. Huang's avatar
M. Huang committed
474
475
476

    urn121 = ps.save(p121).urn
    urn122 = ps.save(p122).urn
477
478
479
480
    p12.history.add_input(refs={'p1-2-1': urn121, 'p1-2-2': urn122})
    assert p11.history.rowCount == 0
    assert p12.history.rowCount == 2

M. Huang's avatar
M. Huang committed
481
482
483
    urn11 = ps.save(p11).urn
    urn12 = ps.save(p12).urn
    p0 = copy.deepcopy(p0_)
484
    v = p0.history
M. Huang's avatar
M. Huang committed
485
    v.add_input(refs={'p1-1': urn11, 'p1-2': urn12})
486
    assert v.rowCount == 2
M. Huang's avatar
M. Huang committed
487
488
489

    # use ref as labels
    th = v.getTaskHistory(use_name=False, verbose=0)
490
491
    pdot = nx.drawing.nx_pydot.to_pydot(th)
    print(pdot.to_string())
492
493
494
495
    assert len(th.nodes) == 7
    assert len(th.adj) == 7
    assert len(list(th.pred['root'])) == 2

M. Huang's avatar
M. Huang committed
496
497
    urn0 = ps.save(p0).urn
    h = p0.history.getTaskHistory(verbose=False)
498
    h.nodes['root']['product_ref'] = f'"{urn0}"'
499
    if 1:
500
501
502
503
504
        assert len(p11.history['Name']) == 0
        assert p12.history['Name'][0] == 'p1-2-1'
        assert p12.history['Name'][1] == 'p1-2-2'
        assert p122.history['Name'][0] == 'p1-2-2-1'
        assert p1221.history['Name'][0] == 'p1-2-2-1-1'
505
        assert nx.is_directed_acyclic_graph(h)
506

507
    assert len(h.adj) == 7
M. Huang's avatar
M. Huang committed
508
509
    pdot = nx.drawing.nx_pydot.to_pydot(h)
    print(pdot.to_string())
510
511


mh001's avatar
mh001 committed
512
def test_no_auth(server, tmp_pools):
513
    # reading pool root dir needs no auth
mh001's avatar
mh001 committed
514
    aburl, client, auth, pool, poolurl, pstore, server_type = server
515
516

    # get pool without auth
M. Huang's avatar
M. Huang committed
517
    x = safe_client(client.get, aburl, auth=None)
518
519
520
521
    o, code = getPayload(x)
    # check to see if the pool url is malformed
    check_response(o, code=code, failed_case=False)
    # pool name is found
522
    assert any(pool._poolname in x for x in o['result'])
523
524


mh001's avatar
mh001 committed
525
def test_need_auth(server):
526

mh001's avatar
mh001 committed
527
    aburl, client, auth, pool, poolurl, pstore, server_type = server
528
529
    url = '/'.join((aburl, pool.poolname, 'hk/'))
    # get pool with auth
M. Huang's avatar
M. Huang committed
530
    x = safe_client(client.get, url, auth=auth)
531
532
533
534
535
536
537
538
539
    o, code = getPayload(x)

    # check to see if the pool url is malformed
    check_response(o, code=code, failed_case=False)
    assert o['msg'] == 'OK.'

    # in session
    url = '/'.join((aburl, pool.poolname, 'hk/dTags'))

M. Huang's avatar
M. Huang committed
540
    x = safe_client(client.get, url, auth=auth)
541
542
543
544

    o, code = getPayload(x)
    check_response(o, code=code, failed_case=False)
    assert o['msg'] == 'dTags HK data returned OK'