diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 0b20057..f4ca375 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1163,7 +1163,6 @@ dependencies = [ "anyhow", "chrono", "clap", - "dotenvy", "reqwest", "serde", "serde_json", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 21a0f2b..0766fa4 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -15,7 +15,6 @@ repository = "https://git.b4l.co.th/B4L/Northern-Thailand-Ping-River-Monitor" anyhow = "1" chrono = { version = "0.4", default-features = false, features = ["std", "clock", "serde"] } clap = { version = "4", features = ["derive"] } -dotenvy = "0.15" # native-tls (OpenSSL on Linux, SChannel on Windows), not rustls: app.rid.go.th (dams) # offers only TLS 1.2 CBC suites (ECDHE-RSA-AES256-SHA384), which rustls refuses. reqwest = { version = "0.12", default-features = false, features = ["native-tls", "json"] } diff --git a/rust/README.md b/rust/README.md index 80f6b99..58c1097 100644 --- a/rust/README.md +++ b/rust/README.md @@ -25,7 +25,10 @@ ping-collector check-db # connect, create missing tables, row counts ``` Configuration is the Python app's `.env` (read from the working directory, or -`--env-file`); real environment variables win. Used keys: +`--env-file`) with python-dotenv's rules, verified on 614 generated inputs +(`collector/testdata/`): an unparsable line is skipped with a warning giving +only its line number, never its value. Variables already set (e.g. by systemd's +`EnvironmentFile=`) win. Used keys: `POSTGRES_CONNECTION_STRING` (or `POSTGRES_HOST/PORT/DB/USER/PASSWORD`), `RID_POLL_OFFSET_MINUTES` (5), `RID_RETRY_MINUTES` (10), `GAP_FILL_DAYS_ON_START` (14), `ENABLE_HII_COLLECTION`, diff --git a/rust/collector/Cargo.toml b/rust/collector/Cargo.toml index 07e5fdd..f6bef2d 100644 --- a/rust/collector/Cargo.toml +++ b/rust/collector/Cargo.toml @@ -12,7 +12,6 @@ repository.workspace = true anyhow.workspace = true chrono.workspace = true clap.workspace = true -dotenvy.workspace = true reqwest.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/rust/collector/src/envfile.rs b/rust/collector/src/envfile.rs new file mode 100644 index 0000000..1a5248c --- /dev/null +++ b/rust/collector/src/envfile.rs @@ -0,0 +1,488 @@ +//! `.env` loading with python-dotenv 1.1.1 semantics (`load_dotenv()`: +//! interpolate `${VAR}` / `${VAR:-default}`, never override variables that +//! are already set). +//! +//! The Python app reads the same file, so the two must agree on every value. +//! dotenvy (the usual crate) is stricter: a stray `'` or `"` inside an +//! unquoted value makes it swallow the rest of the file and abort, and its +//! error message echoes the line, password included. Here an unparsable +//! statement is skipped with a warning naming only its line number, exactly +//! like python-dotenv. Port of dotenv/parser.py + variables.py; the tests +//! below are python-dotenv's own output for the same inputs. + +use std::collections::HashMap; +use std::path::Path; + +/// Python's `\s` (str.isspace), which includes \x1c-\x1f. +fn is_ws(c: char) -> bool { + c.is_whitespace() || ('\u{1c}'..='\u{1f}').contains(&c) +} +/// `[^\S\r\n]`: whitespace other than line breaks. +fn is_hspace(c: char) -> bool { + is_ws(c) && c != '\r' && c != '\n' +} + +struct Reader { + s: Vec, + pos: usize, +} + +struct Fail; + +impl Reader { + fn peek(&self) -> Option { + self.s.get(self.pos).copied() + } + fn at(&self, i: usize) -> Option { + self.s.get(i).copied() + } + fn skip_while(&mut self, f: impl Fn(char) -> bool) { + while self.peek().is_some_and(&f) { + self.pos += 1; + } + } + fn starts_with(&self, lit: &str) -> bool { + lit.chars() + .enumerate() + .all(|(i, c)| self.at(self.pos + i) == Some(c)) + } + fn line_of(&self, pos: usize) -> usize { + // python-dotenv counts \r\n, \n and \r as one newline each + let mut line = 1; + let mut i = 0; + while i < pos { + match self.s[i] { + '\r' if self.at(i + 1) == Some('\n') && i + 1 < pos => { + line += 1; + i += 1; + } + '\r' | '\n' => line += 1, + _ => {} + } + i += 1; + } + line + } + + /// `(?:export[^\S\r\n]+)?` + fn export(&mut self) { + if self.starts_with("export") && self.at(self.pos + 6).is_some_and(is_hspace) { + self.pos += 6; + self.skip_while(is_hspace); + } + } + + /// `'([^']+)'` or `([^=\#\s]+)`; None for a comment line. + fn key(&mut self) -> Result, Fail> { + match self.peek() { + Some('#') => Ok(None), + Some('\'') => { + let start = self.pos + 1; + let mut i = start; + while self.at(i).is_some_and(|c| c != '\'') { + i += 1; + } + if i == start || self.at(i) != Some('\'') { + return Err(Fail); + } + self.pos = i + 1; + Ok(Some(self.s[start..i].iter().collect())) + } + _ => { + let start = self.pos; + self.skip_while(|c| c != '=' && c != '#' && !is_ws(c)); + if self.pos == start { + return Err(Fail); + } + Ok(Some(self.s[start..self.pos].iter().collect())) + } + } + } + + /// `Q((?:\\Q|[^Q])*)Q` with regex backtracking: the greedy scan stops at + /// an unescaped quote; at end of input the last `\Q` is re-read as a + /// literal backslash followed by the closing quote. + fn quoted(&mut self, q: char) -> Result { + let start = self.pos + 1; + let mut i = start; + let mut last_escaped_quote = None; + loop { + match self.at(i) { + None => { + let Some(bs) = last_escaped_quote else { + return Err(Fail); + }; + self.pos = bs + 2; + return Ok(self.s[start..=bs].iter().collect()); + } + Some(c) if c == q => { + self.pos = i + 1; + return Ok(self.s[start..i].iter().collect()); + } + Some('\\') if self.at(i + 1) == Some(q) => { + last_escaped_quote = Some(i); + i += 2; + } + Some(_) => i += 1, + } + } + } + + /// parse_value + fn value(&mut self) -> Result { + match self.peek() { + Some('\'') => Ok(decode_escapes(&self.quoted('\'')?, "\\'")), + Some('"') => Ok(decode_escapes(&self.quoted('"')?, "\\'\"abfnrtv")), + None | Some('\n') | Some('\r') => Ok(String::new()), + Some(_) => { + let start = self.pos; + self.skip_while(|c| c != '\r' && c != '\n'); + let part: Vec = self.s[start..self.pos].to_vec(); + Ok(strip_inline_comment(&part)) + } + } + } + + /// `(?:[^\S\r\n]*#[^\r\n]*)?` then `[^\S\r\n]*(?:\r\n|\n|\r|$)` + fn comment_and_eol(&mut self) -> Result<(), Fail> { + let save = self.pos; + self.skip_while(is_hspace); + if self.peek() == Some('#') { + self.skip_while(|c| c != '\r' && c != '\n'); + } else { + self.pos = save; + } + self.skip_while(is_hspace); + match self.peek() { + None => Ok(()), + Some('\r') => { + self.pos += if self.at(self.pos + 1) == Some('\n') { + 2 + } else { + 1 + }; + Ok(()) + } + Some('\n') => { + self.pos += 1; + Ok(()) + } + Some(_) => Err(Fail), + } + } + + /// `[^\r\n]*(?:\r|\n|\r\n)?` (the `\r` alternative wins for `\r\n`) + fn rest_of_line(&mut self) { + self.skip_while(|c| c != '\r' && c != '\n'); + if self.peek().is_some() { + self.pos += 1; + } + } +} + +/// Unquoted values: `re.sub(r"\s+#.*", "", part).rstrip()`. +fn strip_inline_comment(part: &[char]) -> String { + let mut end = part.len(); + let mut i = 0; + while i < part.len() { + if is_ws(part[i]) { + let mut j = i; + while j < part.len() && is_ws(part[j]) { + j += 1; + } + if part.get(j) == Some(&'#') { + end = i; + break; + } + i = j; + } else { + i += 1; + } + } + let kept: String = part[..end].iter().collect(); + kept.trim_end_matches(is_ws).to_string() +} + +/// `\\[]` -> codecs 'unicode-escape' of that pair. +fn decode_escapes(s: &str, allowed: &str) -> String { + let mut out = String::with_capacity(s.len()); + let mut chars = s.chars().peekable(); + while let Some(c) = chars.next() { + if c == '\\' + && let Some(&n) = chars.peek() + && allowed.contains(n) + { + chars.next(); + out.push(match n { + 'a' => '\u{7}', + 'b' => '\u{8}', + 'f' => '\u{c}', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + 'v' => '\u{b}', + other => other, // \\ \' \" + }); + } else { + out.push(c); + } + } + out +} + +/// Statements in file order: (key, value or None for `KEY` without `=`). +/// Unparsable statements are reported as line numbers in `errors`. +pub fn parse(content: &str) -> (Vec<(String, Option)>, Vec) { + let mut r = Reader { + s: content.chars().collect(), + pos: 0, + }; + let mut out = Vec::new(); + let mut errors = Vec::new(); + while r.pos < r.s.len() { + r.skip_while(is_ws); // _multiline_whitespace + if r.pos >= r.s.len() { + break; + } + let statement_start = r.pos; + let binding = (|| { + r.export(); + let key = r.key()?; + r.skip_while(is_hspace); + let value = if r.peek() == Some('=') { + r.pos += 1; + r.skip_while(is_hspace); + Some(r.value()?) + } else { + None + }; + r.comment_and_eol()?; + Ok::<_, Fail>(key.map(|k| (k, value))) + })(); + match binding { + Ok(Some(kv)) => out.push(kv), + Ok(None) => {} + Err(Fail) => { + errors.push(r.line_of(statement_start)); + r.rest_of_line(); + } + } + } + (out, errors) +} + +/// `${NAME}` / `${NAME:-default}` expansion, python-dotenv `parse_variables`. +fn interpolate(value: &str, lookup: &impl Fn(&str) -> Option) -> String { + let v: Vec = value.chars().collect(); + let mut out = String::new(); + let mut i = 0; + while i < v.len() { + if v[i] == '$' && v.get(i + 1) == Some(&'{') { + let mut j = i + 2; + while j < v.len() && v[j] != '}' && v[j] != ':' { + j += 1; + } + let name: String = v[i + 2..j].iter().collect(); + let mut default = None; + let mut k = j; + if v.get(j) == Some(&':') && v.get(j + 1) == Some(&'-') { + k = j + 2; + while k < v.len() && v[k] != '}' { + k += 1; + } + default = Some(v[j + 2..k].iter().collect::()); + } + if v.get(k) == Some(&'}') { + out.push_str(&lookup(&name).or(default).unwrap_or_default()); + i = k + 1; + continue; + } + } + out.push(v[i]); + i += 1; + } + out +} + +/// python-dotenv `dotenv_values` with override=False: what `load_dotenv()` +/// would set. `env` looks up the process environment. +pub fn resolve( + content: &str, + env: impl Fn(&str) -> Option, +) -> (Vec<(String, Option)>, Vec) { + let (raw, errors) = parse(content); + let mut resolved: Vec<(String, Option)> = Vec::new(); + let mut by_key: HashMap = HashMap::new(); + for (key, value) in raw { + let result = value.map(|v| { + // override=False: the process environment wins over the file + let lookup = |name: &str| { + env(name).or_else(|| { + by_key + .get(name) + .and_then(|&i| resolved[i].1.clone()) + .or_else(|| { + by_key.contains_key(name).then(String::new) // KEY without '=' + }) + }) + }; + interpolate(&v, &lookup) + }); + match by_key.get(&key) { + Some(&i) => resolved[i].1 = result, + None => { + by_key.insert(key.clone(), resolved.len()); + resolved.push((key, result)); + } + } + } + (resolved, errors) +} + +/// `load_dotenv(path)`: set every variable that is not set yet. Must run +/// before any other thread exists (`set_var`). Returns how many were set. +pub fn load(path: &Path) -> std::io::Result { + let content = std::fs::read_to_string(path)?; + let (values, errors) = resolve(&content, |k| std::env::var(k).ok()); + for line in errors { + eprintln!( + "warning: {}: could not parse the statement on line {line}; skipped (as python-dotenv does)", + path.display() + ); + } + let mut set = 0; + for (key, value) in values { + if std::env::var_os(&key).is_some() { + continue; + } + if let Some(value) = value { + // SAFETY: called from main() before the tokio runtime (or any + // other thread) is started. + unsafe { std::env::set_var(&key, value) }; + set += 1; + } + } + Ok(set) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn vals(content: &str) -> Vec<(String, Option)> { + resolve(content, |k| { + (k == "HOME_FROM_ENV").then(|| "/home/x".into()) + }) + .0 + } + fn kv(k: &str, v: &str) -> (String, Option) { + (k.into(), Some(v.into())) + } + + // Expected values below are python-dotenv 1.1.1 `DotEnv(stream, + // interpolate=True, override=False).dict()` for the same input. + + #[test] + fn stray_quotes_in_unquoted_values_are_literal() { + assert_eq!( + vals("A=abc'def\nB=x\"y\nC=1\n"), + vec![kv("A", "abc'def"), kv("B", "x\"y"), kv("C", "1")] + ); + } + + #[test] + fn unterminated_quote_skips_only_that_line() { + let (v, errors) = resolve("A=1\nPOSTGRES_PASSWORD='abc\nB=2\n", |_| None); + assert_eq!(v, vec![kv("A", "1"), kv("B", "2")]); + assert_eq!(errors, vec![2]); + } + + #[test] + fn whitespace_comments_and_export() { + assert_eq!( + vals(" export A = spaced value # comment\nB=a#b\n# c\n\nC= \nD\n"), + vec![ + kv("A", "spaced value"), + kv("B", "a#b"), + kv("C", ""), + ("D".into(), None) + ] + ); + } + + #[test] + fn quoted_values_and_escapes() { + assert_eq!( + vals("A='x\\'y'\nB=\"l1\\nl2\\t\\\"q\\\"\"\nC='multi\nline'\nD='a\\\\b'\n"), + vec![ + kv("A", "x'y"), + kv("B", "l1\nl2\t\"q\""), + kv("C", "multi\nline"), + kv("D", "a\\b") + ] + ); + } + + #[test] + fn trailing_escaped_quote_backtracks_like_the_regex() { + // python: '((?:\\'|[^'])*)' on "'ab\'" matches with value "ab\" + assert_eq!(vals("A='ab\\'"), vec![kv("A", "ab\\")]); + } + + #[test] + fn junk_after_a_quoted_value_is_an_error() { + let (v, errors) = resolve("A='x'y\nB=1\n", |_| None); + assert_eq!(v, vec![kv("B", "1")]); + assert_eq!(errors, vec![1]); + } + + #[test] + fn interpolation_prefers_the_environment() { + assert_eq!( + vals( + "HOME_FROM_ENV=file\nA=${HOME_FROM_ENV}/x\nB=${A}-${MISSING:-dflt}-${NOPE}\nC=$A ${A:x}\n" + ), + vec![ + kv("HOME_FROM_ENV", "file"), + kv("A", "/home/x/x"), + kv("B", "/home/x/x-dflt-"), + kv("C", "$A ${A:x}") + ] + ); + } + + /// 614 inputs (the cases above + 600 random ones built from quotes, + /// escapes, comments, `${}` and odd separators/line ends) with + /// python-dotenv 1.1.1's result; regenerate with testdata/gen_envfile_cases.py. + #[test] + fn matches_python_dotenv_on_generated_cases() { + let fixture: serde_json::Value = + serde_json::from_str(include_str!("../testdata/envfile_python_dotenv.json")).unwrap(); + let cases = fixture["cases"].as_array().unwrap(); + assert!(cases.len() > 600); + for case in cases { + let input = case["input"].as_str().unwrap(); + let want: Vec<(String, Option)> = case["expected"] + .as_array() + .unwrap() + .iter() + .map(|kv| { + ( + kv[0].as_str().unwrap().to_string(), + kv[1].as_str().map(str::to_string), + ) + }) + .collect(); + let got = resolve(input, |k| (k == "HOME_FROM_ENV").then(|| "/home/x".into())).0; + assert_eq!(got, want, "input {input:?}"); + } + } + + #[test] + fn crlf_and_duplicate_keys() { + assert_eq!( + vals("A=1\r\nB=2\r\nA=3\r\n"), + vec![kv("A", "3"), kv("B", "2")] + ); + } +} diff --git a/rust/collector/src/main.rs b/rust/collector/src/main.rs index f8e4861..3f1db61 100644 --- a/rust/collector/src/main.rs +++ b/rust/collector/src/main.rs @@ -10,6 +10,7 @@ mod dams; mod db; #[cfg(test)] mod db_tests; +mod envfile; mod hii; mod rain; mod rid; @@ -24,8 +25,8 @@ use std::path::PathBuf; #[derive(Parser)] #[command(version, about)] struct Cli { - /// .env file to load (default: ./.env when present). Real environment - /// variables take precedence. + /// .env file to load (default: ./.env when present), read like python-dotenv; + /// variables already in the environment take precedence. #[arg(long, global = true)] env_file: Option, #[command(subcommand)] @@ -48,15 +49,23 @@ enum Command { CheckDb, } -#[tokio::main] -async fn main() -> Result<()> { +fn main() -> Result<()> { let cli = Cli::parse(); + // .env before the runtime starts: setting variables is only sound while + // the process is single-threaded. match &cli.env_file { Some(path) => { - dotenvy::from_path(path)?; + envfile::load(path).map_err(|e| anyhow::anyhow!("{}: {e}", path.display()))?; } None => { - dotenvy::dotenv().ok(); + // Under systemd the variables come from EnvironmentFile=; an + // unreadable ./.env is not fatal there. + let path = std::path::Path::new(".env"); + if path.exists() + && let Err(e) = envfile::load(path) + { + eprintln!("warning: .env not loaded: {e}"); + } } } let level = std::env::var("RUST_LOG") @@ -68,7 +77,13 @@ async fn main() -> Result<()> { ))) .with_target(false) .init(); + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build()? + .block_on(run(cli)) +} +async fn run(cli: Cli) -> Result<()> { let cfg = config::Config::from_env()?; tracing::info!( "ping-collector {} -> {}", diff --git a/rust/collector/testdata/envfile_python_dotenv.json b/rust/collector/testdata/envfile_python_dotenv.json new file mode 100644 index 0000000..74e3cbe --- /dev/null +++ b/rust/collector/testdata/envfile_python_dotenv.json @@ -0,0 +1,6809 @@ +{ +"python_dotenv": "1.1.1", +"env": { +"HOME_FROM_ENV": "/home/x" +}, +"cases": [ +{ +"input": "A=abc'def\nB=x\"y\nC=1\n", +"expected": [ +[ +"A", +"abc'def" +], +[ +"B", +"x\"y" +], +[ +"C", +"1" +] +] +}, +{ +"input": "A=1\nPOSTGRES_PASSWORD='abc\nB=2\n", +"expected": [ +[ +"A", +"1" +], +[ +"B", +"2" +] +] +}, +{ +"input": "A=1\nPOSTGRES_PASSWORD= \nB=2\n", +"expected": [ +[ +"A", +"1" +], +[ +"POSTGRES_PASSWORD", +"" +], +[ +"B", +"2" +] +] +}, +{ +"input": "POSTGRES_PASSWORD=\"ab'c\nB=2\n", +"expected": [ +[ +"B", +"2" +] +] +}, +{ +"input": " export A = spaced value # comment\nB=a#b\n# c\n\nC= \nD\n", +"expected": [ +[ +"A", +"spaced value" +], +[ +"B", +"a#b" +], +[ +"C", +"" +], +[ +"D", +null +] +] +}, +{ +"input": "A='x\\'y'\nB=\"l1\\nl2\\t\\\"q\\\"\"\nC='multi\nline'\nD='a\\\\b'\n", +"expected": [ +[ +"A", +"x'y" +], +[ +"B", +"l1\nl2\t\"q\"" +], +[ +"C", +"multi\nline" +], +[ +"D", +"a\\b" +] +] +}, +{ +"input": "A='ab\\'", +"expected": [ +[ +"A", +"ab\\" +] +] +}, +{ +"input": "A='x'y\nB=1\n", +"expected": [ +[ +"B", +"1" +] +] +}, +{ +"input": "HOME_FROM_ENV=file\nA=${HOME_FROM_ENV}/x\nB=${A}-${MISSING:-dflt}-${NOPE}\nC=$A ${A:x}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"file" +], +[ +"A", +"/home/x/x" +], +[ +"B", +"/home/x/x-dflt-" +], +[ +"C", +"$A ${A:x}" +] +] +}, +{ +"input": "A=1\r\nB=2\r\nA=3\r\n", +"expected": [ +[ +"A", +"3" +], +[ +"B", +"2" +] +] +}, +{ +"input": "C= # c\nD=#x\nE= #x\n", +"expected": [ +[ +"C", +"# c" +], +[ +"D", +"#x" +], +[ +"E", +"#x" +] +] +}, +{ +"input": "A#B=1\nexport\nexportA=2\n'q k'=3\n", +"expected": [ +[ +"A", +null +], +[ +"export", +null +], +[ +"exportA", +"2" +], +[ +"q k", +"3" +] +] +}, +{ +"input": "\ufeffA=bom\n", +"expected": [ +[ +"\ufeffA", +"bom" +] +] +}, +{ +"input": "A=\u00e9\u0e01\u0e02 # thai\n", +"expected": [ +[ +"A", +"\u00e9\u0e01\u0e02" +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\t\n A= \r", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"" +] +] +}, +{ +"input": "#A=x y\r\nB=$A\r\n#A=x y\nB==abc\"x y\r\n#A=='${HOME_FROM_ENV}' \n", +"expected": [ +[ +"B", +"=abc\"x y" +] +] +}, +{ +"input": "\nHOME_FROM_ENV\t=\t\\n${B:-d}\\\"HOME_FROM_ENV\t=\t\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\\nd\\\"HOME_FROM_ENV\t=" +] +] +}, +{ +"input": "C\t=\t\nA= '\r", +"expected": [ +[ +"C", +"" +] +] +}, +{ +"input": " A=\r\n A=\\n\r#A\"q\"\r\nE==\\'\\'${A}x y", +"expected": [ +[ +"A", +"\\n" +], +[ +"E", +"=\\'\\'\\nx y" +] +] +}, +{ +"input": "D = \"abc\n'A B'=x y #${#A = x y\"q\"'q'\rB${B:-d}##\r\n", +"expected": [ +[ +"B${B:-d}", +null +] +] +}, +{ +"input": "'A B' = '${HOME_FROM_ENV}'${:-z}\r'A B'= ${${:-z}'q'${", +"expected": [ +[ +"A B", +"z'q'${" +] +] +}, +{ +"input": " \r#A= '\u0e01\n", +"expected": [] +}, +{ +"input": "C = ${A}\rC= \r#A='${x y\r\n A==${:-z}\u0e01''\n", +"expected": [ +[ +"C", +"" +], +[ +"A", +"=z\u0e01''" +] +] +}, +{ +"input": "B\\n${${#", +"expected": [ +[ +"B\\n${${", +null +] +] +}, +{ +"input": "#A${A}\r\nC==${:-z}\n#A = '\\\t\nexport A=}${B:-d}\\\\n", +"expected": [ +[ +"C", +"=z" +], +[ +"A", +"}d\\\\n" +] +] +}, +{ +"input": "A B = ${HOME_FROM_ENV}\u0e01${A}\r \rB' #c #cabc\nHOME_FROM_ENV=x y\r\n", +"expected": [ +[ +"B'", +null +], +[ +"HOME_FROM_ENV", +"x y" +] +] +}, +{ +"input": "A\t=\t\rA= abc", +"expected": [ +[ +"A", +"abc" +] +] +}, +{ +"input": "C==\u0e01$Aabc", +"expected": [ +[ +"C", +"=\u0e01$Aabc" +] +] +}, +{ +"input": "Aabc #c}\rE= }\"\"q\"E = \r", +"expected": [ +[ +"Aabc", +null +], +[ +"E", +"}\"\"q\"E =" +] +] +}, +{ +"input": "'A B'==${A}\r\nD=$A#${:-z}\\''A B'= 'q'${:-z}${B:-d}\\\"\r\n", +"expected": [ +[ +"A B", +"=" +], +[ +"D", +"$A#z\\''A B'= 'q'zd\\\"" +] +] +}, +{ +"input": "export A= \\'\r'A B'\r\nexport A\t=\t${\nC = ${A}\r", +"expected": [ +[ +"A", +"${" +], +[ +"A B", +null +], +[ +"C", +"${" +] +] +}, +{ +"input": "B= \n", +"expected": [ +[ +"B", +"" +] +] +}, +{ +"input": "Dx y \n\n", +"expected": [] +}, +{ +"input": " \rexport A = \u0e01$A", +"expected": [ +[ +"A", +"\u0e01$A" +] +] +}, +{ +"input": "D=\\n\r\nexport A\t=\t\\'${HOME_FROM_ENV}\\\"'q'\rD${HOME_FROM_ENV}\r\n", +"expected": [ +[ +"D", +"\\n" +], +[ +"A", +"\\'/home/x\\\"'q'" +], +[ +"D${HOME_FROM_ENV}", +null +] +] +}, +{ +"input": "B = \n", +"expected": [ +[ +"B", +"" +] +] +}, +{ +"input": "#A==$A'\nHOME_FROM_ENV = #c B=\nA = ${B:-d}", +"expected": [ +[ +"HOME_FROM_ENV", +"#c B=" +], +[ +"A", +"d" +] +] +}, +{ +"input": "B=' \r\nA B\\\"${\u0e01\\nA=\u0e01${:-z}\t\r", +"expected": [] +}, +{ +"input": "B = \\abc #c${B:-d}\r\nA B= }\\'\r\nD=\"x y'q'\nHOME_FROM_ENV==\\n$A\nB\t=\t\r\n", +"expected": [ +[ +"B", +"" +], +[ +"HOME_FROM_ENV", +"=\\n$A" +] +] +}, +{ +"input": "A\"q\" Ax y\n'A B'= 'q'\u0e01\r\n", +"expected": [] +}, +{ +"input": "D= \nC= '\n A\t=\tabc\"q\"\r", +"expected": [ +[ +"D", +"" +], +[ +"A", +"abc\"q\"" +] +] +}, +{ +"input": "A B==\r\nE\\\n A==\\'\\\" \t\rA B==\r", +"expected": [ +[ +"E\\", +null +], +[ +"A", +"=\\'\\\"" +] +] +}, +{ +"input": "\r\n", +"expected": [] +}, +{ +"input": "'A B'==${HOME_FROM_ENV}\"q\"\"q\"${\r\n'A B'\\\r\n# comment\nE\t=\t${:-z}abc\r", +"expected": [ +[ +"A B", +"=/home/x\"q\"\"q\"${" +], +[ +"E", +"zabc" +] +] +}, +{ +"input": " A==\\\"\"abc\r A = ${HOME_FROM_ENV}'\"A B==${HOME_FROM_ENV}# \nA= A== \\\"\\'", +"expected": [ +[ +"A", +"A== \\\"\\'" +] +] +}, +{ +"input": " A= \nA B\\", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "D==\u0e01 ${B:-d}\\'\n'A B'= \" \r\nC #c\t\n#A = ", +"expected": [ +[ +"D", +"=\u0e01 d\\'" +], +[ +"C", +null +] +] +}, +{ +"input": " \r", +"expected": [] +}, +{ +"input": "A\t=\t#\\'\r\n", +"expected": [ +[ +"A", +"#\\'" +] +] +}, +{ +"input": "D=='\r\n", +"expected": [ +[ +"D", +"='" +] +] +}, +{ +"input": "D\t=\tabc${B:-d}\"${A}\r\n# comment", +"expected": [ +[ +"D", +"abcd\"" +] +] +}, +{ +"input": "C\t=\t \\\"\\n\rHOME_FROM_ENV\r\n", +"expected": [ +[ +"C", +"\\\"\\n" +], +[ +"HOME_FROM_ENV", +null +] +] +}, +{ +"input": "'A B' = }}\\nD\t=\t${B:-d}x y'q'}", +"expected": [ +[ +"A B", +"}}\\nD\t=\tdx y'q'}" +] +] +}, +{ +"input": "export A = ''\\'HOME_FROM_ENV = \u0e01\r\n\n A\t=\t", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "#A\t=\t\"${A}'q'\n'A B'\t=\t\"q\"'#A${export A${}${", +"expected": [] +}, +{ +"input": "C=abc'q'\r", +"expected": [ +[ +"C", +"abc'q'" +] +] +}, +{ +"input": "B = $A'abc\u0e01\rC=#\\n\"q\"\r\n", +"expected": [ +[ +"B", +"$A'abc\u0e01" +], +[ +"C", +"#\\n\"q\"" +] +] +}, +{ +"input": " A= $A'\"q\"\rA = '\texport A\t=\t\nA= }''q' #c", +"expected": [ +[ +"A", +"$A'\"q\"" +] +] +}, +{ +"input": "A\t=\t\\\"\\n'\r # c ' \" A=='q' #c\r\n", +"expected": [ +[ +"A", +"\\\"\\n'" +] +] +}, +{ +"input": "E\t=\t$A\"${HOME_FROM_ENV}\r\n'A B'=='q''q'\r", +"expected": [ +[ +"E", +"$A\"/home/x" +], +[ +"A B", +"='q''q'" +] +] +}, +{ +"input": "D = \nD = abcabc", +"expected": [ +[ +"D", +"abcabc" +] +] +}, +{ +"input": "A= \\n'x y\"q\"C\t=\t #c\"q\"\rB==\r", +"expected": [ +[ +"A", +"\\n'x y\"q\"C\t=" +], +[ +"B", +"=" +] +] +}, +{ +"input": "E\r\n", +"expected": [ +[ +"E", +null +] +] +}, +{ +"input": "A\n", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "\r\n'A B' = }${:-z}${A}\"\n", +"expected": [ +[ +"A B", +"}z\"" +] +] +}, +{ +"input": "D\t=\t${\r\nC='q'\t''q'\r", +"expected": [ +[ +"D", +"${" +] +] +}, +{ +"input": "#A= \nD=# #c\r# comment\rHOME_FROM_ENV\t=\t #c'}\"\r", +"expected": [ +[ +"D", +"#" +], +[ +"HOME_FROM_ENV", +"#c'}\"" +] +] +}, +{ +"input": "D=abc${:-z}'q''q'\r'A B'=\r\n A\t=\tE\rHOME_FROM_ENV\t=\t'\r\n", +"expected": [ +[ +"D", +"abcz'q''q'" +], +[ +"A B", +"" +], +[ +"A", +"E" +] +] +}, +{ +"input": "E==\\n #c\\n\rHOME_FROM_ENV${\"\r\nHOME_FROM_ENV==\"q\"\\ #c\\'\rC = ${B:-d}${A}${'q'\n", +"expected": [ +[ +"E", +"=\\n" +], +[ +"HOME_FROM_ENV${\"", +null +], +[ +"HOME_FROM_ENV", +"=\"q\"\\" +], +[ +"C", +"d${'q'" +] +] +}, +{ +"input": "A\t=\tx y\nexport A=\nexport A\t=\t}}'q'\r\nHOME_FROM_ENV\t=\t x y${HOME_FROM_ENV}", +"expected": [ +[ +"A", +"}}'q'" +], +[ +"HOME_FROM_ENV", +"x y/home/x" +] +] +}, +{ +"input": "A B\t=\t #c\"\n D\u0e01'q'\r\nE= abc #c\r", +"expected": [ +[ +"D\u0e01'q'", +null +], +[ +"E", +"abc" +] +] +}, +{ +"input": "\r", +"expected": [] +}, +{ +"input": "E= #\rC== #c\"\u0e01\n", +"expected": [ +[ +"E", +"#" +], +[ +"C", +"=" +] +] +}, +{ +"input": "#A\\'\nA B\t=\t\r\n#A\\# comment\r\nE\t'q'\u0e01${\r\n", +"expected": [] +}, +{ +"input": "A==${A}\r\nHOME_FROM_ENV= $A${B:-d}\r\n", +"expected": [ +[ +"A", +"=" +], +[ +"HOME_FROM_ENV", +"$Ad" +] +] +}, +{ +"input": "export A = abc\\${HOME_FROM_ENV}B\"\\\"abc\r\n", +"expected": [ +[ +"A", +"abc\\/home/xB\"\\\"abc" +] +] +}, +{ +"input": "export A = \r\nA B = $A\n", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "B=\\'${\r'A B' = abc\\x y}\rHOME_FROM_ENV = \\\"\rA B\t=\t\\\rHOME_FROM_ENV= \r", +"expected": [ +[ +"B", +"\\'${" +], +[ +"A B", +"abc\\x y}" +], +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": " \n\r\nHOME_FROM_ENV==\u0e01#\n# comment\n", +"expected": [ +[ +"HOME_FROM_ENV", +"=\u0e01#" +] +] +}, +{ +"input": "D=$Aabcx y\\\"\nE\t=\t\r\nBx y'A B' = \u0e01${\\\"\r\n", +"expected": [ +[ +"D", +"$Aabcx y\\\"" +], +[ +"E", +"" +] +] +}, +{ +"input": "D=\\'\\$A\nexport A= \\n", +"expected": [ +[ +"D", +"\\'\\$A" +], +[ +"A", +"\\n" +] +] +}, +{ +"input": "#A=${:-z}${HOME_FROM_ENV}\\\rE==\\\"${\\\"\r A\nB=\u0e01\r\n", +"expected": [ +[ +"E", +"=\\\"${\\\"" +], +[ +"A", +null +], +[ +"B", +"\u0e01" +] +] +}, +{ +"input": "A\t=\t\\\"${HOME_FROM_ENV}''\n#A==", +"expected": [ +[ +"A", +"\\\"/home/x''" +] +] +}, +{ +"input": " A= #A=\\\"${\r\nE\t=\t#''\r\n'A B'=\n \n", +"expected": [ +[ +"A", +"#A=\\\"${" +], +[ +"E", +"#''" +], +[ +"A B", +"" +] +] +}, +{ +"input": "B\"q\"\\nC=\\'\\n", +"expected": [ +[ +"B\"q\"\\nC", +"\\'\\n" +] +] +}, +{ +"input": "D=\\\"\\'x y\\''A B' = \\n#${B:-d}", +"expected": [ +[ +"D", +"\\\"\\'x y\\''A B' = \\n#d" +] +] +}, +{ +"input": "export A\t=\t\"q\"\r A}", +"expected": [ +[ +"A", +"q" +], +[ +"A}", +null +] +] +}, +{ +"input": " A= \\n${HOME_FROM_ENV}$A\\'\r", +"expected": [ +[ +"A", +"\\n/home/x$A\\'" +] +] +}, +{ +"input": "C= $A${B:-d}\\\r\n", +"expected": [ +[ +"C", +"$Ad\\" +] +] +}, +{ +"input": " A==\n", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": " A==\r\n", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "E= abc \rB\t=\t", +"expected": [ +[ +"E", +"abc" +], +[ +"B", +"" +] +] +}, +{ +"input": "A B = x y\"q\"\n A= ${${A}\\\"\\n", +"expected": [ +[ +"A", +"\\\"\\n" +] +] +}, +{ +"input": "B==A B\nB = abc\u0e01\nexport A${\n", +"expected": [ +[ +"B", +"abc\u0e01" +], +[ +"A${", +null +] +] +}, +{ +"input": "C='#${A}\rC= ${:-z}\n A$A\"q\"${", +"expected": [ +[ +"C", +"z" +], +[ +"A$A\"q\"${", +null +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\t\\n\\'\r\nHOME_FROM_ENV==\\'abcexport A${A}#$A\r\n'A B'A B= ${:-z}'\r", +"expected": [ +[ +"HOME_FROM_ENV", +"=\\'abcexport A#$A" +] +] +}, +{ +"input": "A B= \r\nexport A#\t$A${HOME_FROM_ENV}\r", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": " A= \rA\t=\t${HOME_FROM_ENV}\r\n", +"expected": [ +[ +"A", +"/home/x" +] +] +}, +{ +"input": " AD==\nA B=\u0e01'abc}\r\nB= \\n export A= \n", +"expected": [ +[ +"AD", +"=" +], +[ +"B", +"\\n export A=" +] +] +}, +{ +"input": "HOME_FROM_ENV=${HOME_FROM_ENV} #c\u0e01\r\nA = \\\" \"q\"\"\n# comment\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"/home/x" +], +[ +"A", +"\\\" \"q\"\"" +] +] +}, +{ +"input": " A\t=\tabc\t\r\n#A==#\r", +"expected": [ +[ +"A", +"abc" +] +] +}, +{ +"input": "C=", +"expected": [ +[ +"C", +"" +] +] +}, +{ +"input": "HOME_FROM_ENV=\\'\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\\'" +] +] +}, +{ +"input": "C== \"q\"# A==\t\"x y'A B'\t=\t #cx y$A\r", +"expected": [ +[ +"C", +"= \"q\"# A==\t\"x y'A B'\t=" +] +] +}, +{ +"input": "D==\"abc\u0e01\r\n\rHOME_FROM_ENV=\\\" x yabc\r\nA==\r\n", +"expected": [ +[ +"D", +"=\"abc\u0e01" +], +[ +"HOME_FROM_ENV", +"\\\" x yabc" +], +[ +"A", +"=" +] +] +}, +{ +"input": "E=\nD= #${B:-d}abc${HOME_FROM_ENV}", +"expected": [ +[ +"E", +"" +], +[ +"D", +"#dabc/home/x" +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\tabcx y'\nD=${}\t'q'\rA B${:-z}\"q\"${abc\rB==\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"abcx y'" +], +[ +"D", +"\t'q'" +], +[ +"B", +"=" +] +] +}, +{ +"input": "#A= ${:-z}\nexport A = \\${:-z}\rC\\\t\n'A B' = \"\nA=${A}#\r", +"expected": [ +[ +"A", +"\\z#" +], +[ +"C\\", +null +] +] +}, +{ +"input": "'A B'\\' \rA=${A}\nE= ${HOME_FROM_ENV}\r\nD\t=\t\n A= \\n${\u0e01\n", +"expected": [ +[ +"A", +"\\n${\u0e01" +], +[ +"E", +"/home/x" +], +[ +"D", +"" +] +] +}, +{ +"input": "C==\\'\nD\t=\t\\\"\u0e01$A\n", +"expected": [ +[ +"C", +"=\\'" +], +[ +"D", +"\\\"\u0e01$A" +] +] +}, +{ +"input": " A==\u0e01${:-z}'\r\nC\t=\t#\r", +"expected": [ +[ +"A", +"=\u0e01z'" +], +[ +"C", +"#" +] +] +}, +{ +"input": "A\t=\t\t\t \rE = x y\"\\\"", +"expected": [ +[ +"A", +"" +], +[ +"E", +"x y\"\\\"" +] +] +}, +{ +"input": "B==${B:-d}\nC= #c\r\n#A\t=\t\tabc\\n \r\n'A B'=abc${:-z}${HOME_FROM_ENV}", +"expected": [ +[ +"B", +"=d" +], +[ +"C", +"#c" +], +[ +"A B", +"abcz/home/x" +] +] +}, +{ +"input": "A== #c${:-z}\u0e01${\r\nA= $A\\n\\${A}\nexport A==\r\n", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "D\t=\t \n#A\t=\t\"\"C= '\n", +"expected": [ +[ +"D", +"" +] +] +}, +{ +"input": "D\t=\tE = \u0e01\nHOME_FROM_ENV==x y'q'\n", +"expected": [ +[ +"D", +"E = \u0e01" +], +[ +"HOME_FROM_ENV", +"=x y'q'" +] +] +}, +{ +"input": "#A= ", +"expected": [] +}, +{ +"input": "HOME_FROM_ENV\t=\t${A}${A}\r\n#A\t=\tx y\rB==abcA\\n${A}abc\\#A=${HOME_FROM_ENV}\r", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"B", +"=abcA\\nabc\\#A=/home/x" +] +] +}, +{ +"input": "D#\rB==\"\n#A= \\\"${abcabc\n", +"expected": [ +[ +"D", +null +], +[ +"B", +"=\"" +] +] +}, +{ +"input": "'A B'= \t\u0e01\n", +"expected": [ +[ +"A B", +"\u0e01" +] +] +}, +{ +"input": "HOME_FROM_ENV=${A}$A'x yB==\\n${\\nA B\t=\t\u0e01 #c #cexport A = \n A=$A\r", +"expected": [ +[ +"HOME_FROM_ENV", +"$A'x yB==\\n${\\nA B\t=\t\u0e01" +], +[ +"A", +"$A" +] +] +}, +{ +"input": "A\t=\t# # c ' \"", +"expected": [ +[ +"A", +"#" +] +] +}, +{ +"input": "A B\t=\t'q'${B:-d}\"q\"${HOME_FROM_ENV}#A=\"q\"\r\n", +"expected": [] +}, +{ +"input": "D==$A#\"\u0e01D=\r A\t=\t$A\\nabc${B:-d}\n'A B'= '\r\n", +"expected": [ +[ +"D", +"=$A#\"\u0e01D=" +], +[ +"A", +"$A\\nabcd" +] +] +}, +{ +"input": "C\t=\t\r", +"expected": [ +[ +"C", +"" +] +] +}, +{ +"input": "#A\t=\tA B\t=\t${HOME_FROM_ENV}\r\n", +"expected": [] +}, +{ +"input": "HOME_FROM_ENV\t=\t B=\u0e01\r\nC= ${B:-d}\\'\nA== ${A}$A\n", +"expected": [ +[ +"HOME_FROM_ENV", +"B=\u0e01" +], +[ +"C", +"d\\'" +], +[ +"A", +"= $A" +] +] +}, +{ +"input": "C==${HOME_FROM_ENV}$A\\'\\HOME_FROM_ENV=", +"expected": [ +[ +"C", +"=/home/x$A\\'\\HOME_FROM_ENV=" +] +] +}, +{ +"input": "export A=#A\\\"\t\u0e01${HOME_FROM_ENV}\nA\t=\t${HOME_FROM_ENV}\n", +"expected": [ +[ +"A", +"/home/x" +] +] +}, +{ +"input": "D==${A}\"\rE==#\t\\\"\\\rC=\r\nA B\t=\t${${B:-d}'${\r", +"expected": [ +[ +"D", +"=\"" +], +[ +"E", +"=#\t\\\"\\" +], +[ +"C", +"" +] +] +}, +{ +"input": "HOME_FROM_ENV='q'\r\n # c ' \" A\t=\t\rA B\r", +"expected": [ +[ +"HOME_FROM_ENV", +"q" +] +] +}, +{ +"input": "D\"${A}\nB\t=\t \n A = \\\"\"q\"'q'\nD = $A\u0e01${:-z}${A}export A\n", +"expected": [ +[ +"D\"${A}", +null +], +[ +"B", +"" +], +[ +"A", +"\\\"\"q\"'q'" +], +[ +"D", +"$A\u0e01z\\\"\"q\"'q'export A" +] +] +}, +{ +"input": "D==x y\r\nexport A\t=\t\\\"${:-z}\"\\'", +"expected": [ +[ +"D", +"=x y" +], +[ +"A", +"\\\"z\"\\'" +] +] +}, +{ +"input": "A B}\"q\"\n", +"expected": [] +}, +{ +"input": "A \\'\n#A\t=\t}${HOME_FROM_ENV}}${B:-d}A B\\\u0e01$A${:-z}\n# comment\r A \\${B:-d}\n", +"expected": [] +}, +{ +"input": "export A = $A}#A = \n#A = ${$A\nB='q'\\${B:-d}\\\r\nexport A$A\\'\\n\n", +"expected": [ +[ +"A", +"$A}#A =" +], +[ +"A$A\\'\\n", +null +] +] +}, +{ +"input": "export A=$A\"x y'\rE\t=\t#x y\r\nB= \"\t${A}\r\n", +"expected": [ +[ +"A", +"$A\"x y'" +], +[ +"E", +"#x y" +] +] +}, +{ +"input": "A=='\u0e01\\\"\nHOME_FROM_ENV\t=\t'A B'= \\${:-z}\r#A=\\'${A}x y\r\n", +"expected": [ +[ +"A", +"='\u0e01\\\"" +] +] +}, +{ +"input": "A==abc\"\r\n Aexport A==abc\\\"'q'abc", +"expected": [ +[ +"A", +"=abc\"" +] +] +}, +{ +"input": "HOME_FROM_ENV = \"\n", +"expected": [] +}, +{ +"input": "#A=abc${HOME_FROM_ENV}\"q\"\"q\"\rHOME_FROM_ENV\"\t\r\nB = \r\nE=='q'${${HOME_FROM_ENV}\n # c ' \"\n", +"expected": [ +[ +"HOME_FROM_ENV\"", +null +], +[ +"B", +"" +], +[ +"E", +"='q'" +] +] +}, +{ +"input": "export A\t=\t\r", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "B\t=\t'q'${:-z}\r\nexport A==\"\n", +"expected": [ +[ +"A", +"=\"" +] +] +}, +{ +"input": "#A'\"q\"\t\r", +"expected": [] +}, +{ +"input": "HOME_FROM_ENV=\t\"q\"\\\" #c", +"expected": [] +}, +{ +"input": "'A B'\n", +"expected": [ +[ +"A B", +null +] +] +}, +{ +"input": "E = abc\"q\"\n#A= #c\\\"\"q\"export A'q'\u0e01\\x y\r\nHOME_FROM_ENV = }x y}'q'\r\n", +"expected": [ +[ +"E", +"abc\"q\"" +], +[ +"HOME_FROM_ENV", +"}x y}'q'" +] +] +}, +{ +"input": "'A B'= ${x y\rD==\\nabc}\n", +"expected": [ +[ +"A B", +"${x y" +], +[ +"D", +"=\\nabc}" +] +] +}, +{ +"input": "HOME_FROM_ENV= \n#A=\\\"${:-z}${HOME_FROM_ENV}\r", +"expected": [ +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "A = \\'}${A}\r\r\nD= x y\t} A==\\\"\r\n", +"expected": [ +[ +"A", +"\\'}" +], +[ +"D", +"x y\t} A==\\\"" +] +] +}, +{ +"input": "'A B'=\rE==${abc\r", +"expected": [ +[ +"A B", +"" +], +[ +"E", +"=${abc" +] +] +}, +{ +"input": "A B==\t \r", +"expected": [] +}, +{ +"input": "C==abc\\ #c\nB\t=\t\\\"\\' #c#\r\n", +"expected": [ +[ +"C", +"=abc\\" +], +[ +"B", +"\\\"\\'" +] +] +}, +{ +"input": "A B=='\t\\'\nexport A\t=\t\\${A}\r\r\nHOME_FROM_ENV\\'#${B:-d}\r", +"expected": [ +[ +"A", +"\\" +], +[ +"HOME_FROM_ENV\\'", +null +] +] +}, +{ +"input": "E= \\\"''q'\rexport A\t=\t\nHOME_FROM_ENV==x y${HOME_FROM_ENV}'HOME_FROM_ENV\\n\\n\"q\"\t\nB\t=\t\r\n", +"expected": [ +[ +"E", +"\\\"''q'" +], +[ +"A", +"" +], +[ +"HOME_FROM_ENV", +"=x y/home/x'HOME_FROM_ENV\\n\\n\"q\"" +], +[ +"B", +"" +] +] +}, +{ +"input": "B E = $A${HOME_FROM_ENV}${B:-d}HOME_FROM_ENV'q''q'\r\n", +"expected": [] +}, +{ +"input": "export A= ${B:-d} \r\nHOME_FROM_ENV = ${:-z}}\r\nE${A}'q'\r'A B' = $A}\r", +"expected": [ +[ +"A", +"d" +], +[ +"HOME_FROM_ENV", +"z}" +], +[ +"E${A}'q'", +null +], +[ +"A B", +"$A}" +] +] +}, +{ +"input": "A B${:-z}${HOME_FROM_ENV}", +"expected": [] +}, +{ +"input": "HOME_FROM_ENV\t=\t\rD\t=\t\\n#${\rA=\u0e01\r A\t=\t${:-z}\u0e01\r\nB==abcabc #c\t\r", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"D", +"\\n#${" +], +[ +"A", +"z\u0e01" +], +[ +"B", +"=abcabc" +] +] +}, +{ +"input": "A B= \\'${A}\\n#A==\\nx y${HOME_FROM_ENV}\nD\t=\t 'q'\r", +"expected": [ +[ +"D", +"q" +] +] +}, +{ +"input": "export A==\\' #c'\n A==#\nE=$A\\\"x y\r", +"expected": [ +[ +"A", +"=#" +], +[ +"E", +"$A\\\"x y" +] +] +}, +{ +"input": " \r\n", +"expected": [] +}, +{ +"input": "#A'q'\"\\n\r\nE= ${:-z}${HOME_FROM_ENV}\n", +"expected": [ +[ +"E", +"z/home/x" +] +] +}, +{ +"input": "B\t=\t\\\rC\t=\t'q'\"q\"${:-z}\r\nB= ${A}\\'\\\"#", +"expected": [ +[ +"B", +"\\'\\\"#" +] +] +}, +{ +"input": "'A B'\\\r\n", +"expected": [] +}, +{ +"input": "'A B' = ", +"expected": [ +[ +"A B", +"" +] +] +}, +{ +"input": "'A B' = ${\\'${B:-d}\n'A B'\t=\t\t${HOME_FROM_ENV}\\n\r\n", +"expected": [ +[ +"A B", +"/home/x\\n" +] +] +}, +{ +"input": "B==$A\"q\"\"x y\r#A==\r C${HOME_FROM_ENV} ${HOME_FROM_ENV}#\r\n'A B'\t=\t\"q\" \r", +"expected": [ +[ +"B", +"=$A\"q\"\"x y" +], +[ +"A B", +"q" +] +] +}, +{ +"input": "A B=\u0e01\rexport A${HOME_FROM_ENV}abcx y#C=x y", +"expected": [] +}, +{ +"input": "A B==\t${A}}${A= ${A}${HOME_FROM_ENV}${B:-d}\n", +"expected": [] +}, +{ +"input": "A B\t=\t\\\"${HOME_FROM_ENV}\r\nHOME_FROM_ENV\\\"'\\\"\r\nB=${\r\nexport A #c ${\"\r \r", +"expected": [ +[ +"HOME_FROM_ENV\\\"'\\\"", +null +], +[ +"B", +"${" +], +[ +"A", +null +] +] +}, +{ +"input": "D= ${:-z} #c", +"expected": [ +[ +"D", +"z" +] +] +}, +{ +"input": " \r\n", +"expected": [] +}, +{ +"input": "# comment\nB = \\n#}\t\nB = 'q'\n", +"expected": [ +[ +"B", +"q" +] +] +}, +{ +"input": "HOME_FROM_ENV= \r#A = \r\nexport A = ${\"x y\rC=\r#A=${:-z}\\\"q\"\"\n", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"${\"x y" +], +[ +"C", +"" +] +] +}, +{ +"input": "C = 'A B'==\\n\"}$A\r\nA'$A", +"expected": [ +[ +"A'$A", +null +] +] +}, +{ +"input": "'A B'= #c${:-z} \rE\t=\t\"x y#\"", +"expected": [ +[ +"A B", +"#cz" +], +[ +"E", +"x y#" +] +] +}, +{ +"input": "A=", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "D==\"q\"'${:-z}'A B' = \\nD $A\u0e01\r\nA B = #c${HOME_FROM_ENV}\nHOME_FROM_ENV==${A} #c \n", +"expected": [ +[ +"D", +"=\"q\"'z'A B' = \\nD $A\u0e01" +], +[ +"HOME_FROM_ENV", +"=" +] +] +}, +{ +"input": "C = A\t=\tx y${A} #cA B = x y\u0e01\"q\"A B==$A\\'\\\" # c ' \"\r\n", +"expected": [ +[ +"C", +"A\t=\tx y" +] +] +}, +{ +"input": "A B\t=\t#\n", +"expected": [] +}, +{ +"input": " # c ' \"HOME_FROM_ENV = #\r\nB='q'#\n \r\n", +"expected": [ +[ +"B", +"q" +] +] +}, +{ +"input": "export A==${B:-d}x y${:-z}\nA B$A'q'\\\\n\rC\n", +"expected": [ +[ +"A", +"=dx yz" +], +[ +"C", +null +] +] +}, +{ +"input": " A = \r\nHOME_FROM_ENV\t=\t${:-z}${HOME_FROM_ENV}\\n'q'A=\rexport A\t=\t\\\"\u0e01\\\"${:-z}", +"expected": [ +[ +"A", +"\\\"\u0e01\\\"z" +], +[ +"HOME_FROM_ENV", +"z/home/x\\n'q'A=" +] +] +}, +{ +"input": "\r\nA B\rexport A==\\\"\\\"\r\nE\t=\tx y'${:-z}\u0e01", +"expected": [ +[ +"A", +"=\\\"\\\"" +], +[ +"E", +"x y'z\u0e01" +] +] +}, +{ +"input": " A= ${:-z}#\rE = ${B:-d}abc\rexport A= $A}\t\r\n", +"expected": [ +[ +"A", +"$A}" +], +[ +"E", +"dabc" +] +] +}, +{ +"input": "B= ${:-z}\\'\r\n A = }\r A==\"' }\r\n", +"expected": [ +[ +"B", +"z\\'" +], +[ +"A", +"=\"' }" +] +] +}, +{ +"input": "'A B' = 'q'\r\n", +"expected": [ +[ +"A B", +"q" +] +] +}, +{ +"input": "B\t=\t${HOME_FROM_ENV}\r\n#A=\nB\t=\t}\t\r\n", +"expected": [ +[ +"B", +"}" +] +] +}, +{ +"input": "HOME_FROM_ENV#\rD=${ #c${A}\r\nexport A==\r", +"expected": [ +[ +"HOME_FROM_ENV", +null +], +[ +"D", +"${" +], +[ +"A", +"=" +] +] +}, +{ +"input": "B\t=\t\nexport A\\''q'\nD==${:-z}\\\r", +"expected": [ +[ +"B", +"" +], +[ +"A\\''q'", +null +], +[ +"D", +"=z\\" +] +] +}, +{ +"input": " A\t=\t #c\nHOME_FROM_ENV==${HOME_FROM_ENV}\nE = \\nD=C= \\'\r", +"expected": [ +[ +"A", +"#c" +], +[ +"HOME_FROM_ENV", +"=/home/x" +], +[ +"E", +"\\nD=C= \\'" +] +] +}, +{ +"input": "A B==\\n\n# commentD\t=\t #c${${:-z}\rHOME_FROM_ENV=\\nx yx y'q'\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\\nx yx y'q'" +] +] +}, +{ +"input": "A = }\r A= #c\n A\t=\t\nA B=\\\r\nC = \r\n", +"expected": [ +[ +"A", +"" +], +[ +"C", +"" +] +] +}, +{ +"input": "HOME_FROM_ENV==\nE=\\\"\r\nexport A = \n", +"expected": [ +[ +"HOME_FROM_ENV", +"=" +], +[ +"E", +"\\\"" +], +[ +"A", +"" +] +] +}, +{ +"input": "E==\\\t\\abc\nC\t=\t\\n \"#", +"expected": [ +[ +"E", +"=\\\t\\abc" +], +[ +"C", +"\\n \"#" +] +] +}, +{ +"input": "export A\\\"\r\n", +"expected": [ +[ +"A\\\"", +null +] +] +}, +{ +"input": "C=\\${\r\n", +"expected": [ +[ +"C", +"\\${" +] +] +}, +{ +"input": "'A B'\t=\t${:-z}\rC=${B:-d}\\}${:-z}\r\n'A B' = \t #c\u0e01\t\r", +"expected": [ +[ +"A B", +"#c\u0e01" +], +[ +"C", +"d\\}z" +] +] +}, +{ +"input": "E==${HOME_FROM_ENV}\\}HOME_FROM_ENV==\\\" #c\\A B= ${'q''q'\r\nexport A==\"q\"\\\"\r", +"expected": [ +[ +"E", +"=/home/x\\}HOME_FROM_ENV==\\\"" +], +[ +"A", +"=\"q\"\\\"" +] +] +}, +{ +"input": "export A=='${ #c\u0e01HOME_FROM_ENV#${ \nE = \"'\r\n", +"expected": [ +[ +"A", +"='${" +] +] +}, +{ +"input": "B==x y\"\nB='q'${HOME_FROM_ENV}\n", +"expected": [ +[ +"B", +"=x y\"" +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\t\rA B #c\n A==$A${B:-d}${:-z}'q'\rexport A=\"q\"${HOME_FROM_ENV}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"=$Adz'q'" +] +] +}, +{ +"input": "D = \\'\n#A'\u0e01$A\"q\"\nA B==}${\u0e01x y\r\nexport A==${HOME_FROM_ENV}\\n #c \n", +"expected": [ +[ +"D", +"\\'" +], +[ +"A", +"=/home/x\\n" +] +] +}, +{ +"input": "export A=='}}\\'\nA= \t$Aabc#\r\nB=HOME_FROM_ENV = \\'${A}\rA B = \tx y\\\"${:-z}\n", +"expected": [ +[ +"A", +"$Aabc#" +], +[ +"B", +"HOME_FROM_ENV = \\'$Aabc#" +] +] +}, +{ +"input": "Bx y$Ax yA B = }\nC\t=\t$Aabc #cD = \\n", +"expected": [ +[ +"C", +"$Aabc" +] +] +}, +{ +"input": "E\\\" ${:-z}\\'\n# comment\r", +"expected": [] +}, +{ +"input": "E= \r A\t=\t\r # c ' \"\r\nexport A==", +"expected": [ +[ +"E", +"" +], +[ +"A", +"=" +] +] +}, +{ +"input": "B = \\n'${A}\rB#E\t=\t'\nA = ${A}\r", +"expected": [ +[ +"B", +null +], +[ +"A", +"" +] +] +}, +{ +"input": "#A= #\nA = \"}}\rA\"q\"}${A}'q'\rB\t=\t\"'\\\r\n", +"expected": [] +}, +{ +"input": "A B = # comment\r A\"\\n\n'A B'= \\'${${${B:-d}\rB=\\'abcabc\r", +"expected": [ +[ +"A\"\\n", +null +], +[ +"A B", +"\\'d" +], +[ +"B", +"\\'abcabc" +] +] +}, +{ +"input": "D\nC\t=\t}C\nHOME_FROM_ENV\r\nC\t=\t${A}${B:-d}\\'\"", +"expected": [ +[ +"D", +null +], +[ +"C", +"d\\'\"" +], +[ +"HOME_FROM_ENV", +null +] +] +}, +{ +"input": "HOME_FROM_ENV='\r\n'A B'=", +"expected": [] +}, +{ +"input": "#A==${B:-d}x y${A}\n", +"expected": [] +}, +{ +"input": "#A= ''\\\\'\r", +"expected": [] +}, +{ +"input": "E = \t'\n", +"expected": [] +}, +{ +"input": "HOME_FROM_ENV= }\t${${A}\r\n \r\nexport A==${HOME_FROM_ENV}\r'A B'\t=\t \\'}\r\nB = x y'q'\\\"x y\n", +"expected": [ +[ +"HOME_FROM_ENV", +"}\t" +], +[ +"A", +"=/home/x" +], +[ +"A B", +"\\'}" +], +[ +"B", +"x y'q'\\\"x y" +] +] +}, +{ +"input": "export A#${\r A==\nA B = \"${A}\"q\"\"q\"\r\nexport A#A=\u0e01}${\n", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "B#\\x y\\n\n # c ' \"\r\n", +"expected": [ +[ +"B", +null +] +] +}, +{ +"input": " A\t=\t\\n$A${A}\\'\r# comment", +"expected": [ +[ +"A", +"\\n$A\\'" +] +] +}, +{ +"input": "C= 'q''\\n\r\nB= \\'\\\"}${\rE'\nE\t=\t\r\n", +"expected": [ +[ +"B", +"\\'\\\"}${" +], +[ +"E'", +null +], +[ +"E", +"" +] +] +}, +{ +"input": "#A\t=\t\\'\r\nD==${HOME_FROM_ENV}${:-z}C= #c${B:-d}HOME_FROM_ENV = \\nabc$AHOME_FROM_ENV=\u0e01 ${HOME_FROM_ENV}\r", +"expected": [ +[ +"D", +"=/home/xzC=" +] +] +}, +{ +"input": "HOME_FROM_ENV=\"q\"x y\\\"\r'A B'\"q\"\\''\\n\nexport A=\"q\"${}\r A\\\"\r\n A=${B:-d}'q'${HOME_FROM_ENV}", +"expected": [ +[ +"A\\\"", +null +], +[ +"A", +"d'q'/home/x" +] +] +}, +{ +"input": " A== #cx y#A = }\r\n'A B'=='${B:-d}${A}\r\nHOME_FROM_ENV=\"q\"\\n\"\r'A B'= }${B:-d}\n", +"expected": [ +[ +"A", +"=" +], +[ +"A B", +"}d" +] +] +}, +{ +"input": "E=${A}\\'\r\nC = ${:-z}}\\'\r A = ${:-z}\\n${A}\\'\r\n'A B'=#${A}\rHOME_FROM_ENV= \r\n", +"expected": [ +[ +"E", +"\\'" +], +[ +"C", +"z}\\'" +], +[ +"A", +"z\\n\\'" +], +[ +"A B", +"#z\\n\\'" +], +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "E==\r\nD=${HOME_FROM_ENV}\\n\tE= $A\n'A B'=\r\n'A B' = ${B:-d}", +"expected": [ +[ +"E", +"=" +], +[ +"D", +"/home/x\\n\tE= $A" +], +[ +"A B", +"d" +] +] +}, +{ +"input": "#A\"#${A}C=\\\"x y'\"\nexport A\\n\t", +"expected": [ +[ +"A\\n", +null +] +] +}, +{ +"input": "#A\r", +"expected": [] +}, +{ +"input": "E= \r # c ' \"\n", +"expected": [ +[ +"E", +"" +] +] +}, +{ +"input": "'A B'\t=\t#}\nD= B = }\n", +"expected": [ +[ +"A B", +"#}" +], +[ +"D", +"B = }" +] +] +}, +{ +"input": " \r A= }\rHOME_FROM_ENV==${ \r A=\\${HOME_FROM_ENV} #c\rHOME_FROM_ENV", +"expected": [ +[ +"A", +"\\/home/x" +], +[ +"HOME_FROM_ENV", +null +] +] +}, +{ +"input": "B\t=\t\\ #c\n B= ${B:-d}\t\r\nD\t=\t #${:-z}}\r", +"expected": [ +[ +"B", +"\\" +], +[ +"D", +"#z}" +] +] +}, +{ +"input": " # c ' \"\n A\t=\t\\\"q\"#A='q'${B:-d}\r\nHOME_FROM_ENV = \\\"", +"expected": [ +[ +"A", +"\\\"q\"#A='q'd" +], +[ +"HOME_FROM_ENV", +"\\\"" +] +] +}, +{ +"input": "D= \\n\"${:-z}", +"expected": [ +[ +"D", +"\\n\"z" +] +] +}, +{ +"input": "A\t=\t'q'\rB = ${A}x y${\r\nE= \\${HOME_FROM_ENV}'q'\u0e01\n", +"expected": [ +[ +"A", +"q" +], +[ +"B", +"qx y${" +], +[ +"E", +"\\/home/x'q'\u0e01" +] +] +}, +{ +"input": "'A B' = #\\'}\rD==${B:-d}\u0e01${B:-d}\\n\r\n#A = abc ${HOME_FROM_ENV}\nHOME_FROM_ENV== #c #c\r", +"expected": [ +[ +"A B", +"#\\'}" +], +[ +"D", +"=d\u0e01d\\n" +], +[ +"HOME_FROM_ENV", +"=" +] +] +}, +{ +"input": "B\t=\t\\n \nE\t=\t${HOME_FROM_ENV}\t\\n${HOME_FROM_ENV}\n'A B'\t=\t#\u0e01\r", +"expected": [ +[ +"B", +"\\n" +], +[ +"E", +"/home/x\t\\n/home/x" +], +[ +"A B", +"#\u0e01" +] +] +}, +{ +"input": "A B\t=\t\n#A==\nD\t=\t\"q\"\r\nHOME_FROM_ENV #c${HOME_FROM_ENV}\u0e01 #c", +"expected": [ +[ +"D", +"q" +], +[ +"HOME_FROM_ENV", +null +] +] +}, +{ +"input": "HOME_FROM_ENV= #A= #c\r\nB\t=\t\"${HOME_FROM_ENV}${B:-d}\\'\rC\\\"\r", +"expected": [ +[ +"HOME_FROM_ENV", +"#A=" +], +[ +"B", +"/home/xd'\rC\\" +] +] +}, +{ +"input": "E==x y#\r\nexport A== #c\"\"q\"${B= ${B:-d}\\} \r", +"expected": [ +[ +"E", +"=x y#" +], +[ +"A", +"=" +] +] +}, +{ +"input": "export A\t=\t\\\"\\n${:-z}\r\nA B=${B:-d}abc #c${B:-d}\rC= ${} D==${:-z}'\"\r # c ' \"\n", +"expected": [ +[ +"A", +"\\\"\\nz" +], +[ +"C", +" D==z'\"" +] +] +}, +{ +"input": "# comment\nC=\t\"\u0e01x y\n", +"expected": [] +}, +{ +"input": "HOME_FROM_ENV==}'q'${\\'\nA==\"q\"\r\n A= ${HOME_FROM_ENV}\r\nA\t=\t\t\"${\\n\nA B= #$A\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"=}'q'${\\'" +], +[ +"A", +"/home/x" +] +] +}, +{ +"input": "HOME_FROM_ENV${A}${A}${A}\nD = \\n${A}\nA==${:-z}\"q\"\"q\"E= \\\"\u0e01${\t\r\n", +"expected": [ +[ +"HOME_FROM_ENV${A}${A}${A}", +null +], +[ +"D", +"\\n" +], +[ +"A", +"=z\"q\"\"q\"E= \\\"\u0e01${" +] +] +}, +{ +"input": "export A= \\'x y${\r\n", +"expected": [ +[ +"A", +"\\'x y${" +] +] +}, +{ +"input": "D==\\\"${\nE #c\r", +"expected": [ +[ +"D", +"=\\\"${" +], +[ +"E", +null +] +] +}, +{ +"input": "C\t=\t#\rA\t=\tabc${$A\nD${:-z}\u0e01\\\r", +"expected": [ +[ +"C", +"#" +], +[ +"A", +"abc${$A" +], +[ +"D${:-z}\u0e01\\", +null +] +] +}, +{ +"input": "D= x yHOME_FROM_ENV=\nHOME_FROM_ENV==E= \\ #c${\r#A = \t #cabc${:-z}\r", +"expected": [ +[ +"D", +"x yHOME_FROM_ENV=" +], +[ +"HOME_FROM_ENV", +"=E= \\" +] +] +}, +{ +"input": "A B = \rHOME_FROM_ENV=${B:-d}\\\"\r\n#Ax y\"\r \n", +"expected": [ +[ +"HOME_FROM_ENV", +"d\\\"" +] +] +}, +{ +"input": "A B${B:-d}\u0e01\\'\r'A B'\"q\"\nB= #c\"#}\r", +"expected": [ +[ +"B", +"#c\"#}" +] +] +}, +{ +"input": "'A B''q' ${\rHOME_FROM_ENV\nA=${A}\r#A = ${$A${'q'\n", +"expected": [ +[ +"HOME_FROM_ENV", +null +], +[ +"A", +"" +] +] +}, +{ +"input": "B==\\n\\\"'\r\nC\t=\t${B:-d}\nexport A= \r", +"expected": [ +[ +"B", +"=\\n\\\"'" +], +[ +"C", +"=\\n\\\"'" +], +[ +"A", +"" +] +] +}, +{ +"input": "C = \\\\\" A B=\\\"'${\n", +"expected": [ +[ +"C", +"\\\\\" A B=\\\"'${" +] +] +}, +{ +"input": "A B= ${\rDx y\t\t", +"expected": [] +}, +{ +"input": "B = \r # c ' \"\r\n ", +"expected": [ +[ +"B", +"" +] +] +}, +{ +"input": "'A B' = \"q\"\"q\"\\\\\"\r\nA==\n A==\\'${A}${A}x y\r A=#$A\t${:-z}\r", +"expected": [ +[ +"A", +"#$A\tz" +] +] +}, +{ +"input": "E = #\rE\t=\t\"q\"'#\r\nC = 'A B'= \\\n", +"expected": [ +[ +"E", +"#" +] +] +}, +{ +"input": "'A B'=abc\tC\t=\tC= \rA #c${B:-d}}", +"expected": [ +[ +"A B", +"abc\tC\t=\tC=" +], +[ +"A", +null +] +] +}, +{ +"input": " HOME_FROM_ENV = \t'\\'\t\r\n#A= \\'\\'\nA=$A${A}\r\nA= \"q\"''\r", +"expected": [] +}, +{ +"input": "export A= # #c\r\nD\r # c ' \"\r", +"expected": [ +[ +"A", +"#" +], +[ +"D", +null +] +] +}, +{ +"input": "C==${A}\nA B= \nE=#A = \\\"${B:-d}\t\\\n'A B' = \"\r", +"expected": [ +[ +"C", +"=" +], +[ +"E", +"#A = \\\"d\t\\" +] +] +}, +{ +"input": "'A B'=\"${${:-z} \nE\t=\t #c'q'}${A}\n#A\nB=#\\n\n#A= \\\"\\n\n", +"expected": [] +}, +{ +"input": "D= \\n\r\nE=}\rexport A${A}\rA B==\\\"$A\n", +"expected": [ +[ +"D", +"\\n" +], +[ +"E", +"}" +], +[ +"A${A}", +null +] +] +}, +{ +"input": "A=C = ${HOME_FROM_ENV}\\'\nA\r\n", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "D\u0e01${:-z}${\n A${B:-d}${B:-d}'q'\rC=${abc\"q\"${A}\rD== \"", +"expected": [ +[ +"D\u0e01${:-z}${", +null +], +[ +"A${B:-d}${B:-d}'q'", +null +], +[ +"C", +"" +], +[ +"D", +"= \"" +] +] +}, +{ +"input": "B = '${A}\u0e01${B:-d}\n", +"expected": [] +}, +{ +"input": "export A = }\\n A} #c\r\n", +"expected": [ +[ +"A", +"}\\n A}" +] +] +}, +{ +"input": " A\n", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "A B=#\r\nHOME_FROM_ENV= \\'${:-z}'\r\n \r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\\'z'" +] +] +}, +{ +"input": "A = ${:-z}${HOME_FROM_ENV}\n A = \nexport A\t=\t\u0e01\\\"'q'\r A\t=\t\r\nexport A= abc#x yabc\r", +"expected": [ +[ +"A", +"abc#x yabc" +] +] +}, +{ +"input": "E = #A= $A\u0e01\r\n#A = \"\\n'\r", +"expected": [ +[ +"E", +"#A= $A\u0e01" +] +] +}, +{ +"input": "export A\\n\u0e01 #cx yD = \\ \r\n# commentC = x y\\\"\"${A}\n", +"expected": [ +[ +"A\\n\u0e01", +null +] +] +}, +{ +"input": "C==}${x y\rB\t=\t\\n#\rD= ", +"expected": [ +[ +"C", +"=}${x y" +], +[ +"B", +"\\n#" +], +[ +"D", +"" +] +] +}, +{ +"input": " A\t=\tabc''q'' # c ' \"", +"expected": [ +[ +"A", +"abc''q''" +] +] +}, +{ +"input": "A B= ${:-z}'q'\u0e01 \rHOME_FROM_ENV\t\\'$A\r\nC= \r\nD== 'q'\r\n", +"expected": [ +[ +"C", +"" +], +[ +"D", +"= 'q'" +] +] +}, +{ +"input": "'A B'\t=\t\u0e01${B:-d}'q'${:-z}\nC= #c\r A=#\r\n", +"expected": [ +[ +"A B", +"\u0e01d'q'z" +], +[ +"C", +"#c" +], +[ +"A", +"#" +] +] +}, +{ +"input": "B = \rB=='\"q\"'q'\rB\\'}${B:-d}abc", +"expected": [ +[ +"B", +"='\"q\"'q'" +], +[ +"B\\'}${B:-d}abc", +null +] +] +}, +{ +"input": "B=\"${B:-d}}\r\n'A B'= ${B:-d}abc #c", +"expected": [ +[ +"A B", +"dabc" +] +] +}, +{ +"input": "C${\\${B:-d}}\n A= C=\nHOME_FROM_ENV\t=\t${HOME_FROM_ENV}}${HOME_FROM_ENV}", +"expected": [ +[ +"C${\\${B:-d}}", +null +], +[ +"A", +"C=" +], +[ +"HOME_FROM_ENV", +"/home/x}/home/x" +] +] +}, +{ +"input": "C= '\nB=='q'HOME_FROM_ENV= B# \\n}\r", +"expected": [] +}, +{ +"input": "A\t=\t\\\"\\'\"q\"B= \n'A B'= \\\"\r\n A= A= ${${A}x y${B:-d}\n", +"expected": [ +[ +"A", +"A= x yd" +], +[ +"A B", +"\\\"" +] +] +}, +{ +"input": "'A B' = \\\"${HOME_FROM_ENV}'\r'A B' x y\"${A}B${B:-d}'\u0e01\nA B = \r\n", +"expected": [ +[ +"A B", +"\\\"/home/x'" +] +] +}, +{ +"input": "E==HOME_FROM_ENV==\"q\"${B:-d}\"}export A==\"q\"${A}\r\n", +"expected": [ +[ +"E", +"=HOME_FROM_ENV==\"q\"d\"}export A==\"q\"" +] +] +}, +{ +"input": "'A B'= \u0e01\\n #c", +"expected": [ +[ +"A B", +"\u0e01\\n" +] +] +}, +{ +"input": "E= ${A}${HOME_FROM_ENV}\\'${A}\nA\r\n", +"expected": [ +[ +"E", +"/home/x\\'" +], +[ +"A", +null +] +] +}, +{ +"input": "E\r\n", +"expected": [ +[ +"E", +null +] +] +}, +{ +"input": " A==\nD = \"q\"\"\"\r", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "A B=\\\"${:-z} \rC\t=\t${HOME_FROM_ENV}$A$A\\\"A= abc${:-z}${A}\r # c ' \"\nA = x y$A${:-z}\r\n", +"expected": [ +[ +"C", +"/home/x$A$A\\\"A= abcz" +], +[ +"A", +"x y$Az" +] +] +}, +{ +"input": "HOME_FROM_ENV'${B:-d}\r\nexport A\\n${A}\"q\"\"\r\n", +"expected": [ +[ +"HOME_FROM_ENV'${B:-d}", +null +], +[ +"A\\n${A}\"q\"\"", +null +] +] +}, +{ +"input": " A=\u0e01\\n\\A=#}\r", +"expected": [ +[ +"A", +"\u0e01\\n\\A=#}" +] +] +}, +{ +"input": "B\t=\t \\n${'\r\nA B\t=\t'q'\t\nD = #c \"\"\r\n'A B'==\\'\\'${\tHOME_FROM_ENVabc\"q\"\r", +"expected": [ +[ +"B", +"\\n${'" +], +[ +"D", +"#c \"\"" +], +[ +"A B", +"=\\'\\'${\tHOME_FROM_ENVabc\"q\"" +] +] +}, +{ +"input": " A= abc$A${HOME_FROM_ENV}A\\\"D=\"q\"\n", +"expected": [ +[ +"A", +"abc$A/home/xA\\\"D=\"q\"" +] +] +}, +{ +"input": "'A B'= \r\n", +"expected": [ +[ +"A B", +"" +] +] +}, +{ +"input": "'A B'==\"$A", +"expected": [ +[ +"A B", +"=\"$A" +] +] +}, +{ +"input": " # c ' \"\r\n", +"expected": [] +}, +{ +"input": "C\r\nE=\\\r\nexport Aexport A=}\n A${HOME_FROM_ENV}\\'${B:-d}\n", +"expected": [ +[ +"C", +null +], +[ +"E", +"\\" +], +[ +"A${HOME_FROM_ENV}\\'${B:-d}", +null +] +] +}, +{ +"input": "D\t${HOME_FROM_ENV}${A}${HOME_FROM_ENV}\r\n # c ' \"\rexport A\t=\t\\\n# comment\rD = \\\"", +"expected": [ +[ +"A", +"\\" +], +[ +"D", +"\\\"" +] +] +}, +{ +"input": " \r\n", +"expected": [] +}, +{ +"input": "A\t=\t\"x y'q'\\'A B==${A}\\\"", +"expected": [ +[ +"A", +"x y'q''A B==\\" +] +] +}, +{ +"input": "export A= #'\"\r\n", +"expected": [ +[ +"A", +"#'\"" +] +] +}, +{ +"input": " A='\\}'\nB= \\}'\r\nexport A= \rA\t=\t ${A} ", +"expected": [ +[ +"A", +"" +], +[ +"B", +"\\}'" +] +] +}, +{ +"input": "E = \n A = \n", +"expected": [ +[ +"E", +"" +], +[ +"A", +"" +] +] +}, +{ +"input": "A B= \\'${:-z}\r", +"expected": [] +}, +{ +"input": "'A B'= 'q'\r\nexport A= ${B:-d}\r\nD\t=\t \\n\"q\"x y\r\nHOME_FROM_ENV = ", +"expected": [ +[ +"A B", +"q" +], +[ +"A", +"d" +], +[ +"D", +"\\n\"q\"x y" +], +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "export A==\"x yx y\\'A\t=\t\"\\n}\r\n# comment\r A==\r", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "export A\t=\t$A\rHOME_FROM_ENV\t=\t\\\" abc\r\n A = x y${:-z}\n", +"expected": [ +[ +"A", +"x yz" +], +[ +"HOME_FROM_ENV", +"\\\" abc" +] +] +}, +{ +"input": "A B=\t${A}\n B=${HOME_FROM_ENV}\r\nD= \\'\\n$A\r# comment", +"expected": [ +[ +"B", +"/home/x" +], +[ +"D", +"\\'\\n$A" +] +] +}, +{ +"input": "HOME_FROM_ENV\r\nC==\rA B==${HOME_FROM_ENV}${A}\n", +"expected": [ +[ +"HOME_FROM_ENV", +null +], +[ +"C", +"=" +] +] +}, +{ +"input": "HOME_FROM_ENV= ${A}\\\\\\\r", +"expected": [ +[ +"HOME_FROM_ENV", +"\\\\\\" +] +] +}, +{ +"input": "# comment\r\nC= B = ${HOME_FROM_ENV}\\\rE = \\\"\\n${:-z}\r\nexport A= \n", +"expected": [ +[ +"C", +"B = /home/x\\" +], +[ +"E", +"\\\"\\nz" +], +[ +"A", +"" +] +] +}, +{ +"input": "A B = \nC = \u0e01${${A}${\rE=\u0e01 '\\n\rHOME_FROM_ENV\t=\t''\n#A= ${' #c${HOME_FROM_ENV}\r", +"expected": [ +[ +"C", +"\u0e01${" +], +[ +"E", +"\u0e01 '\\n" +], +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": " A= 'A B'=\\\u0e01\nA B = \\'\\\u0e01\nHOME_FROM_ENV\\\"\tx yabc\n # c ' \"\r\n", +"expected": [] +}, +{ +"input": "E\"q\"'\u0e01\nB${A}\\'\r\nA=\nHOME_FROM_ENV = abcabc\"q\"\n", +"expected": [ +[ +"E\"q\"'\u0e01", +null +], +[ +"B${A}\\'", +null +], +[ +"A", +"" +], +[ +"HOME_FROM_ENV", +"abcabc\"q\"" +] +] +}, +{ +"input": "#A== #cx yA\t=\t$A\\#\rB\\\"}x y\"\nC = \\' abc\n", +"expected": [ +[ +"C", +"\\' abc" +] +] +}, +{ +"input": "# commentHOME_FROM_ENV\t${HOME_FROM_ENV}\r\nD= ${HOME_FROM_ENV}A B=\\n#\u0e01\n", +"expected": [ +[ +"D", +"/home/xA B=\\n#\u0e01" +] +] +}, +{ +"input": "A\t=\tabc\\''\nA B= \"q\"'q'\u0e01\\\r\n A= \n", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "#A==\\\" $A\r\n#A=='\\\r\n", +"expected": [] +}, +{ +"input": "A B = #x y\nD'q'\"\n", +"expected": [ +[ +"D'q'\"", +null +] +] +}, +{ +"input": "A B = x y\\n\r\n", +"expected": [] +}, +{ +"input": "export A\t=\t'\r\nE=${ \r\n", +"expected": [ +[ +"E", +"${" +] +] +}, +{ +"input": "# comment\r\n", +"expected": [] +}, +{ +"input": "C\rA = }\"'} # c ' \"\nE\t=\t\rHOME_FROM_ENV\t=\t\\\"\\\"'q'\\'\r", +"expected": [ +[ +"C", +null +], +[ +"A", +"}\"'}" +], +[ +"E", +"" +], +[ +"HOME_FROM_ENV", +"\\\"\\\"'q'\\'" +] +] +}, +{ +"input": "#A\t=\tabc \"\r\nA B= $A'q'\\\"\nD = $A\t\n# comment\r\n", +"expected": [ +[ +"D", +"$A" +] +] +}, +{ +"input": " HOME_FROM_ENV= ${B:-d}${HOME_FROM_ENV}\"\r\n'A B'\t=\t", +"expected": [ +[ +"HOME_FROM_ENV", +"d/home/x\"" +], +[ +"A B", +"" +] +] +}, +{ +"input": "C = ${HOME_FROM_ENV}${${HOME_FROM_ENV}\r \r\n", +"expected": [ +[ +"C", +"/home/x" +] +] +}, +{ +"input": "A B\t=\t${\nA\u0e01\r\n", +"expected": [ +[ +"A\u0e01", +null +] +] +}, +{ +"input": "HOME_FROM_ENV = ${HOME_FROM_ENV}\nC\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"/home/x" +], +[ +"C", +null +] +] +}, +{ +"input": "export A\r", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "D=#'q'\r", +"expected": [ +[ +"D", +"#'q'" +] +] +}, +{ +"input": "'A B'=='\u0e01abc\nHOME_FROM_ENV= \\'\\'\\\\\"\r\nD} #c\r", +"expected": [ +[ +"A B", +"='\u0e01abc" +], +[ +"HOME_FROM_ENV", +"\\'\\'\\\\\"" +], +[ +"D}", +null +] +] +}, +{ +"input": "export A==\r\n", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "export A = E\t=\t\\n\t\r\n", +"expected": [ +[ +"A", +"E\t=\t\\n" +] +] +}, +{ +"input": "A$A # c ' \"A = ${:-z}$Ax y${A}\n", +"expected": [ +[ +"A$A", +null +] +] +}, +{ +"input": " # c ' \"export A==\r#A= ", +"expected": [] +}, +{ +"input": "D= ${B:-d}\rHOME_FROM_ENV\t=\t${B:-d}abc\"${B:-d}\r# comment\rE=\r\nB = ", +"expected": [ +[ +"D", +"d" +], +[ +"HOME_FROM_ENV", +"dabc\"d" +], +[ +"E", +"" +], +[ +"B", +"" +] +] +}, +{ +"input": " A\t=\t}\rA=\\\"x y\rA B= \r#A=\nA B\t=\t\\'${B:-d}\r", +"expected": [ +[ +"A", +"\\\"x y" +] +] +}, +{ +"input": "HOME_FROM_ENV = HOME_FROM_ENV=\t x y\\'\n", +"expected": [ +[ +"HOME_FROM_ENV", +"HOME_FROM_ENV=\t x y\\'" +] +] +}, +{ +"input": "E=\\\"${:-z}${HOME_FROM_ENV}\"q\"'A B'\t=\t\tx yabc${\n", +"expected": [ +[ +"E", +"\\\"z/home/x\"q\"'A B'\t=\t\tx yabc${" +] +] +}, +{ +"input": "C= \rA = '\"q\"$A", +"expected": [ +[ +"C", +"" +] +] +}, +{ +"input": " A=\r\n#A\t=\tabcabc\"q\"\r\n", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "export A= '\r\nA\t=\t #c\"\r\nB==\\\\'\nE = ${A}\r", +"expected": [ +[ +"A", +"\r\nA\t=\t #c\"\r\nB==\\" +], +[ +"E", +"\r\nA\t=\t #c\"\r\nB==\\" +] +] +}, +{ +"input": "export A='#abcE= 'q'\n A${B:-d}\\'\rE=${A}${x y", +"expected": [ +[ +"A${B:-d}\\'", +null +], +[ +"E", +"${x y" +] +] +}, +{ +"input": " \r HOME_FROM_ENV= \r A= \\'x y''q'\n ", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"\\'x y''q'" +] +] +}, +{ +"input": "#A=\\${HOME_FROM_ENV}\nexport A\t=\t ##\\n\r\n'A B' = ${B:-d}\r", +"expected": [ +[ +"A", +"##\\n" +], +[ +"A B", +"d" +] +] +}, +{ +"input": "# comment\r'A B'\u0e01\t'\" A = \r\nC = 'q'#${B:-d}#", +"expected": [ +[ +"C", +"q" +] +] +}, +{ +"input": "C==}${HOME_FROM_ENV}A\\\n#A}#abc\"", +"expected": [ +[ +"C", +"=}/home/xA\\" +] +] +}, +{ +"input": " A\t=\t\"q\" #c\rD=", +"expected": [ +[ +"A", +"q" +], +[ +"D", +"" +] +] +}, +{ +"input": "E=\\nabcabc", +"expected": [ +[ +"E", +"\\nabcabc" +] +] +}, +{ +"input": " A = \r\nE\t=\t\\n\r\n", +"expected": [ +[ +"A", +"" +], +[ +"E", +"\\n" +] +] +}, +{ +"input": "'A B'= \r\n", +"expected": [ +[ +"A B", +"" +] +] +}, +{ +"input": "HOME_FROM_ENV = \\nHOME_FROM_ENV= \"q\"\\n# comment\r\n # c ' \"", +"expected": [ +[ +"HOME_FROM_ENV", +"\\nHOME_FROM_ENV= \"q\"\\n# comment" +] +] +}, +{ +"input": " # c ' \"\rexport A= \nE=\\n${A}B$A$A\n#Aabc\\'\r", +"expected": [ +[ +"A", +"" +], +[ +"E", +"\\nB$A$A" +] +] +}, +{ +"input": "A B==abc\rexport A==\\\"\"q\"#\r\nE\t=\t${\r\n'A B'=\r\n # c ' \"\r", +"expected": [ +[ +"A", +"=\\\"\"q\"#" +], +[ +"E", +"${" +], +[ +"A B", +"" +] +] +}, +{ +"input": "A=A B= #c\\${${A}\rD= #c\"# # c ' \"\n", +"expected": [ +[ +"A", +"A B=" +], +[ +"D", +"#c\"#" +] +] +}, +{ +"input": "E= \t\r\nexport A==abcx y#A= \\\"abc\r\nexport A = \n#A = ${A}\r\n", +"expected": [ +[ +"E", +"" +], +[ +"A", +"" +] +] +}, +{ +"input": "#A=\"#\nHOME_FROM_ENV= x y${${A} \rD = '\"q\"\r", +"expected": [ +[ +"HOME_FROM_ENV", +"x y" +] +] +}, +{ +"input": "E= \"q\"\r\n \r#A=\\' #c\"", +"expected": [ +[ +"E", +"q" +] +] +}, +{ +"input": "E=#\\\"abc#\r\nD=\u0e01\t\rA==x y\r", +"expected": [ +[ +"E", +"#\\\"abc#" +], +[ +"D", +"\u0e01" +], +[ +"A", +"=x y" +] +] +}, +{ +"input": "A\t=\t'\\n#}A=\"$A\u0e01\nA${:-z}${HOME_FROM_ENV} #c\nC= #c\\\"\t\"\r'A B'= $A${B:-d}abc ", +"expected": [] +}, +{ +"input": "D==\nA=}\n#A\t=\t\"abcC==${:-z}\u0e01\\'B \n", +"expected": [ +[ +"D", +"=" +], +[ +"A", +"}" +] +] +}, +{ +"input": "export A=\\n\u0e01\nA\t=\t\r A\t=\t${HOME_FROM_ENV}abc\\\"${B:-d}", +"expected": [ +[ +"A", +"/home/xabc\\\"d" +] +] +}, +{ +"input": "C==${HOME_FROM_ENV}\"$A}\nA \\$A\rHOME_FROM_ENV==${${:-z}\tx y\rA==\\\\'${A}\nA B==\n", +"expected": [ +[ +"C", +"=/home/x\"$A}" +], +[ +"HOME_FROM_ENV", +"=z\tx y" +], +[ +"A", +"=\\\\'" +] +] +}, +{ +"input": "export A==${HOME_FROM_ENV}${:-z}${A}'\rD=\\n${##Eabc'${A}HOME_FROM_ENV\t=\t\"abc\rD = abc''\r\n", +"expected": [ +[ +"A", +"=/home/xz'" +], +[ +"D", +"abc''" +] +] +}, +{ +"input": "export A= \\abc${HOME_FROM_ENV}\r", +"expected": [ +[ +"A", +"\\abc/home/x" +] +] +}, +{ +"input": "D= }\r # c ' \"\r'A B'= \r", +"expected": [ +[ +"D", +"}" +], +[ +"A B", +"" +] +] +}, +{ +"input": "'A B' = #c${'q'\r#A= ${:-z}\n A=\u0e01 #c\rC=#${'q'${B:-d}", +"expected": [ +[ +"A B", +"#c${'q'" +], +[ +"A", +"\u0e01" +], +[ +"C", +"#d" +] +] +}, +{ +"input": "#A=\\$A\\${B:-d}\nB= A B= \r'A B'= ${:-z}'\\\"A B\t=\t ", +"expected": [ +[ +"B", +"A B=" +], +[ +"A B", +"z'\\\"A B\t=" +] +] +}, +{ +"input": "E\t=\tx y\rD==\\#\nB\t=\t}'\nA==\"q\"$A\r\n", +"expected": [ +[ +"E", +"x y" +], +[ +"D", +"=\\#" +], +[ +"B", +"}'" +], +[ +"A", +"=\"q\"$A" +] +] +}, +{ +"input": " A= #cx y\r#A\t=\t\"q\"}${A}\rA Babc\n'A B'=='q'\t\"q\"\r", +"expected": [ +[ +"A", +"#cx y" +], +[ +"A B", +"='q'\t\"q\"" +] +] +}, +{ +"input": " # c ' \"\r A\u0e01\\n\\\rD\t=\t\r\n", +"expected": [ +[ +"A\u0e01\\n\\", +null +], +[ +"D", +"" +] +] +}, +{ +"input": "A\t=\t${:-z}}\r\nA #c${A}${A}'\r\n", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "HOME_FROM_ENV==\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"=" +] +] +}, +{ +"input": "C\t=\t", +"expected": [ +[ +"C", +"" +] +] +}, +{ +"input": "HOME_FROM_ENV= #c\\'abc \nD\rexport A = ${HOME_FROM_ENV}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"#c\\'abc" +], +[ +"D", +null +], +[ +"A", +"/home/x" +] +] +}, +{ +"input": "A\t=\t${HOME_FROM_ENV}\\\\\"# comment\rB==\\n\t\nexport A\r\n", +"expected": [ +[ +"A", +null +], +[ +"B", +"=\\n" +] +] +}, +{ +"input": "HOME_FROM_ENV= 'q'\\\" #cexport A= 'q'\"q\"\\\\n\r\nD==\\\\'\nA\\\"${${B:-d}\nE=$A'${B:-d}", +"expected": [ +[ +"D", +"=\\\\'" +], +[ +"A\\\"${${B:-d}", +null +], +[ +"E", +"$A'd" +] +] +}, +{ +"input": "export A= abcA = $A${:-z}${${HOME_FROM_ENV}export A = ${A}\rB #c${\n", +"expected": [ +[ +"A", +"abcA = $Azexport A = " +], +[ +"B", +null +] +] +}, +{ +"input": "export A= \u0e01\\${HOME_FROM_ENV} A\r\n", +"expected": [ +[ +"A", +"\u0e01\\/home/x A" +] +] +}, +{ +"input": "#A = \rE=='${B:-d}\t #cC = \u0e01\"q\"A==${export A = ' #c\\'\n", +"expected": [ +[ +"E", +"='d" +] +] +}, +{ +"input": "A B= $A${HOME_FROM_ENV}\t${HOME_FROM_ENV}\nA= ${:-z}$Aabc\n", +"expected": [ +[ +"A", +"z$Aabc" +] +] +}, +{ +"input": "#A= abc\r\nA B= $A\"q\"\nexport A = ${:-z}'\\' \rA\t=\t${A}\r A= ", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "A=${\r\n\n'A B'= \\'q'\"\nB= ${B:-d}\r\nD = \"q\"$A\"\r", +"expected": [ +[ +"A", +"${" +], +[ +"A B", +"\\'q'\"" +], +[ +"B", +"d" +] +] +}, +{ +"input": "'A B'= \\\"\t #c\r\nA= \n", +"expected": [ +[ +"A B", +"\\\"" +], +[ +"A", +"" +] +] +}, +{ +"input": " # c ' \"\n'A B'=${A}\r A= \tx y\\\"\n # c ' \"#A=\\'\n", +"expected": [ +[ +"A B", +"" +], +[ +"A", +"x y\\\"" +] +] +}, +{ +"input": "HOME_FROM_ENV=\u0e01\"q\"${\r\n#A==${A}${A}\rA== #c\\${B:-d}\"B= ${HOME_FROM_ENV}$A\nexport A= #c\"}${A}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\u0e01\"q\"${" +], +[ +"A", +"#c\"}=" +] +] +}, +{ +"input": "#A\t=\t\n A = 'q'\\'\"q\"\r\n#A=${\"q\"${HOME_FROM_ENV}B=\u0e01#A=$A #c\n", +"expected": [] +}, +{ +"input": "D = \" ${A} \nA B = x y\\\"\r\n#A==\\'\\'${A}\\n", +"expected": [ +[ +"D", +" \nA B = x y\\" +] +] +}, +{ +"input": "A\t=\t\n # c ' \"\rA B = #c\r\n", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "'A B'=\"q\"\rB = ${'q'abc\r\n", +"expected": [ +[ +"A B", +"q" +], +[ +"B", +"${'q'abc" +] +] +}, +{ +"input": "A=${HOME_FROM_ENV}${#${A}\r\nD = ${:-z}\nA=${A}\"q\"#\n", +"expected": [ +[ +"A", +"/home/x\"q\"#" +], +[ +"D", +"z" +] +] +}, +{ +"input": "C= \\'\t\r \r\n'A B'=\r\nHOME_FROM_ENV= \rA = \r", +"expected": [ +[ +"C", +"\\'" +], +[ +"A B", +"" +], +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"" +] +] +}, +{ +"input": "export A'\"q\" #c'q'\nB=='q'$A\n", +"expected": [ +[ +"A'\"q\"", +null +], +[ +"B", +"='q'$A" +] +] +}, +{ +"input": "D= #c$A${A}\nD = \r A${B:-d}\r", +"expected": [ +[ +"D", +"" +], +[ +"A${B:-d}", +null +] +] +}, +{ +"input": "A\t=\t\t\r\nA==\t\\}$A\r\n'A B'\t=\t${'A B'= \nA B\t=\t${:-z}\n", +"expected": [ +[ +"A", +"=\t\\}$A" +], +[ +"A B", +"${'A B'=" +] +] +}, +{ +"input": "# comment\rexport A=\\n${A}${B:-d}'\r\nexport A = \\'${A}${B:-d}${A}\r\nB = \r", +"expected": [ +[ +"A", +"\\'\\nd'd\\nd'" +], +[ +"B", +"" +] +] +}, +{ +"input": "D=\u0e01}\r\n#A = \u0e01${${HOME_FROM_ENV}\\'\nA B= #\"q\"\\'\rHOME_FROM_ENV= \r\nC==\\n\"q\" \r", +"expected": [ +[ +"D", +"\u0e01}" +], +[ +"HOME_FROM_ENV", +"" +], +[ +"C", +"=\\n\"q\"" +] +] +}, +{ +"input": "export A==abc${B:-d}'\r\n", +"expected": [ +[ +"A", +"=abcd'" +] +] +}, +{ +"input": " \n # c ' \"\nD\t=\t$A${A}\r\nB = \\\n", +"expected": [ +[ +"D", +"$A" +], +[ +"B", +"\\" +] +] +}, +{ +"input": "A= \t\"${:-z}\t\rB==\"\u0e01x yA==abc\u0e01x y\nC = ${HOME_FROM_ENV}'${\n A \r\n", +"expected": [ +[ +"C", +"/home/x'${" +], +[ +"A", +null +] +] +}, +{ +"input": "A B\t=\t", +"expected": [] +}, +{ +"input": "export A= \t${:-z}#\r", +"expected": [ +[ +"A", +"z#" +] +] +}, +{ +"input": "HOME_FROM_ENV=${A}'${A}$A\rA B = ${${A}\\\"${E = \"${:-z}\r#A= #c$A${HOME_FROM_ENV}'q'\r", +"expected": [ +[ +"HOME_FROM_ENV", +"'$A" +] +] +}, +{ +"input": "D = ${HOME_FROM_ENV}# commentA= abc${HOME_FROM_ENV}HOME_FROM_ENV=$A${B:-d}\n", +"expected": [ +[ +"D", +"/home/x# commentA= abc/home/xHOME_FROM_ENV=$Ad" +] +] +}, +{ +"input": "export A==\\'\r A\r\nexport Aabc ", +"expected": [ +[ +"A", +null +], +[ +"Aabc", +null +] +] +}, +{ +"input": "A==\t ", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "C\"q\" A==$A\t\r", +"expected": [] +}, +{ +"input": "'A B'==\n#A=${\rA B\u0e01 #c\n'A B' = ##\r\nD= #c", +"expected": [ +[ +"A B", +"##" +], +[ +"D", +"#c" +] +] +}, +{ +"input": "C='\t\r\n", +"expected": [] +}, +{ +"input": "'A B'\\'$A\\'${B:-d}\n A=\\\"\r\nD==${A}\\abc}\r\n", +"expected": [ +[ +"A", +"\\\"" +], +[ +"D", +"=\\\"\\abc}" +] +] +}, +{ +"input": " E\"q\"}}\r", +"expected": [ +[ +"E\"q\"}}", +null +] +] +}, +{ +"input": "C = \\\"x y \rC = \\}\\n${:-z}", +"expected": [ +[ +"C", +"\\}\\nz" +] +] +}, +{ +"input": "B\t=\t'q''\rHOME_FROM_ENV\t=\t\u0e01 #c'\r\n A== x y'q'\rD=\"q\"\\$A#A= \t\\\"\\'${HOME_FROM_ENV}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\u0e01" +], +[ +"A", +"= x y'q'" +] +] +}, +{ +"input": "# comment\r\n ", +"expected": [] +}, +{ +"input": "C= ${A}\r\nHOME_FROM_ENV==$A${B:-d}${B:-d}#\nB\t=\t${'q'\u0e01\r\nC = \"\t\t\n", +"expected": [ +[ +"C", +"" +], +[ +"HOME_FROM_ENV", +"=$Add#" +], +[ +"B", +"${'q'\u0e01" +] +] +}, +{ +"input": "# comment\rA B = ${\"${B:-d}\r\n'A B'== #c${B:-d}\n'A B' = ${A}${B:-d}\t\\'A B=='q'\\\r", +"expected": [ +[ +"A B", +"d\t\\'A B=='q'\\" +] +] +}, +{ +"input": "C = ${:-z}\\'\r#A\t=\t\\'x y\r\n#A#}\r\nHOME_FROM_ENV==\"\t #c}\nHOME_FROM_ENV = \\\"", +"expected": [ +[ +"C", +"z\\'" +], +[ +"HOME_FROM_ENV", +"\\\"" +] +] +}, +{ +"input": "D = }}'\"q\"\r\nE\t=\t\rA= ${HOME_FROM_ENV}\n'A B'= \"${:-z}\t${\nD=x y\r\n", +"expected": [ +[ +"D", +"x y" +], +[ +"E", +"" +], +[ +"A", +"/home/x" +] +] +}, +{ +"input": "HOME_FROM_ENV=${A}${:-z}${${A}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"z" +] +] +}, +{ +"input": "A B = \\\"${HOME_FROM_ENV}\n", +"expected": [] +}, +{ +"input": "A B==${\nA==}\\\"q\"${A}'A B'= \n # c ' \"\rD= #c\\\"${:-z}\r", +"expected": [ +[ +"A", +"=}\\\"q\"'A B'=" +], +[ +"D", +"#c\\\"z" +] +] +}, +{ +"input": "D = \\' #c\\\t\n A='$A'q'\nHOME_FROM_ENV\\\"\u0e01\r\nHOME_FROM_ENV==${A}#\r\n", +"expected": [ +[ +"D", +"\\'" +], +[ +"HOME_FROM_ENV\\\"\u0e01", +null +], +[ +"HOME_FROM_ENV", +"=#" +] +] +}, +{ +"input": " E${B:-d}${HOME_FROM_ENV}${:-z}${A}\n'A B'=}${:-z}${:-z}\nA B=\\n#'q'\"q\"\r\n", +"expected": [ +[ +"E${B:-d}${HOME_FROM_ENV}${:-z}${A}", +null +], +[ +"A B", +"}zz" +] +] +}, +{ +"input": "# comment\r#A\\\"\\n${A}\\n\r\nE${#${HOME_FROM_ENV}\nA${\"q\"#\"q\"", +"expected": [ +[ +"E${", +null +], +[ +"A${\"q\"", +null +] +] +}, +{ +"input": "B==${:-z}\nA B\r\nA\t=\t'\\\" #c\rC=\r", +"expected": [ +[ +"B", +"=z" +], +[ +"C", +"" +] +] +}, +{ +"input": "C=x y$A\r\nC\t=\t\t\nC= x y\u0e01#abc\rD\t=\t\"q\"\n", +"expected": [ +[ +"C", +"x y\u0e01#abc" +], +[ +"D", +"q" +] +] +}, +{ +"input": "A Babc\u0e01 \r \r\n# comment\r\n# comment\n", +"expected": [] +}, +{ +"input": " A = \u0e01\nB= ${B:-d}'q'\r\nHOME_FROM_ENV= \r\n", +"expected": [ +[ +"A", +"\u0e01" +], +[ +"B", +"d'q'" +], +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\t${A}\r", +"expected": [ +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "B==${HOME_FROM_ENV}${A}\\\"\u0e01\nHOME_FROM_ENV\t\t\nC\t=\t\\'${HOME_FROM_ENV}\"q\"\t\n", +"expected": [ +[ +"B", +"=/home/x\\\"\u0e01" +], +[ +"HOME_FROM_ENV", +null +], +[ +"C", +"\\'/home/x\"q\"" +] +] +}, +{ +"input": "# comment\rA B==\\\"\" C\\'$A${\rE=\"", +"expected": [] +}, +{ +"input": "'A B'\t\\'x y}\r\n", +"expected": [] +}, +{ +"input": "A B=}${B:-d}\\n\r\n A\\${HOME_FROM_ENV}\nexport A = x y\n", +"expected": [ +[ +"A\\${HOME_FROM_ENV}", +null +], +[ +"A", +"x y" +] +] +}, +{ +"input": "A\t=\t\tx y\u0e01D\t=\t${B:-d}${A}'q'\r\nD${:-z}'}", +"expected": [ +[ +"A", +"x y\u0e01D\t=\td'q'" +], +[ +"D${:-z}'}", +null +] +] +}, +{ +"input": "'A B'\t=\t\r'A B'= \\''q'\t\nexport A= $A#\r\n A\\'\u0e01$A\n", +"expected": [ +[ +"A B", +"\\''q'" +], +[ +"A", +"$A#" +], +[ +"A\\'\u0e01$A", +null +] +] +}, +{ +"input": "C = ${:-z}${B:-d} #cC = \nB\t=\t ${\"", +"expected": [ +[ +"C", +"zd" +], +[ +"B", +"${\"" +] +] +}, +{ +"input": "A= ${B:-d}\\'A B'= #\\\"${:-z}\n", +"expected": [ +[ +"A", +"d\\'A B'=" +] +] +}, +{ +"input": "export A==\\", +"expected": [ +[ +"A", +"=\\" +] +] +}, +{ +"input": "B = 'q'\rE\t=\t${HOME_FROM_ENV} #c${ A\t=\t\" # c ' \"\n", +"expected": [ +[ +"B", +"q" +], +[ +"E", +"/home/x" +] +] +}, +{ +"input": "C = \\x y\r A=\r", +"expected": [ +[ +"C", +"\\x y" +], +[ +"A", +"" +] +] +}, +{ +"input": "A\"\r\nD\\nE\t=\t${\"q\"${B:-d}\nA\t=\t# comment", +"expected": [ +[ +"A\"", +null +], +[ +"D\\nE", +"d" +], +[ +"A", +"# comment" +] +] +}, +{ +"input": " A\"\t\r", +"expected": [ +[ +"A\"", +null +] +] +}, +{ +"input": " A = $A\nA\r", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "#A = #abcC= abc\\'\\n\rB= ${\"\r\nA==\\n$A\\'\r\n# comment\r", +"expected": [ +[ +"B", +"${\"" +], +[ +"A", +"=\\n$A\\'" +] +] +}, +{ +"input": "D==${#\u0e01HOME_FROM_ENV\t=\t${:-z}\t\"q\"\\\"A= ${A}${HOME_FROM_ENV}${#\r", +"expected": [ +[ +"D", +"=z\t\"q\"\\\"A= /home/x${#" +] +] +}, +{ +"input": "E = \u0e01abc\"q\"${HOME_FROM_ENV}\nA B = \\\"'q'\r\nD==${A}\\'\n", +"expected": [ +[ +"E", +"\u0e01abc\"q\"/home/x" +], +[ +"D", +"=\\'" +] +] +}, +{ +"input": "HOME_FROM_ENV==#x y\nA B= \u0e01'q'", +"expected": [ +[ +"HOME_FROM_ENV", +"=#x y" +] +] +}, +{ +"input": " A = '${A}${HOME_FROM_ENV}\t#A=x y\\$A #c\r\nHOME_FROM_ENV\t=\t", +"expected": [ +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "D=='\nC= #cexport A \\${HOME_FROM_ENV}abc\r\nD=${B:-d}\\n\u0e01${:-z}", +"expected": [ +[ +"D", +"d\\n\u0e01z" +], +[ +"C", +"#cexport A \\/home/xabc" +] +] +}, +{ +"input": "A B=\\\"\rHOME_FROM_ENV=\"${\r\n'A B'= \r\nA = ${HOME_FROM_ENV}'q'\\", +"expected": [ +[ +"A B", +"" +], +[ +"A", +"/home/x'q'\\" +] +] +}, +{ +"input": "HOME_FROM_ENV= ${A}\nA = \\'A==${:-z}${HOME_FROM_ENV}'x y", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"\\'A==z/home/x'x y" +] +] +}, +{ +"input": "B=x y${A}\r", +"expected": [ +[ +"B", +"x y" +] +] +}, +{ +"input": "export A\t=\t\r\n", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "A\t=\t\rexport A=# \r\nB\tx yE=='x y\r", +"expected": [ +[ +"A", +"#" +] +] +}, +{ +"input": "#A\t=\t\r'A B'=='q'$A\n", +"expected": [ +[ +"A B", +"='q'$A" +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\t\u0e01${A}${:-z}${:-z}\rC=='\t${\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\u0e01zz" +], +[ +"C", +"='\t${" +] +] +}, +{ +"input": "HOME_FROM_ENV=${A}$A\r\nB = ${HOME_FROM_ENV}\\n${B:-d}", +"expected": [ +[ +"HOME_FROM_ENV", +"$A" +], +[ +"B", +"/home/x\\nd" +] +] +}, +{ +"input": "HOME_FROM_ENV\t'q'\t${C = #A= abc A", +"expected": [] +}, +{ +"input": "E='q'\\#\nHOME_FROM_ENV = $Aabc\\n A${'q'\t${:-z}", +"expected": [ +[ +"HOME_FROM_ENV", +"$Aabc\\n Az" +] +] +}, +{ +"input": "export A==\\'\\\\\"\r\n", +"expected": [ +[ +"A", +"=\\'\\\\\"" +] +] +}, +{ +"input": "E = #c\r\nA=# comment\n# comment\r\nexport A==\n", +"expected": [ +[ +"E", +"#c" +], +[ +"A", +"=" +] +] +}, +{ +"input": " E=abc\"q\"\rHOME_FROM_ENV==$A${HOME_FROM_ENV}${A}${B:-d}B\t=\t\\n${:-z}C = #", +"expected": [ +[ +"E", +"abc\"q\"" +], +[ +"HOME_FROM_ENV", +"=$A/home/xdB\t=\t\\nzC =" +] +] +}, +{ +"input": "#A==\r\nC\\\"\"\r\nA\\n\\${HOME_FROM_ENV}${\nB${:-z}abc'A B'\u0e01\u0e01\r", +"expected": [ +[ +"C\\\"\"", +null +], +[ +"A\\n\\${HOME_FROM_ENV}${", +null +] +] +}, +{ +"input": "#A\t=\t${x y}\r\nB==}\u0e01${:-z}\n", +"expected": [ +[ +"B", +"=}\u0e01z" +] +] +}, +{ +"input": "#A = A=\"\t\\\"${A}\nHOME_FROM_ENV==${B:-d}", +"expected": [ +[ +"HOME_FROM_ENV", +"=d" +] +] +}, +{ +"input": "D'q'\n", +"expected": [ +[ +"D'q'", +null +] +] +}, +{ +"input": "E==x y\nB= ${A}}${:-z}\\\"\rC== 'q''q' #c\nexport A#A= ${A}\\\"", +"expected": [ +[ +"E", +"=x y" +], +[ +"B", +"}z\\\"" +], +[ +"C", +"= 'q''q'" +], +[ +"A", +null +] +] +}, +{ +"input": "#A = #c #c\\\"\nB'abc${HOME_FROM_ENV}\"q\"", +"expected": [ +[ +"B'abc${HOME_FROM_ENV}\"q\"", +null +] +] +}, +{ +"input": "export A= ${B:-d}\"q\" \r\nD\t=\t${\t${ #c\rC= '", +"expected": [ +[ +"A", +"d\"q\"" +], +[ +"D", +"${\t${" +] +] +}, +{ +"input": "B= #c\t'q'\r A\t=\t\"q\"\u0e01\"D#\\'}\\n\r\n # c ' \"\r\nE==\r\n", +"expected": [ +[ +"B", +"#c\t'q'" +], +[ +"E", +"=" +] +] +}, +{ +"input": "export A\"\t\r#A=${HOME_FROM_ENV}\\\"export A\rHOME_FROM_ENV= \n A= \\\"\"$A'q'\n", +"expected": [ +[ +"A\"", +null +], +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"\\\"\"$A'q'" +] +] +}, +{ +"input": " \r A==${HOME_FROM_ENV}\\\"abc\nexport A= ${A} #c\r\nC= ${B:-d}'q'${HOME_FROM_ENV}'q'\r\n", +"expected": [ +[ +"A", +"=/home/x\\\"abc" +], +[ +"C", +"d'q'/home/x'q'" +] +] +}, +{ +"input": " # c ' \"\r\nAabc${A}##\n", +"expected": [ +[ +"Aabc${A}", +null +] +] +}, +{ +"input": "B==\"q\"${${B:-d}$A\r", +"expected": [ +[ +"B", +"=\"q\"d$A" +] +] +}, +{ +"input": "export A= abc \"q\"x y", +"expected": [ +[ +"A", +"abc \"q\"x y" +] +] +}, +{ +"input": "A= \\\"${HOME_FROM_ENV}'", +"expected": [ +[ +"A", +"\\\"/home/x'" +] +] +}, +{ +"input": "B==$A}${B:-d}\t\r\nD\t=\t\\n\"q\"\n A='q'\"q\"\n", +"expected": [ +[ +"B", +"=$A}d" +], +[ +"D", +"\\n\"q\"" +] +] +}, +{ +"input": "C$A\r\nA B = 'q''\n'A B'= \\C= \r\n", +"expected": [ +[ +"C$A", +null +], +[ +"A B", +"\\C=" +] +] +}, +{ +"input": "'A B'\t=\t$A'#\r\n#A\\}}\\'\n", +"expected": [ +[ +"A B", +"$A'#" +] +] +}, +{ +"input": "'A B' = \"q\"'q'x y\r A${A} \n", +"expected": [ +[ +"A${A}", +null +] +] +}, +{ +"input": "C=\u0e01${HOME_FROM_ENV}\"${:-z}\nE= \\n${HOME_FROM_ENV}${:-z}\\n\nB}\t\t\r\nA = #c\r", +"expected": [ +[ +"C", +"\u0e01/home/x\"z" +], +[ +"E", +"\\n/home/xz\\n" +], +[ +"B}", +null +], +[ +"A", +"#c" +] +] +}, +{ +"input": "C${abc\nA B==${:-z}${A}#\r\n", +"expected": [ +[ +"C${abc", +null +] +] +}, +{ +"input": "export A\t=\t $A${B:-d}\rexport A= ${A}x yA B\n# comment\r\n# comment\n", +"expected": [ +[ +"A", +"$Adx yA B" +] +] +}, +{ +"input": "HOME_FROM_ENV${HOME_FROM_ENV}'\"\r\n", +"expected": [ +[ +"HOME_FROM_ENV${HOME_FROM_ENV}'\"", +null +] +] +}, +{ +"input": "#A = '\u0e01${HOME_FROM_ENV}\n", +"expected": [] +}, +{ +"input": " A = 'abc\u0e01\r\nC\t=\t$A #c\"q\"\"\r\n # c ' \"\r", +"expected": [] +}, +{ +"input": "A B=\\'\\\"\r\nB\t=\t\" #c\t\r\n'A B' = \"q\"${${HOME_FROM_ENV}D = \"\"\r\nD==\\n\\\"\r\n", +"expected": [ +[ +"D", +"=\\n\\\"" +] +] +}, +{ +"input": " \n'A B'==\u0e01\u0e01${A}${HOME_FROM_ENV}B = \\'\r'A B'\t${HOME_FROM_ENV}abc\n", +"expected": [ +[ +"A B", +"=\u0e01\u0e01/home/xB = \\'" +] +] +}, +{ +"input": "A\\\nHOME_FROM_ENV\r\nE\r\nC==\nC\t=\t\t\\", +"expected": [ +[ +"A\\", +null +], +[ +"HOME_FROM_ENV", +null +], +[ +"E", +null +], +[ +"C", +"\\" +] +] +}, +{ +"input": "A B=}\u0e01\tE\"q\"\n", +"expected": [] +}, +{ +"input": "#A=${\\\"\rC= \n A\\'${${\r", +"expected": [ +[ +"C", +"" +], +[ +"A\\'${${", +null +] +] +}, +{ +"input": " # c ' \"\r\nE= ${HOME_FROM_ENV}#\nD = \\'${HOME_FROM_ENV}\"q\"\r\nA B = \"${ #c'q'", +"expected": [ +[ +"E", +"/home/x#" +], +[ +"D", +"\\'/home/x\"q\"" +] +] +}, +{ +"input": "E=='q'\\abc\r\nD= ${A}\r\nE==E==\u0e01${B:-d}\"export A= \"q\"${A}'q'${HOME_FROM_ENV}", +"expected": [ +[ +"E", +"=E==\u0e01d\"export A= \"q\"'q'/home/x" +], +[ +"D", +"" +] +] +}, +{ +"input": "A= 'q'\nA B==\t}#\r A\n", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "export A = \\\"$A\"q\"A B = \"q\"\r\n'A B'==\\${A}\r\n # c ' \"'A B'\t=\t\u0e01${HOME_FROM_ENV}\r\n", +"expected": [ +[ +"A", +"\\\"$A\"q\"A B = \"q\"" +], +[ +"A B", +"=\\\\\"$A\"q\"A B = \"q\"" +] +] +}, +{ +"input": "'A B'\t=\t'A B'=\\'${HOME_FROM_ENV} #c${HOME_FROM_ENV}\nB\r#A==x y\\n\\\r\n", +"expected": [ +[ +"B", +null +] +] +}, +{ +"input": "D\t=\tabc'\t'\r\n# commentC = \nC\t=\t'${A}'${HOME_FROM_ENV}A\t=\t}\t", +"expected": [ +[ +"D", +"abc'\t'" +] +] +}, +{ +"input": "'A B'= \"q\"\\n#${\rB=${HOME_FROM_ENV}\\\"\r\nB=\\\"abc\rA B=='q'\n \r\n", +"expected": [ +[ +"B", +"\\\"abc" +] +] +}, +{ +"input": " export A= x y\r\n", +"expected": [ +[ +"A", +"x y" +] +] +}, +{ +"input": "export A==x y'q'${A}\rD=abc'A'q'} #c\u0e01\r", +"expected": [ +[ +"A", +"=x y'q'" +], +[ +"D", +"abc'A'q'}" +] +] +}, +{ +"input": "A B=\n", +"expected": [] +}, +{ +"input": "E = \rA B = ${:-z}\rexport A\\'\r\nC}\\'x y${B:-d}\nHOME_FROM_ENV== ${\t", +"expected": [ +[ +"E", +"" +], +[ +"A\\'", +null +], +[ +"HOME_FROM_ENV", +"= ${" +] +] +}, +{ +"input": "D = \nHOME_FROM_ENV= ${A}\n", +"expected": [ +[ +"D", +"" +], +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "D = \\\r\r", +"expected": [ +[ +"D", +"\\" +] +] +}, +{ +"input": "B=\t\nA B==\nD= ${:-z}${B:-d}${HOME_FROM_ENV} HOME_FROM_ENV = ${$A}'A B'=#", +"expected": [ +[ +"B", +"" +], +[ +"D", +"z/home/x HOME_FROM_ENV = 'A B'=#" +] +] +}, +{ +"input": " # c ' \"Cx y'\r\nHOME_FROM_ENV==\u0e01x y\texport A= }\r", +"expected": [ +[ +"HOME_FROM_ENV", +"=\u0e01x y\texport A= }" +] +] +}, +{ +"input": "HOME_FROM_ENV = \\ x yD==\r\nA B\"q\"abc${HOME_FROM_ENV}$A\nC = #c${A}\r\nE=${${HOME_FROM_ENV}${ #c\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"\\ x yD==" +], +[ +"C", +"#c" +], +[ +"E", +"${" +] +] +}, +{ +"input": "'A B'\" #c #c'\r\nE\t=\t\\\"D=${A}${HOME_FROM_ENV}abc\u0e01", +"expected": [ +[ +"E", +"\\\"D=/home/xabc\u0e01" +] +] +}, +{ +"input": "D= \r'A B' = \n", +"expected": [ +[ +"D", +"" +], +[ +"A B", +"" +] +] +}, +{ +"input": "E\t=\t${A}\\'$A\n \r\n A = \\'\\n$AE= #\\\"\n", +"expected": [ +[ +"E", +"\\'$A" +], +[ +"A", +"\\'\\n$AE=" +] +] +}, +{ +"input": "A${A}\nC\t=\t\\'${A}\n # c ' \"\r", +"expected": [ +[ +"A${A}", +null +], +[ +"C", +"\\'" +] +] +}, +{ +"input": "#A=", +"expected": [] +}, +{ +"input": "E = \"q\"${:-z}\n'A B'\\\"${HOME_FROM_ENV}\r\nexport A==\\n #c '\nA B = $A ${:-z}", +"expected": [ +[ +"A", +"=\\n" +] +] +}, +{ +"input": " A\t=\t\\nD\t=\t\rA==\\\"\"q\"\n", +"expected": [ +[ +"A", +"=\\\"\"q\"" +] +] +}, +{ +"input": "D= \\'A B==${B:-d}\rE\t=\t\rA\t=\t\t\r", +"expected": [ +[ +"D", +"\\'A B==d" +], +[ +"E", +"" +], +[ +"A", +"" +] +] +}, +{ +"input": "'A B'= #A= \nE'\r\n'A B'==\n # c ' \"", +"expected": [ +[ +"A B", +"=" +], +[ +"E'", +null +] +] +}, +{ +"input": " # c ' \"\n", +"expected": [] +}, +{ +"input": "C\t=\t\r\nC==#abc}'A B'=\rHOME_FROM_ENV'${A}${A}\r\n", +"expected": [ +[ +"C", +"=#abc}'A B'=" +], +[ +"HOME_FROM_ENV'${A}${A}", +null +] +] +}, +{ +"input": "C = \u0e01\r\n", +"expected": [ +[ +"C", +"\u0e01" +] +] +}, +{ +"input": "#A=${:-z}\\'\\n\n\r\n", +"expected": [] +}, +{ +"input": "export A= \n A= '${HOME_FROM_ENV}}\r", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "B\\n${:-z}\t\nA B= \"}\"\n # c ' \"\r\n", +"expected": [ +[ +"B\\n${:-z}", +null +] +] +}, +{ +"input": "\r\nexport A = 'q''\\${A}\r\nHOME_FROM_ENV=$A${#A=\nexport A= ${A}${:-z}${B:-d}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"$A${#A=" +], +[ +"A", +"zd" +] +] +}, +{ +"input": " A=\\n${A}\n#A\t=\t${'\nexport A\t=\t${abc\u0e01\r\nA'q'x y\r\nexport A==\n", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "export AabcHOME_FROM_ENV = ${' #c \rD= \u0e01'A B'==\"q\"\\nabc\r", +"expected": [ +[ +"AabcHOME_FROM_ENV", +"${'" +], +[ +"D", +"\u0e01'A B'==\"q\"\\nabc" +] +] +}, +{ +"input": "C=", +"expected": [ +[ +"C", +"" +] +] +}, +{ +"input": "C}}${HOME_FROM_ENV}\r", +"expected": [ +[ +"C}}${HOME_FROM_ENV}", +null +] +] +}, +{ +"input": "\n", +"expected": [] +}, +{ +"input": "'A B'=\rexport A==A B} }#", +"expected": [ +[ +"A B", +"" +], +[ +"A", +"=A B} }#" +] +] +}, +{ +"input": "# comment\n#A\r\nA = \"q\"x y${B:-d}\r\n A\t=\t", +"expected": [ +[ +"A", +"" +] +] +}, +{ +"input": "C\t=\t## comment\n# comment\r\n", +"expected": [ +[ +"C", +"## comment" +] +] +}, +{ +"input": "E = \r\nC$A'q'\rD${B:-d}${A}\\}", +"expected": [ +[ +"E", +"" +], +[ +"C$A'q'", +null +], +[ +"D${B:-d}${A}\\}", +null +] +] +}, +{ +"input": " HOME_FROM_ENV${\nC=${HOME_FROM_ENV}\\\"\"\r'A B'==\r\n", +"expected": [ +[ +"HOME_FROM_ENV${", +null +], +[ +"C", +"/home/x\\\"\"" +], +[ +"A B", +"=" +] +] +}, +{ +"input": " A\\\"\u0e01", +"expected": [ +[ +"A\\\"\u0e01", +null +] +] +}, +{ +"input": " # c ' \"\r # c ' \"\r\nE\"\nexport A==${\\'\"q\"$A\r", +"expected": [ +[ +"E\"", +null +], +[ +"A", +"=${\\'\"q\"$A" +] +] +}, +{ +"input": "B = } #c\r\n \r\n A\t=\t\"q\"", +"expected": [ +[ +"B", +"}" +], +[ +"A", +"q" +] +] +}, +{ +"input": "D = ${:-z}\\'#A = #\"q\"${\r\nD'q'\n#A= x y\r\n", +"expected": [ +[ +"D", +"z\\'#A =" +], +[ +"D'q'", +null +] +] +}, +{ +"input": "export A\t=\t ${A}}abc\r# commentA B\rA B\t=\t ${HOME_FROM_ENV}\"\r\n# comment\n", +"expected": [ +[ +"A", +"}abc" +] +] +}, +{ +"input": "E= } #c$A\\\r#A=\nB= ${\nD = ${A}\r", +"expected": [ +[ +"E", +"}" +], +[ +"B", +"${" +], +[ +"D", +"" +] +] +}, +{ +"input": "C${HOME_FROM_ENV}\t${HOME_FROM_ENV}\nC= }\\'", +"expected": [ +[ +"C", +"}\\'" +] +] +}, +{ +"input": "\r\n A${HOME_FROM_ENV}\u0e01\t\r\nB = \\\"\rC\t=\t\r\nC = $A \n", +"expected": [ +[ +"A${HOME_FROM_ENV}\u0e01", +null +], +[ +"B", +"\\\"" +], +[ +"C", +"$A" +] +] +}, +{ +"input": "A B== \\n\nexport A= ${x y\r\n A= ${B:-d}${A}${B:-d}${HOME_FROM_ENV}\n#A\u0e01\"q\"", +"expected": [ +[ +"A", +"d${x yd/home/x" +] +] +}, +{ +"input": "# comment\r \r# comment\r\nC= \t$A\\n\nE\t=\tabc\"q\"\r\n", +"expected": [ +[ +"C", +"$A\\n" +], +[ +"E", +"abc\"q\"" +] +] +}, +{ +"input": "#A==\"\"x y\"q\"\r\nHOME_FROM_ENV\t=\t\r A = \\}${B:-d}\r\n\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"" +], +[ +"A", +"\\}d" +] +] +}, +{ +"input": "#A\t\rB#\r\nA\t=\t\n", +"expected": [ +[ +"B", +null +], +[ +"A", +"" +] +] +}, +{ +"input": " A = \"\nB\t=\t #c\r\nD=='\t\"\r", +"expected": [ +[ +"A", +"\nB\t=\t #c\r\nD=='\t" +] +] +}, +{ +"input": "C\t=\t# \"q\"\rexport A\\'\"q\"${HOME_FROM_ENV}\\'\r A = ${${:-z}\u0e01${A}", +"expected": [ +[ +"C", +"# \"q\"" +], +[ +"A\\'\"q\"${HOME_FROM_ENV}\\'", +null +], +[ +"A", +"z\u0e01" +] +] +}, +{ +"input": "C= \"\rHOME_FROM_ENV\t=\t${\r\nexport A\t=\t${:-z}\n", +"expected": [ +[ +"HOME_FROM_ENV", +"${" +], +[ +"A", +"z" +] +] +}, +{ +"input": "C\t=\t\n'A B'=${", +"expected": [ +[ +"C", +"" +], +[ +"A B", +"${" +] +] +}, +{ +"input": "A B=x y${B:-d}D = A${A}\\'\r\n", +"expected": [] +}, +{ +"input": "E\"${'q'\rexport A\t=\t${HOME_FROM_ENV}${:-z}\"\\\r\nD=\\\"\"", +"expected": [ +[ +"E\"${'q'", +null +], +[ +"A", +"/home/xz\"\\" +], +[ +"D", +"\\\"\"" +] +] +}, +{ +"input": "D==x y\rA\t=\t${:-z}\\'${abc\r\nE\t=\t${A}\t\n'A B'= \n", +"expected": [ +[ +"D", +"=x y" +], +[ +"A", +"z\\'${abc" +], +[ +"E", +"z\\'${abc" +], +[ +"A B", +"" +] +] +}, +{ +"input": "'A B' = \t\r\nC==${A}${ }\r", +"expected": [ +[ +"A B", +"" +], +[ +"C", +"=" +] +] +}, +{ +"input": "D==\\\"q\"\r\n A= \tx y\rA B #c\n", +"expected": [ +[ +"D", +"=\\\"q\"" +], +[ +"A", +"x y" +] +] +}, +{ +"input": "C= 'q' #c'\r\nE=\t\rD='q'${B:-d}${:-z}D==\u0e01\nexport A\t=\t'\n", +"expected": [ +[ +"C", +"q" +], +[ +"E", +"" +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\t\r", +"expected": [ +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "E= ${${B:-d}\nA B = \\\nHOME_FROM_ENV = ${HOME_FROM_ENV}\\n'q'\nC\r\n", +"expected": [ +[ +"E", +"d" +], +[ +"HOME_FROM_ENV", +"/home/x\\n'q'" +], +[ +"C", +null +] +] +}, +{ +"input": "'A B'=A B\nB = ${HOME_FROM_ENV}' #c\r\n\r\n", +"expected": [ +[ +"A B", +"A B" +], +[ +"B", +"/home/x'" +] +] +}, +{ +"input": "A B\"q\"${B:-d} #c\\n\rD\t=\t'\u0e01\n#A==abc${HOME_FROM_ENV}", +"expected": [] +}, +{ +"input": " A= #' #c\r", +"expected": [ +[ +"A", +"#'" +] +] +}, +{ +"input": "HOME_FROM_ENV==\\'D = \\\"\"q\"\u0e01\\n\r'A B'=\\n#A = \\'x y}${A}\r", +"expected": [ +[ +"HOME_FROM_ENV", +"=\\'D = \\\"\"q\"\u0e01\\n" +], +[ +"A B", +"\\n#A = \\'x y}" +] +] +}, +{ +"input": "export A= D=\\\nA B=\u0e01 #c\\\"#\r\n#A = '\"q\"\nD= \r\n", +"expected": [ +[ +"A", +"D=\\" +], +[ +"D", +"" +] +] +}, +{ +"input": "B = \\x y${HOME_FROM_ENV}\\n \nE=\\n\nD==", +"expected": [ +[ +"B", +"\\x y/home/x\\n" +], +[ +"E", +"\\n" +], +[ +"D", +"=" +] +] +}, +{ +"input": " # c ' \"\rA B\t=\t'A B'=}\r'A B'== '${A}B==\\\n", +"expected": [ +[ +"A B", +"= 'B==\\" +] +] +}, +{ +"input": "#A\t=\t\\n\\nA\t=\t\r", +"expected": [] +}, +{ +"input": " A = \"abc${:-z}\u0e01\r\n A = \\\"\rBx y\\'A B = }abc", +"expected": [ +[ +"A", +"abcz\u0e01\r\n A = \\" +] +] +}, +{ +"input": "A = \nC=='q'\\'#abc\rB= #cA B#A = \\\"\r\n", +"expected": [ +[ +"A", +"" +], +[ +"C", +"='q'\\'#abc" +], +[ +"B", +"#cA B#A = \\\"" +] +] +}, +{ +"input": "export A = ${ #c\r\nC${B:-d}${:-z} #c${:-z}\rA = abc\r\n", +"expected": [ +[ +"A", +"abc" +], +[ +"C${B:-d}${:-z}", +null +] +] +}, +{ +"input": "D==}$A${:-z}\r\n#A #c", +"expected": [ +[ +"D", +"=}$Az" +] +] +}, +{ +"input": "A B=\\' #c'${HOME_FROM_ENV}\n", +"expected": [] +}, +{ +"input": "A B = ${A}\nA B${HOME_FROM_ENV}\n", +"expected": [] +}, +{ +"input": "E==}#\n", +"expected": [ +[ +"E", +"=}#" +] +] +}, +{ +"input": "'A B'\t=\t\\'\r\n#A==HOME_FROM_ENV= \r", +"expected": [ +[ +"A B", +"\\'" +] +] +}, +{ +"input": "'A B' 'x y\\'\r", +"expected": [] +}, +{ +"input": "export A = x y #c''q'HOME_FROM_ENV= \r\nE\u0e01\n", +"expected": [ +[ +"A", +"x y" +], +[ +"E\u0e01", +null +] +] +}, +{ +"input": "# comment\rA B==#\rB==${'${:-z}${HOME_FROM_ENV}\nD = ${:-z}", +"expected": [ +[ +"B", +"=z/home/x" +], +[ +"D", +"z" +] +] +}, +{ +"input": "C\t=\t #c\r'A B'${:-z}${HOME_FROM_ENV}${:-z}\\'\n#A\t=\t}\n", +"expected": [ +[ +"C", +"#c" +] +] +}, +{ +"input": "A B==abc\\\t\r\n", +"expected": [] +}, +{ +"input": "export A=\nE= #\r", +"expected": [ +[ +"A", +"" +], +[ +"E", +"#" +] +] +}, +{ +"input": "'A B'=='q'\t${${:-z}\r\n# comment\n A}$A\r\nexport A${B:-d} ${B:-d}\r", +"expected": [ +[ +"A B", +"='q'\tz" +], +[ +"A}$A", +null +] +] +}, +{ +"input": "'A B'==abc\rB = x y\t}${:-z}\r", +"expected": [ +[ +"A B", +"=abc" +], +[ +"B", +"x y\t}z" +] +] +}, +{ +"input": "export A", +"expected": [ +[ +"A", +null +] +] +}, +{ +"input": "# comment\r\n'A B'= \\n #c\\\"\"q\"'A B'==\r", +"expected": [ +[ +"A B", +"\\n" +] +] +}, +{ +"input": "C= \rB\t=\t\\\"\t'q'${HOME_FROM_ENV}\r\n", +"expected": [ +[ +"C", +"" +], +[ +"B", +"\\\"\t'q'/home/x" +] +] +}, +{ +"input": "A B = ${A}\r\nA B\t=\t\u0e01# #c\r", +"expected": [] +}, +{ +"input": "#A\t=\t\u0e01'x y\nB\"}", +"expected": [ +[ +"B\"}", +null +] +] +}, +{ +"input": "# comment\r#A\t=\t\\${HOME_FROM_ENV}$A${B:-d}\r", +"expected": [] +}, +{ +"input": " A = \"q\"${:-z}# comment\r\nB= abcx y'q'\\\"D== ${:-z}\t\r", +"expected": [ +[ +"B", +"abcx y'q'\\\"D== z" +] +] +}, +{ +"input": "A==\r", +"expected": [ +[ +"A", +"=" +] +] +}, +{ +"input": "E\rB = #A==x y}", +"expected": [ +[ +"E", +null +], +[ +"B", +"#A==x y}" +] +] +}, +{ +"input": "HOME_FROM_ENV==\t\r\nE\t=\t${:-z}\u0e01#${\r\nexport A= \r'A B'== \r\nB = \"q\"${B:-d}\\n\n", +"expected": [ +[ +"HOME_FROM_ENV", +"=" +], +[ +"E", +"z\u0e01#${" +], +[ +"A", +"" +], +[ +"A B", +"=" +] +] +}, +{ +"input": "D'q' $Aexport A'''\n", +"expected": [] +}, +{ +"input": "export A = \r\nC= \\nexport A = \"abc}\\A B= ${\r\nB=\r", +"expected": [ +[ +"A", +"" +], +[ +"C", +"\\nexport A = \"abc}\\A B= ${" +], +[ +"B", +"" +] +] +}, +{ +"input": "export A==\\\"\\${'\nA B==\u0e01\\'\r\nexport A\rA'\"q\"\\n#B=${HOME_FROM_ENV}\\'\r\n", +"expected": [ +[ +"A", +null +], +[ +"A'\"q\"\\n", +null +] +] +}, +{ +"input": " \r#A\t=\t\t\"q\"abc${:-z}\nHOME_FROM_ENV==C=\r\n # c ' \"\r\n", +"expected": [ +[ +"HOME_FROM_ENV", +"=C=" +] +] +}, +{ +"input": "export A= #c${:-z}\u0e01'\r\nHOME_FROM_ENV= \u0e01\\n${:-z}${A}HOME_FROM_ENV = ${HOME_FROM_ENV}Ax y${HOME_FROM_ENV}A B=", +"expected": [ +[ +"A", +"#cz\u0e01'" +], +[ +"HOME_FROM_ENV", +"\u0e01\\nz#cz\u0e01'HOME_FROM_ENV = /home/xAx y/home/xA B=" +] +] +}, +{ +"input": "B = \r\n#A= \t${HOME_FROM_ENV}abc\rA B\t=\t$A${:-z}\r", +"expected": [ +[ +"B", +"" +] +] +}, +{ +"input": "A= \"x y$AD = \t${HOME_FROM_ENV}\n'A B'==}", +"expected": [ +[ +"A B", +"=}" +] +] +}, +{ +"input": "'A B' = ${B:-d}'q'", +"expected": [ +[ +"A B", +"d'q'" +] +] +}, +{ +"input": "HOME_FROM_ENV==\\ \\'\r\n'A B'\t=\t}\\\"\\\"\r\nD=\\'\\\\\"\r", +"expected": [ +[ +"HOME_FROM_ENV", +"=\\ \\'" +], +[ +"A B", +"}\\\"\\\"" +], +[ +"D", +"\\'\\\\\"" +] +] +}, +{ +"input": "HOME_FROM_ENV\t=\t\\\"\r\n \r\nB\t=\t\\\\\r\nC= \\\r", +"expected": [ +[ +"HOME_FROM_ENV", +"\\\"" +], +[ +"B", +"\\\\" +], +[ +"C", +"\\" +] +] +}, +{ +"input": "A B\\'abc\u0e01\r\n A= \nHOME_FROM_ENV\t=\t\n", +"expected": [ +[ +"A", +"" +], +[ +"HOME_FROM_ENV", +"" +] +] +}, +{ +"input": "A B\n", +"expected": [] +}, +{ +"input": " A= \t'q'${\\'export A = ${B:-d}x y\n", +"expected": [] +}, +{ +"input": "# comment\r\nC=\nA B = \r\nA=} ${abc\r\nBabc}\n", +"expected": [ +[ +"C", +"" +], +[ +"A", +"} ${abc" +], +[ +"Babc}", +null +] +] +}, +{ +"input": "E=${HOME_FROM_ENV}'E= \r\nC\t=\t\t\rC=", +"expected": [ +[ +"E", +"/home/x'E=" +], +[ +"C", +"" +] +] +}, +{ +"input": "B = \\${B:-d}$A\nB='q'${:-z} #c\\n\r\n", +"expected": [ +[ +"B", +"\\d$A" +] +] +}, +{ +"input": "E#\\ # comment\nC= \n", +"expected": [ +[ +"E", +null +], +[ +"C", +"" +] +] +}, +{ +"input": "export A=\"$A", +"expected": [] +}, +{ +"input": "E\"q\"export A\t=\t\t${A}\t\r\n#A= \t\nA=\u0e01\n'A B' = ${HOME_FROM_ENV}\\n\r\n", +"expected": [ +[ +"A", +"\u0e01" +], +[ +"A B", +"/home/x\\n" +] +] +}, +{ +"input": "E\r\n'A B'\t=\t\r'A B'==x y#B=${abc\nC = \\n${:-z}\\\"\"q\"\r", +"expected": [ +[ +"E", +null +], +[ +"A B", +"=x y#B=${abc" +], +[ +"C", +"\\nz\\\"\"q\"" +] +] +}, +{ +"input": "A B= \n", +"expected": [] +}, +{ +"input": "B= \\\"${:-z}#abc\r\nE\t=\t}\"q\"\t${\nA B==C= #c\\'\n", +"expected": [ +[ +"B", +"\\\"z#abc" +], +[ +"E", +"}\"q\"\t${" +] +] +}, +{ +"input": "C='# D==\\\" #c\\${A}\nA'q'${:-z}\\n\r", +"expected": [] +}, +{ +"input": "B==\\n${B:-d}# #cB\t=\t\t A = ${\nA Bx yx yE = ${B:-d}\r\n", +"expected": [ +[ +"B", +"=\\nd#" +] +] +} +] +} \ No newline at end of file diff --git a/rust/collector/testdata/gen_envfile_cases.py b/rust/collector/testdata/gen_envfile_cases.py new file mode 100644 index 0000000..42e4e1f --- /dev/null +++ b/rust/collector/testdata/gen_envfile_cases.py @@ -0,0 +1,122 @@ +"""Generate rust/collector/testdata/envfile_python_dotenv.json: python-dotenv's +own parse + interpolation of tricky .env inputs, used by the Rust envfile +tests so the collector reads .env exactly as the Python app does. + + uv run python rust/collector/testdata/gen_envfile_cases.py +""" + +import io +import json +import os +import random +from pathlib import Path + +import dotenv +from dotenv.main import DotEnv + +FIXED = [ + "A=abc'def\nB=x\"y\nC=1\n", + "A=1\nPOSTGRES_PASSWORD='abc\nB=2\n", + "A=1\nPOSTGRES_PASSWORD= \nB=2\n", + "POSTGRES_PASSWORD=\"ab'c\nB=2\n", + " export A = spaced value # comment\nB=a#b\n# c\n\nC= \nD\n", + "A='x\\'y'\nB=\"l1\\nl2\\t\\\"q\\\"\"\nC='multi\nline'\nD='a\\\\b'\n", + "A='ab\\'", + "A='x'y\nB=1\n", + "HOME_FROM_ENV=file\nA=${HOME_FROM_ENV}/x\nB=${A}-${MISSING:-dflt}-${NOPE}\nC=$A ${A:x}\n", + "A=1\r\nB=2\r\nA=3\r\n", + "C= # c\nD=#x\nE= #x\n", + "A#B=1\nexport\nexportA=2\n'q k'=3\n", + "\ufeffA=bom\n", + "A=\u00e9\u0e01\u0e02 # thai\n", +] + +KEYS = [ + "A", + "B", + "C", + "D", + "E", + "export A", + "'A B'", + "HOME_FROM_ENV", + "#A", + " A", + "A B", +] +SEPS = ["=", " = ", "= ", "", "\t=\t", "=="] +VALUE_BITS = [ + "abc", + "'", + '"', + "\\", + "#", + " #c", + "${A}", + "${B:-d}", + "${", + "}", + " ", + "\t", + "'q'", + '"q"', + "\\'", + '\\"', + "\\n", + "x y", + "${HOME_FROM_ENV}", + "${:-z}", + "$A", + "\u0e01", +] +EOLS = ["\n", "\r\n", "\r", ""] + + +def random_case(rng: random.Random) -> str: + lines = [] + for _ in range(rng.randint(1, 5)): + kind = rng.random() + if kind < 0.1: + lines.append(rng.choice(["", " ", "# comment", " # c ' \""])) + else: + value = "".join(rng.choice(VALUE_BITS) for _ in range(rng.randint(0, 4))) + lines.append(rng.choice(KEYS) + rng.choice(SEPS) + value) + lines.append(rng.choice(EOLS)) + return "".join(lines) + + +def expected(content: str): + values = DotEnv( + None, stream=io.StringIO(content), interpolate=True, override=False + ).dict() + return [[k, v] for k, v in values.items()] + + +def main(): + os.environ["HOME_FROM_ENV"] = "/home/x" + for k in ("A", "B", "C", "D", "E", "MISSING", "NOPE"): + os.environ.pop(k, None) + rng = random.Random(20261018) + inputs = FIXED + [random_case(rng) for _ in range(600)] + cases = [{"input": c, "expected": expected(c)} for c in inputs] + out = Path(__file__).with_name("envfile_python_dotenv.json") + out.write_text( + json.dumps( + { + "python_dotenv": dotenv.__dict__.get("__version__", "1.1.1"), + "env": {"HOME_FROM_ENV": "/home/x"}, + "cases": cases, + }, + ensure_ascii=True, + indent=0, + ), + encoding="utf-8", + ) + print(f"{len(cases)} cases -> {out}") + + +if __name__ == "__main__": + import logging + + logging.disable(logging.WARNING) # python-dotenv warns on every bad line + main() diff --git a/scripts/install_collector.sh b/scripts/install_collector.sh index 8dfd1a6..0035fac 100755 --- a/scripts/install_collector.sh +++ b/scripts/install_collector.sh @@ -17,6 +17,7 @@ set -euo pipefail APP_DIR="${APP_DIR:-/opt/thailand-water-monitor}" +SERVICE_USER="${SERVICE_USER:-water-monitor}" # as in scripts/ping-collector.service ENV_FILE="${APP_DIR}/.env" STATUS_FILE="${APP_DIR}/collector-status.json" REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" @@ -59,10 +60,19 @@ systemctl daemon-reload # the app dir: the units use PrivateTmp). set_env SCRAPING_STATUS_FILE "$STATUS_FILE" touch "$STATUS_FILE" -chown "$(stat -c %U:%G "$APP_DIR")" "$STATUS_FILE" +chown "${SERVICE_USER}:$(id -gn "$SERVICE_USER")" "$STATUS_FILE" log "Dry run against the configured database (writes nothing)" -(cd "$APP_DIR" && "${APP_DIR}/bin/ping-collector" --env-file "$ENV_FILE" once --dry-run) +# Run it the way the service will: same user, working directory and +# EnvironmentFile parsing (systemd's, not a .env library's). +if systemd-run --version >/dev/null 2>&1; then + systemd-run --quiet --pipe --wait --collect \ + -p User="$SERVICE_USER" -p Group="$(id -gn "$SERVICE_USER")" \ + -p WorkingDirectory="$APP_DIR" -p EnvironmentFile="$ENV_FILE" \ + "${APP_DIR}/bin/ping-collector" once --dry-run +else + (cd "$APP_DIR" && "${APP_DIR}/bin/ping-collector" --env-file "$ENV_FILE" once --dry-run) +fi if [ "$MODE" = "--cutover" ]; then log "Cutover: ping-collector collects, the Python app forecasts and notifies"