evaluator_spec.js 11 KB

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