Skip to content

Commit fa72079

Browse files
committed
add merger sources
1 parent 5d8b903 commit fa72079

32 files changed

+2201
-7
lines changed

examples/marge_files.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
extern crate lcov_parser;
2+
3+
use lcov_parser:: { merge_files };
4+
5+
fn main() {
6+
let trace_files = [
7+
"../../../tests/fixtures/fixture1.info",
8+
"../../../tests/fixtures/fixture2.info"
9+
];
10+
let _ = match merge_files(&trace_files) {
11+
Ok(report) => report.save_as("/tmp/merged_report.info"),
12+
Err(err) => panic!(err)
13+
};
14+
}

src/lib.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313
#[macro_use]
1414
extern crate combine;
1515

16-
pub use self::record::*;
17-
pub use self::parser::*;
18-
19-
mod combinator;
16+
#[macro_use]
17+
mod macros;
18+
mod merger;
2019
mod record;
20+
mod report;
21+
mod combinator;
2122
mod parser;
23+
24+
pub use self::record::*;
25+
pub use self::parser::*;
26+
pub use self::merger:: { merge_files };
27+
pub use self::report::*;

src/macros.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) 2015-2016 lcov-parser developers
2+
//
3+
// Licensed under the Apache License, Version 2.0
4+
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5+
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. All files in the project carrying such notice may not be copied,
7+
// modified, or distributed except according to those terms.
8+
9+
#[macro_export]
10+
macro_rules! impl_summary {
11+
($dest:ty, $field:ident<$key:ty, $value:ty>) => {
12+
impl $crate::report::summary::Summary<$key, $value> for $dest {
13+
fn iter(&self) -> ::std::collections::btree_map::Iter<$key, $value> {
14+
self.$field.iter()
15+
}
16+
fn contains_key(&self, key: &$key) -> bool {
17+
self.$field.contains_key(key)
18+
}
19+
fn get(&self, key: &$key) -> Option<&$value> {
20+
self.$field.get(key)
21+
}
22+
fn len(&self) -> usize {
23+
self.$field.len()
24+
}
25+
}
26+
}
27+
}
28+
29+
#[macro_export]
30+
macro_rules! impl_try_merge_self_summary {
31+
($dest:ty:$field:ident, $err:ty) => {
32+
impl<'a> $crate::merger::ops::TryMerge<&'a $dest> for $dest {
33+
type Err = $err;
34+
35+
fn try_merge(&mut self, other: &'a $dest) -> MergeResult<Self::Err> {
36+
for (key, other_value) in other.iter() {
37+
if !self.$field.contains_key(key) {
38+
self.$field.insert(key.clone(), other_value.clone());
39+
continue;
40+
}
41+
let mut value = self.$field.get_mut(key).unwrap();
42+
let _ = try!(value.try_merge(other_value));
43+
}
44+
Ok(())
45+
}
46+
}
47+
}
48+
}

src/merger/merger.rs

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// Copyright (c) 2015-2016 lcov-parser developers
2+
//
3+
// Licensed under the Apache License, Version 2.0
4+
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5+
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. All files in the project carrying such notice may not be copied,
7+
// modified, or distributed except according to those terms.
8+
9+
use std::path::Path;
10+
use std::convert::{ AsRef };
11+
use std::result:: { Result };
12+
use parser:: { LCOVParser, FromFile };
13+
use record:: { LCOVRecord, LineData, FunctionData as FunctionDataRecord, BranchData as BranchDataRecord, FunctionName };
14+
use report:: { Report };
15+
use report::test:: { Tests };
16+
use report::file:: { File, Files };
17+
use merger::ops:: { Merge, TryMerge, MergeError, TestError, ChecksumError, BranchError, FunctionError, MergeResult };
18+
19+
pub struct ReportMerger {
20+
test_name: Option<String>,
21+
source_name: Option<String>,
22+
tests: Tests,
23+
files: Files
24+
}
25+
26+
impl ReportMerger {
27+
pub fn new() -> Self {
28+
ReportMerger {
29+
test_name: None,
30+
source_name: None,
31+
tests: Tests::new(),
32+
files: Files::new()
33+
}
34+
}
35+
pub fn merge<T: AsRef<Path>>(&mut self, files: &[T]) -> Result<Report, MergeError> {
36+
for file in files.iter() {
37+
try!(self.process_file(file));
38+
}
39+
Ok(Report::new(self.files.clone()))
40+
}
41+
fn process_file<T: AsRef<Path>>(&mut self, file: T) -> Result<(), MergeError> {
42+
let mut parser = try!(LCOVParser::from_file(file));
43+
44+
loop {
45+
let result = try!(parser.next());
46+
47+
if result.is_none() {
48+
break;
49+
}
50+
let record = result.unwrap();
51+
52+
match record {
53+
LCOVRecord::TestName(ref name) => self.on_test_name(name),
54+
LCOVRecord::SourceFile(ref name) => self.on_source_file(name),
55+
LCOVRecord::Data(ref data) => try!(self.on_data(data)),
56+
LCOVRecord::FunctionName(ref func_name) => try!(self.on_func_name(func_name)),
57+
LCOVRecord::FunctionData(ref func_data) => try!(self.on_func_data(func_data)),
58+
LCOVRecord::BranchData(ref branch_data) => try!(self.on_branch_data(branch_data)),
59+
LCOVRecord::EndOfRecord => try!(self.on_end_of_record()),
60+
_ => { continue; }
61+
};
62+
}
63+
Ok(())
64+
}
65+
66+
fn on_test_name(&mut self, test_name: &Option<String>) {
67+
self.test_name = match test_name {
68+
&Some(ref name) => Some(name.clone()),
69+
&None => Some(String::new())
70+
};
71+
let current_test_name = self.test_name.as_ref().unwrap();
72+
self.tests.merge(current_test_name);
73+
}
74+
fn on_source_file(&mut self, source_name: &String) {
75+
self.source_name = Some(source_name.clone());
76+
}
77+
fn on_data(&mut self, line_data: &LineData) -> MergeResult<ChecksumError> {
78+
if self.test_name.is_some() {
79+
let test_name = self.test_name.as_ref().unwrap();
80+
try!(self.tests.try_merge((test_name, line_data)));
81+
}
82+
Ok(())
83+
}
84+
fn on_func_name(&mut self, func_name: &FunctionName) -> MergeResult<FunctionError> {
85+
if self.test_name.is_none() {
86+
return Ok(());
87+
}
88+
89+
let test_name = self.test_name.as_ref().unwrap();
90+
try!(self.tests.try_merge((test_name, func_name)));
91+
Ok(())
92+
}
93+
fn on_func_data(&mut self, func_data: &FunctionDataRecord) -> MergeResult<FunctionError> {
94+
if self.test_name.is_none() {
95+
return Ok(());
96+
}
97+
98+
let test_name = self.test_name.as_ref().unwrap();
99+
try!(self.tests.try_merge((test_name, func_data)));
100+
Ok(())
101+
}
102+
fn on_branch_data(&mut self, branch_data: &BranchDataRecord) -> MergeResult<BranchError> {
103+
if self.test_name.is_none() {
104+
return Ok(());
105+
}
106+
let test_name = self.test_name.as_ref().unwrap();
107+
try!(self.tests.try_merge((test_name, branch_data)));
108+
Ok(())
109+
}
110+
fn on_end_of_record(&mut self) -> MergeResult<TestError> {
111+
let source_name = self.source_name.as_ref().unwrap();
112+
let file = File::new(self.tests.clone());
113+
114+
try!(self.files.try_merge((source_name, &file)));
115+
self.tests = Tests::new();
116+
Ok(())
117+
}
118+
}
119+
120+
121+
#[cfg(test)]
122+
mod tests {
123+
use merger::*;
124+
use std::path::Path;
125+
use std::fs::File;
126+
use std::io::*;
127+
128+
#[test]
129+
fn save_as() {
130+
let report_path = "tests/fixtures/merge/fixture1.info";
131+
132+
let mut parse = ReportMerger::new();
133+
let report = parse.merge(&[ report_path ]).unwrap();
134+
let _ = report.save_as("/tmp/report.lcov").unwrap();
135+
136+
assert_eq!(Path::new("/tmp/report.lcov").exists(), true);
137+
}
138+
139+
#[test]
140+
fn display() {
141+
let report_path = "tests/fixtures/merge/fixture1.info";
142+
let readed_file_content = {
143+
let mut output = String::new();
144+
let mut f = File::open(report_path).unwrap();
145+
let _ = f.read_to_string(&mut output);
146+
output
147+
};
148+
let mut parse = ReportMerger::new();
149+
let report = parse.merge(&[ report_path ]).unwrap();
150+
151+
assert_eq!(report.to_string(), readed_file_content);
152+
}
153+
}

src/merger/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2015-2016 lcov-parser developers
2+
//
3+
// Licensed under the Apache License, Version 2.0
4+
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5+
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. All files in the project carrying such notice may not be copied,
7+
// modified, or distributed except according to those terms.
8+
9+
mod merger;
10+
pub mod ops;
11+
12+
pub use merger::merger:: { ReportMerger };
13+
14+
use std::path::Path;
15+
use report::*;
16+
use self::ops::MergeError;
17+
18+
pub fn merge_files<T: AsRef<Path>>(files: &[T]) -> Result<Report, MergeError> {
19+
let mut merger = ReportMerger::new();
20+
merger.merge(files)
21+
}

0 commit comments

Comments
 (0)