Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / test / data / extensions / api_test / terminal / component_extension / test.js
blob5538746f9edebf261f3e020762cd4e71644fd17d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var shellCommand = 'shell\n';
6 var catCommand = 'cat\n';
7 var catErrCommand = 'cat 1>&2\n';
9 // Ensure this has all distinct characters.
10 var testLine = 'abcdefgh\n';
12 var startCharacter = '#';
14 var croshName = 'crosh';
15 var invalidName = 'some name';
17 var invalidNameError = 'Invalid process name.';
19 var testLineNum = 10;
20 var testProcessTotal = 2;
22 var testProcessCount = 0;
23 var testProcesses = [];
25 function TestProcess(pid, type) {
26   this.pid_ = pid;
27   this.type_= type;
29   this.lineExpectation_ = '';
30   this.linesLeftToCheck_ = -1;
31   // We receive two streams from the process.
32   this.checkedStreamEnd_ = [0, 0];
34   this.closed_ = false;
35   this.startCharactersFound_ = 0;
36   this.started_ = false;
39 // Method to test validity of received input. We will receive two streams of
40 // the same data. (input will be echoed twice by the testing process). Each
41 // stream will contain the same string repeated |kTestLineNum| times. So we
42 // have to match 2 * |kTestLineNum| lines. The problem is the received lines
43 // from different streams may be interleaved (e.g. we may receive
44 // abc|abcdef|defgh|gh). To deal with that, we allow to test received text
45 // against two lines. The lines MUST NOT have two same characters for this
46 // algorithm to work.
47 TestProcess.prototype.testExpectation = function(text) {
48   chrome.test.assertTrue(this.linesLeftToCheck_ >= 0,
49                          "Test expectations not set.")
50   for (var i = 0; i < text.length; i++) {
51     if (this.processReceivedCharacter_(text[i], 0))
52       continue;
53     if (this.processReceivedCharacter_(text[i], 1))
54       continue;
55     chrome.test.fail("Received: " + text);
56   }
59 TestProcess.prototype.processReceivedCharacter_ = function(char, stream) {
60   if (this.checkedStreamEnd_[stream] >= this.lineExpectation_.length)
61     return false;
63   var expectedChar = this.lineExpectation_[this.checkedStreamEnd_[stream]];
64   if (expectedChar != char)
65     return false
67   this.checkedStreamEnd_[stream]++;
69   if (this.checkedStreamEnd_[stream] == this.lineExpectation_.length &&
70       this.linesLeftToCheck_ > 0) {
71     this.checkedStreamEnd_[stream] = 0;
72     this.linesLeftToCheck_--;
73   }
74   return true;
77 TestProcess.prototype.testOutputType = function(receivedType) {
78   if (receivedType == 'exit')
79     chrome.test.assertTrue(this.done());
80   else
81     chrome.test.assertEq('stdout', receivedType);
84 TestProcess.prototype.pid = function() {
85   return this.pid_;
88 TestProcess.prototype.started = function() {
89   return this.started_;
92 TestProcess.prototype.done = function() {
93   return this.checkedStreamEnd_[0] == this.lineExpectation_.length &&
94          this.checkedStreamEnd_[1] == this.lineExpectation_.length &&
95          this.linesLeftToCheck_ == 0;
98 TestProcess.prototype.isClosed = function() {
99   return this.closed_;
102 TestProcess.prototype.setClosed = function() {
103   this.closed_ = true;
106 TestProcess.prototype.canStart = function() {
107   return (this.startCharactersFound_ == 2);
110 TestProcess.prototype.startCharacterFound = function() {
111   this.startCharactersFound_++;
114 TestProcess.prototype.getCatCommand = function() {
115   if (this.type_ == "stdout")
116     return catCommand;
117   return catErrCommand;
120 TestProcess.prototype.addLineExpectation = function(line, times) {
121   this.lineExpectation_ = line.replace(/\n/g, "\r\n");
122   this.linesLeftToCheck_ = times - 2;
125 // Set of commands we use to setup terminal for testing (start cat) will produce
126 // some output. We don't care about that output, to avoid having to set that
127 // output in test expectations, we will send |startCharacter| right after cat is
128 // started. After we detect second |startCharacter|s in output, we know process
129 // won't produce any output by itself, so it is safe to start actual test.
130 TestProcess.prototype.maybeKickOffTest = function(text) {
131   var index = 0;
132   while (index != -1) {
133     index = text.indexOf(startCharacter, index);
134     if (index != -1) {
135       this.startCharacterFound();
136       if (this.canStart()) {
137         this.kickOffTest_(testLine, testLineNum);
138         return;
139       }
140       index++;
141     }
142   }
145 TestProcess.prototype.kickOffTest_ = function(line, lineNum) {
146   this.started_ = true;
147   // Each line will be echoed twice.
148   this.addLineExpectation(line, lineNum * 2);
150   for (var i = 0; i < lineNum; i++)
151     chrome.terminalPrivate.sendInput(this.pid_, line,
152         function (result) {
153           chrome.test.assertTrue(result);
154         }
155   );
159 function getProcessIndexForPid(pid) {
160   for (var i = 0; i < testProcessTotal; i++) {
161     if (testProcesses[i] && pid == testProcesses[i].pid())
162       return i;
163   }
164   return undefined;
167 function processOutputListener(pid, type, text) {
168   var processIndex = getProcessIndexForPid(pid);
169   if (processIndex == undefined)
170     return;
172   var process = testProcesses[processIndex];
174   if (!process.started()) {
175     process.maybeKickOffTest(text);
176     return;
177   }
179   process.testOutputType(type);
181   process.testExpectation(text);
183   if (process.done())
184     closeTerminal(processIndex);
187 function maybeEndTest() {
188   for (var i = 0; i < testProcessTotal; i++) {
189     if (!testProcesses[i] || !testProcesses[i].isClosed())
190       return;
191   }
193   chrome.test.succeed();
196 function closeTerminal(index) {
197   var process = testProcesses[index];
198   chrome.terminalPrivate.closeTerminalProcess(
199       process.pid(),
200       function(result) {
201         chrome.test.assertTrue(result);
202         process.setClosed();
203         maybeEndTest();
204       }
205   );
208 function initTest(process) {
209   var sendStartCharacter = function() {
210       chrome.terminalPrivate.sendInput(
211           process.pid(),
212           startCharacter + '\n',
213           function(result) {
214               chrome.test.assertTrue(result);
215           }
216       );
217   };
219   var startCat = function() {
220       chrome.terminalPrivate.sendInput(
221           process.pid(),
222           process.getCatCommand(),
223           function(result) {
224             chrome.test.assertTrue(result);
225             sendStartCharacter();
226           }
227       );
228   };
230   chrome.terminalPrivate.sendInput(
231       process.pid(),
232       shellCommand,
233       function(result) {
234         chrome.test.assertTrue(result);
235         startCat();
236       }
237   );
240 chrome.test.runTests([
241   function terminalTest() {
242     chrome.terminalPrivate.onProcessOutput.addListener(processOutputListener);
244     for (var i = 0; i < testProcessTotal; i++) {
245       chrome.terminalPrivate.openTerminalProcess(croshName, function(result) {
246           chrome.test.assertTrue(result >= 0);
247           var type = (testProcessCount % 2) ? 'stderr' : 'stdout';
248           var newProcess = new TestProcess(result, type);
249           testProcesses[testProcessCount] = newProcess;
250           testProcessCount++;
251           initTest(newProcess);
252       });
253     }
254   },
256   function invalidProcessNameTest() {
257     chrome.terminalPrivate.openTerminalProcess(invalidName,
258         chrome.test.callbackFail(invalidNameError));
259   }