1 from __future__
import absolute_import
2 from __future__
import division
3 from __future__
import print_function
4 from __future__
import unicode_literals
6 from caffe2.proto
import caffe2_pb2
10 from zipfile
import ZipFile
13 Generates a document in markdown format summrizing the coverage of serialized 14 testing. The document lives in 15 `caffe2/python/serialized_test/SerializedTestCoverage.md` 18 OpSchema = workspace.C.OpSchema
21 def gen_serialized_test_coverage(source_dir, output_dir):
22 (covered, not_covered, schemaless) = gen_coverage_sets(source_dir)
23 num_covered = len(covered)
24 num_not_covered = len(not_covered)
25 num_schemaless = len(schemaless)
26 total_ops = num_covered + num_not_covered
28 with open(os.path.join(output_dir,
'SerializedTestCoverage.md'),
'w+')
as f:
29 f.write(
'# Serialized Test Coverage Report\n')
30 f.write(
"This is an automatically generated file. Please see " 31 "`caffe2/python/serialized_test/README.md` for details. " 32 "In the case of merge conflicts, please rebase and regenerate.\n")
33 f.write(
'## Summary\n')
35 'Serialized tests have covered {}/{} ({}%) operators\n\n'.format(
36 num_covered, total_ops,
37 (int)(num_covered / total_ops * 1000) / 10))
39 f.write(
'## Not covered operators\n')
40 f.write(
'<details>\n')
42 '<summary>There are {} not covered operators</summary>\n\n'.format(
44 for n
in sorted(not_covered):
45 f.write(
'* ' + n +
'\n')
46 f.write(
'</details>\n\n')
48 f.write(
'## Covered operators\n')
49 f.write(
'<details>\n')
51 '<summary>There are {} covered operators</summary>\n\n'.format(
53 for n
in sorted(covered):
54 f.write(
'* ' + n +
'\n')
55 f.write(
'</details>\n\n')
57 f.write(
'## Excluded from coverage statistics\n')
58 f.write(
'### Schemaless operators\n')
59 f.write(
'<details>\n')
61 '<summary>There are {} schemaless operators</summary>\n\n'.format(
63 for n
in sorted(schemaless):
64 f.write(
'* ' + n +
'\n')
65 f.write(
'</details>\n\n')
68 def gen_coverage_sets(source_dir):
69 covered_ops = gen_covered_ops(source_dir)
71 not_covered_ops = set()
73 for op_name
in core._GetRegisteredOperators():
74 s = OpSchema.get(op_name)
76 if s
is not None and s.private:
79 if op_name
not in covered_ops:
80 not_covered_ops.add(op_name)
82 if op_name.find(
"_ENGINE_") == -1:
83 schemaless_ops.append(op_name)
84 return (covered_ops, not_covered_ops, schemaless_ops)
87 def gen_covered_ops(source_dir):
89 proto = caffe2_pb2.OperatorDef()
90 proto.ParseFromString(x)
94 for f
in os.listdir(source_dir):
95 zipfile = os.path.join(source_dir, f)
96 if not os.path.isfile(zipfile):
98 temp_dir = tempfile.mkdtemp()
99 with ZipFile(zipfile)
as z:
100 z.extractall(temp_dir)
101 op_path = os.path.join(temp_dir,
'op.pb')
102 with open(op_path,
'rb')
as f:
104 op_proto = parse_proto(loaded_op)
105 covered.add(op_proto.type)
108 grad_path = os.path.join(temp_dir,
'grad_{}.pb'.format(index))
109 while os.path.isfile(grad_path):
110 with open(grad_path,
'rb')
as f:
111 loaded_grad = f.read()
112 grad_proto = parse_proto(loaded_grad)
113 covered.add(grad_proto.type)
115 grad_path = os.path.join(temp_dir,
'grad_{}.pb'.format(index))