Skip to content

Commit cfbf52b

Browse files
committed
JS: Add tests.
1 parent 36994cd commit cfbf52b

3 files changed

Lines changed: 122 additions & 0 deletions

File tree

‎javascript/ql/test/library-tests/frameworks/NodeJSLib/StreamPipeDataFlow.expected‎

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import javascript
2+
import utils.test.InlineExpectationsTest
3+
4+
module StreamPipeConfig implements DataFlow::ConfigSig {
5+
predicate isSource(DataFlow::Node source) {
6+
source.getFile().getBaseName() = ["stream-pipe.js", "stream-pipe.mjs"] and
7+
source.(DataFlow::CallNode).getCalleeName() = "source"
8+
}
9+
10+
predicate isSink(DataFlow::Node sink) {
11+
exists(DataFlow::CallNode call |
12+
call.getFile().getBaseName() = ["stream-pipe.js", "stream-pipe.mjs"] and
13+
call.getCalleeName() = "consumeChunk" and
14+
sink = call.getArgument(0)
15+
)
16+
}
17+
}
18+
19+
module Flow = DataFlow::Global<StreamPipeConfig>;
20+
21+
module InlineTest implements TestSig {
22+
string getARelevantTag() { result = "flow" }
23+
24+
predicate hasActualResult(Location location, string element, string tag, string value) {
25+
tag = "flow" and
26+
element = "" and
27+
exists(DataFlow::CallNode source, DataFlow::Node sink |
28+
Flow::flow(source, sink) and
29+
value = source.getArgument(0).getStringValue() and
30+
location = sink.getLocation()
31+
)
32+
}
33+
}
34+
35+
import MakeTest<InlineTest>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
const { Readable, Writable } = require("stream");
2+
3+
class DirectDestination extends Writable {
4+
write(chunk) {
5+
consumeChunk(chunk); // $ flow=direct
6+
return true;
7+
}
8+
}
9+
10+
class PipedDestination extends Writable {
11+
write(chunk) {
12+
consumeChunk(chunk); // $ MISSING: flow=piped flow=piped-second
13+
return true;
14+
}
15+
}
16+
17+
new DirectDestination().write(source("direct"));
18+
Readable.from([source("piped"), source("piped-second")]).pipe(new PipedDestination());
19+
20+
21+
class SetDestination extends Writable {
22+
write(chunk) {
23+
consumeChunk(chunk); // $ MISSING: flow=set
24+
return true;
25+
}
26+
}
27+
28+
Readable.from(new Set([source("set")])).pipe(new SetDestination());
29+
30+
class GeneratorDestination extends Writable {
31+
write(chunk) {
32+
consumeChunk(chunk); // $ MISSING: flow=generator
33+
return true;
34+
}
35+
}
36+
37+
function* chunks() {
38+
yield source("generator");
39+
}
40+
41+
Readable.from(chunks()).pipe(new GeneratorDestination());
42+
43+
class CleanDestination extends Writable {
44+
write(chunk) {
45+
consumeChunk(chunk);
46+
return true;
47+
}
48+
}
49+
50+
const cleanReadable = Readable.from(["clean"]);
51+
cleanReadable.metadata = source("metadata");
52+
cleanReadable.pipe(new CleanDestination());
53+
54+
class ReceiverDestination extends Writable {
55+
constructor(value) {
56+
super();
57+
this.value = value;
58+
}
59+
60+
write(chunk) {
61+
consumeChunk(this.value); // $ MISSING: flow=receiver
62+
return true;
63+
}
64+
}
65+
66+
const returnedDestination =
67+
Readable.from(["clean"]).pipe(new ReceiverDestination(source("receiver")));
68+
consumeChunk(returnedDestination.value); // $ MISSING: flow=receiver
69+
70+
class UncalledDestination extends Writable {
71+
constructor(value) {
72+
super();
73+
this.value = value;
74+
}
75+
76+
write(chunk) {
77+
consumeChunk(this.value);
78+
return true;
79+
}
80+
}
81+
82+
const unrelated = {
83+
pipe(destination) {
84+
return destination;
85+
}
86+
};
87+
unrelated.pipe(new UncalledDestination(source("unrelated")));

0 commit comments

Comments
 (0)