##// END OF EJS Templates
Variants validation + fail-fast
cin -
r28:1a0b4caf9976 default
parent child
Show More
@@ -120,7 +120,10 public abstract class BuildVariant imple
120 120
121 121 public LayerLink link(String from, String to, String kind) {
122 122 ensureMutable("add links");
123 var link = new LayerLink(from, to, kind);
123 var link = new LayerLink(
124 requireLinkValue("from", from),
125 requireLinkValue("to", to),
126 requireLinkValue("kind", kind));
124 127 links.add(link);
125 128 return link;
126 129 }
@@ -191,6 +194,13 public abstract class BuildVariant imple
191 194 throw new InvalidUserDataException("Variant '" + name + "' is finalized and cannot " + operation);
192 195 }
193 196
197 private static String requireLinkValue(String field, String value) {
198 if (value == null || value.trim().isEmpty())
199 throw new InvalidUserDataException("Link '" + field + "' must not be null or blank");
200
201 return value.trim();
202 }
203
194 204 public final class RolesSpec {
195 205 public BuildRole role(String name, Action<? super BuildRole> configure) {
196 206 return BuildVariant.this.role(name, configure);
@@ -158,8 +158,18 public abstract class BuildVariantsExten
158 158 var errors = new ArrayList<String>();
159 159
160 160 var layersByName = new LinkedHashMap<String, BuildLayer>();
161 for (var layer : layers)
162 layersByName.put(layer.getName(), layer);
161 for (var layer : layers) {
162 var layerName = normalize(layer.getName());
163 if (layerName == null) {
164 errors.add("Layer name must not be blank");
165 continue;
166 }
167
168 var previous = layersByName.putIfAbsent(layerName, layer);
169 if (previous != null) {
170 errors.add("Layer '" + layerName + "' is declared more than once");
171 }
172 }
163 173
164 174 for (var variant : variants)
165 175 validateVariant(variant, layersByName, errors);
@@ -174,28 +184,69 public abstract class BuildVariantsExten
174 184 }
175 185
176 186 private static void validateVariant(BuildVariant variant, Map<String, BuildLayer> layersByName, List<String> errors) {
187 var variantName = normalize(variant.getName());
188 if (variantName == null) {
189 errors.add("Variant name must not be blank");
190 return;
191 }
192
193 validateRoleAndArtifactNames(variant, errors);
177 194 var variantLayers = validateRoleMappings(variant, layersByName, errors);
178 195 validateLinks(variant, variantLayers, errors);
179 196 }
180 197
198 private static void validateRoleAndArtifactNames(BuildVariant variant, List<String> errors) {
199 var roleNames = new LinkedHashSet<String>();
200 for (var role : variant.getRoles()) {
201 var roleName = normalize(role.getName());
202 if (roleName == null) {
203 errors.add("Variant '" + variant.getName() + "' contains blank role name");
204 continue;
205 }
206 if (!roleNames.add(roleName)) {
207 errors.add("Variant '" + variant.getName() + "' contains duplicated role name '" + roleName + "'");
208 }
209 }
210
211 var slotNames = new LinkedHashSet<String>();
212 for (var slot : variant.getArtifactSlots()) {
213 var slotName = normalize(slot.getName());
214 if (slotName == null) {
215 errors.add("Variant '" + variant.getName() + "' contains blank artifact slot name");
216 continue;
217 }
218 if (!slotNames.add(slotName)) {
219 errors.add("Variant '" + variant.getName() + "' contains duplicated artifact slot name '" + slotName + "'");
220 }
221 }
222 }
223
181 224 private static Set<String> validateRoleMappings(BuildVariant variant, Map<String, BuildLayer> layersByName,
182 225 List<String> errors) {
183 226 var variantLayers = new LinkedHashSet<String>();
184 227
185 228 for (var role : variant.getRoles()) {
229 var seenLayers = new LinkedHashSet<String>();
186 230 for (var layerName : role.getLayers().getOrElse(List.of())) {
187 if (isBlank(layerName)) {
231 var normalizedLayerName = normalize(layerName);
232 if (normalizedLayerName == null) {
188 233 errors.add("Variant '" + variant.getName() + "', role '" + role.getName() + "' contains blank layer name");
189 234 continue;
190 235 }
191 236
192 var layer = layersByName.get(layerName);
237 var layer = layersByName.get(normalizedLayerName);
193 238 if (layer == null) {
194 errors.add("Variant '" + variant.getName() + "' references unknown layer '" + layerName + "'");
239 errors.add("Variant '" + variant.getName() + "' references unknown layer '" + normalizedLayerName + "'");
195 240 continue;
196 241 }
197 242
198 variantLayers.add(layerName);
243 if (!seenLayers.add(normalizedLayerName)) {
244 errors.add("Variant '" + variant.getName() + "', role '" + role.getName()
245 + "' contains duplicated layer reference '" + normalizedLayerName + "'");
246 continue;
247 }
248
249 variantLayers.add(normalizedLayerName);
199 250 }
200 251 }
201 252
@@ -40,6 +40,7 public abstract class VariantSourcesExte
40 40 private final List<SourceSetContext> boundContexts = new ArrayList<>();
41 41 private final LinkedHashMap<String, NamedDomainObjectProvider<GenericSourceSet>> sourceSetsByName = new LinkedHashMap<>();
42 42 private final LinkedHashMap<String, String> sourceSetLayersByName = new LinkedHashMap<>();
43 private boolean sourceSetsRegistered;
43 44
44 45 @Inject
45 46 public VariantSourcesExtension(ObjectFactory objects) {
@@ -137,6 +138,10 public abstract class VariantSourcesExte
137 138 }
138 139
139 140 void registerSourceSets(BuildVariantsExtension variants, NamedDomainObjectContainer<GenericSourceSet> sources) {
141 if (sourceSetsRegistered) {
142 throw new InvalidUserDataException("variantSources source sets are already registered");
143 }
144
140 145 validateBindings(variants);
141 146
142 147 var usages = layerUsages(variants).toList();
@@ -157,6 +162,8 public abstract class VariantSourcesExte
157 162 registeredContexts.size() - registeredBefore,
158 163 boundContexts.size() - boundBefore,
159 164 sourceSetsByName.size());
165
166 sourceSetsRegistered = true;
160 167 }
161 168
162 169 private Stream<LayerUsage> layerUsages(BuildVariantsExtension variants) {
@@ -156,7 +156,7 class VariantsPluginFunctionalTest {
156 156 link('a', 'b', null)
157 157 }
158 158 }
159 """, "has incomplete link (from/to/kind are required)");
159 """, "Link 'kind' must not be null or blank");
160 160 }
161 161
162 162 @Test
@@ -224,6 +224,25 class VariantsPluginFunctionalTest {
224 224 }
225 225
226 226 @Test
227 void failsOnDuplicatedLayerReferenceInRole() throws Exception {
228 assertBuildFails("""
229 plugins {
230 id 'org.implab.gradle-variants'
231 }
232
233 variants {
234 layer('a')
235
236 variant('browser') {
237 role('main') {
238 layers('a', 'a')
239 }
240 }
241 }
242 """, "contains duplicated layer reference 'a'");
243 }
244
245 @Test
227 246 void failsOnLateLayerMutationAfterFinalize() throws Exception {
228 247 assertBuildFails("""
229 248 plugins {
General Comments 0
You need to be logged in to leave comments. Login now