2
0

evaluator_spec.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2018 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. var _primitives = require("../../core/primitives");
  24. var _util = require("../../shared/util");
  25. var _stream = require("../../core/stream");
  26. var _operator_list = require("../../core/operator_list");
  27. var _evaluator = require("../../core/evaluator");
  28. var _worker = require("../../core/worker");
  29. var _test_utils = require("./test_utils");
  30. describe('evaluator', function () {
  31. function HandlerMock() {
  32. this.inputs = [];
  33. }
  34. HandlerMock.prototype = {
  35. send: function send(name, data) {
  36. this.inputs.push({
  37. name: name,
  38. data: data
  39. });
  40. }
  41. };
  42. function ResourcesMock() {}
  43. ResourcesMock.prototype = {
  44. get: function get(name) {
  45. return this[name];
  46. }
  47. };
  48. function PdfManagerMock() {}
  49. function runOperatorListCheck(evaluator, stream, resources, callback) {
  50. var result = new _operator_list.OperatorList();
  51. var task = new _worker.WorkerTask('OperatorListCheck');
  52. evaluator.getOperatorList({
  53. stream: stream,
  54. task: task,
  55. resources: resources,
  56. operatorList: result
  57. }).then(function () {
  58. callback(result);
  59. }, function (reason) {
  60. callback(reason);
  61. });
  62. }
  63. var partialEvaluator;
  64. beforeAll(function (done) {
  65. partialEvaluator = new _evaluator.PartialEvaluator({
  66. pdfManager: new PdfManagerMock(),
  67. xref: new _test_utils.XRefMock(),
  68. handler: new HandlerMock(),
  69. pageIndex: 0
  70. });
  71. done();
  72. });
  73. afterAll(function () {
  74. partialEvaluator = null;
  75. });
  76. describe('splitCombinedOperations', function () {
  77. it('should reject unknown operations', function (done) {
  78. var stream = new _stream.StringStream('fTT');
  79. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  80. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  81. expect(result.fnArray.length).toEqual(1);
  82. expect(result.fnArray[0]).toEqual(_util.OPS.fill);
  83. expect(result.argsArray[0]).toEqual(null);
  84. done();
  85. });
  86. });
  87. it('should handle one operation', function (done) {
  88. var stream = new _stream.StringStream('Q');
  89. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  90. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  91. expect(result.fnArray.length).toEqual(1);
  92. expect(result.fnArray[0]).toEqual(_util.OPS.restore);
  93. done();
  94. });
  95. });
  96. it('should handle two glued operations', function (done) {
  97. var resources = new ResourcesMock();
  98. resources.Res1 = {};
  99. var stream = new _stream.StringStream('/Res1 DoQ');
  100. runOperatorListCheck(partialEvaluator, stream, resources, function (result) {
  101. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  102. expect(result.fnArray.length).toEqual(2);
  103. expect(result.fnArray[0]).toEqual(_util.OPS.paintXObject);
  104. expect(result.fnArray[1]).toEqual(_util.OPS.restore);
  105. done();
  106. });
  107. });
  108. it('should handle three glued operations', function (done) {
  109. var stream = new _stream.StringStream('fff');
  110. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  111. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  112. expect(result.fnArray.length).toEqual(3);
  113. expect(result.fnArray[0]).toEqual(_util.OPS.fill);
  114. expect(result.fnArray[1]).toEqual(_util.OPS.fill);
  115. expect(result.fnArray[2]).toEqual(_util.OPS.fill);
  116. done();
  117. });
  118. });
  119. it('should handle three glued operations #2', function (done) {
  120. var resources = new ResourcesMock();
  121. resources.Res1 = {};
  122. var stream = new _stream.StringStream('B*Bf*');
  123. runOperatorListCheck(partialEvaluator, stream, resources, function (result) {
  124. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  125. expect(result.fnArray.length).toEqual(3);
  126. expect(result.fnArray[0]).toEqual(_util.OPS.eoFillStroke);
  127. expect(result.fnArray[1]).toEqual(_util.OPS.fillStroke);
  128. expect(result.fnArray[2]).toEqual(_util.OPS.eoFill);
  129. done();
  130. });
  131. });
  132. it('should handle glued operations and operands', function (done) {
  133. var stream = new _stream.StringStream('f5 Ts');
  134. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  135. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  136. expect(result.fnArray.length).toEqual(2);
  137. expect(result.fnArray[0]).toEqual(_util.OPS.fill);
  138. expect(result.fnArray[1]).toEqual(_util.OPS.setTextRise);
  139. expect(result.argsArray.length).toEqual(2);
  140. expect(result.argsArray[1].length).toEqual(1);
  141. expect(result.argsArray[1][0]).toEqual(5);
  142. done();
  143. });
  144. });
  145. it('should handle glued operations and literals', function (done) {
  146. var stream = new _stream.StringStream('trueifalserinulln');
  147. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  148. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  149. expect(result.fnArray.length).toEqual(3);
  150. expect(result.fnArray[0]).toEqual(_util.OPS.setFlatness);
  151. expect(result.fnArray[1]).toEqual(_util.OPS.setRenderingIntent);
  152. expect(result.fnArray[2]).toEqual(_util.OPS.endPath);
  153. expect(result.argsArray.length).toEqual(3);
  154. expect(result.argsArray[0].length).toEqual(1);
  155. expect(result.argsArray[0][0]).toEqual(true);
  156. expect(result.argsArray[1].length).toEqual(1);
  157. expect(result.argsArray[1][0]).toEqual(false);
  158. expect(result.argsArray[2]).toEqual(null);
  159. done();
  160. });
  161. });
  162. });
  163. describe('validateNumberOfArgs', function () {
  164. it('should execute if correct number of arguments', function (done) {
  165. var stream = new _stream.StringStream('5 1 d0');
  166. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  167. expect(result.argsArray[0][0]).toEqual(5);
  168. expect(result.argsArray[0][1]).toEqual(1);
  169. expect(result.fnArray[0]).toEqual(_util.OPS.setCharWidth);
  170. done();
  171. });
  172. });
  173. it('should execute if too many arguments', function (done) {
  174. var stream = new _stream.StringStream('5 1 4 d0');
  175. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  176. expect(result.argsArray[0][0]).toEqual(1);
  177. expect(result.argsArray[0][1]).toEqual(4);
  178. expect(result.fnArray[0]).toEqual(_util.OPS.setCharWidth);
  179. done();
  180. });
  181. });
  182. it('should execute if nested commands', function (done) {
  183. var stream = new _stream.StringStream('/F2 /GS2 gs 5.711 Tf');
  184. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  185. expect(result.fnArray.length).toEqual(3);
  186. expect(result.fnArray[0]).toEqual(_util.OPS.setGState);
  187. expect(result.fnArray[1]).toEqual(_util.OPS.dependency);
  188. expect(result.fnArray[2]).toEqual(_util.OPS.setFont);
  189. expect(result.argsArray.length).toEqual(3);
  190. expect(result.argsArray[0].length).toEqual(1);
  191. expect(result.argsArray[1].length).toEqual(1);
  192. expect(result.argsArray[2].length).toEqual(2);
  193. done();
  194. });
  195. });
  196. it('should skip if too few arguments', function (done) {
  197. var stream = new _stream.StringStream('5 d0');
  198. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  199. expect(result.argsArray).toEqual([]);
  200. expect(result.fnArray).toEqual([]);
  201. done();
  202. });
  203. });
  204. it('should error if (many) path operators have too few arguments ' + '(bug 1443140)', function (done) {
  205. var NUM_INVALID_OPS = 25;
  206. var tempArr = new Array(NUM_INVALID_OPS + 1);
  207. var invalidMoveText = tempArr.join('10 Td\n');
  208. var moveTextStream = new _stream.StringStream(invalidMoveText);
  209. runOperatorListCheck(partialEvaluator, moveTextStream, new ResourcesMock(), function (result) {
  210. expect(result.argsArray).toEqual([]);
  211. expect(result.fnArray).toEqual([]);
  212. done();
  213. });
  214. var invalidLineTo = tempArr.join('20 l\n');
  215. var lineToStream = new _stream.StringStream(invalidLineTo);
  216. runOperatorListCheck(partialEvaluator, lineToStream, new ResourcesMock(), function (error) {
  217. expect(error instanceof _util.FormatError).toEqual(true);
  218. expect(error.message).toEqual('Invalid command l: expected 2 args, but received 1 args.');
  219. done();
  220. });
  221. });
  222. it('should close opened saves', function (done) {
  223. var stream = new _stream.StringStream('qq');
  224. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  225. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  226. expect(result.fnArray.length).toEqual(4);
  227. expect(result.fnArray[0]).toEqual(_util.OPS.save);
  228. expect(result.fnArray[1]).toEqual(_util.OPS.save);
  229. expect(result.fnArray[2]).toEqual(_util.OPS.restore);
  230. expect(result.fnArray[3]).toEqual(_util.OPS.restore);
  231. done();
  232. });
  233. });
  234. it('should skip paintXObject if name is missing', function (done) {
  235. var stream = new _stream.StringStream('/ Do');
  236. runOperatorListCheck(partialEvaluator, stream, new ResourcesMock(), function (result) {
  237. expect(result instanceof _util.FormatError).toEqual(true);
  238. expect(result.message).toEqual('XObject must be referred to by name.');
  239. done();
  240. });
  241. });
  242. it('should skip paintXObject if subtype is PS', function (done) {
  243. var xobjStreamDict = new _primitives.Dict();
  244. xobjStreamDict.set('Subtype', _primitives.Name.get('PS'));
  245. var xobjStream = new _stream.Stream([], 0, 0, xobjStreamDict);
  246. var xobjs = new _primitives.Dict();
  247. xobjs.set('Res1', xobjStream);
  248. var resources = new _primitives.Dict();
  249. resources.set('XObject', xobjs);
  250. var stream = new _stream.StringStream('/Res1 Do');
  251. runOperatorListCheck(partialEvaluator, stream, resources, function (result) {
  252. expect(result.argsArray).toEqual([]);
  253. expect(result.fnArray).toEqual([]);
  254. done();
  255. });
  256. });
  257. });
  258. describe('thread control', function () {
  259. it('should abort operator list parsing', function (done) {
  260. var stream = new _stream.StringStream('qqQQ');
  261. var resources = new ResourcesMock();
  262. var result = new _operator_list.OperatorList();
  263. var task = new _worker.WorkerTask('OperatorListAbort');
  264. task.terminate();
  265. partialEvaluator.getOperatorList({
  266. stream: stream,
  267. task: task,
  268. resources: resources,
  269. operatorList: result
  270. }).catch(function () {
  271. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  272. expect(result.fnArray.length).toEqual(0);
  273. done();
  274. });
  275. });
  276. it('should abort text parsing parsing', function (done) {
  277. var resources = new ResourcesMock();
  278. var stream = new _stream.StringStream('qqQQ');
  279. var task = new _worker.WorkerTask('TextContentAbort');
  280. task.terminate();
  281. partialEvaluator.getTextContent({
  282. stream: stream,
  283. task: task,
  284. resources: resources
  285. }).catch(function () {
  286. expect(true).toEqual(true);
  287. done();
  288. });
  289. });
  290. });
  291. describe('operator list', function () {
  292. function MessageHandlerMock() {}
  293. MessageHandlerMock.prototype = {
  294. send: function send() {}
  295. };
  296. it('should get correct total length after flushing', function () {
  297. var operatorList = new _operator_list.OperatorList(null, new MessageHandlerMock());
  298. operatorList.addOp(_util.OPS.save, null);
  299. operatorList.addOp(_util.OPS.restore, null);
  300. expect(operatorList.totalLength).toEqual(2);
  301. expect(operatorList.length).toEqual(2);
  302. operatorList.flush();
  303. expect(operatorList.totalLength).toEqual(2);
  304. expect(operatorList.length).toEqual(0);
  305. });
  306. });
  307. });