diff --git a/README.md b/README.md
index 67afb619..c51423ec 100644
--- a/README.md
+++ b/README.md
@@ -297,9 +297,10 @@ displayed, we recommend setting those variables in the personal
### Configuration variable list
-| Variable name | Description |
-| ------------------- | -------------------------------------------------- |
-| GTEST_RUST_NO_COLOR | If set to any value, disables ANSI output from the failure message. This is useful when the failure description is piped to a file or another process. |
+| Variable name | Description |
+| ------------- | ------------------------------------------------------- |
+| NO_COLOR | Disables coloured output. See . |
+| FORCE_COLOR | Forces colours even when the output is piped to a file. |
## Contributing Changes
diff --git a/googletest/Cargo.toml b/googletest/Cargo.toml
index 62778dcb..601c3ceb 100644
--- a/googletest/Cargo.toml
+++ b/googletest/Cargo.toml
@@ -34,8 +34,9 @@ authors = [
googletest_macro = { path = "../googletest_macro", version = "0.9.0" }
anyhow = { version = "1", optional = true }
num-traits = "0.2.15"
-regex = "1.6.0"
proptest = { version = "1.2.0", optional = true }
+regex = "1.6.0"
+rustversion = "1.0.14"
[dev-dependencies]
indoc = "2"
diff --git a/googletest/config.toml b/googletest/config.toml
new file mode 100644
index 00000000..7bc2412e
--- /dev/null
+++ b/googletest/config.toml
@@ -0,0 +1,2 @@
+[env]
+NO_COLOR = "1"
diff --git a/googletest/src/matcher_support/summarize_diff.rs b/googletest/src/matcher_support/summarize_diff.rs
index 6981496f..53f43807 100644
--- a/googletest/src/matcher_support/summarize_diff.rs
+++ b/googletest/src/matcher_support/summarize_diff.rs
@@ -14,14 +14,13 @@
#![doc(hidden)]
-use std::borrow::Cow;
-use std::fmt::{Display, Write};
-
use crate::matcher_support::edit_distance;
-
-/// Environment variable controlling the usage of ansi color in difference
-/// summary.
-const NO_COLOR_VAR: &str = "GTEST_RUST_NO_COLOR";
+#[rustversion::since(1.70)]
+use std::io::IsTerminal;
+use std::{
+ borrow::Cow,
+ fmt::{Display, Write},
+};
/// Returns a string describing how the expected and actual lines differ.
///
@@ -195,7 +194,7 @@ struct StyledLine<'a> {
impl<'a> Display for StyledLine<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- if std::env::var(NO_COLOR_VAR).is_err() {
+ if stdout_supports_colour() {
write!(
f,
"{}{}{}{}",
@@ -207,36 +206,29 @@ impl<'a> Display for StyledLine<'a> {
}
}
+#[rustversion::since(1.70)]
+fn stdout_supports_colour() -> bool {
+ match (is_env_var_set("NO_COLOR"), is_env_var_set("FORCE_COLOR")) {
+ (true, _) => false,
+ (false, true) => true,
+ (false, false) => std::io::stdout().is_terminal(),
+ }
+}
+
+#[rustversion::not(since(1.70))]
+fn stdout_supports_colour() -> bool {
+ is_env_var_set("FORCE_COLOR")
+}
+
+fn is_env_var_set(var: &'static str) -> bool {
+ std::env::var(var).map(|s| !s.is_empty()).unwrap_or(false)
+}
+
#[cfg(test)]
mod tests {
use super::*;
use crate::{matcher_support::edit_distance::Mode, prelude::*};
use indoc::indoc;
- use serial_test::serial;
-
- #[must_use]
- fn remove_var() -> TempVar {
- let old_value = std::env::var(NO_COLOR_VAR);
- std::env::remove_var(NO_COLOR_VAR);
- TempVar(old_value.ok())
- }
-
- #[must_use]
- fn set_var(var: &str) -> TempVar {
- let old_value = std::env::var(NO_COLOR_VAR);
- std::env::set_var(NO_COLOR_VAR, var);
- TempVar(old_value.ok())
- }
- struct TempVar(Option);
-
- impl Drop for TempVar {
- fn drop(&mut self) {
- match &self.0 {
- Some(old_var) => std::env::set_var(NO_COLOR_VAR, old_var),
- None => std::env::remove_var(NO_COLOR_VAR),
- }
- }
- }
// Make a long text with each element of the iterator on one line.
// `collection` must contains at least one element.
@@ -277,30 +269,8 @@ mod tests {
}
#[test]
- #[serial]
- fn create_diff_exact_small_difference() -> Result<()> {
- let _cleanup = remove_var();
-
- verify_that!(
- create_diff(&build_text(1..50), &build_text(1..51), Mode::Exact),
- eq(indoc! {
- "
-
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
- 1
- 2
- \x1B[3m<---- 45 common lines omitted ---->\x1B[0m
- 48
- 49
- +\x1B[1;32m50\x1B[0m"
- })
- )
- }
-
- #[test]
- #[serial]
fn create_diff_exact_small_difference_no_color() -> Result<()> {
- let _cleanup = set_var("NO_COLOR");
+ std::env::set_var("NO_COLOR", "1");
verify_that!(
create_diff(&build_text(1..50), &build_text(1..51), Mode::Exact),
diff --git a/googletest/src/matchers/display_matcher.rs b/googletest/src/matchers/display_matcher.rs
index 3c110acb..628769be 100644
--- a/googletest/src/matchers/display_matcher.rs
+++ b/googletest/src/matchers/display_matcher.rs
@@ -108,10 +108,10 @@ mod tests {
err(displays_as(contains_substring(indoc!(
"
which displays as a string which isn't equal to \"123\\n345\"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
123
- -\x1B[1;31m234\x1B[0m
- +\x1B[1;32m345\x1B[0m
+ -234
+ +345
"
))))
)
diff --git a/googletest/src/matchers/eq_deref_of_matcher.rs b/googletest/src/matchers/eq_deref_of_matcher.rs
index cb810ead..15409058 100644
--- a/googletest/src/matchers/eq_deref_of_matcher.rs
+++ b/googletest/src/matchers/eq_deref_of_matcher.rs
@@ -138,12 +138,12 @@ mod tests {
"
Actual: Strukt { int: 123, string: \"something\" },
which isn't equal to Strukt { int: 321, string: \"someone\" }
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
Strukt {
- -\x1B[1;31m int: 123,\x1B[0m
- +\x1B[1;32m int: 321,\x1B[0m
- -\x1B[1;31m string: \"something\",\x1B[0m
- +\x1B[1;32m string: \"someone\",\x1B[0m
+ - int: 123,
+ + int: 321,
+ - string: \"something\",
+ + string: \"someone\",
}
"})))
)
diff --git a/googletest/src/matchers/eq_matcher.rs b/googletest/src/matchers/eq_matcher.rs
index fc52ecb2..42684c97 100644
--- a/googletest/src/matchers/eq_matcher.rs
+++ b/googletest/src/matchers/eq_matcher.rs
@@ -178,12 +178,12 @@ mod tests {
"
Actual: Strukt { int: 123, string: \"something\" },
which isn't equal to Strukt { int: 321, string: \"someone\" }
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
Strukt {
- -\x1B[1;31m int: 123,\x1B[0m
- +\x1B[1;32m int: 321,\x1B[0m
- -\x1B[1;31m string: \"something\",\x1B[0m
- +\x1B[1;32m string: \"someone\",\x1B[0m
+ - int: 123,
+ + int: 321,
+ - string: \"something\",
+ + string: \"someone\",
}
"})))
)
@@ -200,12 +200,12 @@ mod tests {
Expected: is equal to [1, 3, 4]
Actual: [1, 2, 3],
which isn't equal to [1, 3, 4]
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
[
1,
- -\x1B[1;31m 2,\x1B[0m
+ - 2,
3,
- +\x1B[1;32m 4,\x1B[0m
+ + 4,
]
"})))
)
@@ -222,12 +222,12 @@ mod tests {
Expected: is equal to [1, 3, 5]
Actual: [1, 2, 3, 4, 5],
which isn't equal to [1, 3, 5]
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
[
1,
- -\x1B[1;31m 2,\x1B[0m
+ - 2,
3,
- -\x1B[1;31m 4,\x1B[0m
+ - 4,
5,
]
"})))
@@ -241,17 +241,17 @@ mod tests {
result,
err(displays_as(contains_substring(indoc! {
"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
[
- -\x1B[1;31m 1,\x1B[0m
- -\x1B[1;31m 2,\x1B[0m
+ - 1,
+ - 2,
3,
4,
- \x1B[3m<---- 43 common lines omitted ---->\x1B[0m
+ <---- 43 common lines omitted ---->
48,
49,
- +\x1B[1;32m 50,\x1B[0m
- +\x1B[1;32m 51,\x1B[0m
+ + 50,
+ + 51,
]"})))
)
}
@@ -263,17 +263,17 @@ mod tests {
result,
err(displays_as(contains_substring(indoc! {
"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
[
- -\x1B[1;31m 1,\x1B[0m
- -\x1B[1;31m 2,\x1B[0m
+ - 1,
+ - 2,
3,
4,
5,
6,
7,
- +\x1B[1;32m 8,\x1B[0m
- +\x1B[1;32m 9,\x1B[0m
+ + 8,
+ + 9,
]"})))
)
}
@@ -285,14 +285,14 @@ mod tests {
result,
err(displays_as(contains_substring(indoc! {
"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
[
1,
- \x1B[3m<---- 46 common lines omitted ---->\x1B[0m
+ <---- 46 common lines omitted ---->
48,
49,
- +\x1B[1;32m 50,\x1B[0m
- +\x1B[1;32m 51,\x1B[0m
+ + 50,
+ + 51,
]"})))
)
}
@@ -304,13 +304,13 @@ mod tests {
result,
err(displays_as(contains_substring(indoc! {
"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ Difference(-actual / +expected):
[
- -\x1B[1;31m 1,\x1B[0m
- -\x1B[1;31m 2,\x1B[0m
+ - 1,
+ - 2,
3,
4,
- \x1B[3m<---- 46 common lines omitted ---->\x1B[0m
+ <---- 46 common lines omitted ---->
51,
]"})))
)
@@ -357,8 +357,8 @@ mod tests {
err(displays_as(contains_substring(indoc!(
"
First line
- -\x1B[1;31mSecond line\x1B[0m
- +\x1B[1;32mSecond lines\x1B[0m
+ -Second line
+ +Second lines
Third line
"
))))
@@ -380,9 +380,7 @@ mod tests {
verify_that!(
result,
- err(displays_as(not(contains_substring(
- "Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):"
- ))))
+ err(displays_as(not(contains_substring("Difference(-actual / +expected):"))))
)
}
@@ -401,9 +399,7 @@ mod tests {
verify_that!(
result,
- err(displays_as(not(contains_substring(
- "Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):"
- ))))
+ err(displays_as(not(contains_substring("Difference(-actual / +expected):"))))
)
}
}
diff --git a/googletest/src/matchers/str_matcher.rs b/googletest/src/matchers/str_matcher.rs
index c8a510e3..3a4e2e99 100644
--- a/googletest/src/matchers/str_matcher.rs
+++ b/googletest/src/matchers/str_matcher.rs
@@ -974,8 +974,8 @@ mod tests {
err(displays_as(contains_substring(indoc!(
"
First line
- -\x1B[1;31mSecond line\x1B[0m
- +\x1B[1;32mSecond lines\x1B[0m
+ -Second line
+ +Second lines
Third line
"
))))
@@ -1007,10 +1007,10 @@ mod tests {
err(displays_as(contains_substring(indoc!(
"
First line
- -\x1B[1;31mSecond line\x1B[0m
- +\x1B[1;32mSecond lines\x1B[0m
+ -Second line
+ +Second lines
Third line
- \x1B[3m<---- remaining lines omitted ---->\x1B[0m
+ <---- remaining lines omitted ---->
"
))))
)
@@ -1040,9 +1040,9 @@ mod tests {
err(displays_as(contains_substring(indoc!(
"
First line
- -\x1B[1;31mSecond line\x1B[0m
- +\x1B[1;32mSecond lines\x1B[0m
- \x1B[3m<---- remaining lines omitted ---->\x1B[0m
+ -Second line
+ +Second lines
+ <---- remaining lines omitted ---->
"
))))
)
@@ -1072,11 +1072,11 @@ mod tests {
result,
err(displays_as(contains_substring(indoc!(
"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
- \x1B[3m<---- remaining lines omitted ---->\x1B[0m
+ Difference(-actual / +expected):
+ <---- remaining lines omitted ---->
Second line
- +\x1B[1;32mThird lines\x1B[0m
- -\x1B[1;31mThird line\x1B[0m
+ +Third lines
+ -Third line
Fourth line
"
))))
@@ -1109,13 +1109,13 @@ mod tests {
result,
err(displays_as(contains_substring(indoc!(
"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
- \x1B[3m<---- remaining lines omitted ---->\x1B[0m
+ Difference(-actual / +expected):
+ <---- remaining lines omitted ---->
Second line
- +\x1B[1;32mThird lines\x1B[0m
- -\x1B[1;31mThird line\x1B[0m
+ +Third lines
+ -Third line
Fourth line
- \x1B[3m<---- remaining lines omitted ---->\x1B[0m"
+ <---- remaining lines omitted ---->"
))))
)
}
@@ -1146,16 +1146,16 @@ mod tests {
result,
err(displays_as(contains_substring(indoc!(
"
- Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
- \x1B[3m<---- remaining lines omitted ---->\x1B[0m
- +\x1B[1;32mline\x1B[0m
- -\x1B[1;31mSecond line\x1B[0m
+ Difference(-actual / +expected):
+ <---- remaining lines omitted ---->
+ +line
+ -Second line
Third line
- +\x1B[1;32mFoorth line\x1B[0m
- -\x1B[1;31mFourth line\x1B[0m
- +\x1B[1;32mFifth\x1B[0m
- -\x1B[1;31mFifth line\x1B[0m
- \x1B[3m<---- remaining lines omitted ---->\x1B[0m
+ +Foorth line
+ -Fourth line
+ +Fifth
+ -Fifth line
+ <---- remaining lines omitted ---->
"
))))
)
@@ -1186,10 +1186,10 @@ mod tests {
err(displays_as(contains_substring(indoc!(
"
First line
- -\x1B[1;31mSecond line\x1B[0m
- +\x1B[1;32mSecond lines\x1B[0m
+ -Second line
+ +Second lines
Third line
- -\x1B[1;31mFourth line\x1B[0m
+ -Fourth line
"
))))
)
@@ -1209,9 +1209,7 @@ mod tests {
verify_that!(
result,
- err(displays_as(not(contains_substring(
- "Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):"
- ))))
+ err(displays_as(not(contains_substring("Difference(-actual / +expected):"))))
)
}
@@ -1230,9 +1228,7 @@ mod tests {
verify_that!(
result,
- err(displays_as(not(contains_substring(
- "Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):"
- ))))
+ err(displays_as(not(contains_substring("Difference(-actual / +expected):"))))
)
}
}
diff --git a/googletest/tests/colourised_diff_test.rs b/googletest/tests/colourised_diff_test.rs
new file mode 100644
index 00000000..d1b4ecbd
--- /dev/null
+++ b/googletest/tests/colourised_diff_test.rs
@@ -0,0 +1,52 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use googletest::prelude::*;
+use indoc::indoc;
+use std::fmt::{Display, Write};
+
+// Make a long text with each element of the iterator on one line.
+// `collection` must contains at least one element.
+fn build_text(mut collection: impl Iterator- ) -> String {
+ let mut text = String::new();
+ write!(&mut text, "{}", collection.next().expect("Provided collection without elements"))
+ .unwrap();
+ for item in collection {
+ write!(&mut text, "\n{}", item).unwrap();
+ }
+ text
+}
+
+#[test]
+fn colors_appear_when_no_color_is_no_set_and_force_color_is_set() -> Result<()> {
+ std::env::remove_var("NO_COLOR");
+ std::env::set_var("FORCE_COLOR", "1");
+
+ let result = verify_that!(build_text(1..50), eq(build_text(1..51)));
+
+ verify_that!(
+ result,
+ err(displays_as(contains_substring(indoc! {
+ "
+
+ Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
+ 1
+ 2
+ \x1B[3m<---- 45 common lines omitted ---->\x1B[0m
+ 48
+ 49
+ +\x1B[1;32m50\x1B[0m"
+ })))
+ )
+}
diff --git a/googletest/tests/lib.rs b/googletest/tests/lib.rs
index f6b3ec10..6cb158e5 100644
--- a/googletest/tests/lib.rs
+++ b/googletest/tests/lib.rs
@@ -14,6 +14,7 @@
mod all_matcher_test;
mod any_matcher_test;
+mod colourised_diff_test;
mod composition_test;
mod elements_are_matcher_test;
mod field_matcher_test;
diff --git a/googletest/tests/no_color_test.rs b/googletest/tests/no_color_test.rs
new file mode 100644
index 00000000..86c40f47
--- /dev/null
+++ b/googletest/tests/no_color_test.rs
@@ -0,0 +1,54 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#![cfg(feature = "supports-color")]
+
+use googletest::prelude::*;
+use indoc::indoc;
+use std::fmt::{Display, Write};
+
+// Make a long text with each element of the iterator on one line.
+// `collection` must contains at least one element.
+fn build_text(mut collection: impl Iterator
- ) -> String {
+ let mut text = String::new();
+ write!(&mut text, "{}", collection.next().expect("Provided collection without elements"))
+ .unwrap();
+ for item in collection {
+ write!(&mut text, "\n{}", item).unwrap();
+ }
+ text
+}
+
+#[test]
+fn colours_suppressed_when_both_no_color_and_force_color_are_set() -> Result<()> {
+ std::env::set_var("NO_COLOR", "1");
+ std::env::set_var("FORCE_COLOR", "1");
+
+ let result = verify_that!(build_text(1..50), eq(build_text(1..51)));
+
+ verify_that!(
+ result,
+ err(displays_as(contains_substring(indoc! {
+ "
+
+ Difference(-actual / +expected):
+ 1
+ 2
+ <---- 45 common lines omitted ---->
+ 48
+ 49
+ +50"
+ })))
+ )
+}