~ubuntu-branches/ubuntu/precise/nodejs/precise

« back to all changes in this revision

Viewing changes to test/simple/test-sendfd.js

  • Committer: Bazaar Package Importer
  • Author(s): Jérémy Lal
  • Date: 2010-08-20 11:49:04 UTC
  • mfrom: (7.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100820114904-lz22w6fkth7yh179
Tags: 0.2.0-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Test sending and receiving a file descriptor.
 
2
//
 
3
// This test is pretty complex. It ends up spawning test/fixtures/recvfd.js
 
4
// as a child to test desired behavior. What happens is
 
5
//
 
6
//  1. Create an in-memory pipe via pipe(2). These two file descriptors
 
7
//     are not visible to any other process, and so make a good test-case
 
8
//     for sharing.
 
9
//  2. Create a a UNIX socket at SOCK_PATH. When a client connects to this
 
10
//     path, they are sent the write end of the pipe from above.
 
11
//  3. The client is sent n JSON representations of the DATA variable, each
 
12
//     with a different ordinal. We send these delimited by '\n' strings
 
13
//     so that the receiving end can avoid any coalescing that hapepns
 
14
//     due to the stream nature of the socket (e.g. '{}{}' is not a valid
 
15
//     JSON string).
 
16
//  4. The child process receives file descriptors and JSON blobs and,
 
17
//     whenever it has at least one of each, writes a modified JSON blob
 
18
//     to the FD. The blob is modified to include the child's process ID.
 
19
//  5. Once the child process has sent n responses, it closes the write end
 
20
//     of the pipe, which signals to the parent that there is no more data
 
21
//     coming.
 
22
//  6. The parent listens to the read end of the pipe, accumulating JSON
 
23
//     blobs (again, delimited by '\n') and verifying that a) the 'pid'
 
24
//     attribute belongs to the child and b) the 'ord' field has not been
 
25
//     seen in a response yet. This is intended to ensure that all blobs
 
26
//     sent out have been relayed back to us.
 
27
 
 
28
common = require("../common");
 
29
assert = common.assert
 
30
 
 
31
var buffer = require('buffer');
 
32
var child_process = require('child_process');
 
33
var fs = require('fs');
 
34
var net = require('net');
 
35
var netBinding = process.binding('net');
 
36
var path = require('path');
 
37
var sys = require('sys');
 
38
 
 
39
var DATA = {
 
40
  'ppid' : process.pid,
 
41
  'ord' : 0
 
42
};
 
43
 
 
44
var SOCK_PATH = path.join(
 
45
  __dirname,
 
46
  '..',
 
47
  path.basename(__filename, '.js') + '.sock'
 
48
);
 
49
 
 
50
var logChild = function(d) {
 
51
  if (typeof d == 'object') {
 
52
    d = d.toString();
 
53
  }
 
54
 
 
55
  d.split('\n').forEach(function(l) {
 
56
    if (l.length > 0) {
 
57
      common.debug('CHILD: ' + l);
 
58
    }
 
59
  });
 
60
};
 
61
 
 
62
// Create a pipe
 
63
//
 
64
// We establish a listener on the read end of the pipe so that we can
 
65
// validate any data sent back by the child. We send the write end of the
 
66
// pipe to the child and close it off in our process.
 
67
var pipeFDs = netBinding.pipe();
 
68
assert.equal(pipeFDs.length, 2);
 
69
 
 
70
var seenOrdinals = [];
 
71
 
 
72
var pipeReadStream = new net.Stream();
 
73
pipeReadStream.addListener('data', function(data) {
 
74
  data.toString('utf8').trim().split('\n').forEach(function(d) {
 
75
    var rd = JSON.parse(d);
 
76
 
 
77
    assert.equal(rd.pid, cpp);
 
78
    assert.equal(seenOrdinals.indexOf(rd.ord), -1);
 
79
 
 
80
    seenOrdinals.unshift(rd.ord);
 
81
  });
 
82
});
 
83
pipeReadStream.open(pipeFDs[0]);
 
84
pipeReadStream.resume();
 
85
 
 
86
// Create a UNIX socket at SOCK_PATH and send DATA and the write end
 
87
// of the pipe to whoever connects.
 
88
//
 
89
// We send two messages here, both with the same pipe FD: one string, and
 
90
// one buffer. We want to make sure that both datatypes are handled
 
91
// correctly.
 
92
var srv = net.createServer(function(s) {
 
93
  var str = JSON.stringify(DATA) + '\n';
 
94
 
 
95
  DATA.ord = DATA.ord + 1;
 
96
  var buf = new buffer.Buffer(str.length);
 
97
  buf.write(JSON.stringify(DATA) + '\n', 'utf8');
 
98
 
 
99
  s.write(str, 'utf8', pipeFDs[1]);
 
100
  if (s.write(buf, undefined, pipeFDs[1])) {
 
101
    netBinding.close(pipeFDs[1]);
 
102
  } else {
 
103
    s.addListener('drain', function() {
 
104
      netBinding.close(pipeFDs[1]);
 
105
    });
 
106
  }
 
107
});
 
108
srv.listen(SOCK_PATH);
 
109
 
 
110
// Spawn a child running test/fixtures/recvfd.js
 
111
var cp = child_process.spawn(process.argv[0],
 
112
                             [path.join(common.fixturesDir, 'recvfd.js'), SOCK_PATH]);
 
113
 
 
114
cp.stdout.addListener('data', logChild);
 
115
cp.stderr.addListener('data', logChild);
 
116
 
 
117
// When the child exits, clean up and validate its exit status
 
118
var cpp = cp.pid;
 
119
cp.addListener('exit', function(code, signal) {
 
120
  srv.close();
 
121
  // fs.unlinkSync(SOCK_PATH);
 
122
 
 
123
  assert.equal(code, 0);
 
124
  assert.equal(seenOrdinals.length, 2);
 
125
});
 
126
 
 
127
// vim:ts=2 sw=2 et