3 # Copyright 2021-2022. The MBI project. All rights reserved.
4 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
8 import generator_utils as gen
10 template = """// @{generatedby}@
11 /* ///////////////////////// The MPI Bugs Initiative ////////////////////////
15 Description: @{shortdesc}@
18 Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
22 P2P!nonblocking: Lacking
23 P2P!persistent: Lacking
24 COLL!basic: @{collfeature}@
25 COLL!nonblocking: @{icollfeature}@
26 COLL!persistent: Lacking
36 ////////////////////// End of MBI headers /////////////////// */
44 int main(int argc, char **argv) {
49 MPI_Init(&argc, &argv);
50 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
51 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
52 printf("Hello from rank %d \\n", rank);
55 printf("MBI ERROR: This test needs at least 2 processes to produce a bug.\\n");
57 MPI_Comm newcom = MPI_COMM_WORLD;
58 MPI_Datatype type = MPI_INT;
61 int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
65 if (@{change_cond}@) {
66 @{operation1a}@ /* MBIERROR1 */
71 @{operation1b}@ /* MBIERROR2 */
81 printf("Rank %d finished normally\\n", rank);
86 for c1 in gen.coll + gen.icoll + gen.ibarrier:
87 for c2 in gen.coll + gen.icoll + gen.ibarrier:
89 patterns = {'c1': c1, 'c2': c2}
90 patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
91 patterns['collfeature'] = 'Yes' if c1 in gen.coll or c2 in gen.coll else 'Lacking'
92 patterns['icollfeature'] = 'Yes' if c1 in gen.icoll + gen.ibarrier or c2 in gen.icoll + gen.ibarrier else 'Lacking'
95 patterns['init1'] = gen.init[c1]("1")
96 patterns['init2'] = gen.init[c2]("2")
97 patterns['fini1a'] = gen.fini[c1]("1")
98 patterns['fini2a'] = gen.fini[c2]("2")
99 patterns['fini1b'] = gen.fini[c1]("1")
100 patterns['fini2b'] = gen.fini[c2]("2")
101 patterns['free1'] = gen.free[c1]("1")
102 patterns['free2'] = gen.free[c2]("2")
103 patterns['operation1a'] = gen.operation[c1]("1")
104 patterns['operation1b'] = gen.operation[c1]("1")
105 patterns['operation2a'] = gen.operation[c2]("2")
106 patterns['operation2b'] = gen.operation[c2]("2")
107 patterns['change_cond'] = 'rank % 2'
110 # Generate the correct code using the same collective twice
111 replace = patterns.copy()
112 replace['shortdesc'] = 'Correct collective ordering'
113 replace['longdesc'] = f'All ranks call {c1} twice'
114 replace['outcome'] = 'OK'
115 replace['errormsg'] = ''
116 gen.make_file(template, f'CallOrdering_{c1}_{c2}_ok.c', replace)
117 # Generate the correct code using the collective once
118 replace = patterns.copy()
119 replace['shortdesc'] = 'Correct collective ordering'
120 replace['longdesc'] = f'All ranks call {c1} once'
121 replace['outcome'] = 'OK'
122 replace['errormsg'] = ''
123 replace['init2'] = ''
124 replace['operation2a'] = ''
125 replace['operation2b'] = ''
126 replace['fini2a'] = ''
127 replace['fini2b'] = ''
128 replace['free2'] = ''
129 gen.make_file(template, f'CallOrdering_{c1}_ok.c', replace)
131 # Generate the correct ordering with two different collectives
132 replace = patterns.copy()
133 replace['shortdesc'] = 'Correct collective ordering'
134 replace['longdesc'] = f'All ranks call {c1} and then {c2}'
135 replace['outcome'] = 'OK'
136 replace['errormsg'] = ''
137 gen.make_file(template, f'CallOrdering_{c1}_{c2}_ok.c', replace)
138 # Generate the incorrect ordering with two different collectives
139 replace = patterns.copy()
140 replace['shortdesc'] = 'Incorrect collective ordering'
141 replace['longdesc'] = f'Odd ranks call {c1} and then {c2} while even ranks call these collectives in the other order'
142 replace['outcome'] = 'ERROR: CallMatching'
143 replace['errormsg'] = 'Collective mistmatch. @{c1}@ at @{filename}@:@{line:MBIERROR1}@ is matched with @{c2}@ line @{filename}@:@{line:MBIERROR2}@.'
144 replace['operation1b'] = gen.operation[c2]("2") # Inversion
145 replace['operation2b'] = gen.operation[c1]("1")
146 replace['fini1a'] = gen.fini[c1]("1") # Inversion
147 replace['fini2a'] = gen.fini[c2]("2")
148 replace['fini1b'] = gen.fini[c2]("2") # Inversion
149 replace['fini2b'] = gen.fini[c1]("1")
150 replace['free1'] = gen.free[c2]("2")
151 replace['free2'] = gen.free[c1]("1")
153 gen.make_file(template, f'CallOrdering_{c1}_{c2}_nok.c', replace)
155 # Generate the incorrect ordering with one collective
156 replace = patterns.copy()
157 replace['shortdesc'] = 'Incorrect collective ordering'
158 replace['longdesc'] = f'Odd ranks call {c1} while even ranks do not call any collective'
159 replace['outcome'] = 'ERROR: CallMatching'
160 replace['errormsg'] = 'Collective mistmatch. @{c1}@ at @{filename}@:@{line:MBIERROR1}@ is not matched.'
161 replace['operation1b'] = '' # Remove functions
162 replace['operation2b'] = ''
163 replace['operation2a'] = ''
164 replace['init2'] = ''
165 replace['fini1b'] = ''
166 replace['fini2a'] = ''
167 replace['fini2b'] = ''
168 replace['free1'] = gen.free[c1]("1")
169 replace['free2'] = ''
170 gen.make_file(template, f'CallOrdering_{c1}_none_nok.c', replace)
171 # Generate a correct ordering with a conditional not depending on ranks
172 replace = patterns.copy()
173 replace['shortdesc'] = 'Correct collective ordering'
174 replace['longdesc'] = f'All ranks call {c1}'
175 replace['outcome'] = 'OK'
176 replace['errormsg'] = ''
177 replace['change_cond'] = 'nprocs<256'
178 replace['operation1b'] = '' # Remove functions
179 replace['operation2b'] = ''
180 replace['operation2a'] = ''
181 replace['init2'] = ''
182 replace['fini1b'] = ''
183 replace['fini2a'] = ''
184 replace['fini2b'] = ''
185 replace['free1'] = gen.free[c1]("1")
186 replace['free2'] = ''
187 gen.make_file(template, f'CallOrdering_{c1}_none_ok.c', replace)