@@ -179,4 +179,140 @@ mod tests {
179179 "m_middle.sol (id=1) should appear before a_first.sol (id=2) in output.sources"
180180 ) ;
181181 }
182+
183+ #[ test]
184+ fn sources_ordering_empty ( ) {
185+ let v: Version = "0.8.4+commit.c7e474f2" . parse ( ) . unwrap ( ) ;
186+ let input = SolcVersionedInput :: build (
187+ Sources :: new ( ) ,
188+ Default :: default ( ) ,
189+ SolcLanguage :: Solidity ,
190+ v,
191+ ) ;
192+
193+ let output = CompilerOutput :: < Error , Contract > :: default ( ) ;
194+ let raw_info = RawBuildInfo :: new ( & input, & output, true ) . unwrap ( ) ;
195+ let json_str = serde_json:: to_string ( & raw_info) . unwrap ( ) ;
196+
197+ assert ! ( json_str. contains( r#""sources":{}"# ) ) ;
198+ }
199+
200+ #[ test]
201+ fn sources_ordering_single_source ( ) {
202+ let v: Version = "0.8.4+commit.c7e474f2" . parse ( ) . unwrap ( ) ;
203+ let input = SolcVersionedInput :: build (
204+ Sources :: from ( [ ( PathBuf :: from ( "only.sol" ) , Source :: new ( "" ) ) ] ) ,
205+ Default :: default ( ) ,
206+ SolcLanguage :: Solidity ,
207+ v,
208+ ) ;
209+
210+ let mut output = CompilerOutput :: < Error , Contract > :: default ( ) ;
211+ output. sources . insert ( PathBuf :: from ( "only.sol" ) , SourceFile { id : 42 , ast : None } ) ;
212+
213+ let raw_info = RawBuildInfo :: new ( & input, & output, true ) . unwrap ( ) ;
214+ let json_str = serde_json:: to_string ( & raw_info) . unwrap ( ) ;
215+
216+ assert ! ( json_str. contains( r#""only.sol":{"id":42"# ) ) ;
217+ }
218+
219+ #[ test]
220+ fn sources_ordering_with_gaps_in_ids ( ) {
221+ let v: Version = "0.8.4+commit.c7e474f2" . parse ( ) . unwrap ( ) ;
222+ let input = SolcVersionedInput :: build (
223+ Sources :: from ( [
224+ ( PathBuf :: from ( "a.sol" ) , Source :: new ( "" ) ) ,
225+ ( PathBuf :: from ( "b.sol" ) , Source :: new ( "" ) ) ,
226+ ( PathBuf :: from ( "c.sol" ) , Source :: new ( "" ) ) ,
227+ ] ) ,
228+ Default :: default ( ) ,
229+ SolcLanguage :: Solidity ,
230+ v,
231+ ) ;
232+
233+ let mut output = CompilerOutput :: < Error , Contract > :: default ( ) ;
234+ output. sources . insert ( PathBuf :: from ( "a.sol" ) , SourceFile { id : 100 , ast : None } ) ;
235+ output. sources . insert ( PathBuf :: from ( "b.sol" ) , SourceFile { id : 5 , ast : None } ) ;
236+ output. sources . insert ( PathBuf :: from ( "c.sol" ) , SourceFile { id : 50 , ast : None } ) ;
237+
238+ let raw_info = RawBuildInfo :: new ( & input, & output, true ) . unwrap ( ) ;
239+ let json_str = serde_json:: to_string ( & raw_info) . unwrap ( ) ;
240+
241+ let output_start = json_str. find ( r#""output":"# ) . unwrap ( ) ;
242+ let output_section = & json_str[ output_start..] ;
243+
244+ let b_pos = output_section. find ( "b.sol" ) . unwrap ( ) ;
245+ let c_pos = output_section. find ( "c.sol" ) . unwrap ( ) ;
246+ let a_pos = output_section. find ( "a.sol" ) . unwrap ( ) ;
247+
248+ assert ! ( b_pos < c_pos, "b.sol (id=5) should appear before c.sol (id=50)" ) ;
249+ assert ! ( c_pos < a_pos, "c.sol (id=50) should appear before a.sol (id=100)" ) ;
250+ }
251+
252+ #[ test]
253+ fn sources_ordering_roundtrip ( ) {
254+ let v: Version = "0.8.4+commit.c7e474f2" . parse ( ) . unwrap ( ) ;
255+ let input = SolcVersionedInput :: build (
256+ Sources :: from ( [
257+ ( PathBuf :: from ( "z.sol" ) , Source :: new ( "" ) ) ,
258+ ( PathBuf :: from ( "a.sol" ) , Source :: new ( "" ) ) ,
259+ ] ) ,
260+ Default :: default ( ) ,
261+ SolcLanguage :: Solidity ,
262+ v,
263+ ) ;
264+
265+ let mut output = CompilerOutput :: < Error , Contract > :: default ( ) ;
266+ output. sources . insert ( PathBuf :: from ( "z.sol" ) , SourceFile { id : 0 , ast : None } ) ;
267+ output. sources . insert ( PathBuf :: from ( "a.sol" ) , SourceFile { id : 1 , ast : None } ) ;
268+
269+ let raw_info = RawBuildInfo :: new ( & input, & output, true ) . unwrap ( ) ;
270+ let json_str = serde_json:: to_string ( & raw_info) . unwrap ( ) ;
271+
272+ let parsed: BuildInfo < SolcVersionedInput , CompilerOutput < Error , Contract > > =
273+ serde_json:: from_str ( & json_str) . unwrap ( ) ;
274+
275+ assert_eq ! ( parsed. output. sources. len( ) , 2 ) ;
276+ assert_eq ! ( parsed. output. sources. get( & PathBuf :: from( "z.sol" ) ) . unwrap( ) . id, 0 ) ;
277+ assert_eq ! ( parsed. output. sources. get( & PathBuf :: from( "a.sol" ) ) . unwrap( ) . id, 1 ) ;
278+ }
279+
280+ #[ test]
281+ fn sources_ordering_many_sources ( ) {
282+ let v: Version = "0.8.4+commit.c7e474f2" . parse ( ) . unwrap ( ) ;
283+
284+ let sources: Sources = ( 0 ..50 )
285+ . map ( |i| ( PathBuf :: from ( format ! ( "contract_{:02}.sol" , 49 - i) ) , Source :: new ( "" ) ) )
286+ . collect ( ) ;
287+
288+ let input =
289+ SolcVersionedInput :: build ( sources, Default :: default ( ) , SolcLanguage :: Solidity , v) ;
290+
291+ let mut output = CompilerOutput :: < Error , Contract > :: default ( ) ;
292+ for i in 0 ..50u32 {
293+ output. sources . insert (
294+ PathBuf :: from ( format ! ( "contract_{:02}.sol" , 49 - i) ) ,
295+ SourceFile { id : i, ast : None } ,
296+ ) ;
297+ }
298+
299+ let raw_info = RawBuildInfo :: new ( & input, & output, true ) . unwrap ( ) ;
300+ let json_str = serde_json:: to_string ( & raw_info) . unwrap ( ) ;
301+
302+ let output_start = json_str. find ( r#""output":"# ) . unwrap ( ) ;
303+ let output_section = & json_str[ output_start..] ;
304+
305+ let mut last_pos = 0 ;
306+ for i in 0 ..50 {
307+ let filename = format ! ( "contract_{:02}.sol" , 49 - i) ;
308+ let pos = output_section. find ( & filename) . unwrap ( ) ;
309+ assert ! (
310+ pos > last_pos || i == 0 ,
311+ "Sources should be ordered by ID: {} (id={}) at wrong position" ,
312+ filename,
313+ i
314+ ) ;
315+ last_pos = pos;
316+ }
317+ }
182318}
0 commit comments