Project

General

Profile

Download (5.44 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / test / unit / test_indexeddb_files_server.py @ 92fc67cf

1
# SPDX-License-Identifier: CC0-1.0
2

    
3
"""
4
Haketilo unit tests - serving indexeddb resource script files to content scripts
5
"""
6

    
7
# This file is part of Haketilo
8
#
9
# Copyright (C) 2021,2022 Wojtek Kosior <koszko@koszko.org>
10
#
11
# This program is free software: you can redistribute it and/or modify
12
# it under the terms of the CC0 1.0 Universal License as published by
13
# the Creative Commons Corporation.
14
#
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
# CC0 1.0 Universal License for more details.
19

    
20
import pytest
21
import copy
22
from uuid import uuid4
23
from selenium.webdriver.support.ui import WebDriverWait
24

    
25
from ..script_loader import load_script
26
from .utils import *
27

    
28
"""
29
How many test resources we're going to have.
30
"""
31
count = 15
32

    
33
sample_files_list = [(f'file_{n}_{i}', f'contents {n} {i}')
34
                       for n in range(count) for i in range(2)]
35

    
36
sample_files = dict(sample_files_list)
37

    
38
sample_files, sample_files_by_sha256 = make_sample_files(sample_files)
39

    
40
def make_sample_resource_with_deps(n):
41
    resource = make_sample_resource(with_files=False)
42

    
43
    resource['identifier'] = f'res-{n}'
44
    resource['dependencies'] = [{'identifier': f'res-{m}'}
45
                                for m in range(max(n - 4, 0), n)]
46
    resource['scripts'] = [sample_file_ref(f'file_{n}_{i}', sample_files)
47
                           for i in range(2)]
48

    
49
    return resource
50

    
51
resources = [make_sample_resource_with_deps(n) for n in range(count)]
52

    
53
sample_data = {
54
    'resource': sample_data_dict(resources),
55
    'mapping': {},
56
    'file': {
57
        'sha256': sample_files_by_sha256
58
    }
59
}
60

    
61
def prepare_test_page(initial_indexeddb_data, execute_in_page):
62
    js = load_script('background/indexeddb_files_server.js',
63
                     code_to_add='#IMPORT common/broadcast.js')
64
    execute_in_page(js)
65

    
66
    mock_broadcast(execute_in_page)
67
    clear_indexeddb(execute_in_page)
68

    
69
    execute_in_page(
70
        '''
71
        let registered_listener;
72
        const new_addListener = cb => registered_listener = cb;
73

    
74
        browser = {runtime: {onMessage: {addListener: new_addListener}}};
75

    
76
        haketilodb.save_items(arguments[0]);
77

    
78
        start();
79
        ''',
80
        initial_indexeddb_data)
81

    
82
@pytest.mark.get_page('https://gotmyowndoma.in')
83
def test_indexeddb_files_server_normal_usage(driver, execute_in_page):
84
    """
85
    Test querying resource files (with resource dependency resolution)
86
    from IndexedDB and serving them in messages to content scripts.
87
    """
88
    prepare_test_page(sample_data, execute_in_page)
89

    
90
    # Verify other types of messages are ignored.
91
    function_returned_value = execute_in_page(
92
        '''
93
        returnval(registered_listener(["???"], {},
94
                                      () => location.reload()));
95
        ''')
96
    assert function_returned_value == None
97

    
98
    # Verify single resource's files get properly resolved.
99
    function_returned_value = execute_in_page(
100
        '''
101
        var result_cb, contents_prom = new Promise(cb => result_cb = cb);
102

    
103
        returnval(registered_listener(["indexeddb_files", "res-0"],
104
                                      {}, result_cb));
105
        ''')
106
    assert function_returned_value == True
107

    
108
    assert execute_in_page('returnval(contents_prom);') == \
109
        {'files': [tuple[1] for tuple in sample_files_list[0:2]]}
110

    
111
    # Verify multiple resources' files get properly resolved.
112
    function_returned_value = execute_in_page(
113
        '''
114
        var result_cb, contents_prom = new Promise(cb => result_cb = cb);
115

    
116
        returnval(registered_listener(["indexeddb_files", arguments[0]],
117
                                      {}, result_cb));
118
        ''',
119
        f'res-{count - 1}')
120
    assert function_returned_value == True
121

    
122
    assert execute_in_page('returnval(contents_prom);') == \
123
        {'files': [tuple[1] for tuple in sample_files_list]}
124

    
125
@pytest.mark.get_page('https://gotmyowndoma.in')
126
@pytest.mark.parametrize('error', [
127
    'missing',
128
    'circular',
129
    'db',
130
    'other'
131
])
132
def test_indexeddb_files_server_errors(driver, execute_in_page, error):
133
    """
134
    Test reporting of errors when querying resource files (with resource
135
    dependency resolution) from IndexedDB and serving them in messages to
136
    content scripts.
137
    """
138
    sample_data_copy = copy.deepcopy(sample_data)
139

    
140
    if error == 'missing':
141
        del sample_data_copy['resource']['res-3']
142
    elif error == 'circular':
143
        res3_defs = sample_data_copy['resource']['res-3'].values()
144
        next(iter(res3_defs))['dependencies'].append({'identifier': 'res-8'})
145

    
146
    prepare_test_page(sample_data_copy, execute_in_page)
147

    
148
    if error == 'db':
149
        execute_in_page('haketilodb.idb_get = t => t.onerror("oooops");')
150
    elif error == 'other':
151
        execute_in_page('haketilodb.idb_get = () => {throw "oooops"};')
152

    
153
    response = execute_in_page(
154
        '''
155
        var result_cb, contents_prom = new Promise(cb => result_cb = cb);
156

    
157
        registered_listener(["indexeddb_files", arguments[0]],
158
                            {}, result_cb);
159

    
160
        returnval(contents_prom);
161
        ''',
162
        f'res-{count - 1}')
163

    
164
    assert response['error']['haketilo_error_type'] == error
165

    
166
    if error == 'missing':
167
        assert response['error']['id'] == 'res-3'
168
    elif error == 'circular':
169
        assert response['error']['id'] in ('res-3', 'res-8')
170
    elif error not in ('db', 'other'):
171
        raise Exception('made a typo in test function params?')
(9-9/25)