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+ */
17import * as fs from 'fs' ;
28
39import MemoryMap from 'nrf-intel-hex' ;
410
5- import { strToBytes } from '../common' ;
11+ import { bytesToStr , strToBytes } from '../common' ;
612import {
713 addIntelHexFile ,
814 addIntelHexFiles ,
@@ -177,6 +183,126 @@ describe('Writing files to the filesystem.', () => {
177183 expect ( file1data ) . toEqual ( files [ 1 ] . bytes ( ) ) ;
178184 } ) ;
179185
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+
180306 it ( 'Empty file name throws an error.' , ( ) => {
181307 const failCase = ( ) => addIntelHexFile ( uPyHexFile , '' , randContent ) ;
182308
@@ -266,11 +392,6 @@ describe('Writing files to the filesystem.', () => {
266392} ) ;
267393
268394describe ( '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-
274395 const alastFilename = 'alast.py' ;
275396 const alastContent = strToBytes (
276397 '# Lorem Ipsum is simply dummy text of the printing and\n' +
@@ -410,7 +531,7 @@ describe('Reading files from the filesystem.', () => {
410531 'display.scroll(full)\n' +
411532 'print(full)\n'
412533 ) ;
413- // Uses chunk 0xCA, 0xCB, 0xCC
534+ // Uses chunks 0xCA, 0xCB, 0xCC
414535 const mainHex =
415536 ':020000040003F7\n' +
416537 ':10F08000FE37076D61696E2E707966726F6D206D47\n' +
@@ -436,19 +557,16 @@ describe('Reading files from the filesystem.', () => {
436557 ':00000001FF\n' ;
437558
438559 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+ } ;
439566 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 ) ;
452570
453571 const foundFiles = getIntelHexFiles ( fullUpyFsMemMap . asHexString ( ) ) ;
454572
@@ -457,6 +575,8 @@ describe('Reading files from the filesystem.', () => {
457575 expect ( foundFiles ) . toHaveProperty ( [ mainFilename ] , mainContent ) ;
458576 } ) ;
459577
578+ // When MicroPython saves a file that takes full chunk it still utilises
579+ // the next chunk and leaves it empty
460580 const oneChunkPlusFilename = 'one_chunk_plus.py' ;
461581 const oneChunkPlusContent =
462582 'a = """abcdefghijklmnopqrstuvwxyz\n' +
@@ -588,7 +708,7 @@ describe('Calculate sizes.', () => {
588708 expect ( totalSize ) . toEqual ( 27 * 1024 ) ;
589709 } ) ;
590710
591- it ( 'Calculate the space ocupied for a file in the fs.' , ( ) => {
711+ it ( 'Calculate the space occupied for a file in the fs.' , ( ) => {
592712 const fileSizeOne = calculateFileSize (
593713 'one_chunk.txt' ,
594714 new Uint8Array ( [ 30 , 31 , 32 , 33 , 34 ] )
0 commit comments