1# Copyright 2021 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Unit tests for generate_cc_blob_library.py""" 15 16from pathlib import Path 17import tempfile 18import textwrap 19import unittest 20 21from pw_build import generate_cc_blob_library 22 23 24class TestSplitIntoChunks(unittest.TestCase): 25 """Unit tests for the split_into_chunks() function.""" 26 def test_perfect_split(self): 27 """Tests basic splitting where the iterable divides perfectly.""" 28 data = (1, 7, 0, 1) 29 self.assertEqual( 30 ((1, 7), (0, 1)), 31 tuple(generate_cc_blob_library.split_into_chunks(data, 2))) 32 33 def test_split_with_remainder(self): 34 """Tests basic splitting where there is a remainder.""" 35 data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 36 self.assertEqual( 37 ((1, 2, 3), (4, 5, 6), (7, 8, 9), (10, )), 38 tuple(generate_cc_blob_library.split_into_chunks(data, 3))) 39 40 41class TestHeaderFromBlobs(unittest.TestCase): 42 """Unit tests for the header_from_blobs() function.""" 43 def test_single_blob_header(self): 44 """Tests the generation of a header for a single blob.""" 45 foo_blob = Path(tempfile.NamedTemporaryFile().name) 46 foo_blob.write_bytes(bytes((1, 2, 3, 4, 5, 6))) 47 blobs = [generate_cc_blob_library.Blob('fooBlob', foo_blob, None)] 48 49 header = generate_cc_blob_library.header_from_blobs(blobs) 50 expected_header = textwrap.dedent("""\ 51 // This file is auto-generated; Do not hand-modify! 52 // See https://pigweed.dev/pw_build/#pw-cc-blob-library for details. 53 54 #pragma once 55 56 #include <array> 57 #include <cstddef> 58 59 extern const std::array<std::byte, 6> fooBlob; 60 """) 61 62 self.assertEqual(expected_header, header) 63 64 def test_multi_blob_header(self): 65 """Tests the generation of a header for multiple blobs.""" 66 foo_blob = Path(tempfile.NamedTemporaryFile().name) 67 foo_blob.write_bytes(bytes((1, 2, 3, 4, 5, 6))) 68 bar_blob = Path(tempfile.NamedTemporaryFile().name) 69 bar_blob.write_bytes(bytes((10, 9, 8, 7, 6))) 70 blobs = [ 71 generate_cc_blob_library.Blob('fooBlob', foo_blob, None), 72 generate_cc_blob_library.Blob('barBlob', bar_blob, None), 73 ] 74 75 header = generate_cc_blob_library.header_from_blobs(blobs) 76 expected_header = textwrap.dedent("""\ 77 // This file is auto-generated; Do not hand-modify! 78 // See https://pigweed.dev/pw_build/#pw-cc-blob-library for details. 79 80 #pragma once 81 82 #include <array> 83 #include <cstddef> 84 85 extern const std::array<std::byte, 6> fooBlob; 86 87 extern const std::array<std::byte, 5> barBlob; 88 """) 89 90 self.assertEqual(expected_header, header) 91 92 def test_header_with_namespace(self): 93 """Tests the header generation of namespace definitions.""" 94 foo_blob = Path(tempfile.NamedTemporaryFile().name) 95 foo_blob.write_bytes(bytes((1, 2, 3, 4, 5, 6))) 96 blobs = [generate_cc_blob_library.Blob('fooBlob', foo_blob, None)] 97 98 header = generate_cc_blob_library.header_from_blobs(blobs, 'pw::foo') 99 expected_header = textwrap.dedent("""\ 100 // This file is auto-generated; Do not hand-modify! 101 // See https://pigweed.dev/pw_build/#pw-cc-blob-library for details. 102 103 #pragma once 104 105 #include <array> 106 #include <cstddef> 107 108 namespace pw::foo { 109 110 extern const std::array<std::byte, 6> fooBlob; 111 112 } // namespace pw::foo 113 """) 114 115 self.assertEqual(expected_header, header) 116 117 118class TestArrayDefFromBlobData(unittest.TestCase): 119 """Unit tests for the array_def_from_blob_data() function.""" 120 def test_single_line(self): 121 """Tests the generation of single-line array definitions.""" 122 foo_data = bytes((1, 2)) 123 124 foo_definition = generate_cc_blob_library.array_def_from_blob_data( 125 'fooBlob', foo_data) 126 expected_definition = ('const std::array<std::byte, 2> fooBlob' 127 ' = { std::byte{0x01}, std::byte{0x02} };') 128 129 self.assertEqual(expected_definition, foo_definition) 130 131 def test_multi_line(self): 132 """Tests the generation of multi-line array definitions.""" 133 foo_data = bytes((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) 134 135 foo_definition = generate_cc_blob_library.array_def_from_blob_data( 136 'fooBlob', foo_data) 137 expected_definition = ('const std::array<std::byte, 10> fooBlob = {\n' 138 ' std::byte{0x01}, std::byte{0x02}, ' 139 'std::byte{0x03}, std::byte{0x04},\n' 140 ' std::byte{0x05}, std::byte{0x06}, ' 141 'std::byte{0x07}, std::byte{0x08},\n' 142 ' std::byte{0x09}, std::byte{0x0A}\n' 143 '};') 144 145 self.assertEqual(expected_definition, foo_definition) 146 147 148class TestSourceFromBlobs(unittest.TestCase): 149 """Unit tests for the source_from_blobs() function.""" 150 def test_source_with_mixed_blobs(self): 151 """Tests generation of a source file with single- and multi-liners.""" 152 foo_blob = Path(tempfile.NamedTemporaryFile().name) 153 foo_blob.write_bytes(bytes((1, 2))) 154 bar_blob = Path(tempfile.NamedTemporaryFile().name) 155 bar_blob.write_bytes(bytes((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))) 156 blobs = [ 157 generate_cc_blob_library.Blob('fooBlob', foo_blob, None), 158 generate_cc_blob_library.Blob('barBlob', bar_blob, None), 159 ] 160 161 source = generate_cc_blob_library.source_from_blobs( 162 blobs, 'path/to/header.h') 163 expected_source = textwrap.dedent("""\ 164 // This file is auto-generated; Do not hand-modify! 165 // See https://pigweed.dev/pw_build/#pw-cc-blob-library for details. 166 167 #include "path/to/header.h" 168 169 #include <array> 170 #include <cstddef> 171 172 #include "pw_preprocessor/compiler.h" 173 174 """) 175 expected_source += ('const std::array<std::byte, 2> fooBlob' 176 ' = { std::byte{0x01}, std::byte{0x02} };\n\n') 177 expected_source += ('const std::array<std::byte, 10> barBlob = {\n' 178 ' std::byte{0x01}, std::byte{0x02}, ' 179 'std::byte{0x03}, std::byte{0x04},\n' 180 ' std::byte{0x05}, std::byte{0x06}, ' 181 'std::byte{0x07}, std::byte{0x08},\n' 182 ' std::byte{0x09}, std::byte{0x0A}\n' 183 '};\n') 184 185 self.assertEqual(expected_source, source) 186 187 def test_source_with_namespace(self): 188 """Tests the source generation of namespace definitions.""" 189 foo_blob = Path(tempfile.NamedTemporaryFile().name) 190 foo_blob.write_bytes(bytes((1, 2))) 191 blobs = [generate_cc_blob_library.Blob('fooBlob', foo_blob, None)] 192 193 source = generate_cc_blob_library.source_from_blobs( 194 blobs, 'path/to/header.h', 'pw::foo') 195 expected_source = textwrap.dedent("""\ 196 // This file is auto-generated; Do not hand-modify! 197 // See https://pigweed.dev/pw_build/#pw-cc-blob-library for details. 198 199 #include "path/to/header.h" 200 201 #include <array> 202 #include <cstddef> 203 204 #include "pw_preprocessor/compiler.h" 205 206 namespace pw::foo { 207 208 const std::array<std::byte, 2> fooBlob = { std::byte{0x01}, std::byte{0x02} }; 209 210 } // namespace pw::foo 211 """) 212 213 self.assertEqual(expected_source, source) 214 215 def test_source_with_linker_sections(self): 216 """Tests generation of a source file with defined linker sections""" 217 foo_blob = Path(tempfile.NamedTemporaryFile().name) 218 foo_blob.write_bytes(bytes((1, 2))) 219 bar_blob = Path(tempfile.NamedTemporaryFile().name) 220 bar_blob.write_bytes(bytes((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))) 221 blobs = [ 222 generate_cc_blob_library.Blob('fooBlob', foo_blob, ".foo_section"), 223 generate_cc_blob_library.Blob('barBlob', bar_blob, ".bar_section"), 224 ] 225 226 source = generate_cc_blob_library.source_from_blobs( 227 blobs, 'path/to/header.h') 228 expected_source = textwrap.dedent("""\ 229 // This file is auto-generated; Do not hand-modify! 230 // See https://pigweed.dev/pw_build/#pw-cc-blob-library for details. 231 232 #include "path/to/header.h" 233 234 #include <array> 235 #include <cstddef> 236 237 #include "pw_preprocessor/compiler.h" 238 239 """) 240 expected_source += ('PW_PLACE_IN_SECTION(".foo_section")\n' 241 'const std::array<std::byte, 2> fooBlob' 242 ' = { std::byte{0x01}, std::byte{0x02} };\n\n') 243 expected_source += ('PW_PLACE_IN_SECTION(".bar_section")\n' 244 'const std::array<std::byte, 10> barBlob = {\n' 245 ' std::byte{0x01}, std::byte{0x02}, ' 246 'std::byte{0x03}, std::byte{0x04},\n' 247 ' std::byte{0x05}, std::byte{0x06}, ' 248 'std::byte{0x07}, std::byte{0x08},\n' 249 ' std::byte{0x09}, std::byte{0x0A}\n' 250 '};\n') 251 252 self.assertEqual(expected_source, source) 253 254 255if __name__ == '__main__': 256 unittest.main() 257