tools: Initial version of test_reports utility
[odoo/odoo.git] / bin / tools / test_reports.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 """ Helper functions for reports testing.
23
24     Please /do not/ import this file by default, but only explicitly call it
25     through the code of yaml tests.
26 """
27
28 import netsvc
29 import tools
30 import logging
31 from subprocess import Popen, PIPE
32 import os
33 import tempfile
34
35 def try_report(cr, uid, rname, ids, data=None, context=None):
36     """ Try to render a report <rname> with contents of ids
37     
38         This function should also check for common pitfalls of reports.
39     """
40     log = logging.getLogger('tools.test_reports')
41     if data is None:
42         data = {}
43     if context is None:
44         context = {}
45     if rname.startswith('report.'):
46         rname_s = rname[7:]
47     else:
48         rname_s = rname
49     log.debug("Trying %s.create(%r)", rname, ids)
50     res = netsvc.LocalService(rname).create(cr, uid, ids, data, context)
51     if not isinstance(res, tuple):
52         raise RuntimeError("Result of %s.create() should be a (data,format) tuple, now it is a %s" % \
53                                 (rname, type(res)))
54     (res_data, res_format) = res
55    
56     if not res_data:
57         raise ValueError("Report %s produced an empty result!" % rname)
58     
59     if tools.config['test_report_directory']:
60         file(os.path.join(tools.config['test_report_directory'], rname+ '.'+res_format), 'wb+').write(res_data)
61
62     log.debug("Have a %s report for %s, will examine it", res_format, rname)
63     if res_format == 'pdf':
64         if res_data[:5] != '%PDF-':
65             raise ValueError("Report %s produced a non-pdf header, %r" % (rname, res_data[:10]))
66     
67         res_text = False
68         try:
69             fd, rfname = tempfile.mkstemp(suffix=res_format)
70             os.write(fd, res_data)
71             os.close(fd)
72
73             fp = Popen(['pdftotext', '-enc', 'UTF-8', '-nopgbrk', rfname, '-'], shell=False, stdout=PIPE).stdout
74             res_text = tools.ustr(fp.read())
75             os.unlink(rfname)
76         except Exception:
77             log.warning("Cannot extract report's text:", exc_info=True)
78         
79         if res_text is not False:
80             for line in res_text.split('\n'):
81                 if ('[[' in line) or ('[ [' in line):
82                     log.error("Report %s may have bad expression near: \"%s\".", rname, line[80:])
83             # TODO more checks, what else can be a sign of a faulty report?
84     elif res_format == 'foobar':
85         # TODO
86         pass
87     else:
88         log.warning("Report %s produced a \"%s\" chunk, cannot examine it", rname, res_format)
89
90     return True
91 #eof