• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3# Copyright 2012-2013 Daniel James
4# Distributed under the Boost Software License, Version 1.0.
5# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
7import sys, os, subprocess, tempfile, re
8
9def main(args, directory):
10    if len(args) != 1:
11        print "Usage: output-deps.py quickbook-command"
12        exit(1)
13    quickbook_command = args[0]
14
15    failures = 0
16
17    # Dependency tests
18
19    failures += run_quickbook(quickbook_command, 'svg_missing.qbk',
20            deps_gold = 'svg_missing_deps.txt')
21    failures += run_quickbook(quickbook_command, 'svg_missing.qbk',
22            locations_gold = 'svg_missing_locs.txt')
23    failures += run_quickbook(quickbook_command, 'missing_relative.qbk',
24            deps_gold = 'missing_relative_deps.txt',
25            locations_gold = 'missing_relative_locs.txt')
26    failures += run_quickbook(quickbook_command, 'include_path.qbk',
27            deps_gold = 'include_path_deps.txt',
28            locations_gold = 'include_path_locs.txt',
29            input_path = ['sub1', 'sub2'])
30    failures += run_quickbook(quickbook_command, 'include_glob.qbk',
31            deps_gold = 'include_glob_deps.txt',
32            locations_gold = 'include_glob_locs.txt',
33            input_path = ['sub1', 'sub2'])
34
35    # Try building a simple document with various flags.
36
37    failures += run_quickbook(quickbook_command, 'simple.qbk',
38        output_gold = 'simple.xml')
39    failures += run_quickbook(quickbook_command, 'simple.qbk',
40        extra_flags = ['--no-self-linked-headers'],
41        output_gold = 'simple_no_self_linked.xml')
42    failures += run_quickbook(quickbook_command, 'simple.qbk',
43        extra_flags = ['--no-pretty-print'],
44        output_gold = 'simple_no_pretty_print.xml')
45    failures += run_quickbook(quickbook_command, 'simple.qbk',
46        extra_flags = ['--indent','4','--linewidth','60'],
47        output_gold = 'simple_custom_pretty_print.xml')
48
49    if failures == 0:
50        print "Success"
51    else:
52        print "Failures:",failures
53        exit(failures)
54
55def run_quickbook(quickbook_command, filename, output_gold = None,
56        deps_gold = None, locations_gold = None, input_path = [],
57        extra_flags = None):
58    failures = 0
59
60    command = [quickbook_command, '--debug', filename]
61
62    output_filename = None
63    if output_gold:
64        output_filename = temp_filename('.qbk')
65        command.extend(['--output-file', output_filename])
66
67    deps_filename = None
68    if deps_gold:
69        deps_filename = temp_filename('.txt')
70        command.extend(['--output-deps', deps_filename])
71
72    locations_filename = None
73    if locations_gold:
74        locations_filename = temp_filename('.txt')
75        command.extend(['--output-checked-locations', locations_filename])
76
77    for path in input_path:
78        command.extend(['-I', path])
79
80    if extra_flags:
81        command.extend(extra_flags)
82
83    try:
84        print 'Running: ' + ' '.join(command)
85        print
86        exit_code = subprocess.call(command)
87        print
88        success = not exit_code
89
90        if output_filename:
91            output = load_file(output_filename)
92        else:
93            output = None
94
95        if deps_filename:
96            deps = load_dependencies(deps_filename)
97        else:
98            deps = None
99
100        if locations_filename:
101            locations = load_locations(locations_filename)
102        else:
103            locations = None
104    finally:
105        if output_filename: os.unlink(output_filename)
106        if deps_filename: os.unlink(deps_filename)
107
108    if deps_gold:
109        gold = load_dependencies(deps_gold)
110        if deps != gold:
111            failures = failures + 1
112            print "Dependencies don't match:"
113            print "Gold:", gold
114            print "Result:", deps
115            print
116
117    if locations_gold:
118        gold = load_locations(locations_gold)
119        if locations != gold:
120            failures = failures + 1
121            print "Dependencies don't match:"
122            print "Gold:", gold
123            print "Result:", locations
124            print
125
126    if output_gold:
127        gold = load_file(output_gold)
128        if gold != output:
129            failures = failures + 1
130            print "Output doesn't match:"
131            print
132            print gold
133            print
134            print output
135            print
136
137    return failures
138
139def load_dependencies(filename):
140    dependencies = set()
141    f = open(filename, 'r')
142    for path in f:
143        if path[0] == '#': continue
144        if path in dependencies:
145            raise Exception("Duplicate path (%1s) in %2s" % (path, filename))
146        dependencies.add(path)
147    return dependencies
148
149def load_locations(filename):
150    line_matcher = re.compile("^([+-g]) (.*)$")
151    dependencies = {}
152    f = open(filename, 'r')
153    glob = None
154    globs = {}
155    for line in f:
156        if line[0] == '#': continue
157        m = line_matcher.match(line)
158
159        path = m.group(2)
160
161        if not m:
162            raise Exception("Invalid dependency file: %1s" % filename)
163        if m.group(1) == 'g':
164            globs[path] = []
165            glob = path
166        elif glob:
167            if m.group(1) != '+':
168                raise Exception("Negative match in glob.")
169            globs[glob].append(path)
170        else:
171            found = m.group(1) == '+'
172            if path in dependencies:
173                raise Exception("Duplicate path (%1s) in %2s" % (path, filename))
174            dependencies[path] = found
175    return { 'dependencies': dependencies, 'globs': globs }
176
177def temp_filename(extension):
178    file = tempfile.mkstemp(suffix = extension)
179    os.close(file[0])
180    return file[1]
181
182def load_file(filename):
183    f = open(filename, 'r')
184    try:
185        return f.read()
186    finally:
187        f.close()
188
189    return None
190
191main(sys.argv[1:], os.path.dirname(sys.argv[0]))
192