1+ import { ElfAnalyzer , Section , Symbol } from './index' ;
2+ import * as path from 'path' ;
3+ import * as fs from 'fs' ;
4+
5+ describe ( 'ElfAnalyzer' , ( ) => {
6+ let analyzer : ElfAnalyzer ;
7+ const elfPath = path . join ( __dirname , '..' , 'rtthread.elf' ) ;
8+ const mapPath = path . join ( __dirname , '..' , 'rtthread.map' ) ;
9+
10+ beforeAll ( ( ) => {
11+ // Skip tests if files don't exist
12+ if ( ! fs . existsSync ( elfPath ) || ! fs . existsSync ( mapPath ) ) {
13+ console . warn ( 'Test files not found. Skipping tests.' ) ;
14+ return ;
15+ }
16+ analyzer = new ElfAnalyzer ( elfPath , mapPath ) ;
17+ } ) ;
18+
19+ describe ( 'getSections()' , ( ) => {
20+ it ( 'should return an array of sections' , ( ) => {
21+ if ( ! analyzer ) return ;
22+
23+ const sections = analyzer . getSections ( ) ;
24+
25+ expect ( Array . isArray ( sections ) ) . toBe ( true ) ;
26+ expect ( sections . length ) . toBeGreaterThan ( 0 ) ;
27+ } ) ;
28+
29+ it ( 'should return sections with required properties' , ( ) => {
30+ if ( ! analyzer ) return ;
31+
32+ const sections = analyzer . getSections ( ) ;
33+
34+ sections . forEach ( section => {
35+ expect ( section ) . toHaveProperty ( 'name' ) ;
36+ expect ( section ) . toHaveProperty ( 'address' ) ;
37+ expect ( section ) . toHaveProperty ( 'size' ) ;
38+ expect ( section ) . toHaveProperty ( 'needsLoad' ) ;
39+
40+ expect ( typeof section . name ) . toBe ( 'string' ) ;
41+ expect ( typeof section . address ) . toBe ( 'number' ) ;
42+ expect ( typeof section . size ) . toBe ( 'number' ) ;
43+ expect ( typeof section . needsLoad ) . toBe ( 'boolean' ) ;
44+ } ) ;
45+ } ) ;
46+
47+ it ( 'should include common sections like .text' , ( ) => {
48+ if ( ! analyzer ) return ;
49+
50+ const sections = analyzer . getSections ( ) ;
51+ const sectionNames = sections . map ( s => s . name ) ;
52+
53+ expect ( sectionNames ) . toContain ( '.text' ) ;
54+ } ) ;
55+ } ) ;
56+
57+ describe ( 'getSymbolsBySection()' , ( ) => {
58+ it ( 'should return symbols for a valid section' , ( ) => {
59+ if ( ! analyzer ) return ;
60+
61+ const symbols = analyzer . getSymbolsBySection ( '.text' ) ;
62+
63+ expect ( Array . isArray ( symbols ) ) . toBe ( true ) ;
64+ expect ( symbols . length ) . toBeGreaterThan ( 0 ) ;
65+ } ) ;
66+
67+ it ( 'should return symbols with required properties' , ( ) => {
68+ if ( ! analyzer ) return ;
69+
70+ const symbols = analyzer . getSymbolsBySection ( '.text' ) ;
71+
72+ symbols . forEach ( symbol => {
73+ expect ( symbol ) . toHaveProperty ( 'name' ) ;
74+ expect ( symbol ) . toHaveProperty ( 'type' ) ;
75+ expect ( symbol ) . toHaveProperty ( 'address' ) ;
76+ expect ( symbol ) . toHaveProperty ( 'size' ) ;
77+
78+ expect ( typeof symbol . name ) . toBe ( 'string' ) ;
79+ expect ( typeof symbol . type ) . toBe ( 'string' ) ;
80+ expect ( typeof symbol . address ) . toBe ( 'number' ) ;
81+ expect ( typeof symbol . size ) . toBe ( 'number' ) ;
82+ } ) ;
83+ } ) ;
84+
85+ it ( 'should return symbols sorted by size in descending order' , ( ) => {
86+ if ( ! analyzer ) return ;
87+
88+ const symbols = analyzer . getSymbolsBySection ( '.text' ) ;
89+
90+ for ( let i = 1 ; i < symbols . length ; i ++ ) {
91+ expect ( symbols [ i ] . size ) . toBeLessThanOrEqual ( symbols [ i - 1 ] . size ) ;
92+ }
93+ } ) ;
94+
95+ it ( 'should return empty array for non-existent section' , ( ) => {
96+ if ( ! analyzer ) return ;
97+
98+ const symbols = analyzer . getSymbolsBySection ( '.nonexistent' ) ;
99+
100+ expect ( Array . isArray ( symbols ) ) . toBe ( true ) ;
101+ expect ( symbols . length ) . toBe ( 0 ) ;
102+ } ) ;
103+ } ) ;
104+
105+ describe ( 'getAllSymbols()' , ( ) => {
106+ it ( 'should return an array of all symbols' , ( ) => {
107+ if ( ! analyzer ) return ;
108+
109+ const symbols = analyzer . getAllSymbols ( ) ;
110+
111+ expect ( Array . isArray ( symbols ) ) . toBe ( true ) ;
112+ expect ( symbols . length ) . toBeGreaterThan ( 0 ) ;
113+ } ) ;
114+
115+ it ( 'should not include symbols with zero size' , ( ) => {
116+ if ( ! analyzer ) return ;
117+
118+ const symbols = analyzer . getAllSymbols ( ) ;
119+
120+ symbols . forEach ( symbol => {
121+ expect ( symbol . size ) . toBeGreaterThan ( 0 ) ;
122+ } ) ;
123+ } ) ;
124+
125+ it ( 'should return symbols sorted by size in descending order' , ( ) => {
126+ if ( ! analyzer ) return ;
127+
128+ const symbols = analyzer . getAllSymbols ( ) ;
129+
130+ for ( let i = 1 ; i < symbols . length ; i ++ ) {
131+ expect ( symbols [ i ] . size ) . toBeLessThanOrEqual ( symbols [ i - 1 ] . size ) ;
132+ }
133+ } ) ;
134+
135+ it ( 'should return symbols with valid addresses' , ( ) => {
136+ if ( ! analyzer ) return ;
137+
138+ const symbols = analyzer . getAllSymbols ( ) ;
139+
140+ symbols . forEach ( symbol => {
141+ expect ( symbol . address ) . toBeGreaterThanOrEqual ( 0 ) ;
142+ expect ( Number . isInteger ( symbol . address ) ) . toBe ( true ) ;
143+ } ) ;
144+ } ) ;
145+ } ) ;
146+
147+ describe ( 'getSymbols()' , ( ) => {
148+ it ( 'should return symbols for a specific object file' , ( ) => {
149+ if ( ! analyzer ) return ;
150+
151+ // First get all symbols to find an object file
152+ const allSymbols = analyzer . getAllSymbols ( ) ;
153+ const objectFiles = new Set < string > ( ) ;
154+
155+ allSymbols . forEach ( s => {
156+ if ( s . object ) {
157+ objectFiles . add ( s . object ) ;
158+ }
159+ } ) ;
160+
161+ if ( objectFiles . size > 0 ) {
162+ const testObject = Array . from ( objectFiles ) [ 0 ] ;
163+ const symbols = analyzer . getSymbols ( testObject ) ;
164+
165+ expect ( Array . isArray ( symbols ) ) . toBe ( true ) ;
166+
167+ // All returned symbols should belong to the specified object
168+ symbols . forEach ( symbol => {
169+ expect ( symbol . object ) . toBe ( testObject ) ;
170+ } ) ;
171+ }
172+ } ) ;
173+
174+ it ( 'should return symbols sorted by size in descending order' , ( ) => {
175+ if ( ! analyzer ) return ;
176+
177+ const allSymbols = analyzer . getAllSymbols ( ) ;
178+ const objectFiles = new Set < string > ( ) ;
179+
180+ allSymbols . forEach ( s => {
181+ if ( s . object ) {
182+ objectFiles . add ( s . object ) ;
183+ }
184+ } ) ;
185+
186+ if ( objectFiles . size > 0 ) {
187+ const testObject = Array . from ( objectFiles ) [ 0 ] ;
188+ const symbols = analyzer . getSymbols ( testObject ) ;
189+
190+ for ( let i = 1 ; i < symbols . length ; i ++ ) {
191+ expect ( symbols [ i ] . size ) . toBeLessThanOrEqual ( symbols [ i - 1 ] . size ) ;
192+ }
193+ }
194+ } ) ;
195+
196+ it ( 'should return empty array for non-existent object' , ( ) => {
197+ if ( ! analyzer ) return ;
198+
199+ const symbols = analyzer . getSymbols ( 'nonexistent.o' ) ;
200+
201+ expect ( Array . isArray ( symbols ) ) . toBe ( true ) ;
202+ expect ( symbols . length ) . toBe ( 0 ) ;
203+ } ) ;
204+ } ) ;
205+
206+ describe ( 'Error handling' , ( ) => {
207+ it ( 'should throw error when accessing getSections without ELF file' , ( ) => {
208+ const noElfAnalyzer = new ElfAnalyzer ( undefined , mapPath ) ;
209+
210+ expect ( ( ) => {
211+ noElfAnalyzer . getSections ( ) ;
212+ } ) . toThrow ( 'ELF file not loaded' ) ;
213+ } ) ;
214+
215+ it ( 'should throw error when accessing getSymbolsBySection without ELF file' , ( ) => {
216+ const noElfAnalyzer = new ElfAnalyzer ( undefined , mapPath ) ;
217+
218+ expect ( ( ) => {
219+ noElfAnalyzer . getSymbolsBySection ( '.text' ) ;
220+ } ) . toThrow ( 'ELF file not loaded' ) ;
221+ } ) ;
222+
223+ it ( 'should throw error when accessing getAllSymbols without any file' , ( ) => {
224+ const emptyAnalyzer = new ElfAnalyzer ( ) ;
225+
226+ expect ( ( ) => {
227+ emptyAnalyzer . getAllSymbols ( ) ;
228+ } ) . toThrow ( 'No ELF or MAP file loaded' ) ;
229+ } ) ;
230+ } ) ;
231+ } ) ;
0 commit comments