Project

General

Profile

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

haketilo / test / unit / test_indexeddb_files_server.py @ 5c58b3d6

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_hash = 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'] = [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
    'resources': sample_data_dict(resources),
55
    'mapping': {},
56
    'files': sample_files_by_hash
57
}
58

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

    
64
    mock_broadcast(execute_in_page)
65
    clear_indexeddb(execute_in_page)
66

    
67
    execute_in_page(
68
        '''
69
        let registered_listener;
70
        const new_addListener = cb => registered_listener = cb;
71

    
72
        browser = {runtime: {onMessage: {addListener: new_addListener}}};
73

    
74
        haketilodb.save_items(arguments[0]);
75

    
76
        start();
77
        ''',
78
        initial_indexeddb_data)
79

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

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

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

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

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

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

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

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

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

    
138
    if error == 'missing':
139
        del sample_data_copy['resources']['res-3']
140
    elif error == 'circular':
141
        res3_defs = sample_data_copy['resources']['res-3'].values()
142
        next(iter(res3_defs))['dependencies'].append('res-8')
143

    
144
    prepare_test_page(sample_data_copy, execute_in_page)
145

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

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

    
155
        registered_listener(["indexeddb_files", arguments[0]],
156
                            {}, result_cb);
157

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

    
162
    assert response['error']['haketilo_error_type'] == error
163

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