about summary refs log tree commit diff stats
path: root/003trace.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-03-12 18:56:55 -0700
committerKartik Agaram <vc@akkartik.com>2019-03-12 19:14:12 -0700
commit4a943d4ed313eff001504c2b5c472266e86a38af (patch)
treea5757233a8c81b303a808f251180c7344071ed51 /003trace.cc
parent43711b0e9f18e0225ce14687fb6ea0902aa6fc61 (diff)
downloadmu-4a943d4ed313eff001504c2b5c472266e86a38af.tar.gz
5001 - drop the :(scenario) DSL
I've been saying for a while[1][2][3] that adding extra abstractions makes
things harder for newcomers, and adding new notations doubly so. And then
I notice this DSL in my own backyard. Makes me feel like a hypocrite.

[1] https://news.ycombinator.com/item?id=13565743#13570092
[2] https://lobste.rs/s/to8wpr/configuration_files_are_canary_warning
[3] https://lobste.rs/s/mdmcdi/little_languages_by_jon_bentley_1986#c_3miuf2

The implementation of the DSL was also highly hacky:

a) It was happening in the tangle/ tool, but was utterly unrelated to tangling
layers.

b) There were several persnickety constraints on the different kinds of
lines and the specific order they were expected in. I kept finding bugs
where the translator would silently do the wrong thing. Or the error messages
sucked, and readers may be stuck looking at the generated code to figure
out what happened. Fixing error messages would require a lot more code,
which is one of my arguments against DSLs in the first place: they may
be easy to implement, but they're hard to design to go with the grain of
the underlying platform. They require lots of iteration. Is that effort
worth prioritizing in this project?

On the other hand, the DSL did make at least some readers' life easier,
the ones who weren't immediately put off by having to learn a strange syntax.
There were fewer quotes to parse, fewer backslash escapes.

Anyway, since there are also people who dislike having to put up with strange
syntaxes, we'll call that consideration a wash and tear this DSL out.

---

This commit was sheer drudgery. Hopefully it won't need to be redone with
a new DSL because I grow sick of backslashes.
Diffstat (limited to '003trace.cc')
-rw-r--r--003trace.cc44
1 files changed, 21 insertions, 23 deletions
diff --git a/003trace.cc b/003trace.cc
index af707354..18f15347 100644
--- a/003trace.cc
+++ b/003trace.cc
@@ -16,28 +16,26 @@
 //: In response, this layer introduces the notion of domain-driven *white-box*
 //: testing. We focus on the domain of inputs the whole program needs to
 //: handle rather than the correctness of individual functions. All white-box
-//: tests (we call them 'scenarios') invoke the program in a single way: by
-//: calling run() with some input. As the program operates on the input, it
-//: traces out a list of _facts_ deduced about the domain:
+//: tests invoke the program in a single way: by calling run() with some
+//: input. As the program operates on the input, it traces out a list of
+//: _facts_ deduced about the domain:
 //:   trace("label") << "fact 1: " << val;
 //:
-//: Scenarios can now check these facts:
-//:   :(scenario foo)
-//:   34  # call run() with this input
-//:   +label: fact 1: 34  # 'run' should have deduced this fact
-//:   -label: fact 1: 35  # the trace should not contain such a fact
+//: Tests can now check for these facts in the trace:
+//:   CHECK_TRACE_CONTENTS("label", "fact 1: 34\n"
+//:                                 "fact 2: 35\n");
 //:
 //: Since we never call anything but the run() function directly, we never have
-//: to rewrite the scenarios when we reorganize the internals of the program. We
+//: to rewrite the tests when we reorganize the internals of the program. We
 //: just have to make sure our rewrite deduces the same facts about the domain,
 //: and that's something we're going to have to do anyway.
 //:
 //: To avoid the combinatorial explosion of integration tests, each layer
-//: mainly logs facts to the trace with a common *label*. All scenarios in a
-//: layer tend to check facts with this label. Validating the facts logged
-//: with a specific label is like calling functions of that layer directly.
+//: mainly logs facts to the trace with a common *label*. All tests in a layer
+//: tend to check facts with this label. Validating the facts logged with a
+//: specific label is like calling functions of that layer directly.
 //:
-//: To build robust scenarios, trace facts about your domain rather than details of
+//: To build robust tests, trace facts about your domain rather than details of
 //: how you computed them.
 //:
 //: More details: http://akkartik.name/blog/tracing-tests
@@ -50,10 +48,10 @@
 //: we allow programmers to engage with the a) deep, b) global structure of
 //: the c) domain. If you can systematically track discontinuities in the
 //: domain, you don't care if the code used gotos as long as it passed all
-//: scenarios. If scenarios become more robust to run, it becomes easier to
-//: try out radically different implementations for the same program. If code
-//: is super-easy to rewrite, it becomes less important what indentation style
-//: it uses, or that the objects are appropriately encapsulated, or that the
+//: tests. If tests become more robust to run, it becomes easier to try out
+//: radically different implementations for the same program. If code is
+//: super-easy to rewrite, it becomes less important what indentation style it
+//: uses, or that the objects are appropriately encapsulated, or that the
 //: functions are referentially transparent.
 //:
 //: Instead of plumbing, programming becomes building and gradually refining a
@@ -61,7 +59,7 @@
 //: is 'correct' at a given point in time is a red herring; what matters is
 //: avoiding regression by monotonically nailing down the more 'eventful'
 //: parts of the terrain. It helps readers new and old, and rewards curiosity,
-//: to organize large programs in self-similar hierarchies of example scenarios
+//: to organize large programs in self-similar hierarchies of example tests
 //: colocated with the code that makes them work.
 //:
 //:   "Programming properly should be regarded as an activity by which
@@ -177,7 +175,7 @@ void trace_stream::newline() {
   curr_depth = Max_depth;
 }
 
-//:: == Initializing the trace in scenarios
+//:: == Initializing the trace in tests
 
 :(before "End Includes")
 #define START_TRACING_UNTIL_END_OF_SCOPE  lease_tracer leased_tracer;
@@ -221,7 +219,7 @@ bool should_incrementally_print_trace();
 :(before "End Globals")
 int Trace_errors = 0;  // used only when Trace_stream is NULL
 
-// Fail scenarios that displayed (unexpected) errors.
+// Fail tests that displayed (unexpected) errors.
 // Expected errors should always be hidden and silently checked for.
 :(before "End Test Teardown")
 if (Passed && !Hide_errors && trace_contains_errors()) {
@@ -292,14 +290,14 @@ void scroll_to_bottom_and_close_console() {
     return; \
   }
 
-// Allow scenarios to ignore trace lines generated during setup.
+// Allow tests to ignore trace lines generated during setup.
 #define CLEAR_TRACE  delete Trace_stream, Trace_stream = new trace_stream
 
 :(code)
 bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expected) {
   if (!Passed) return false;
   if (!Trace_stream) return false;
-  vector<string> expected_lines = split(expected, "");
+  vector<string> expected_lines = split(expected, "\n");
   int curr_expected_line = 0;
   while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty())
     ++curr_expected_line;
@@ -413,7 +411,7 @@ vector<string> split_first(string s, string delim) {
 //:: == Helpers for debugging using traces
 
 :(before "End Includes")
-// To debug why a scenario is failing, dump its trace using '?'.
+// To debug why a test is failing, dump its trace using '?'.
 #define DUMP(label)  if (Trace_stream) cerr << Trace_stream->readable_contents(label);
 
 // To add temporary prints to the trace, use 'dbg'.