This introduces a new utility, which I'm calling FileEdit, which is intended to increase portability in tests across platforms and shells, while adding some additional functionality that enables us to write more concise, easily-understandable, and easily-creatable tests.
To elaborate on the first point, a (somewhat) common pattern in tests is to run sed against the test file, replacing certain fixed strings in the check statements with values that are known only during the run line. For example, you might compile something and get some debug info with a path relative to the test output directory, and you want to write a check statement that checks the path is correct. Or you might want to run the same command multiple times where only the value of a single command line argument is changed, which would cause some small sectino of the output to be different but the test to otherwise be identical. In these and other cases, you may wish to use the same CHECK prefix with a replacement variable.
sed solves this, but a) it's needlessly complicated and not everyone is a Level 99 sed wizard, and b) There are real portability issues when it comes to escaping and slashes that are not easily solvable.
For the second point, lit tests are convenient to write when only have 1 input file to whatever tool we wish to exercise, because we can inline the text of the input file within the test file itself, meaning a test is entirely self contained.
This is not true anymore when a test requires multiple input files (for example, consider the case where you want to compile 2 .cpp files into separate object files and link them together. It would be nice we could have the same level of test-isolation for these kinds of tests as well.
This patch addresses both of the above issues, but one could easily imagine other use cases for a tool such as this, so it has potential for a larger feature set.
It addresses the first by having a command line option --replace=<string>, where <string> is of the form s/pattern/replace/ and behaves in a mostly intuitive way -- it replaces all occurrences of pattern (quirk: pattern is not a regex, it is a string literal).
It addresses the second by scanning lines for a directive that identifies the beginning of a file, and it copies everything that follows (until the next directive) to the corresponding file. For example,
{!-- Foo.cpp int main(int argc, char **argv) { return 0; }
would create a file named Foo.cpp with the aforementioned text, which can then be referenced in a run line.