|
|
@@ -0,0 +1,223 @@
|
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
|
+
|
|
|
+use solang::codegen::Options;
|
|
|
+use solang::file_resolver::FileResolver;
|
|
|
+use solang::sema::diagnostics::Diagnostics;
|
|
|
+use solang::{compile, Target};
|
|
|
+use std::ffi::OsStr;
|
|
|
+
|
|
|
+fn build_with_strict_soroban_types(src: &str, strict: bool) -> Diagnostics {
|
|
|
+ let tmp_file = OsStr::new("test.sol");
|
|
|
+ let mut cache = FileResolver::default();
|
|
|
+ cache.set_file_contents(tmp_file.to_str().unwrap(), src.to_string());
|
|
|
+ let opt = inkwell::OptimizationLevel::Default;
|
|
|
+ let target = Target::Soroban;
|
|
|
+ let (_, ns) = compile(
|
|
|
+ tmp_file,
|
|
|
+ &mut cache,
|
|
|
+ target,
|
|
|
+ &Options {
|
|
|
+ opt_level: opt.into(),
|
|
|
+ log_runtime_errors: true,
|
|
|
+ log_prints: true,
|
|
|
+ strict_soroban_types: strict,
|
|
|
+ #[cfg(feature = "wasm_opt")]
|
|
|
+ wasm_opt: Some(contract_build::OptimizationPasses::Z),
|
|
|
+ soroban_version: None,
|
|
|
+ ..Default::default()
|
|
|
+ },
|
|
|
+ std::vec!["unknown".to_string()],
|
|
|
+ "0.0.1",
|
|
|
+ );
|
|
|
+ ns.diagnostics
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_warning_for_int56_without_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_int56(int56 a) public returns (int64) {
|
|
|
+ return int64(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, false);
|
|
|
+
|
|
|
+ // Should have a warning about int56 being rounded to int64
|
|
|
+ let warnings: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Warning).collect();
|
|
|
+ assert!(!warnings.is_empty(), "Expected warnings for int56 rounding");
|
|
|
+
|
|
|
+ let warning_messages: Vec<_> = warnings.iter().map(|w| w.message.as_str()).collect();
|
|
|
+ assert!(warning_messages.iter().any(|msg| msg.contains("int56") && msg.contains("int64")),
|
|
|
+ "Expected warning about int56 being rounded to int64");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_warning_for_uint56_without_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_uint56(uint56 a) public returns (uint64) {
|
|
|
+ return uint64(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, false);
|
|
|
+
|
|
|
+ // Should have a warning about uint56 being rounded to uint64
|
|
|
+ let warnings: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Warning).collect();
|
|
|
+ assert!(!warnings.is_empty(), "Expected warnings for uint56 rounding");
|
|
|
+
|
|
|
+ let warning_messages: Vec<_> = warnings.iter().map(|w| w.message.as_str()).collect();
|
|
|
+ assert!(warning_messages.iter().any(|msg| msg.contains("uint56") && msg.contains("uint64")),
|
|
|
+ "Expected warning about uint56 being rounded to uint64");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_warning_for_int96_without_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_int96(int96 a) public returns (int128) {
|
|
|
+ return int128(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, false);
|
|
|
+
|
|
|
+ // Should have a warning about int96 being rounded to int128
|
|
|
+ let warnings: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Warning).collect();
|
|
|
+ assert!(!warnings.is_empty(), "Expected warnings for int96 rounding");
|
|
|
+
|
|
|
+ let warning_messages: Vec<_> = warnings.iter().map(|w| w.message.as_str()).collect();
|
|
|
+ assert!(warning_messages.iter().any(|msg| msg.contains("int96") && msg.contains("int128")),
|
|
|
+ "Expected warning about int96 being rounded to int128");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_warning_for_uint96_without_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_uint96(uint96 a) public returns (uint128) {
|
|
|
+ return uint128(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, false);
|
|
|
+
|
|
|
+ // Should have a warning about uint96 being rounded to uint128
|
|
|
+ let warnings: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Warning).collect();
|
|
|
+ assert!(!warnings.is_empty(), "Expected warnings for uint96 rounding");
|
|
|
+
|
|
|
+ let warning_messages: Vec<_> = warnings.iter().map(|w| w.message.as_str()).collect();
|
|
|
+ assert!(warning_messages.iter().any(|msg| msg.contains("uint96") && msg.contains("uint128")),
|
|
|
+ "Expected warning about uint96 being rounded to uint128");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_error_for_int56_with_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_int56(int56 a) public returns (int64) {
|
|
|
+ return int64(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, true);
|
|
|
+
|
|
|
+ // Should have an error about int56 being rounded to int64
|
|
|
+ let errors: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Error).collect();
|
|
|
+ assert!(!errors.is_empty(), "Expected errors for int56 rounding with strict mode");
|
|
|
+
|
|
|
+ let error_messages: Vec<_> = errors.iter().map(|e| e.message.as_str()).collect();
|
|
|
+ assert!(error_messages.iter().any(|msg| msg.contains("int56") && msg.contains("int64")),
|
|
|
+ "Expected error about int56 being rounded to int64");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_error_for_uint56_with_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_uint56(uint56 a) public returns (uint64) {
|
|
|
+ return uint64(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, true);
|
|
|
+
|
|
|
+ // Should have an error about uint56 being rounded to uint64
|
|
|
+ let errors: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Error).collect();
|
|
|
+ assert!(!errors.is_empty(), "Expected errors for uint56 rounding with strict mode");
|
|
|
+
|
|
|
+ let error_messages: Vec<_> = errors.iter().map(|e| e.message.as_str()).collect();
|
|
|
+ assert!(error_messages.iter().any(|msg| msg.contains("uint56") && msg.contains("uint64")),
|
|
|
+ "Expected error about uint56 being rounded to uint64");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_error_for_int96_with_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_int96(int96 a) public returns (int128) {
|
|
|
+ return int128(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, true);
|
|
|
+
|
|
|
+ // Should have an error about int96 being rounded to int128
|
|
|
+ let errors: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Error).collect();
|
|
|
+ assert!(!errors.is_empty(), "Expected errors for int96 rounding with strict mode");
|
|
|
+
|
|
|
+ let error_messages: Vec<_> = errors.iter().map(|e| e.message.as_str()).collect();
|
|
|
+ assert!(error_messages.iter().any(|msg| msg.contains("int96") && msg.contains("int128")),
|
|
|
+ "Expected error about int96 being rounded to int128");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_error_for_uint96_with_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_uint96(uint96 a) public returns (uint128) {
|
|
|
+ return uint128(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, true);
|
|
|
+
|
|
|
+ // Should have an error about uint96 being rounded to uint128
|
|
|
+ let errors: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Error).collect();
|
|
|
+ assert!(!errors.is_empty(), "Expected errors for uint96 rounding with strict mode");
|
|
|
+
|
|
|
+ let error_messages: Vec<_> = errors.iter().map(|e| e.message.as_str()).collect();
|
|
|
+ assert!(error_messages.iter().any(|msg| msg.contains("uint96") && msg.contains("uint128")),
|
|
|
+ "Expected error about uint96 being rounded to uint128");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_error_for_int200_with_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_int200(int200 a) public returns (int256) {
|
|
|
+ return int256(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, true);
|
|
|
+
|
|
|
+ // Should have an error about int200 being rounded to int256
|
|
|
+ let errors: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Error).collect();
|
|
|
+ assert!(!errors.is_empty(), "Expected errors for int200 rounding with strict mode");
|
|
|
+
|
|
|
+ let error_messages: Vec<_> = errors.iter().map(|e| e.message.as_str()).collect();
|
|
|
+ assert!(error_messages.iter().any(|msg| msg.contains("int200") && msg.contains("int256")),
|
|
|
+ "Expected error about int200 being rounded to int256");
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_error_for_uint200_with_strict() {
|
|
|
+ let src = r#"contract test {
|
|
|
+ function test_uint200(uint200 a) public returns (uint256) {
|
|
|
+ return uint256(a);
|
|
|
+ }
|
|
|
+ }"#;
|
|
|
+
|
|
|
+ let diagnostics = build_with_strict_soroban_types(src, true);
|
|
|
+
|
|
|
+ // Should have an error about uint200 being rounded to uint256
|
|
|
+ let errors: Vec<_> = diagnostics.iter().filter(|d| d.level == solang_parser::diagnostics::Level::Error).collect();
|
|
|
+ assert!(!errors.is_empty(), "Expected errors for uint200 rounding with strict mode");
|
|
|
+
|
|
|
+ let error_messages: Vec<_> = errors.iter().map(|e| e.message.as_str()).collect();
|
|
|
+ assert!(error_messages.iter().any(|msg| msg.contains("uint200") && msg.contains("uint256")),
|
|
|
+ "Expected error about uint200 being rounded to uint256");
|
|
|
+}
|