Skip to content
This repository was archived by the owner on May 23, 2024. It is now read-only.

Commit bda6ec7

Browse files
WIP: Automation for adding tests
1 parent ffaef82 commit bda6ec7

File tree

5 files changed

+206
-0
lines changed

5 files changed

+206
-0
lines changed

Cargo.lock

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ tempfile = "3.1.0"
1515
[workspace]
1616
members = [
1717
"autofix",
18+
"grabber",
1819
"labeler"
1920
]
2021

grabber/Cargo.toml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "glacier-grabber"
3+
version = "0.1.0"
4+
authors = ["Langston Barrett <langston.barrett@gmail.com>"]
5+
edition = "2021"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
glacier = "0.1.0"
11+
once_cell = { workspace = true }
12+
regex = "1"
13+
reqwest = { workspace = true }
14+
serde = { workspace = true }

grabber/src/github.rs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use once_cell::sync::{Lazy, OnceCell};
2+
use regex::Regex;
3+
use reqwest::blocking::Client;
4+
use serde::{Deserialize, Serialize};
5+
use std::env::{var, VarError};
6+
7+
static CLIENT: Lazy<Client> = Lazy::new(|| {
8+
Client::builder()
9+
.user_agent("rust-lang/glacier")
10+
.build()
11+
.unwrap()
12+
});
13+
14+
pub(crate) struct Config {
15+
token: String,
16+
}
17+
18+
impl Config {
19+
pub(crate) fn from_env(on_glacier: bool) -> Result<Self, VarError> {
20+
Ok(Self {
21+
token: if on_glacier {
22+
var("GITHUB_TOKEN")?
23+
} else {
24+
var("GRAB_TOKEN")?
25+
},
26+
})
27+
}
28+
}
29+
30+
pub(crate) fn get_labeled_issues(
31+
config: &Config,
32+
repo: &str,
33+
label_name: String,
34+
) -> Result<Vec<Issue>, reqwest::Error> {
35+
let url = format!("https://api.github.com/repos/{repo}/issues?labels={label_name}&state=open");
36+
37+
let mut issues: Vec<Issue> = CLIENT
38+
.get(&url)
39+
.bearer_auth(&config.token)
40+
.send()?
41+
.error_for_status()?
42+
.json()?;
43+
44+
let pages = get_result_length(config, &url).unwrap();
45+
46+
if pages > 1 {
47+
for i in 2..=pages {
48+
let url = format!(
49+
"https://api.github.com/repos/rust-lang/rust/issues?labels={label_name}&state=open&page={i}"
50+
);
51+
let mut paged_issues: Vec<Issue> = CLIENT
52+
.get(&url)
53+
.bearer_auth(&config.token)
54+
.send()?
55+
.error_for_status()?
56+
.json()?;
57+
58+
issues.append(&mut paged_issues);
59+
}
60+
}
61+
62+
Ok(issues)
63+
}
64+
65+
fn get_result_length(config: &Config, url: &str) -> Result<usize, Box<dyn std::error::Error>> {
66+
static RE_LAST_PAGE: OnceCell<Regex> = OnceCell::new();
67+
let res = CLIENT.get(url).bearer_auth(&config.token).send()?;
68+
69+
if res.status().is_success() {
70+
if let Some(link) = res.headers().get("Link") {
71+
let link_string = String::from_utf8(link.as_bytes().to_vec()).unwrap();
72+
let re_last_page =
73+
RE_LAST_PAGE.get_or_init(|| Regex::new(r#"page=([0-9]+)>; rel="last""#).unwrap());
74+
let last_page_number = re_last_page
75+
.captures(&link_string)
76+
.unwrap()
77+
.get(1)
78+
.unwrap()
79+
.as_str();
80+
let pages: usize = last_page_number.parse().unwrap();
81+
82+
Ok(pages)
83+
} else {
84+
Ok(0)
85+
}
86+
} else {
87+
Ok(0)
88+
}
89+
}
90+
91+
#[derive(Serialize, Debug)]
92+
pub(crate) struct Labels {
93+
pub(crate) labels: Vec<String>,
94+
}
95+
96+
#[derive(Deserialize, Debug)]
97+
pub(crate) struct Issue {
98+
pub(crate) number: usize,
99+
pub(crate) body: String,
100+
}
101+
102+
#[derive(Deserialize, Debug, PartialEq, Eq)]
103+
#[serde(rename_all = "lowercase")]
104+
pub(crate) enum IssueState {
105+
Open,
106+
Closed,
107+
}

grabber/src/main.rs

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use glacier::rayon::iter::ParallelIterator;
2+
3+
mod github;
4+
5+
fn main() {
6+
let config = github::Config::from_env(false).unwrap();
7+
8+
let mut tested_issue_list = glacier::discover("./ices")
9+
.unwrap()
10+
.into_iter()
11+
.map(|ice| ice.id())
12+
.collect::<Vec<_>>();
13+
tested_issue_list.sort_unstable();
14+
tested_issue_list.dedup();
15+
16+
let mut untesteds =
17+
crate::github::get_labeled_issues(&config, "rust-lang/rust", "I-ICE".to_string()).unwrap();
18+
untesteds.retain(|i| !tested_issue_list.contains(&i.number));
19+
for untested in untesteds {
20+
let mut reproduction = Vec::new();
21+
let mut in_code_section = false;
22+
let mut in_code = false;
23+
let mut has_main = false;
24+
for line in untested.body.lines() {
25+
if in_code {
26+
if line.starts_with("```") {
27+
in_code = false;
28+
continue;
29+
}
30+
if line.starts_with("fn main") {
31+
has_main = true;
32+
}
33+
reproduction.push(line);
34+
}
35+
if line.starts_with("### Code") {
36+
in_code_section = true;
37+
} else if line.starts_with('#') && in_code_section {
38+
in_code_section = false;
39+
}
40+
if (line.starts_with("```rust") || line.starts_with("```Rust")) && in_code_section {
41+
in_code = true;
42+
}
43+
}
44+
if reproduction.is_empty() {
45+
continue;
46+
}
47+
if !has_main {
48+
reproduction.push("");
49+
reproduction.push("fn main() {}");
50+
}
51+
std::fs::write(
52+
format!("./ices/{}.rs", untested.number),
53+
reproduction.join("\n"),
54+
)
55+
.unwrap();
56+
}
57+
58+
let failed = glacier::test_all()
59+
.unwrap()
60+
.filter(|res| {
61+
if let Ok(test) = res {
62+
test.outcome() != glacier::Outcome::ICEd
63+
} else {
64+
true
65+
}
66+
})
67+
.collect::<Result<Vec<glacier::TestResult>, _>>()
68+
.unwrap();
69+
70+
for result in &failed {
71+
std::fs::remove_file(result.path()).unwrap();
72+
}
73+
}

0 commit comments

Comments
 (0)