Skip to content

Commit

Permalink
Fix integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasSte committed Aug 18, 2021
1 parent 5cc218f commit 2054162
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 46 deletions.
13 changes: 8 additions & 5 deletions src/file_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ impl FileCache {

/// Get file with contents. This must be a file which was previously
/// add to the cache
pub fn get_file_contents(&mut self, file: &Path) -> Arc<str> {
pub fn get_file_contents_and_number(&mut self, file: &Path) -> (Arc<str>, usize) {
let file_no = self.cached_paths[file];

self.files[file_no].clone()
(self.files[file_no].clone(), file_no)
}

/// Populate the cache with absolute file path
Expand Down Expand Up @@ -207,11 +207,15 @@ impl FileCache {
) -> (String, usize, usize, usize) {
let (beg_line_no, mut beg_offset) = file.offset_to_line_column(loc.1);
let (end_line_no, mut end_offset) = file.offset_to_line_column(loc.2);
let mut full_line = self.files[loc.0].lines().nth(beg_line_no).unwrap().to_owned();
let mut full_line = self.files[file.cache_no]
.lines()
.nth(beg_line_no)
.unwrap()
.to_owned();
// If the loc spans across multiple lines, we concatenate them
if beg_line_no != end_line_no {
for i in beg_offset + 1..end_offset + 1 {
let line = self.files[loc.0].lines().nth(i).unwrap();
let line = self.files[file.cache_no].lines().nth(i).unwrap();
if i == end_offset {
end_offset += full_line.len();
}
Expand All @@ -223,7 +227,6 @@ impl FileCache {
full_line = full_line.trim_start().parse().unwrap();
// Calculate the size of the symbol we want to highlight
let size = end_offset - beg_offset;

// Update the offset after trimming the line
beg_offset -= old_size - full_line.len();

Expand Down
2 changes: 2 additions & 0 deletions src/sema/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ pub struct File {
pub path: PathBuf,
/// Used for offset to line-column conversions
pub line_starts: Vec<usize>,
/// Indicates the file number in FileCache.files
pub cache_no: usize,
}

/// When resolving a Solidity file, this holds all the resolved items
Expand Down
8 changes: 6 additions & 2 deletions src/sema/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::parser::pt::Loc;
use std::path::PathBuf;

impl File {
pub fn new(path: PathBuf, contents: &str) -> Self {
pub fn new(path: PathBuf, contents: &str, cache_no: usize) -> Self {
let mut line_starts = Vec::new();

for (ind, c) in contents.char_indices() {
Expand All @@ -12,7 +12,11 @@ impl File {
}
}

File { path, line_starts }
File {
path,
line_starts,
cache_no,
}
}

/// Give a position as a human readable position
Expand Down
9 changes: 6 additions & 3 deletions src/sema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ pub fn sema(file: &ResolvedFile, cache: &mut FileCache, ns: &mut ast::Namespace)
fn sema_file(file: &ResolvedFile, cache: &mut FileCache, ns: &mut ast::Namespace) {
let file_no = ns.files.len();

let source_code = cache.get_file_contents(&file.full_path);
let (source_code, file_cache_no) = cache.get_file_contents_and_number(&file.full_path);

ns.files
.push(ast::File::new(file.full_path.clone(), &source_code));
ns.files.push(ast::File::new(
file.full_path.clone(),
&source_code,
file_cache_no,
));

let pt = match parse(&source_code, file_no) {
Ok(s) => s,
Expand Down
170 changes: 134 additions & 36 deletions tests/undefined_variable_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,39 +610,137 @@ contract test {
));
}

//TODO: Fix this test

// #[test]
// fn try_catch() {
// let file = r#"
// contract AddNumbers { function add(uint256 a, uint256 b) external pure returns (uint256 c) {c = b;} }
// contract Example {
// AddNumbers addContract;
// event StringFailure(string stringFailure);
// event BytesFailure(bytes bytesFailure);
//
// function exampleFunction(uint256 _a, uint256 _b) public returns (bytes c) {
// bytes r;
// try addContract.add(_a, _b) returns (uint256 _value) {
// r = hex"ABCD";
// return r;
// } catch Error(string memory _err) {
// r = hex"ABCD";
// emit StringFailure(_err);
// } catch (bytes memory _err) {
// emit BytesFailure(_err);
// }
//
// return r;
// }
//
// }
// "#;
//
// let ns = parse_and_codegen(file);
// let errors = get_errors(&ns);
// assert_eq!(errors.len(), 1);
// assert_eq!(errors[0].message, "Variable 'r' is undefined");
// assert_eq!(errors[0].notes.len(), 1);
// assert_eq!(errors[0].notes[0].message, "Variable read before being defined");
// }
#[test]
fn try_catch() {
//TODO: Fix this test case

// let file = r#"
// contract AddNumbers { function add(uint256 a, uint256 b) external pure returns (uint256 c) {c = b;} }
// contract Example {
// AddNumbers addContract;
// event StringFailure(string stringFailure);
// event BytesFailure(bytes bytesFailure);
//
// function exampleFunction(uint256 _a, uint256 _b) public returns (bytes c) {
// bytes r;
// try addContract.add(_a, _b) returns (uint256 _value) {
// r = hex"ABCD";
// return r;
// } catch Error(string memory _err) {
// r = hex"ABCD";
// emit StringFailure(_err);
// } catch (bytes memory _err) {
// emit BytesFailure(_err);
// }
//
// return r;
// }
//
// }
// "#;
//
// let ns = parse_and_codegen(file);
// let errors = get_errors(&ns);
// assert_eq!(errors.len(), 1);
// assert_eq!(errors[0].message, "Variable 'r' is undefined");
// assert_eq!(errors[0].notes.len(), 1);
// assert_eq!(errors[0].notes[0].message, "Variable read before being defined");

let file = r#"
contract AddNumbers { function add(uint256 a, uint256 b) external pure returns (uint256 c) {c = b;} }
contract Example {
AddNumbers addContract;
event StringFailure(string stringFailure);
event BytesFailure(bytes bytesFailure);
function exampleFunction(uint256 _a, uint256 _b) public returns (bytes c) {
bytes r;
try addContract.add(_a, _b) returns (uint256 _value) {
r = hex"ABCD";
return r;
} catch Error(string memory _err) {
r = hex"ABCD";
emit StringFailure(_err);
} catch (bytes memory _err) {
r = hex"ABCD";
emit BytesFailure(_err);
}
return r;
}
}
"#;

let ns = parse_and_codegen(file);
let errors = get_errors(&ns);
assert_eq!(errors.len(), 0);

let file = r#"
contract AddNumbers { function add(uint256 a, uint256 b) external pure returns (uint256 c) {c = b;} }
contract Example {
AddNumbers addContract;
event StringFailure(string stringFailure);
event BytesFailure(bytes bytesFailure);
function exampleFunction(uint256 _a, uint256 _b) public returns (bytes c) {
bytes r;
try addContract.add(_a, _b) returns (uint256 _value) {
return r;
} catch Error(string memory _err) {
r = hex"ABCD";
emit StringFailure(_err);
} catch (bytes memory _err) {
emit BytesFailure(_err);
}
return r;
}
}
"#;

let ns = parse_and_codegen(file);
let errors = get_errors(&ns);
assert_eq!(errors.len(), 1);
assert_eq!(errors[0].message, "Variable 'r' is undefined");
assert_eq!(errors[0].notes.len(), 1);
assert_eq!(
errors[0].notes[0].message,
"Variable read before being defined"
);

let file = r#"
contract AddNumbers { function add(uint256 a, uint256 b) external pure returns (uint256 c) {c = b;} }
contract Example {
AddNumbers addContract;
event StringFailure(string stringFailure);
event BytesFailure(bytes bytesFailure);
function exampleFunction(uint256 _a, uint256 _b) public returns (bytes c) {
bytes r;
try addContract.add(_a, _b) returns (uint256 _value) {
r = hex"ABCD";
return r;
} catch Error(string memory _err) {
emit StringFailure(_err);
} catch (bytes memory _err) {
emit BytesFailure(_err);
}
return r;
}
}
"#;

let ns = parse_and_codegen(file);
let errors = get_errors(&ns);
assert_eq!(errors.len(), 1);
assert_eq!(errors[0].message, "Variable 'r' is undefined");
assert_eq!(errors[0].notes.len(), 1);
assert_eq!(
errors[0].notes[0].message,
"Variable read before being defined"
);
}

0 comments on commit 2054162

Please sign in to comment.