Skip to content

Commit e6d681c

Browse files
committed
feat: patch imports of benchmarks
1 parent 2263b00 commit e6d681c

11 files changed

+319
-0
lines changed

go-runner/src/builder/patcher.rs

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
//! Patches the imports to use codspeed rather than the official "testing" package.
2+
3+
use crate::prelude::*;
4+
use std::fs;
5+
use std::path::{Path, PathBuf};
6+
use std::process::Command;
7+
8+
pub fn patch_imports<P: AsRef<Path>>(
9+
folder: P,
10+
files_to_patch: Vec<PathBuf>,
11+
) -> anyhow::Result<()> {
12+
let folder = folder.as_ref();
13+
debug!("Patching imports in folder: {folder:?}");
14+
15+
// 1. Find all imports that match "testing" and replace them with codspeed equivalent
16+
let mut patched_files = 0;
17+
for go_file in files_to_patch {
18+
let content =
19+
fs::read_to_string(&go_file).context(format!("Failed to read Go file: {go_file:?}"))?;
20+
21+
let patched_content = patch_go_source(&content)?;
22+
23+
if patched_content != content {
24+
fs::write(&go_file, patched_content)
25+
.context(format!("Failed to write patched Go file: {go_file:?}"))?;
26+
27+
debug!("Patched imports in: {go_file:?}");
28+
patched_files += 1;
29+
}
30+
}
31+
debug!("Patched {patched_files} files");
32+
33+
// 2. Update the go module to use the codspeed package
34+
let version = env!("CARGO_PKG_VERSION");
35+
let pkg = format!("github.com/CodSpeedHQ/codspeed-go@v{version}");
36+
debug!("Installing pkg");
37+
38+
let mut cmd: Command = Command::new("go");
39+
cmd.arg("get")
40+
.arg(pkg)
41+
// Bypass Go proxy cache to fetch directly from source - prevents issues with
42+
// cached versions that may have incorrect module paths or outdated content
43+
.env("GOPROXY", "direct")
44+
.current_dir(folder);
45+
46+
let output = cmd.output().context("Failed to execute 'go get' command")?;
47+
if !output.status.success() {
48+
let stderr = String::from_utf8_lossy(&output.stderr);
49+
bail!("Failed to install codspeed-go dependency: {}", stderr);
50+
}
51+
52+
debug!("Successfully installed codspeed-go dependency");
53+
54+
Ok(())
55+
}
56+
57+
/// Internal function to apply import patterns to Go source code
58+
pub fn patch_go_source(source: &str) -> anyhow::Result<String> {
59+
let parsed = gosyn::parse_source(source)?;
60+
61+
let mut modified_content = source.to_string();
62+
if let Some(import) = parsed
63+
.imports
64+
.iter()
65+
.find(|import| import.path.value == "\"testing\"")
66+
{
67+
let start_pos = import.path.pos;
68+
let end_pos = start_pos + import.path.value.len();
69+
70+
let replacement = "testing \"github.com/CodSpeedHQ/codspeed-go/compat/testing\"";
71+
modified_content.replace_range(start_pos..end_pos, replacement);
72+
}
73+
74+
Ok(modified_content)
75+
}
76+
77+
#[cfg(test)]
78+
mod tests {
79+
use super::*;
80+
use insta::assert_snapshot;
81+
use rstest::rstest;
82+
83+
const SINGLE_IMPORT: &str = r#"package main
84+
85+
import "testing"
86+
87+
func TestExample(t *testing.T) {
88+
// test code
89+
}
90+
"#;
91+
92+
const MULTILINE_IMPORT: &str = r#"package main
93+
94+
import (
95+
"fmt"
96+
"testing"
97+
"strings"
98+
)
99+
100+
func TestExample(t *testing.T) {
101+
// test code
102+
}
103+
"#;
104+
105+
const MULTILINE_IMPORT_WITH_TABS: &str = r#"package main
106+
107+
import (
108+
"fmt"
109+
"testing"
110+
"strings"
111+
)
112+
"#;
113+
114+
const IMPORT_WITH_COMMENTS: &str = r#"package main
115+
116+
import (
117+
"fmt"
118+
"testing" // for unit tests
119+
"strings"
120+
)
121+
"#;
122+
123+
const ALREADY_PATCHED_IMPORT: &str = r#"package main
124+
125+
import testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
126+
127+
func BenchmarkExample(b *testing.B) {
128+
// benchmark code
129+
}
130+
"#;
131+
132+
const MIXED_IMPORT_STYLES: &str = r#"package main
133+
134+
import "testing"
135+
136+
import (
137+
"fmt"
138+
"something"
139+
)
140+
"#;
141+
142+
const IMPORT_AT_END_OF_BLOCK: &str = r#"package main
143+
144+
import (
145+
"fmt"
146+
"strings"
147+
"testing"
148+
)
149+
"#;
150+
151+
const IMPORT_WITH_EXTRA_WHITESPACE: &str = r#"package main
152+
153+
import (
154+
"fmt"
155+
156+
"testing"
157+
158+
"strings"
159+
)
160+
"#;
161+
162+
const MULTILINE_IMPORT_WITH_TESTING_STRING: &str = r#"package main
163+
import (
164+
"fmt"
165+
"testing"
166+
)
167+
168+
func TestExample(t *testing.T) {
169+
fmt.Println("testing")
170+
}
171+
"#;
172+
173+
const IMPORT_WITH_TESTING_STRING: &str = r#"package main
174+
import "testing"
175+
import "fmt"
176+
177+
func TestExample(t *testing.T) {
178+
fmt.Println("testing")
179+
}
180+
"#;
181+
182+
#[rstest]
183+
#[case("single_import_replacement", SINGLE_IMPORT)]
184+
#[case("multiline_import_replacement", MULTILINE_IMPORT)]
185+
#[case("multiline_import_with_tabs", MULTILINE_IMPORT_WITH_TABS)]
186+
#[case("import_with_comments", IMPORT_WITH_COMMENTS)]
187+
#[case("already_patched_import", ALREADY_PATCHED_IMPORT)]
188+
#[case("mixed_import_styles", MIXED_IMPORT_STYLES)]
189+
#[case("import_at_end_of_block", IMPORT_AT_END_OF_BLOCK)]
190+
#[case("import_with_extra_whitespace", IMPORT_WITH_EXTRA_WHITESPACE)]
191+
#[case("import_with_testing_string", IMPORT_WITH_TESTING_STRING)]
192+
#[case(
193+
"multiline_import_with_testing_string",
194+
MULTILINE_IMPORT_WITH_TESTING_STRING
195+
)]
196+
fn test_patch_go_source(#[case] test_name: &str, #[case] source: &str) {
197+
let result = patch_go_source(source).unwrap();
198+
assert_snapshot!(test_name, result);
199+
}
200+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
7+
import testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
8+
9+
func BenchmarkExample(b *testing.B) {
10+
// benchmark code
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
7+
import (
8+
"fmt"
9+
"strings"
10+
testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
11+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
7+
import (
8+
"fmt"
9+
testing "github.com/CodSpeedHQ/codspeed-go/compat/testing" // for unit tests
10+
"strings"
11+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
7+
import (
8+
"fmt"
9+
10+
testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
11+
12+
"strings"
13+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
import testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
7+
import "fmt"
8+
9+
func TestExample(t *testing.T) {
10+
fmt.Println("testing")
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
7+
import testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
8+
9+
import (
10+
"fmt"
11+
"something"
12+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
7+
import (
8+
"fmt"
9+
testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
10+
"strings"
11+
)
12+
13+
func TestExample(t *testing.T) {
14+
// test code
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
7+
import (
8+
"fmt"
9+
testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
10+
"strings"
11+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
source: src/builder/patcher.rs
3+
expression: result
4+
---
5+
package main
6+
import (
7+
"fmt"
8+
testing "github.com/CodSpeedHQ/codspeed-go/compat/testing"
9+
)
10+
11+
func TestExample(t *testing.T) {
12+
fmt.Println("testing")
13+
}

0 commit comments

Comments
 (0)