@@ -1732,30 +1732,41 @@ mod tests {
1732
1732
Ok ( ( ) )
1733
1733
}
1734
1734
1735
+ const ADD_CODE : & str = r#"pub fn add(a: u8, b: u8) -> u8 { a + b }"# ;
1736
+
1737
+ const ARBITRARY_ASSEMBLY_REQUEST : CompileRequest = CompileRequest {
1738
+ target : CompileTarget :: Assembly (
1739
+ DEFAULT_ASSEMBLY_FLAVOR ,
1740
+ DEFAULT_ASSEMBLY_DEMANGLE ,
1741
+ DEFAULT_ASSEMBLY_PROCESS ,
1742
+ ) ,
1743
+ channel : Channel :: Beta ,
1744
+ crate_type : CrateType :: Library ( LibraryType :: Lib ) ,
1745
+ mode : Mode :: Release ,
1746
+ edition : Edition :: Rust2018 ,
1747
+ tests : false ,
1748
+ backtrace : false ,
1749
+ code : String :: new ( ) ,
1750
+ } ;
1751
+
1752
+ const DEFAULT_ASSEMBLY_FLAVOR : AssemblyFlavor = AssemblyFlavor :: Intel ;
1753
+ const DEFAULT_ASSEMBLY_DEMANGLE : DemangleAssembly = DemangleAssembly :: Demangle ;
1754
+ const DEFAULT_ASSEMBLY_PROCESS : ProcessAssembly = ProcessAssembly :: Filter ;
1755
+
1735
1756
#[ tokio:: test]
1736
1757
#[ snafu:: report]
1737
1758
async fn compile_assembly ( ) -> Result < ( ) > {
1738
1759
let coordinator = new_coordinator ( ) . await ;
1739
1760
1740
1761
let req = CompileRequest {
1741
- target : CompileTarget :: Assembly (
1742
- AssemblyFlavor :: Intel ,
1743
- DemangleAssembly :: Demangle ,
1744
- ProcessAssembly :: Filter ,
1745
- ) ,
1746
- channel : Channel :: Beta ,
1747
- crate_type : CrateType :: Library ( LibraryType :: Lib ) ,
1748
- mode : Mode :: Release ,
1749
- edition : Edition :: Rust2018 ,
1750
- tests : false ,
1751
- backtrace : false ,
1752
- code : r#"pub fn add(a: u8, b: u8) -> u8 { a + b }"# . into ( ) ,
1762
+ code : ADD_CODE . into ( ) ,
1763
+ ..ARBITRARY_ASSEMBLY_REQUEST
1753
1764
} ;
1754
1765
1755
1766
let response = coordinator. compile ( req) . with_timeout ( ) . await . unwrap ( ) ;
1756
1767
1757
- // #[cfg(target_arch = "x86_64")]
1758
- // let asm = "";
1768
+ #[ cfg( target_arch = "x86_64" ) ]
1769
+ let asm = "eax, [rsi + rdi] " ;
1759
1770
1760
1771
#[ cfg( target_arch = "aarch64" ) ]
1761
1772
let asm = "w0, w1, w0" ;
@@ -1768,6 +1779,109 @@ mod tests {
1768
1779
Ok ( ( ) )
1769
1780
}
1770
1781
1782
+ #[ tokio:: test]
1783
+ #[ snafu:: report]
1784
+ // Assembly flavor only makes sense when targeting x86(_64): this
1785
+ // test will always fail on aarch64.
1786
+ async fn compile_assembly_flavor ( ) -> Result < ( ) > {
1787
+ let cases = [
1788
+ ( AssemblyFlavor :: Att , "(%rsi,%rdi), %eax" ) ,
1789
+ ( AssemblyFlavor :: Intel , "eax, [rsi + rdi]" ) ,
1790
+ ] ;
1791
+
1792
+ for ( flavor, expected) in cases {
1793
+ let coordinator = new_coordinator ( ) . await ;
1794
+
1795
+ let req = CompileRequest {
1796
+ target : CompileTarget :: Assembly (
1797
+ flavor,
1798
+ DEFAULT_ASSEMBLY_DEMANGLE ,
1799
+ DEFAULT_ASSEMBLY_PROCESS ,
1800
+ ) ,
1801
+ code : ADD_CODE . into ( ) ,
1802
+ ..ARBITRARY_ASSEMBLY_REQUEST
1803
+ } ;
1804
+
1805
+ let response = coordinator. compile ( req) . with_timeout ( ) . await . unwrap ( ) ;
1806
+
1807
+ assert ! ( response. success, "stderr: {}" , response. stderr) ;
1808
+ assert_contains ! ( response. code, expected) ;
1809
+
1810
+ coordinator. shutdown ( ) . await ?;
1811
+ }
1812
+ Ok ( ( ) )
1813
+ }
1814
+
1815
+ #[ tokio:: test]
1816
+ #[ snafu:: report]
1817
+ // The demangling expects Linux-style symbols, not macOS: this
1818
+ // test will always fail on macOS.
1819
+ async fn compile_assembly_demangle ( ) -> Result < ( ) > {
1820
+ let cases = [
1821
+ ( DemangleAssembly :: Mangle , "10playground3add" ) ,
1822
+ ( DemangleAssembly :: Demangle , "playground::add" ) ,
1823
+ ] ;
1824
+
1825
+ for ( mangle, expected) in cases {
1826
+ let coordinator = new_coordinator ( ) . await ;
1827
+
1828
+ let req = CompileRequest {
1829
+ target : CompileTarget :: Assembly (
1830
+ DEFAULT_ASSEMBLY_FLAVOR ,
1831
+ mangle,
1832
+ DEFAULT_ASSEMBLY_PROCESS ,
1833
+ ) ,
1834
+ code : ADD_CODE . into ( ) ,
1835
+ ..ARBITRARY_ASSEMBLY_REQUEST
1836
+ } ;
1837
+
1838
+ let response = coordinator. compile ( req) . with_timeout ( ) . await . unwrap ( ) ;
1839
+
1840
+ assert ! ( response. success, "stderr: {}" , response. stderr) ;
1841
+ assert_contains ! ( response. code, expected) ;
1842
+
1843
+ coordinator. shutdown ( ) . await ?;
1844
+ }
1845
+
1846
+ Ok ( ( ) )
1847
+ }
1848
+
1849
+ #[ tokio:: test]
1850
+ #[ snafu:: report]
1851
+ async fn compile_assembly_process ( ) -> Result < ( ) > {
1852
+ let cases = [
1853
+ ( ProcessAssembly :: Raw , true ) ,
1854
+ ( ProcessAssembly :: Filter , false ) ,
1855
+ ] ;
1856
+
1857
+ for ( process, expected) in cases {
1858
+ let coordinator = new_coordinator ( ) . await ;
1859
+
1860
+ let req = CompileRequest {
1861
+ target : CompileTarget :: Assembly (
1862
+ DEFAULT_ASSEMBLY_FLAVOR ,
1863
+ DEFAULT_ASSEMBLY_DEMANGLE ,
1864
+ process,
1865
+ ) ,
1866
+ code : ADD_CODE . into ( ) ,
1867
+ ..ARBITRARY_ASSEMBLY_REQUEST
1868
+ } ;
1869
+
1870
+ let response = coordinator. compile ( req) . with_timeout ( ) . await . unwrap ( ) ;
1871
+
1872
+ assert ! ( response. success, "stderr: {}" , response. stderr) ;
1873
+ if expected {
1874
+ assert_contains ! ( response. code, ".cfi_startproc" ) ;
1875
+ } else {
1876
+ assert_not_contains ! ( response. code, ".cfi_startproc" ) ;
1877
+ }
1878
+
1879
+ coordinator. shutdown ( ) . await ?;
1880
+ }
1881
+
1882
+ Ok ( ( ) )
1883
+ }
1884
+
1771
1885
const SUBTRACT_CODE : & str = r#"pub fn sub(a: u8, b: u8) -> u8 { a - b }"# ;
1772
1886
1773
1887
const ARBITRARY_HIR_REQUEST : CompileRequest = CompileRequest {
@@ -1934,6 +2048,100 @@ mod tests {
1934
2048
Ok ( ( ) )
1935
2049
}
1936
2050
2051
+ fn new_execution_limited_request ( ) -> ExecuteRequest {
2052
+ ExecuteRequest {
2053
+ channel : Channel :: Stable ,
2054
+ mode : Mode :: Debug ,
2055
+ edition : Edition :: Rust2021 ,
2056
+ crate_type : CrateType :: Binary ,
2057
+ tests : false ,
2058
+ backtrace : false ,
2059
+ code : Default :: default ( ) ,
2060
+ }
2061
+ }
2062
+
2063
+ #[ tokio:: test]
2064
+ #[ snafu:: report]
2065
+ async fn network_connections_are_disabled ( ) -> Result < ( ) > {
2066
+ // The limits are only applied to the container
2067
+ let coordinator = Coordinator :: new_docker ( ) . await ;
2068
+
2069
+ let req = ExecuteRequest {
2070
+ code : r#"
2071
+ fn main() {
2072
+ match ::std::net::TcpStream::connect("google.com:80") {
2073
+ Ok(_) => println!("Able to connect to the outside world"),
2074
+ Err(e) => println!("Failed to connect {}, {:?}", e, e),
2075
+ }
2076
+ }
2077
+ "#
2078
+ . into ( ) ,
2079
+ ..new_execution_limited_request ( )
2080
+ } ;
2081
+
2082
+ let res = coordinator. execute ( req) . with_timeout ( ) . await . unwrap ( ) ;
2083
+
2084
+ assert_contains ! ( res. stdout, "Failed to connect" ) ;
2085
+
2086
+ Ok ( ( ) )
2087
+ }
2088
+
2089
+ #[ tokio:: test]
2090
+ #[ snafu:: report]
2091
+ async fn memory_usage_is_limited ( ) -> Result < ( ) > {
2092
+ // The limits are only applied to the container
2093
+ let coordinator = Coordinator :: new_docker ( ) . await ;
2094
+
2095
+ let req = ExecuteRequest {
2096
+ code : r#"
2097
+ fn main() {
2098
+ let gigabyte = 1024 * 1024 * 1024;
2099
+ let mut big = vec![0u8; 1 * gigabyte];
2100
+ for i in &mut big { *i += 1; }
2101
+ }
2102
+ "#
2103
+ . into ( ) ,
2104
+ ..new_execution_limited_request ( )
2105
+ } ;
2106
+
2107
+ let res = coordinator. execute ( req) . with_timeout ( ) . await . unwrap ( ) ;
2108
+
2109
+ assert ! ( !res. success) ;
2110
+ // TODO: We need to actually inform the user about this somehow. The UI is blank.
2111
+ // assert_contains!(res.stdout, "Killed");
2112
+
2113
+ Ok ( ( ) )
2114
+ }
2115
+
2116
+ #[ tokio:: test]
2117
+ #[ snafu:: report]
2118
+ async fn number_of_pids_is_limited ( ) -> Result < ( ) > {
2119
+ // The limits are only applied to the container
2120
+ let coordinator = Coordinator :: new_docker ( ) . await ;
2121
+
2122
+ let req = ExecuteRequest {
2123
+ code : r##"
2124
+ fn main() {
2125
+ ::std::process::Command::new("sh").arg("-c").arg(r#"
2126
+ z() {
2127
+ z&
2128
+ z
2129
+ }
2130
+ z
2131
+ "#).status().unwrap();
2132
+ }
2133
+ "##
2134
+ . into ( ) ,
2135
+ ..new_execution_limited_request ( )
2136
+ } ;
2137
+
2138
+ let res = coordinator. execute ( req) . with_timeout ( ) . await . unwrap ( ) ;
2139
+
2140
+ assert_contains ! ( res. stderr, "Cannot fork" ) ;
2141
+
2142
+ Ok ( ( ) )
2143
+ }
2144
+
1937
2145
trait TimeoutExt : Future + Sized {
1938
2146
#[ allow( clippy:: type_complexity) ]
1939
2147
fn with_timeout (
0 commit comments