1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
const fs = require('fs')
const test = require('ava')
const {
execFilePromise, matchOutput, reorderings, updateExpectedPaths, updatePath
} = require('./util')
// We are going to run the server directly, not through npm
const {INIT_CWD, ...GREP_ENV} = process.env
process.chdir(__dirname)
const RUST_MUTABLE_EXPECTED = updateExpectedPaths([
[
'files/rust-book/ch10-03-lifetime-syntax.md:reference to an `i32` that has a lifetime parameter named `\'a`, and a mutable',
'files/rust-book/ch10-03-lifetime-syntax.md:&\'a mut i32 // a mutable reference with an explicit lifetime'
],
['files/rust-book/ch15-00-smart-pointers.md:In addition, we’ll cover the *interior mutability* pattern where an immutable'],
['files/rust-book/ch15-03-drop.md:`drop` that takes a mutable reference to `self`. To see when Rust calls `drop`,'],
[
'files/rust-book/ch04-01-what-is-ownership.md:immutable. Another is that not every string value can be known when we write',
'files/rust-book/ch04-01-what-is-ownership.md:With the `String` type, in order to support a mutable, growable piece of text,'
],
[
'files/rust-book/ch15-04-rc.md:Via immutable references, `Rc<T>` allows you to share data between multiple',
'files/rust-book/ch15-04-rc.md:mutable references too, you might violate one of the borrowing rules discussed',
'files/rust-book/ch15-04-rc.md:in Chapter 4: multiple mutable borrows to the same place can cause data races'
],
[
'files/rust-book/ch20-03-graceful-shutdown-and-cleanup.md:this because `self` is a mutable reference, and we also need to be able to',
'files/rust-book/ch20-03-graceful-shutdown-and-cleanup.md:The error tells us we can’t call `join` because we only have a mutable borrow'
],
['files/rust-book/ch13-01-closures.md:captured variables also implement `FnMut`, and closures that don’t need mutable'],
['files/rust-book/ch20-01-single-threaded.md:In the `handle_connection` function, we’ve made the `stream` parameter mutable.'],
['files/rust-book/ch08-02-strings.md:coded into the core language, is a growable, mutable, owned, UTF-8 encoded'],
[
'files/rust-book/ch08-01-vectors.md:make it mutable using the `mut` keyword, as discussed in Chapter 3. The numbers',
'files/rust-book/ch08-01-vectors.md:rule that states you can’t have mutable and immutable references in the same',
'files/rust-book/ch08-01-vectors.md:scope. That rule applies in Listing 8-7, where we hold an immutable reference to',
'files/rust-book/ch08-01-vectors.md:8-8 shows how to use a `for` loop to get immutable references to each element',
'files/rust-book/ch08-01-vectors.md:We can also iterate over mutable references to each element in a mutable vector',
'files/rust-book/ch08-01-vectors.md:<span class="caption">Listing 8-9: Iterating over mutable references to',
'files/rust-book/ch08-01-vectors.md:To change the value that the mutable reference refers to, we have to use the'
],
[
'files/rust-book/ch15-02-deref.md:immutable references, you can use the `DerefMut` trait to override the `*`',
'files/rust-book/ch15-02-deref.md:operator on mutable references.',
'files/rust-book/ch15-02-deref.md:happens for mutable references.',
'files/rust-book/ch15-02-deref.md:The third case is trickier: Rust will also coerce a mutable reference to an',
'files/rust-book/ch15-02-deref.md:immutable one. But the reverse is *not* possible: immutable references will',
'files/rust-book/ch15-02-deref.md:never coerce to mutable references. Because of the borrowing rules, if you have',
'files/rust-book/ch15-02-deref.md:a mutable reference, that mutable reference must be the only reference to that',
'files/rust-book/ch15-02-deref.md:data (otherwise, the program wouldn’t compile). Converting one mutable',
'files/rust-book/ch15-02-deref.md:reference to one immutable reference will never break the borrowing rules.',
'files/rust-book/ch15-02-deref.md:Converting an immutable reference to a mutable reference would require that the',
'files/rust-book/ch15-02-deref.md:initial immutable reference is the only immutable reference to that data, but',
'files/rust-book/ch15-02-deref.md:assumption that converting an immutable reference to a mutable reference is'
],
[
'files/rust-book/ch17-03-oo-design-patterns.md:The `add_text` method takes a mutable reference to `self`, because we’re',
'files/rust-book/ch17-03-oo-design-patterns.md:We give `Post` a public method named `request_review` that will take a mutable'
],
[
'files/rust-book/ch15-05-interior-mutability.md:data even when there are immutable references to that data; normally, this',
'files/rust-book/ch15-05-interior-mutability.md:safe API, and the outer type is still immutable.',
'files/rust-book/ch15-05-interior-mutability.md:* At any given time, you can have *either* (but not both of) one mutable',
'files/rust-book/ch15-05-interior-mutability.md: reference or any number of immutable references.',
'files/rust-book/ch15-05-interior-mutability.md:* `Box<T>` allows immutable or mutable borrows checked at compile time; `Rc<T>`',
'files/rust-book/ch15-05-interior-mutability.md: allows only immutable borrows checked at compile time; `RefCell<T>` allows',
'files/rust-book/ch15-05-interior-mutability.md: immutable or mutable borrows checked at runtime.',
'files/rust-book/ch15-05-interior-mutability.md:* Because `RefCell<T>` allows mutable borrows checked at runtime, you can',
'files/rust-book/ch15-05-interior-mutability.md: immutable.',
'files/rust-book/ch15-05-interior-mutability.md:Mutating the value inside an immutable value is the *interior mutability*',
'files/rust-book/ch15-05-interior-mutability.md:### Interior Mutability: A Mutable Borrow to an Immutable Value',
'files/rust-book/ch15-05-interior-mutability.md:A consequence of the borrowing rules is that when you have an immutable value,',
'files/rust-book/ch15-05-interior-mutability.md:{{#rustdoc_include ../listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/src/main.rs}}',
'files/rust-book/ch15-05-interior-mutability.md:{{#include ../listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/output.txt}}',
'files/rust-book/ch15-05-interior-mutability.md:itself in its methods but appear immutable to other code. Code outside the',
'files/rust-book/ch15-05-interior-mutability.md:an immutable value and see why that is useful.',
'files/rust-book/ch15-05-interior-mutability.md:called `send` that takes an immutable reference to `self` and the text of the',
'files/rust-book/ch15-05-interior-mutability.md:`send` method takes an immutable reference to `self`. We also can’t take the',
'files/rust-book/ch15-05-interior-mutability.md:value while the outer value is considered immutable</span>',
'files/rust-book/ch15-05-interior-mutability.md:immutable borrow of `self`, which matches the trait definition. We call',
'files/rust-book/ch15-05-interior-mutability.md:mutable reference to the value inside the `RefCell<Vec<String>>`, which is',
'files/rust-book/ch15-05-interior-mutability.md:the vector. Then we can call `push` on the mutable reference to the vector to',
'files/rust-book/ch15-05-interior-mutability.md:immutable reference to the vector.',
'files/rust-book/ch15-05-interior-mutability.md:When creating immutable and mutable references, we use the `&` and `&mut`',
'files/rust-book/ch15-05-interior-mutability.md:increases its count of how many immutable borrows are active. When a `Ref<T>`',
'files/rust-book/ch15-05-interior-mutability.md:value goes out of scope, the count of immutable borrows goes down by one. Just',
'files/rust-book/ch15-05-interior-mutability.md:like the compile-time borrowing rules, `RefCell<T>` lets us have many immutable',
'files/rust-book/ch15-05-interior-mutability.md:borrows or one mutable borrow at any point in time.',
'files/rust-book/ch15-05-interior-mutability.md:Listing 15-22. We’re deliberately trying to create two mutable borrows active',
'files/rust-book/ch15-05-interior-mutability.md:<span class="caption">Listing 15-23: Creating two mutable references in the',
'files/rust-book/ch15-05-interior-mutability.md:from `borrow_mut`. Then we create another mutable borrow in the same way in the',
'files/rust-book/ch15-05-interior-mutability.md:variable `two_borrow`. This makes two mutable references in the same scope,',
'files/rust-book/ch15-05-interior-mutability.md:messages it has seen while you’re using it in a context where only immutable',
'files/rust-book/ch15-05-interior-mutability.md:`Rc<T>` lets you have multiple owners of some data, but it only gives immutable',
'files/rust-book/ch15-05-interior-mutability.md:`Rc<T>` holds only immutable values, we can’t change any of the values in the',
'files/rust-book/ch15-05-interior-mutability.md:immutable `List` value. But we can use the methods on `RefCell<T>` that provide'
],
[
'files/rust-book/ch13-02-iterators.md:Note that we needed to make `v1_iter` mutable: calling the `next` method on an',
'files/rust-book/ch13-02-iterators.md:to make `v1_iter` mutable when we used a `for` loop because the loop took',
'files/rust-book/ch13-02-iterators.md:ownership of `v1_iter` and made it mutable behind the scenes.',
'files/rust-book/ch13-02-iterators.md:Also note that the values we get from the calls to `next` are immutable',
'files/rust-book/ch13-02-iterators.md:over immutable references. If we want to create an iterator that takes',
'files/rust-book/ch13-02-iterators.md:`iter`. Similarly, if we want to iterate over mutable references, we can call'
],
[
'files/rust-book/ch03-01-variables-and-mutability.md:As mentioned in Chapter 2, by default variables are immutable. This is one of',
'files/rust-book/ch03-01-variables-and-mutability.md:option to make your variables mutable. Let’s explore how and why Rust',
'files/rust-book/ch03-01-variables-and-mutability.md:When a variable is immutable, once a value is bound to a name, you can’t change',
'files/rust-book/ch03-01-variables-and-mutability.md:{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs}}',
'files/rust-book/ch03-01-variables-and-mutability.md:{{#include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt}}',
'files/rust-book/ch03-01-variables-and-mutability.md:assign twice to immutable variable x`, because you tried to assign a second',
'files/rust-book/ch03-01-variables-and-mutability.md:value to the immutable `x` variable.',
'files/rust-book/ch03-01-variables-and-mutability.md:value that we previously designated as immutable because this very situation',
'files/rust-book/ch03-01-variables-and-mutability.md:But mutability can be very useful. Variables are immutable only by default; as',
'files/rust-book/ch03-01-variables-and-mutability.md:you did in Chapter 2, you can make them mutable by adding `mut` in front of the',
'files/rust-book/ch03-01-variables-and-mutability.md:is used. In some cases, you’ll want to make a variable mutable because it makes',
'files/rust-book/ch03-01-variables-and-mutability.md:the code more convenient to write than if it had only immutable variables.',
'files/rust-book/ch03-01-variables-and-mutability.md:immutable variables, constants are values that are bound to a name and are not',
'files/rust-book/ch03-01-variables-and-mutability.md:immutable by default—they’re always immutable.',
'files/rust-book/ch03-01-variables-and-mutability.md:on a value but have the variable be immutable after those transformations have'
],
[
'files/rust-book/ch08-03-hash-maps.md:The `or_insert` method on `Entry` is defined to return a mutable reference to',
'files/rust-book/ch08-03-hash-maps.md:inserts the parameter as the new value for this key and returns a mutable',
'files/rust-book/ch08-03-hash-maps.md:`or_insert` method actually returns a mutable reference (`&mut V`) to the value',
'files/rust-book/ch08-03-hash-maps.md:for this key. Here we store that mutable reference in the `count` variable, so',
'files/rust-book/ch08-03-hash-maps.md:asterisk (`*`). The mutable reference goes out of scope at the end of the `for`'
],
[
'files/rust-book/ch04-02-references-and-borrowing.md:Just as variables are immutable by default, so are references. We’re not',
'files/rust-book/ch04-02-references-and-borrowing.md:First, we had to change `s` to be `mut`. Then we had to create a mutable',
'files/rust-book/ch04-02-references-and-borrowing.md:reference with `&mut s` and accept a mutable reference with `some_string: &mut',
'files/rust-book/ch04-02-references-and-borrowing.md:But mutable references have one big restriction: you can have only one mutable',
'files/rust-book/ch04-02-references-and-borrowing.md:multiple mutable references, just not *simultaneous* ones:',
'files/rust-book/ch04-02-references-and-borrowing.md:A similar rule exists for combining mutable and immutable references. This code',
'files/rust-book/ch04-02-references-and-borrowing.md:{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs:here}}',
'files/rust-book/ch04-02-references-and-borrowing.md:{{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}}',
'files/rust-book/ch04-02-references-and-borrowing.md:Whew! We *also* cannot have a mutable reference while we have an immutable one.',
'files/rust-book/ch04-02-references-and-borrowing.md:Users of an immutable reference don’t expect the values to suddenly change out',
'files/rust-book/ch04-02-references-and-borrowing.md:from under them! However, multiple immutable references are okay because no one',
'files/rust-book/ch04-02-references-and-borrowing.md:compile because the last usage of the immutable references occurs before the',
'files/rust-book/ch04-02-references-and-borrowing.md:mutable reference is introduced:',
'files/rust-book/ch04-02-references-and-borrowing.md:The scopes of the immutable references `r1` and `r2` end after the `println!`',
'files/rust-book/ch04-02-references-and-borrowing.md:where they are last used, which is before the mutable reference `r3` is',
'files/rust-book/ch04-02-references-and-borrowing.md:* At any given time, you can have *either* one mutable reference *or* any',
'files/rust-book/ch04-02-references-and-borrowing.md: number of immutable references.'
],
['files/rust-book/ch05-02-example-structs.md:`rectangle`, whose type is an immutable borrow of a struct `Rectangle`'],
[
'files/rust-book/ch19-01-unsafe-rust.md:* Access or modify a mutable static variable',
'files/rust-book/ch19-01-unsafe-rust.md:references. As with references, raw pointers can be immutable or mutable and',
'files/rust-book/ch19-01-unsafe-rust.md:pointers, *immutable* means that the pointer can’t be directly assigned to',
'files/rust-book/ch19-01-unsafe-rust.md:* Are allowed to ignore the borrowing rules by having both immutable and',
'files/rust-book/ch19-01-unsafe-rust.md: mutable pointers or multiple mutable pointers to the same location',
'files/rust-book/ch19-01-unsafe-rust.md:Listing 19-1 shows how to create an immutable and a mutable raw pointer from',
'files/rust-book/ch19-01-unsafe-rust.md:We’ve created raw pointers by using `as` to cast an immutable and a mutable',
'files/rust-book/ch19-01-unsafe-rust.md:stored. If we instead tried to create an immutable and a mutable reference to',
'files/rust-book/ch19-01-unsafe-rust.md:allow a mutable reference at the same time as any immutable references. With',
'files/rust-book/ch19-01-unsafe-rust.md:raw pointers, we can create a mutable pointer and an immutable pointer to the',
'files/rust-book/ch19-01-unsafe-rust.md:same location and change data through the mutable pointer, potentially creating',
'files/rust-book/ch19-01-unsafe-rust.md:might implement it. This safe method is defined on mutable slices: it takes one',
'files/rust-book/ch19-01-unsafe-rust.md:Then we return two mutable slices in a tuple: one from the start of the',
'files/rust-book/ch19-01-unsafe-rust.md:mutable slice to `i32` values, `as_mut_ptr` returns a raw pointer with the type',
'files/rust-book/ch19-01-unsafe-rust.md:accessing the same mutable global variable, it can cause a data race.',
'files/rust-book/ch19-01-unsafe-rust.md:<span class="caption">Listing 19-9: Defining and using an immutable static',
'files/rust-book/ch19-01-unsafe-rust.md:immutable static variable is safe.',
'files/rust-book/ch19-01-unsafe-rust.md:Constants and immutable static variables might seem similar, but a subtle',
'files/rust-book/ch19-01-unsafe-rust.md:variables can be mutable. Accessing and modifying mutable static variables is',
'files/rust-book/ch19-01-unsafe-rust.md:*unsafe*. Listing 19-10 shows how to declare, access, and modify a mutable',
'files/rust-book/ch19-01-unsafe-rust.md:<span class="caption">Listing 19-10: Reading from or writing to a mutable',
'files/rust-book/ch19-01-unsafe-rust.md:With mutable data that is globally accessible, it’s difficult to ensure there',
'files/rust-book/ch19-01-unsafe-rust.md:are no data races, which is why Rust considers mutable static variables to be'
],
['files/rust-book/ch15-06-reference-cycles.md:mutability gives us a type that we can use when we need an immutable type but'],
[
'files/rust-book/ch05-01-defining-structs.md:to use this value. If the instance is mutable, we can change a value by using',
'files/rust-book/ch05-01-defining-structs.md:to change the value in the `email` field of a mutable `User` instance.',
'files/rust-book/ch05-01-defining-structs.md:Note that the entire instance must be mutable; Rust doesn’t allow us to mark',
'files/rust-book/ch05-01-defining-structs.md:only certain fields as mutable. As with any expression, we can construct a new'
],
['files/rust-book/ch12-04-testing-the-librarys-functionality.md:we can make a mutable vector before the `for` loop and call the `push` method'],
[
'files/rust-book/ch13-03-improving-our-io-project.md:keyword into the specification of the `args` parameter to make it mutable.',
'files/rust-book/ch13-03-improving-our-io-project.md:Doing so also lets us avoid having a mutable intermediate `results` vector. The',
'files/rust-book/ch13-03-improving-our-io-project.md:functional programming style prefers to minimize the amount of mutable state to',
'files/rust-book/ch13-03-improving-our-io-project.md:make code clearer. Removing the mutable state might enable a future enhancement'
],
[
'files/rust-book/ch05-03-method-syntax.md:block. The method name will be `can_hold`, and it will take an immutable borrow',
'files/rust-book/ch05-03-method-syntax.md:`rect1.can_hold(&rect2)` passes in `&rect2`, which is an immutable borrow to',
'files/rust-book/ch05-03-method-syntax.md:read `rect2` (rather than write, which would mean we’d need a mutable borrow),'
],
[
'files/rust-book/ch02-00-guessing-game-tutorial.md:`bar` variable. In Rust, variables are immutable by default. We’ll be',
'files/rust-book/ch02-00-guessing-game-tutorial.md:a variable mutable:',
'files/rust-book/ch02-00-guessing-game-tutorial.md:let foo = 5; // immutable',
'files/rust-book/ch02-00-guessing-game-tutorial.md:let mut bar = 5; // mutable',
'files/rust-book/ch02-00-guessing-game-tutorial.md:will introduce a mutable variable named `guess`. On the other side of the equal',
'files/rust-book/ch02-00-guessing-game-tutorial.md:To summarize, the `let mut guess = String::new();` line has created a mutable',
'files/rust-book/ch02-00-guessing-game-tutorial.md:string argument needs to be mutable so the method can change the string’s',
'files/rust-book/ch02-00-guessing-game-tutorial.md:immutable by default. Hence, you need to write `&mut guess` rather than',
'files/rust-book/ch02-00-guessing-game-tutorial.md:`&guess` to make it mutable. (Chapter 4 will explain references more'
],
[
'files/rust-book/ch04-03-slices.md:Recall from the borrowing rules that if we have an immutable reference to',
'files/rust-book/ch04-03-slices.md:something, we cannot also take a mutable reference. Because `clear` needs to',
'files/rust-book/ch04-03-slices.md:truncate the `String`, it needs to get a mutable reference. Rust disallows',
'files/rust-book/ch04-03-slices.md:the binary. This is also why string literals are immutable; `&str` is an',
'files/rust-book/ch04-03-slices.md:immutable reference.'
],
[
'files/rust-book/ch16-03-shared-state.md:this case, as a mutable reference to the data inside. The type system ensures',
'files/rust-book/ch16-03-shared-state.md:You might have noticed that `counter` is immutable but we could get a mutable'
]
])
const MULTIPLE_RUST_FILES = [
'files/rust-book/ch04-01-what-is-ownership.md',
'files/rust-book/ch08-03-hash-maps.md',
'files/rust-book/ch17-00-oop.md',
'files/rust-book/ch19-01-unsafe-rust.md',
'files/rust-book/ch19-06-macros.md'
]
const TESTS = [
{
// The example from the spec
args: ['ss', 'files/independence.txt'],
expected: [[
'it becomes necessary for one people',
'to dissolve the political bands',
'and to assume among the powers of the earth,'
]]
},
{
// Test that the pattern is treated as a regular expression.
// This example is from the spec.
args: ['the[a-z]', 'files/independence.txt'],
expected: [[
'which have connected them with another,',
'the Laws of Nature and of Nature\'s God entitle them,',
'that they should declare the causes',
'which impel them to the separation.'
]]
},
{
// Test on a larger file with multiple occurrences in some lines
args: ['lock', 'files/rust-book/ch20-02-multithreaded.md'],
expected: [[
'`else if` after the `if` block to check for the request to */sleep*. When that',
'Here, we first call `lock` on the `receiver` to acquire the mutex, and then we',
'call `unwrap` to panic on any errors. Acquiring a lock might fail if the mutex',
'holding the lock rather than releasing the lock. In this situation, calling',
'If we get the lock on the mutex, we call `recv` to receive a `Job` from the',
'The call to `recv` blocks, so if there is no job yet, the current thread will',
'`unlock` method because the ownership of the lock is based on the lifetime of',
'the `MutexGuard<T>` within the `LockResult<MutexGuard<T>>` that the `lock`',
'lock. But this implementation can also result in the lock being held longer',
'scope for the duration of the block, the lock remains held for the duration of',
'By using `loop` instead and acquiring the lock without assigning to a variable,',
'the temporary `MutexGuard` returned from the `lock` method is dropped as soon',
'as the `let job` statement ends. This ensures that the lock is held during the'
]]
},
{
// Test multiple input files
args: ['mutable', ...MULTIPLE_RUST_FILES],
expected: RUST_MUTABLE_EXPECTED.filter(([firstLine]) =>
MULTIPLE_RUST_FILES.some(file => firstLine.startsWith(file))
)
},
{
// Test -v flag
args: ['-v', 'ss', 'files/independence.txt'],
expected: [[
'When in the Course of human events,',
'which have connected them with another,',
'the separate and equal station to which',
'the Laws of Nature and of Nature\'s God entitle them,',
'a decent respect to the opinions of mankind requires',
'that they should declare the causes',
'which impel them to the separation.'
]]
},
{
// Test -i flag
args: ['-i', 'ZoUnDs', 'files/richard-iii/1/2.txt'],
expected: [[
'Zounds , he dies ! I had forgot the reward .',
'Zounds , ’tis even now at my elbow , persuading me not to kill the Duke .'
]]
},
{
// Test -r flag
args: ['-r', 'mutable', 'files/rust-book'],
expected: RUST_MUTABLE_EXPECTED
},
{
// Test -r with omitted directory.
// This also tests a more deeply-nested recursive structure.
args: ['-r', 'crow' + 'n'],
expected: updateExpectedPaths([
[
'files/richard-iii/1/1/3/2.txt:To fight on Edward’s party for the crow' + 'n ;',
'files/richard-iii/1/1/3/2.txt:When thou didst crow' + 'n his warlike brows with paper ,'
],
[
'files/richard-iii/2.txt:Let him be crow' + 'ned . In him your comfort lives .',
'files/richard-iii/2.txt:Hither to London , to be crow' + 'ned our king .',
'files/richard-iii/2.txt:Was crow' + 'ned in Paris but at nine months old .'
],
['files/richard-iii/3/1/1/3.txt:I mean your voice for crow' + 'ning of the King .'],
[
'files/richard-iii/3/1/1/2.txt:How “ wear the garland ” ? Dost thou mean the crow' + 'n ?',
'files/richard-iii/3/1/1/2.txt:I’ll have this crow' + 'n of mine cut from my shoulders',
'files/richard-iii/3/1/1/2.txt:Before I’ll see the crow' + 'n so foul misplaced .'
],
['files/richard-iii/3/1/1/1.txt:My husband lost his life to get the crow' + 'n ,'],
[
'files/richard-iii/3/1/3/2.txt:Now by my George , my Garter , and my crow' + 'n —',
'files/richard-iii/3/1/3/2.txt:Thy crow' + 'n , usurped , disgraced his kingly glory .',
'files/richard-iii/3/1/3/2.txt:He makes for England , here to claim the crow' + 'n .'
],
[
'files/richard-iii/3/1/2/1/3.txt:Tomorrow may it please you to be crow' + 'ned ?',
'files/richard-iii/3/1/2/1/3.txt:There to be crow' + 'nèd Richard’s royal queen .'
],
['files/richard-iii/3/1/2/1/2.txt:And that my path were even to the crow' + 'n'],
[
'files/richard-iii/3/1/2/3.txt:For queen , a very caitiff crow' + 'ned with care ;',
'files/richard-iii/3/1/2/3.txt:Hid’st thou that forehead with a golden crow' + 'n',
'files/richard-iii/3/1/2/3.txt:The slaughter of the prince that owed that crow' + 'n'
],
['files/richard-iii/3/1/2/2.txt:And by that knot looks proudly on the crow' + 'n ,'],
['files/richard-iii/3/2.txt:The first was I that helped thee to the crow' + 'n ;']
])
},
{
// Test a more complicated regex
args: ['-r', '[a-z]{3}\\d', 'files/rust-book'],
expected: updateExpectedPaths([
[
'files/rust-book/ch10-03-lifetime-syntax.md:type stored in the variable `string1`) as well as string literals (which is',
'files/rust-book/ch10-03-lifetime-syntax.md:what variable `string2` contains).',
'files/rust-book/ch10-03-lifetime-syntax.md:In this example, `string1` is valid until the end of the outer scope, `string2`',
'files/rust-book/ch10-03-lifetime-syntax.md:`string2`. Then we’ll move the `println!` that uses `result` outside the inner',
'files/rust-book/ch10-03-lifetime-syntax.md:<span class="caption">Listing 10-24: Attempting to use `result` after `string2`',
'files/rust-book/ch10-03-lifetime-syntax.md:`string2` would need to be valid until the end of the outer scope. Rust knows',
'files/rust-book/ch10-03-lifetime-syntax.md:As humans, we can look at this code and see that `string1` is longer than',
'files/rust-book/ch10-03-lifetime-syntax.md:`string2` and therefore `result` will contain a reference to `string1`.',
'files/rust-book/ch10-03-lifetime-syntax.md:Because `string1` has not gone out of scope yet, a reference to `string1` will'
],
[
'files/rust-book/ch09-01-unrecoverable-errors-with-panic.md: at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88',
'files/rust-book/ch09-01-unrecoverable-errors-with-panic.md: at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66'
],
[
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="String in memory" src="img/trpl04-01.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="s1 and s2 pointing to the same value" src="img/trpl04-02.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="s1 and s2 to two places" src="img/trpl04-03.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="s1 moved to s2" src="img/trpl04-04.svg" class="center" style="width: 50%;" />'
],
['files/rust-book/ch15-04-rc.md:<img alt="Two lists that share ownership of a third list" src="img/trpl15-03.svg" class="center" />'],
['files/rust-book/ch13-01-closures.md:parameter, we would separate them with commas, like `|param1, param2|`.'],
['files/rust-book/ch20-01-single-threaded.md:The `String::from_utf8_lossy` function takes a `&[u8]` and produces a `String`'],
[
'files/rust-book/appendix-06-translation.md:- [Cebuano](https://github.com/agentzero1/book)',
'files/rust-book/appendix-06-translation.md:- [Tagalog](https://github.com/josephace135/book)'
],
['files/rust-book/ch20-00-final-project-a-web-server.md:'],
['files/rust-book/ch14-03-cargo-workspaces.md: Running target/debug/deps/add_one-b3235fea9a156f74'],
[
'files/rust-book/ch04-02-references-and-borrowing.md:<img alt="&String s pointing at String s1" src="img/trpl04-05.svg" class="center" />',
'files/rust-book/ch04-02-references-and-borrowing.md:```rust,edition2018',
],
[
'files/rust-book/ch05-02-example-structs.md:using `rect1`, which is the reason we use the `&` in the function signature and',
'files/rust-book/ch05-02-example-structs.md:Let’s try it! The `println!` macro call will now look like `println!("rect1 is',
'files/rust-book/ch05-02-example-structs.md:{:?}", rect1);`. Putting the specifier `:?` inside the curly brackets tells'
],
['files/rust-book/ch11-03-test-organization.md:target/debug/deps/integration_test-ce99bcc2479f4607` (the hash at the end of'],
['files/rust-book/ch15-06-reference-cycles.md:<img alt="Reference cycle of lists" src="img/trpl15-04.svg" class="center" />'],
[
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered HTML documentation for the `add_one` function of `my_crate`" src="img/trpl14-01.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered HTML documentation with a comment for the crate as a whole" src="img/trpl14-02.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered documentation for the `art` crate that lists the `kinds` and `utils` modules" src="img/trpl14-03.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered documentation for the `art` crate with the re-exports on the front page" src="img/trpl14-04.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:$ cargo login abcdefghijklmnopqrstuvwxyz012345'
],
[
'files/rust-book/ch05-01-defining-structs.md:just this user’s email address, we could use `user1.email` wherever we wanted',
'files/rust-book/ch05-01-defining-structs.md:First, Listing 5-6 shows how we create a new `User` instance in `user2` without',
'files/rust-book/ch05-01-defining-structs.md:use the same values from `user1` that we created in Listing 5-2.',
'files/rust-book/ch05-01-defining-structs.md:the values from `user1`</span>',
'files/rust-book/ch05-01-defining-structs.md:values from the fields of the instance in the `user1` variable</span>',
'files/rust-book/ch05-01-defining-structs.md:The code in Listing 5-7 also creates an instance in `user2` that has a',
'files/rust-book/ch05-01-defining-structs.md:`active` and `sign_in_count` fields from `user1`.',
'files/rust-book/ch05-01-defining-structs.md:> let user1 = User {',
'files/rust-book/ch05-01-defining-structs.md:> username: "someusername123",'
],
[
'files/rust-book/ch05-03-method-syntax.md:called the `area` function and passed `rect1` as an argument, we can instead',
'files/rust-book/ch05-03-method-syntax.md:of `rect2` are smaller than the dimensions of `rect1` but `rect3` is wider than',
'files/rust-book/ch05-03-method-syntax.md:`rect1`:',
'files/rust-book/ch05-03-method-syntax.md:Can rect1 hold rect2? true',
'files/rust-book/ch05-03-method-syntax.md:Can rect1 hold rect3? false',
'files/rust-book/ch05-03-method-syntax.md:`rect1.can_hold(&rect2)` passes in `&rect2`, which is an immutable borrow to',
'files/rust-book/ch05-03-method-syntax.md:`rect2`, an instance of `Rectangle`. This makes sense because we only need to',
'files/rust-book/ch05-03-method-syntax.md:read `rect2` (rather than write, which would mean we’d need a mutable borrow),',
'files/rust-book/ch05-03-method-syntax.md:and we want `main` to retain ownership of `rect2` so we can use it again after'
],
['files/rust-book/ch04-03-slices.md:<img alt="world containing a pointer to the 6th byte of String s and a length 5" src="img/trpl04-06.svg" class="center" style="width: 50%;" />'],
[
'files/rust-book/ch10-02-traits.md:pub fn notify(item1: impl Summary, item2: impl Summary) {',
'files/rust-book/ch10-02-traits.md:If we wanted this function to allow `item1` and `item2` to have different',
'files/rust-book/ch10-02-traits.md:pub fn notify<T: Summary>(item1: T, item2: T) {',
'files/rust-book/ch10-02-traits.md:The generic type `T` specified as the type of the `item1` and `item2`',
'files/rust-book/ch10-02-traits.md:passed as an argument for `item1` and `item2` must be the same.'
],
[
'files/rust-book/ch15-01-box.md:<img alt="An infinite Cons list" src="img/trpl15-01.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch15-01-box.md:<img alt="A finite Cons list" src="img/trpl15-02.svg" class="center" />'
]
])
},
{
// Test -i with regex
args: ['-i', '-r', '[a-z]{3}\\d', 'files/rust-book'],
expected: updateExpectedPaths([
[
'files/rust-book/ch10-03-lifetime-syntax.md:type stored in the variable `string1`) as well as string literals (which is',
'files/rust-book/ch10-03-lifetime-syntax.md:what variable `string2` contains).',
'files/rust-book/ch10-03-lifetime-syntax.md:In this example, `string1` is valid until the end of the outer scope, `string2`',
'files/rust-book/ch10-03-lifetime-syntax.md:`string2`. Then we’ll move the `println!` that uses `result` outside the inner',
'files/rust-book/ch10-03-lifetime-syntax.md:<span class="caption">Listing 10-24: Attempting to use `result` after `string2`',
'files/rust-book/ch10-03-lifetime-syntax.md:`string2` would need to be valid until the end of the outer scope. Rust knows',
'files/rust-book/ch10-03-lifetime-syntax.md:As humans, we can look at this code and see that `string1` is longer than',
'files/rust-book/ch10-03-lifetime-syntax.md:`string2` and therefore `result` will contain a reference to `string1`.',
'files/rust-book/ch10-03-lifetime-syntax.md:Because `string1` has not gone out of scope yet, a reference to `string1` will'
],
[
'files/rust-book/ch09-01-unrecoverable-errors-with-panic.md: at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88',
'files/rust-book/ch09-01-unrecoverable-errors-with-panic.md: at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66',
'files/rust-book/ch09-01-unrecoverable-errors-with-panic.md: 4: core::fmt::ArgumentV1::show_usize'
],
[
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="String in memory" src="img/trpl04-01.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="s1 and s2 pointing to the same value" src="img/trpl04-02.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="s1 and s2 to two places" src="img/trpl04-03.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch04-01-what-is-ownership.md:<img alt="s1 moved to s2" src="img/trpl04-04.svg" class="center" style="width: 50%;" />'
],
['files/rust-book/ch15-04-rc.md:<img alt="Two lists that share ownership of a third list" src="img/trpl15-03.svg" class="center" />'],
['files/rust-book/ch13-01-closures.md:parameter, we would separate them with commas, like `|param1, param2|`.'],
[
'files/rust-book/ch20-01-single-threaded.md:The `String::from_utf8_lossy` function takes a `&[u8]` and produces a `String`',
'files/rust-book/ch20-01-single-threaded.md:User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101',
'files/rust-book/ch20-01-single-threaded.md:This is a minimal HTML5 document with a heading and some text. To return this'
],
[
'files/rust-book/appendix-06-translation.md:- [Cebuano](https://github.com/agentzero1/book)',
'files/rust-book/appendix-06-translation.md:- [Tagalog](https://github.com/josephace135/book)'
],
['files/rust-book/ch20-00-final-project-a-web-server.md:'],
['files/rust-book/ch14-03-cargo-workspaces.md: Running target/debug/deps/add_one-b3235fea9a156f74'],
[
'files/rust-book/ch04-02-references-and-borrowing.md:<img alt="&String s pointing at String s1" src="img/trpl04-05.svg" class="center" />',
'files/rust-book/ch04-02-references-and-borrowing.md:```rust,edition2018'
],
[
'files/rust-book/ch05-02-example-structs.md:using `rect1`, which is the reason we use the `&` in the function signature and',
'files/rust-book/ch05-02-example-structs.md:Let’s try it! The `println!` macro call will now look like `println!("rect1 is',
'files/rust-book/ch05-02-example-structs.md:{:?}", rect1);`. Putting the specifier `:?` inside the curly brackets tells'
],
[
'files/rust-book/ch06-01-defining-an-enum.md:struct Ipv4Addr {',
'files/rust-book/ch06-01-defining-an-enum.md:struct Ipv6Addr {',
'files/rust-book/ch06-01-defining-an-enum.md: V4(Ipv4Addr),',
'files/rust-book/ch06-01-defining-an-enum.md: V6(Ipv6Addr),'
],
['files/rust-book/ch11-03-test-organization.md:target/debug/deps/integration_test-ce99bcc2479f4607` (the hash at the end of'],
['files/rust-book/ch15-06-reference-cycles.md:<img alt="Reference cycle of lists" src="img/trpl15-04.svg" class="center" />'],
[
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered HTML documentation for the `add_one` function of `my_crate`" src="img/trpl14-01.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered HTML documentation with a comment for the crate as a whole" src="img/trpl14-02.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered documentation for the `art` crate that lists the `kinds` and `utils` modules" src="img/trpl14-03.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:<img alt="Rendered documentation for the `art` crate with the re-exports on the front page" src="img/trpl14-04.png" class="center" />',
'files/rust-book/ch14-02-publishing-to-crates-io.md:$ cargo login abcdefghijklmnopqrstuvwxyz012345'
],
[
'files/rust-book/ch05-01-defining-structs.md:just this user’s email address, we could use `user1.email` wherever we wanted',
'files/rust-book/ch05-01-defining-structs.md:First, Listing 5-6 shows how we create a new `User` instance in `user2` without',
'files/rust-book/ch05-01-defining-structs.md:use the same values from `user1` that we created in Listing 5-2.',
'files/rust-book/ch05-01-defining-structs.md:the values from `user1`</span>',
'files/rust-book/ch05-01-defining-structs.md:values from the fields of the instance in the `user1` variable</span>',
'files/rust-book/ch05-01-defining-structs.md:The code in Listing 5-7 also creates an instance in `user2` that has a',
'files/rust-book/ch05-01-defining-structs.md:`active` and `sign_in_count` fields from `user1`.',
'files/rust-book/ch05-01-defining-structs.md:> let user1 = User {',
'files/rust-book/ch05-01-defining-structs.md:> username: "someusername123",'
],
[
'files/rust-book/ch05-03-method-syntax.md:called the `area` function and passed `rect1` as an argument, we can instead',
'files/rust-book/ch05-03-method-syntax.md:of `rect2` are smaller than the dimensions of `rect1` but `rect3` is wider than',
'files/rust-book/ch05-03-method-syntax.md:`rect1`:',
'files/rust-book/ch05-03-method-syntax.md:Can rect1 hold rect2? true',
'files/rust-book/ch05-03-method-syntax.md:Can rect1 hold rect3? false',
'files/rust-book/ch05-03-method-syntax.md:`rect1.can_hold(&rect2)` passes in `&rect2`, which is an immutable borrow to',
'files/rust-book/ch05-03-method-syntax.md:`rect2`, an instance of `Rectangle`. This makes sense because we only need to',
'files/rust-book/ch05-03-method-syntax.md:read `rect2` (rather than write, which would mean we’d need a mutable borrow),',
'files/rust-book/ch05-03-method-syntax.md:and we want `main` to retain ownership of `rect2` so we can use it again after'
],
['files/rust-book/ch04-03-slices.md:<img alt="world containing a pointer to the 6th byte of String s and a length 5" src="img/trpl04-06.svg" class="center" style="width: 50%;" />'],
[
'files/rust-book/ch10-02-traits.md:pub fn notify(item1: impl Summary, item2: impl Summary) {',
'files/rust-book/ch10-02-traits.md:If we wanted this function to allow `item1` and `item2` to have different',
'files/rust-book/ch10-02-traits.md:pub fn notify<T: Summary>(item1: T, item2: T) {',
'files/rust-book/ch10-02-traits.md:The generic type `T` specified as the type of the `item1` and `item2`',
'files/rust-book/ch10-02-traits.md:passed as an argument for `item1` and `item2` must be the same.'
],
[
'files/rust-book/ch15-01-box.md:<img alt="An infinite Cons list" src="img/trpl15-01.svg" class="center" style="width: 50%;" />',
'files/rust-book/ch15-01-box.md:<img alt="A finite Cons list" src="img/trpl15-02.svg" class="center" />'
]
])
},
{
// Test -z flag,
args: ['-z', 'function', 'files/rust-book-gz/ch02-00-guessing-game-tutorial.md.gz'],
expected: [[
'functions, using external crates, and more! The following chapters will explore',
'As you saw in Chapter 1, the `main` function is the entry point into the',
'The `fn` syntax declares a new function, the parentheses, `()`, indicate there',
'are no parameters, and the curly bracket, `{`, starts the body of the function.',
'calling `String::new`, a function that returns a new instance of a `String`.',
'function* of the `String` type. An associated function is implemented on a type,',
'This `new` function creates a new, empty string. You’ll find a `new` function',
'on many types, because it’s a common name for a function that makes a new value',
'Recall that we included the input/output functionality from the standard',
'the `stdin` function from the `io` module:',
'could have written this function call as `std::io::stdin`. The `stdin` function',
'difficult. Rust doesn’t yet include random number functionality in its standard',
'Next, we’re adding two lines in the middle. The `rand::thread_rng` function',
'> Note: You won’t just know which traits to use and which methods and functions',
'> other functionality in the `rand` crate, for example, run `cargo doc --open`',
'do that by adding the following two lines to the `main` function body:',
'`let`, `match`, methods, associated functions, the use of external crates, and',
'variables, data types, and functions, and shows how to use them in Rust.'
]]
},
{
// Test -z flag with -r
args: ['-r', '-z', 'mutable', 'files/rust-book-gz'],
expected: RUST_MUTABLE_EXPECTED.map(file => file.map(line =>
line.replace('rust-book', 'rust-book-gz').replace('.md', '.md.gz')
))
}
]
for (const {args, expected} of TESTS) {
const flags = args.filter(arg => arg.startsWith('-'))
const parameters = args.filter(arg => !arg.startsWith('-'))
// Update all paths in the parameters to have correct separators
for (let i = 1; i < parameters.length; i++) parameters[i] = updatePath(parameters[i])
for (const args of reorderings(parameters, flags)) {
test(`grep ${args.join(' ')}`, async t => {
const {stdout} = await execFilePromise(
'node', ['../grep.js', ...args],
{env: GREP_ENV}
)
matchOutput(t, stdout, expected)
})
}
}
// grep.js is allowed to return a nonzero exit code if no matches were found
test('grep no matches', async t => {
let stdout
try {
({stdout} = await execFilePromise(
'node', ['../grep.js', 'no-such-string', updatePath('files/independence.txt')],
{env: GREP_ENV}
))
}
catch (e) { ({stdout} = e) }
matchOutput(t, stdout, [])
})
// Test grepping the standard input
test('grep stdin', async t => {
const grepPromise = execFilePromise('node', ['../grep.js', 'Rust'], {env: GREP_ENV})
fs.createReadStream('files/rust-book/SUMMARY.md')
.on('error', _ => t.fail('Failed to open file'))
.pipe(grepPromise.child.stdin)
.on('error', _ => t.fail('grep.js did not read stdin'))
const {stdout} = await grepPromise
matchOutput(t, stdout, [[
'# The Rust Programming Language',
'[The Rust Programming Language](title-page.md)',
'## Basic Rust Literacy',
'## Thinking in Rust',
'- [Object Oriented Programming Features of Rust](ch17-00-oop.md)',
' - [Unsafe Rust](ch19-01-unsafe-rust.md)',
' - [G - How Rust is Made and “Nightly Rust”](appendix-07-nightly-rust.md)'
]])
})
// Ensure that the streams deal with lines spread across chunks correctly
test('multiple-chunk input file', async t => {
const lines = new Array(1e5).fill().map((_, i) => `Line ${i + 1}`)
for (let i = 0; i < 10; i++) {
const search = `${i}`
const {stdout} = await execFilePromise(
'node', ['../grep.js', search, updatePath('files/long.txt')],
{env: GREP_ENV}
)
const expectedLines = lines.filter(line => line.includes(search))
t.deepEqual(stdout, expectedLines.map(line => `${line}\n`).join(''))
}
})
// Ensure that the streams deal with lines containing multiple chunks
test('multiple-chunk lines', async t => {
const contents = await fs.promises.readFile('files/long-lines.txt', 'utf8')
const lines = contents.trim().split('\n')
for (let i = 0; i < 10; i++) {
const {stdout} = await execFilePromise(
'node', ['../grep.js', `${i}`, updatePath('files/long-lines.txt')],
{env: GREP_ENV}
)
t.deepEqual(stdout, lines[i] + '\n')
}
})