@@ -11,7 +11,9 @@ use generators::{
1111 OpenChannelGenerator ,
1212} ;
1313use minimizers:: { CommonSubexpressionEliminator , DeadCodeEliminator , Minimizer } ;
14- use mutators:: { InputSwapMutator , InstructionDeleteMutator , OperationParamMutator } ;
14+ use mutators:: {
15+ InputSwapMutator , InstructionDeleteMutator , InstructionReorderMutator , OperationParamMutator ,
16+ } ;
1517use operation:: { AcceptChannelField , ChannelTypeVariant , ShutdownScriptVariant } ;
1618
1719/// Helper to build a private key with a single distinguishing byte.
@@ -1361,6 +1363,16 @@ fn assert_false_is_noop<M: Mutator>(mutator: &M, original: &Program) {
13611363 }
13621364}
13631365
1366+ fn assert_mutator_preserves_well_formedness < M : Mutator > ( mutator : & M , original : & Program ) {
1367+ let mut rng = SmallRng :: seed_from_u64 ( 0 ) ;
1368+ for _ in 0 ..100 {
1369+ let mut program = original. clone ( ) ;
1370+ if mutator. mutate ( & mut program, & mut rng) {
1371+ assert_well_formed ( & program) ;
1372+ }
1373+ }
1374+ }
1375+
13641376#[ test]
13651377fn param_mutator_false_is_noop ( ) {
13661378 let original = Program {
@@ -1650,15 +1662,7 @@ fn input_swap_returns_false_when_no_alternatives() {
16501662#[ test]
16511663fn input_swap_preserves_well_formedness ( ) {
16521664 let original = generate_open_channel_program ( 0 ) ;
1653- let mutator = InputSwapMutator ;
1654- let mut rng = SmallRng :: seed_from_u64 ( 0 ) ;
1655-
1656- for _ in 0 ..100 {
1657- let mut program = original. clone ( ) ;
1658- if mutator. mutate ( & mut program, & mut rng) {
1659- assert_well_formed ( & program) ;
1660- }
1661- }
1665+ assert_mutator_preserves_well_formedness ( & InputSwapMutator , & original) ;
16621666}
16631667
16641668#[ test]
@@ -1922,6 +1926,156 @@ fn instr_delete_maintains_validity() {
19221926 }
19231927}
19241928
1929+ // -- InstructionReorderMutator tests --
1930+
1931+ #[ test]
1932+ fn instr_reorder_false_is_noop ( ) {
1933+ let original = generate_open_channel_program ( 0 ) ;
1934+ assert_false_is_noop ( & InstructionReorderMutator , & original) ;
1935+ }
1936+
1937+ #[ test]
1938+ fn instr_reorder_returns_false_on_empty ( ) {
1939+ let mut program = Program {
1940+ instructions : vec ! [ ] ,
1941+ } ;
1942+ let mut rng = SmallRng :: seed_from_u64 ( 0 ) ;
1943+ let mutator = InstructionReorderMutator ;
1944+ assert ! ( !mutator. mutate( & mut program, & mut rng) ) ;
1945+ }
1946+
1947+ #[ test]
1948+ fn instr_reorder_returns_false_on_single_or_no_act ( ) {
1949+ // ChannelAnnouncementGenerator produces a single Act instruction: SendMessage.
1950+ let mut program = generate_channel_announcement_program ( 0 ) ;
1951+ let mutator = InstructionReorderMutator ;
1952+ let mut rng = SmallRng :: seed_from_u64 ( 0 ) ;
1953+
1954+ assert ! ( !mutator. mutate( & mut program, & mut rng) ) ;
1955+ // Delete the SendMessage instruction at the end. The program is now
1956+ // non-empty with 0 Act instructions.
1957+ program. instructions . pop ( ) ;
1958+ assert ! ( !mutator. mutate( & mut program, & mut rng) ) ;
1959+ }
1960+
1961+ #[ test]
1962+ fn instr_reorder_returns_false_if_act2_is_past_usage_boundary ( ) {
1963+ // Invalid program, but mutators shouldn't care about program validity.
1964+ // Two of the three Act instructions are immediately consumed.
1965+ let mut program = Program {
1966+ instructions : vec ! [
1967+ Instruction {
1968+ operation: Operation :: BuildOpenChannel ,
1969+ inputs: vec![ ] ,
1970+ } ,
1971+ Instruction {
1972+ operation: Operation :: SendOpenChannel ,
1973+ inputs: vec![ 0 ] ,
1974+ } ,
1975+ Instruction {
1976+ operation: Operation :: RecvAcceptChannel ,
1977+ inputs: vec![ 1 ] ,
1978+ } ,
1979+ Instruction {
1980+ operation: Operation :: ExtractAcceptChannel ( AcceptChannelField :: ChannelType ) ,
1981+ inputs: vec![ 2 ] ,
1982+ } ,
1983+ Instruction {
1984+ operation: Operation :: SendOpenChannel ,
1985+ inputs: vec![ 0 ] ,
1986+ } ,
1987+ ] ,
1988+ } ;
1989+ let mut rng = SmallRng :: seed_from_u64 ( 0 ) ;
1990+ let mutator = InstructionReorderMutator ;
1991+ for _ in 0 ..100 {
1992+ assert ! ( !mutator. mutate( & mut program, & mut rng) ) ;
1993+ }
1994+ }
1995+
1996+ #[ test]
1997+ fn instr_reorder_swaps_and_heals ( ) {
1998+ // The only swappable instructions are RecvAcceptChannel and SendMessage.
1999+ let mut program = Program {
2000+ instructions : vec ! [
2001+ Instruction {
2002+ operation: Operation :: BuildOpenChannel ,
2003+ inputs: vec![ ] ,
2004+ } ,
2005+ Instruction {
2006+ operation: Operation :: SendOpenChannel ,
2007+ inputs: vec![ 0 ] ,
2008+ } ,
2009+ Instruction {
2010+ operation: Operation :: RecvAcceptChannel ,
2011+ inputs: vec![ 1 ] ,
2012+ } ,
2013+ Instruction {
2014+ operation: Operation :: LoadChainHashFromContext ,
2015+ inputs: vec![ ] ,
2016+ } ,
2017+ Instruction {
2018+ operation: Operation :: SendMessage ,
2019+ inputs: vec![ 0 ] ,
2020+ } ,
2021+ Instruction {
2022+ operation: Operation :: ExtractAcceptChannel ( AcceptChannelField :: ChannelType ) ,
2023+ inputs: vec![ 2 ] ,
2024+ } ,
2025+ ] ,
2026+ } ;
2027+ let mut rng = SmallRng :: seed_from_u64 ( 0 ) ;
2028+ let mutator = InstructionReorderMutator ;
2029+ let mut mutated = false ;
2030+ for _ in 0 ..100 {
2031+ if mutator. mutate ( & mut program, & mut rng) {
2032+ mutated = true ;
2033+ break ;
2034+ }
2035+ }
2036+ assert ! (
2037+ mutated,
2038+ "InstructionReorderMutator never mutated the program"
2039+ ) ;
2040+
2041+ // RecvAcceptChannel and SendMessage should've been swapped.
2042+ assert_eq ! ( program. instructions[ 2 ] . operation, Operation :: SendMessage ) ;
2043+ assert_eq ! (
2044+ program. instructions[ 4 ] . operation,
2045+ Operation :: RecvAcceptChannel
2046+ ) ;
2047+ // The inteleaved instruction shouldn't have been changed.
2048+ assert_eq ! (
2049+ program. instructions[ 3 ] . operation,
2050+ Operation :: LoadChainHashFromContext
2051+ ) ;
2052+ // Downstream instructions should be healed.
2053+ assert_eq ! ( program. instructions[ 5 ] . inputs[ 0 ] , 4 ) ;
2054+ }
2055+
2056+ #[ test]
2057+ fn instr_reorder_preserves_well_formedness ( ) {
2058+ let mut original = generate_open_channel_program ( 0 ) ;
2059+ // The generic OpenChannelGenerator program doesn't have swappable Act
2060+ // instructions, so add some.
2061+ let open_channel_msg = original. instructions . len ( ) - 3 ;
2062+ original. instructions . extend ( [
2063+ Instruction {
2064+ operation : Operation :: MineBlocks ( 6 ) ,
2065+ inputs : vec ! [ ] ,
2066+ } ,
2067+ Instruction {
2068+ operation : Operation :: SendOpenChannel ,
2069+ inputs : vec ! [ open_channel_msg] ,
2070+ } ,
2071+ Instruction {
2072+ operation : Operation :: MineBlocks ( 42 ) ,
2073+ inputs : vec ! [ ] ,
2074+ } ,
2075+ ] ) ;
2076+ assert_mutator_preserves_well_formedness ( & InstructionReorderMutator , & original) ;
2077+ }
2078+
19252079// -- DeadCodeEliminator tests --
19262080
19272081#[ test]
0 commit comments