1
+ /**
2
+ * All the hex file strings generated below have been created by transferring
3
+ * the files to a micro:bit running MicroPython v1.0.1 using Mu.
4
+ * Because the filesystem limits depend on the MicroPython version, these will
5
+ * only work if combined with v1.0.1.
6
+ */
1
7
import * as fs from 'fs' ;
2
8
3
9
import MemoryMap from 'nrf-intel-hex' ;
4
10
5
- import { strToBytes } from '../common' ;
11
+ import { bytesToStr , strToBytes } from '../common' ;
6
12
import {
7
13
addIntelHexFile ,
8
14
addIntelHexFiles ,
@@ -177,6 +183,126 @@ describe('Writing files to the filesystem.', () => {
177
183
expect ( file1data ) . toEqual ( files [ 1 ] . bytes ( ) ) ;
178
184
} ) ;
179
185
186
+ // A chunk using up the last byte will also use the next and leave it empty
187
+ const fullChunkPlus = {
188
+ fileName : 'one_chunk_plus.py' ,
189
+ fileStr :
190
+ 'a = """abcdefghijklmnopqrstuvwxyz\n' +
191
+ 'abcdefghijklmnopqrstuvwxyz\n' +
192
+ 'abcdefghijklmnopqrstuvwxyz\n' +
193
+ 'abcdefghijklmno"""\n' ,
194
+ hex :
195
+ ':020000040003F7\n' +
196
+ ':108C0000FE00116F6E655F6368756E6B5F706C75EB\n' +
197
+ ':108C1000732E707961203D20222222616263646597\n' +
198
+ ':108C2000666768696A6B6C6D6E6F7071727374756C\n' +
199
+ ':108C3000767778797A0A6162636465666768696ADB\n' +
200
+ ':108C40006B6C6D6E6F707172737475767778797AFC\n' +
201
+ ':108C50000A6162636465666768696A6B6C6D6E6FF2\n' +
202
+ ':108C6000707172737475767778797A0A6162636469\n' +
203
+ ':108C700065666768696A6B6C6D6E6F2222220A02F4\n' +
204
+ ':108C800001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2\n' +
205
+ ':00000001FF' ,
206
+ fileAddress : 0x38c00 ,
207
+ fsSize : 144 ,
208
+ bytes ( ) {
209
+ return MemoryMap . fromHex ( this . hex ) . get ( this . fileAddress ) ;
210
+ } ,
211
+ } ;
212
+ // Using space except the last byte should only use a single chunk
213
+ const fullChunkMinus = {
214
+ fileName : 'one_chunk_minus.py' ,
215
+ fileStr :
216
+ 'a = """abcdefghijklmnopqrstuvwxyz\n' +
217
+ 'abcdefghijklmnopqrstuvwxyz\n' +
218
+ 'abcdefghijklmnopqrstuvwxyz\n' +
219
+ 'abcdefghijklm"""\n' ,
220
+ hex :
221
+ ':020000040003F7\n' +
222
+ ':108C0000FE7D126F6E655F6368756E6B5F6D696E7A\n' +
223
+ ':108C100075732E707961203D202222226162636487\n' +
224
+ ':108C200065666768696A6B6C6D6E6F70717273747C\n' +
225
+ ':108C300075767778797A0A616263646566676869D0\n' +
226
+ ':108C40006A6B6C6D6E6F707172737475767778790C\n' +
227
+ ':108C50007A0A6162636465666768696A6B6C6D6EE7\n' +
228
+ ':108C60006F707172737475767778797A0A6162635E\n' +
229
+ ':108C70006465666768696A6B6C6D2222220AFFFF71\n' +
230
+ ':00000001FF' ,
231
+ fileAddress : 0x38c00 ,
232
+ fsSize : 128 ,
233
+ bytes ( ) {
234
+ return MemoryMap . fromHex ( this . hex ) . get ( this . fileAddress ) ;
235
+ } ,
236
+ } ;
237
+ // One full chunk + a single byte on the second
238
+ const twoChunks = {
239
+ fileName : 'two_chunks.py' ,
240
+ fileStr :
241
+ 'a = """abcdefghijklmnopqrstuvwxyz\n' +
242
+ 'abcdefghijklmnopqrstuvwxyz\n' +
243
+ 'abcdefghijklmnopqrstuvwxyz\n' +
244
+ 'abcdefghijklmnopqrst"""\n' ,
245
+ hex :
246
+ ':020000040003F7\n' +
247
+ ':108C0000FE010D74776F5F6368756E6B732E7079FC\n' +
248
+ ':108C100061203D2022222261626364656667686983\n' +
249
+ ':108C20006A6B6C6D6E6F707172737475767778792C\n' +
250
+ ':108C30007A0A6162636465666768696A6B6C6D6E07\n' +
251
+ ':108C40006F707172737475767778797A0A6162637E\n' +
252
+ ':108C50006465666768696A6B6C6D6E6F707172735C\n' +
253
+ ':108C60007475767778797A0A616263646566676895\n' +
254
+ ':108C7000696A6B6C6D6E6F7071727374222222025E\n' +
255
+ ':108C8000010AFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7\n' +
256
+ ':00000001FF' ,
257
+ fileAddress : 0x38c00 ,
258
+ fsSize : 144 ,
259
+ bytes ( ) {
260
+ return MemoryMap . fromHex ( this . hex ) . get ( this . fileAddress ) ;
261
+ } ,
262
+ } ;
263
+
264
+ it ( 'Can generate a full chunk that also uses the next one.' , ( ) => {
265
+ const fwWithFsOther = addIntelHexFile (
266
+ uPyHexFile ,
267
+ fullChunkPlus . fileName ,
268
+ strToBytes ( fullChunkPlus . fileStr )
269
+ ) ;
270
+
271
+ const opMap = MemoryMap . fromHex ( fwWithFsOther ) ;
272
+ const readFileData = opMap
273
+ . slice ( fullChunkPlus . fileAddress , fullChunkPlus . fsSize )
274
+ . get ( fullChunkPlus . fileAddress ) ;
275
+ expect ( readFileData ) . toEqual ( fullChunkPlus . bytes ( ) ) ;
276
+ } ) ;
277
+
278
+ it ( 'Correctly generate an almost full chunk (not using last byte).' , ( ) => {
279
+ const fwWithFsOther = addIntelHexFile (
280
+ uPyHexFile ,
281
+ fullChunkMinus . fileName ,
282
+ strToBytes ( fullChunkMinus . fileStr )
283
+ ) ;
284
+
285
+ const opMap = MemoryMap . fromHex ( fwWithFsOther ) ;
286
+ const readFileData = opMap
287
+ . slice ( fullChunkMinus . fileAddress , fullChunkMinus . fsSize )
288
+ . get ( fullChunkMinus . fileAddress ) ;
289
+ expect ( readFileData ) . toEqual ( fullChunkMinus . bytes ( ) ) ;
290
+ } ) ;
291
+
292
+ it ( 'Correctlty generate just over a full chunk.' , ( ) => {
293
+ const fwWithFsOther = addIntelHexFile (
294
+ uPyHexFile ,
295
+ twoChunks . fileName ,
296
+ strToBytes ( twoChunks . fileStr )
297
+ ) ;
298
+
299
+ const opMap = MemoryMap . fromHex ( fwWithFsOther ) ;
300
+ const readFileData = opMap
301
+ . slice ( twoChunks . fileAddress , twoChunks . fsSize )
302
+ . get ( twoChunks . fileAddress ) ;
303
+ expect ( readFileData ) . toEqual ( twoChunks . bytes ( ) ) ;
304
+ } ) ;
305
+
180
306
it ( 'Empty file name throws an error.' , ( ) => {
181
307
const failCase = ( ) => addIntelHexFile ( uPyHexFile , '' , randContent ) ;
182
308
@@ -266,11 +392,6 @@ describe('Writing files to the filesystem.', () => {
266
392
} ) ;
267
393
268
394
describe ( 'Reading files from the filesystem.' , ( ) => {
269
- // All the files generated below have been created by transferring the files
270
- // to a micro:bit running MicroPython v1.0.1 using Mu.
271
- // Because the filesystem limits depend on the MicroPython version, these will
272
- // only work if combined with v1.0.1.
273
-
274
395
const alastFilename = 'alast.py' ;
275
396
const alastContent = strToBytes (
276
397
'# Lorem Ipsum is simply dummy text of the printing and\n' +
@@ -410,7 +531,7 @@ describe('Reading files from the filesystem.', () => {
410
531
'display.scroll(full)\n' +
411
532
'print(full)\n'
412
533
) ;
413
- // Uses chunk 0xCA, 0xCB, 0xCC
534
+ // Uses chunks 0xCA, 0xCB, 0xCC
414
535
const mainHex =
415
536
':020000040003F7\n' +
416
537
':10F08000FE37076D61696E2E707966726F6D206D47\n' +
@@ -436,19 +557,16 @@ describe('Reading files from the filesystem.', () => {
436
557
':00000001FF\n' ;
437
558
438
559
it ( 'Can read files of different sizes in non-consecutive locations.' , ( ) => {
560
+ const addHexToMap = ( hexMap : MemoryMap , hex : string ) => {
561
+ const newMemMap = MemoryMap . fromHex ( hex ) ;
562
+ newMemMap . forEach ( ( value : Uint8Array , index : number ) => {
563
+ hexMap . set ( index , value ) ;
564
+ } ) ;
565
+ } ;
439
566
const fullUpyFsMemMap = MemoryMap . fromHex ( uPyHexFile ) ;
440
- const afirstMemMap = MemoryMap . fromHex ( afirstHex ) ;
441
- afirstMemMap . forEach ( ( value : Uint8Array , index : number ) => {
442
- fullUpyFsMemMap . set ( index , value ) ;
443
- } ) ;
444
- const alastMemMap = MemoryMap . fromHex ( alastHex ) ;
445
- alastMemMap . forEach ( ( value : Uint8Array , index : number ) => {
446
- fullUpyFsMemMap . set ( index , value ) ;
447
- } ) ;
448
- const mainMemMap = MemoryMap . fromHex ( mainHex ) ;
449
- mainMemMap . forEach ( ( value : Uint8Array , index : number ) => {
450
- fullUpyFsMemMap . set ( index , value ) ;
451
- } ) ;
567
+ addHexToMap ( fullUpyFsMemMap , afirstHex ) ;
568
+ addHexToMap ( fullUpyFsMemMap , alastHex ) ;
569
+ addHexToMap ( fullUpyFsMemMap , mainHex ) ;
452
570
453
571
const foundFiles = getIntelHexFiles ( fullUpyFsMemMap . asHexString ( ) ) ;
454
572
@@ -457,6 +575,8 @@ describe('Reading files from the filesystem.', () => {
457
575
expect ( foundFiles ) . toHaveProperty ( [ mainFilename ] , mainContent ) ;
458
576
} ) ;
459
577
578
+ // When MicroPython saves a file that takes full chunk it still utilises
579
+ // the next chunk and leaves it empty
460
580
const oneChunkPlusFilename = 'one_chunk_plus.py' ;
461
581
const oneChunkPlusContent =
462
582
'a = """abcdefghijklmnopqrstuvwxyz\n' +
@@ -588,7 +708,7 @@ describe('Calculate sizes.', () => {
588
708
expect ( totalSize ) . toEqual ( 27 * 1024 ) ;
589
709
} ) ;
590
710
591
- it ( 'Calculate the space ocupied for a file in the fs.' , ( ) => {
711
+ it ( 'Calculate the space occupied for a file in the fs.' , ( ) => {
592
712
const fileSizeOne = calculateFileSize (
593
713
'one_chunk.txt' ,
594
714
new Uint8Array ( [ 30 , 31 , 32 , 33 , 34 ] )
0 commit comments