1 module dli.string_stream.output_string_stream; 2 3 public shared class OutputStringStream 4 { 5 private string _content = ""; 6 immutable string lineTerminator; 7 8 @property 9 public string content() 10 out(s) 11 { 12 assert(s !is null); 13 } 14 body 15 { 16 return _content; 17 } 18 19 public this(string content = "", string lineTerminator = "\n") 20 in 21 { 22 assert(content !is null); 23 assert(lineTerminator !is null); 24 } 25 body 26 { 27 this.lineTerminator = lineTerminator; 28 write(content); 29 } 30 31 public final void writeln(string s) 32 in 33 { 34 assert(s !is null); 35 } 36 body 37 { 38 write(s ~ lineTerminator); 39 } 40 41 public final void write(string s) 42 in 43 { 44 assert(s !is null); 45 } 46 body 47 { 48 synchronized 49 { 50 _content ~= s; 51 } 52 } 53 } 54 55 // TESTS 56 57 @("OutputStringStream stores content appropriately") 58 unittest 59 { 60 import unit_threaded : shouldEqual; 61 62 immutable string lineTerminator = "\n\r"; // Use something other than the default 63 immutable string initializerContent = "Content passed in the initializer" ~ lineTerminator; 64 65 auto stream = new shared OutputStringStream(initializerContent, lineTerminator); 66 67 stream.content.shouldEqual(initializerContent); 68 69 immutable string startOfLine1 = "This is the start of line 1..."; 70 stream.write(startOfLine1); 71 72 stream.content.shouldEqual(initializerContent ~ startOfLine1); 73 74 immutable string endOfLine1 = "... and this is the end of line 1"; 75 stream.writeln(endOfLine1); 76 77 stream.content.shouldEqual(initializerContent ~ startOfLine1 ~ 78 endOfLine1 ~ lineTerminator); 79 } 80 81 @("OutputStringStream can be written to from multiple threads") 82 unittest 83 { 84 import unit_threaded : shouldEqual; 85 86 import std..string : count; 87 import core.thread : ThreadGroup; 88 89 immutable string toBeWritten = "This is what each thread should write, plus the default line terminator"; 90 91 auto stream = new shared OutputStringStream(); 92 93 auto threadGroup = new ThreadGroup(); 94 95 enum threadsToUse = 20; 96 97 for(size_t i; i < threadsToUse; i++) 98 threadGroup.create( 99 { 100 stream.writeln(toBeWritten); 101 }); 102 103 threadGroup.joinAll(); 104 105 stream.content.count(toBeWritten ~ stream.lineTerminator).shouldEqual(threadsToUse); 106 }