about summary refs log tree commit diff stats
path: root/087file.cc
Commit message (Collapse)AuthorAgeFilesLines
* 3877Kartik K. Agaram2017-05-261-11/+11
|
* 3433Kartik K. Agaram2016-10-011-1/+1
|
* 3374Kartik K. Agaram2016-09-161-4/+4
|
* 3238Kartik K. Agaram2016-08-211-3/+14
| | | | | | Clean up primitive for reading from file. Never return EOF character. Stop using null character to indicate EOF as well. Instead, always use a second product to indicate EOF, and require calls to use it.
* 3237Kartik K. Agaram2016-08-211-0/+36
| | | | | | | | More checks for unsafe filesystem primitives. Most important, make sure the product of any $close-file instruction is never ignored, and that it's the same variable as the ingredient. (No way to indicate that in Mu code yet, but then Mu code should always be safe and not require such checks.)
* 3236Kartik K. Agaram2016-08-211-5/+0
|
* 3225 - testable interface for writing filesKartik K. Agaram2016-08-181-2/+2
| | | | | | | | For example usage of file operations, see filesystem.mu. Is it ugly that we don't actually write to disk unless we wait for the writing routine to exit? Maybe there's a nice way to wrap it. At any rate, all buffering is explicit, which seems a win compared to *nix.
* 3195Kartik K. Agaram2016-08-161-0/+3
|
* 3185Kartik K. Agaram2016-08-141-1/+1
|
* 3184Kartik K. Agaram2016-08-141-0/+2
| | | | Fix CI. How does it work on my Mac without explicitly including errno?
* 3183 - cleanupKartik K. Agaram2016-08-131-33/+33
| | | | | | | | | | | | | | | | | | | | | | | | | | - New plan Primitives: $open-file-for-reading $open-file-for-writing $read-from-file $write-to-file $close-file The '$' prefix indicates that none of these are intended to be used directly since they rely on type-system-busting numbers. Also that they are just temporary hacks depending on primitives provided by the host system. A putative 'Mu machine' would have very different primitives. Testable interfaces: - start-reading: starts a routine to read from a file and returns the source where the contents will become available. - start-writing: starts a routine to write to a file and returns the sink where the contents can be provided. Both operate on the real file-system if the first 'filesystem' ingredient is 0. Once you start them up you can read/write/close the channel as usual.
* 3182 - primitives for manipulating the file systemKartik K. Agaram2016-08-131-9/+160
| | | | | | | | | | | | | | I don't know why this took so long to gel. I just needed to copy my approach to screen management: 1. primitives layer (C++): simple, non-testable, non-safe operations. 2. wrappers layer (Mu): wrap operations with dependency-injected versions that can take a fake file system. 3. scenario layer (C++): implement assume-filesystem that constructs a fake file system. 4. scenario test layer (Mu): test out assume-filesystem in a test. This commit implements step 1.
* 2788Kartik K. Agaram2016-03-161-0/+27
{ CHECK_TRACE_CONTENTS("test layer", ""); trace("test layer") << "foo"; CHECK_TRACE_CONTENTS("test layer", "foo"); } void test_trace_check_filters_layers() { trace("test layer 1") << "foo"; trace("test layer 2") << "bar"; CHECK_TRACE_CONTENTS("test layer 1", "foo"); } void test_trace_check_ignores_other_lines() { trace("test layer 1") << "foo"; trace("test layer 1") << "bar"; CHECK_TRACE_CONTENTS("test layer 1", "foo"); } void test_trace_check_always_finds_empty_lines() { CHECK_TRACE_CONTENTS("test layer 1", ""); } void test_trace_check_treats_empty_layers_as_wildcards() { trace("test layer 1") << "foo"; CHECK_TRACE_CONTENTS("", "foo"); } void test_trace_check_multiple_lines_at_once() { trace("test layer 1") << "foo"; trace("test layer 2") << "bar"; CHECK_TRACE_CONTENTS("", "foobar"); } void test_trace_check_always_finds_empty_lines2() { CHECK_TRACE_CONTENTS("test layer 1", ""); } void test_trace_orders_across_layers() { trace("test layer 1") << "foo"; trace("test layer 2") << "bar"; trace("test layer 1") << "qux"; CHECK_TRACE_CONTENTS("", "foobarqux"); } void test_trace_orders_across_layers2() { trace("test layer 1") << "foo"; trace("test layer 2") << "bar"; trace("test layer 1") << "qux"; CHECK_TRACE_CONTENTS("foobarqux"); } void test_trace_checks_ordering_spanning_multiple_layers() { trace("layer1") << "foo"; trace("layer2") << "bar"; trace("layer1") << "qux"; CHECK_TRACE_CONTENTS("layer1: foolayer2: barlayer1: qux"); } void test_trace_segments_within_layers() { trace("test layer 1") << "foo"; trace("test layer 2") << "bar"; new_trace_frame("test layer 1"); trace("test layer 1") << "qux"; CHECK_TRACE_CONTENTS("test layer 1", "fooqux"); CHECK_TRACE_CONTENTS("test layer 1", 0, "foo"); CHECK_TRACE_DOESNT_CONTAIN("test layer 1", 1, "foo"); } void test_trace_checks_ordering_across_layers_and_frames() { trace("test layer 1") << "foo"; trace("test layer 2") << "bar"; new_trace_frame("test layer 1"); trace("test layer 1") << "qux"; CHECK_TRACE_CONTENTS("test layer 1/0: footest layer 2: bartest layer 1: qux"); CHECK_TRACE_CONTENTS("test layer 1: footest layer 2: bartest layer 1/1: qux"); } void trace_test_fn(int n) { if (n == 0) return; new_trace_frame("foo"); trace("foo") << "before: " << n; trace_test_fn(n-1); trace("foo") << "after: " << n; } void test_trace_keeps_level_together() { CHECK_TRACE_CONTENTS("foo", ""); trace_test_fn(4); CHECK_TRACE_CONTENTS("foo", 2, "before: 3after: 3"); } void test_trace_supports_multiple_layers() { trace("test layer 1") << "foo"; trace("test layer 2") << "bar"; trace("test layer 1") << "qux"; CHECK_TRACE_CONTENTS("test layer 1,test layer 2", "foobarqux"); } void test_trace_supports_hierarchical_layers() { trace("test layer/a") << "foo"; trace("different layer/c") << "foo 2"; trace("test layer/b") << "bar"; CHECK_TRACE_CONTENTS("test layer/", "foobar"); } void test_trace_supports_count() { trace("test layer 1") << "foo"; trace("test layer 1") << "foo"; CHECK_EQ(trace_count("test layer 1", "foo"), 2); } void test_trace_supports_count2() { trace("test layer 1") << "foo"; trace("test layer 1") << "bar"; CHECK_EQ(trace_count("test layer 1"), 2); } // pending: DUMP tests // pending: readable_contents() adds newline if necessary. // pending: RAISE also prints to stderr. // pending: RAISE doesn't print to stderr if Hide_warnings is set. // pending: RAISE doesn't have to be saved if Hide_warnings is set, just printed. // pending: RAISE prints to stderr if Trace_stream is NULL. // pending: RAISE prints to stderr if Trace_stream is NULL even if Hide_warnings is set. // pending: RAISE << ... die() doesn't die if Hide_warnings is set. // can't check trace because trace methods call 'split' void test_split_returns_at_least_one_elem() { vector<string> result = split("", ","); CHECK_EQ(result.size(), 1); CHECK_EQ(result[0], ""); } void test_split_returns_entire_input_when_no_delim() { vector<string> result = split("abc", ","); CHECK_EQ(result.size(), 1); CHECK_EQ(result[0], "abc"); } void test_split_works() { vector<string> result = split("abc,def", ","); CHECK_EQ(result.size(), 2); CHECK_EQ(result[0], "abc"); CHECK_EQ(result[1], "def"); } void test_split_works2() { vector<string> result = split("abc,def,ghi", ","); CHECK_EQ(result.size(), 3); CHECK_EQ(result[0], "abc"); CHECK_EQ(result[1], "def"); CHECK_EQ(result[2], "ghi"); } void test_split_handles_multichar_delim() { vector<string> result = split("abc,,def,,ghi", ",,"); CHECK_EQ(result.size(), 3); CHECK_EQ(result[0], "abc"); CHECK_EQ(result[1], "def"); CHECK_EQ(result[2], "ghi"); }