1. Project Clover database Wed Nov 12 2025 05:07:35 UTC
  2. Package guru.mikelue.foxglove.junit

File FoxgloveJUnitExtension.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

4
31
5
1
148
103
8
0.26
6.2
5
1.6

Classes

Class Line # Actions
FoxgloveJUnitExtension 24 31 0% 8 1
0.97597.5%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package guru.mikelue.foxglove.junit;
2   
3    import java.util.ArrayList;
4    import java.util.function.Supplier;
5   
6    import org.junit.jupiter.api.extension.BeforeAllCallback;
7    import org.junit.jupiter.api.extension.BeforeEachCallback;
8    import org.junit.jupiter.api.extension.ExtensionContext;
9    import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
10    import org.junit.platform.commons.JUnitException;
11    import org.slf4j.Logger;
12    import org.slf4j.LoggerFactory;
13   
14    import guru.mikelue.foxglove.TableFacet;
15    import guru.mikelue.foxglove.annotation.DataGenContext;
16    import guru.mikelue.foxglove.annotation.GenDataProcessor;
17    import guru.mikelue.foxglove.annotation.LayeredDataGenContext;
18   
19    /**
20    * JUnit extension for Foxglove.
21    *
22    * This extension implements semantics defined by {@link guru.mikelue.foxglove.annotation annotation doc}.
23    */
 
24    public class FoxgloveJUnitExtension implements BeforeAllCallback, BeforeEachCallback {
25    private final Logger logger = LoggerFactory.getLogger(FoxgloveJUnitExtension.class);
26   
27    private final static String DATA_GEN_CONTEXT = "foxglove.data_gen";
28    private final static String DATA_GEN_ON_CLASS_LEVEL = "foxglove.data_gen.on_class_level";
29   
30    /**
31    * Default constructor should get called by JUnit engine.
32    */
 
33  3 toggle public FoxgloveJUnitExtension() {}
34   
 
35  10 toggle @Override
36    public void beforeAll(ExtensionContext context) throws Exception
37    {
38  10 var targetClass = context.getTestClass().get();
39  10 var namespace = Namespace.create(targetClass);
40   
41  10 var storeForTestedClass = context.getStore(namespace);
42   
43  10 storeForTestedClass.getOrComputeIfAbsent(
44    DATA_GEN_CONTEXT,
45    key -> DataGenContext.loadFrom(targetClass)
46    );
47    }
48   
 
49  17 toggle @Override
50    public void beforeEach(ExtensionContext context) throws Exception
51    {
52  17 var storeForTestedClass = context.getStore(
53    Namespace.create(context.getRequiredTestClass())
54    );
55   
56  17 var contextSupplier = buildContextSupplier(context);
57   
58    /*
59    * Since we like to perform data generation on class level only once,
60    * we store the marker in the store of tested class.
61    *
62    * Because the testing instance may not be ready in {BeforeAllCallback},
63    * we do it here.
64    */
65  17 storeForTestedClass.getOrComputeIfAbsent(
66    DATA_GEN_ON_CLASS_LEVEL,
67    key -> doOnClassLevel(context.getRequiredTestInstance(), contextSupplier)
68    );
69    // :~)
70   
71  17 new GenDataProcessor(
72    context.getRequiredTestInstance(),
73    context.getRequiredTestMethod(),
74    contextSupplier,
75    context.getRequiredTestMethod().getName()
76    )
77    .performGenerating();
78    }
79   
 
80  17 toggle private Integer doOnClassLevel(Object testingInstance, Supplier<DataGenContext<TableFacet>> dataGenContextSupplier)
81    {
82  17 var processor = new GenDataProcessor(
83    testingInstance, testingInstance.getClass(), dataGenContextSupplier,
84    testingInstance.getClass().getSimpleName()
85    );
86   
87  17 if (!processor.hasDataGenerating()) {
88  15 return -1;
89    }
90   
91  2 logger.debug("Performing data generation on class level: \"{}\"",
92    testingInstance.getClass().getSimpleName()
93    );
94   
95  2 try {
96  2 return processor.performGenerating();
97    } catch (Exception e) {
98  0 throw new JUnitException(
99    String.format(
100    "Preparing @GenData on class level has error: \"%s\"",
101    testingInstance.getClass().getSimpleName()
102    ),
103    e
104    );
105    }
106    }
107   
108    /**
109    * Builds layered {@link DataGenContext} supplier if the testing class is a member class.
110    */
 
111  17 toggle private static Supplier<DataGenContext<TableFacet>> buildContextSupplier(ExtensionContext context)
112    {
113  17 var testingClass = context.getRequiredTestClass();
114   
115  17 if (testingClass.isMemberClass()) {
116  9 return () -> {
117  8 var testingInstances = context.getRequiredTestInstances().getAllInstances();
118  8 var genDataContexts = new ArrayList<DataGenContext<TableFacet>>(testingInstances.size());
119   
120  8 for (var testingInstance : testingInstances) {
121  17 var namespace = Namespace.create(testingInstance.getClass());
122  17 var store = context.getStore(namespace);
123   
124  17 @SuppressWarnings("unchecked")
125    var dataGenContext = (DataGenContext<TableFacet>)
126    store.get(DATA_GEN_CONTEXT, DataGenContext.class);
127   
128  17 genDataContexts.add(dataGenContext);
129    }
130   
131  8 return new LayeredDataGenContext<>(
132    testingInstances, genDataContexts
133    );
134    };
135    }
136   
137  8 return () -> {
138  8 var namespace = Namespace.create(testingClass);
139  8 var store = context.getStore(namespace);
140   
141  8 @SuppressWarnings("unchecked")
142    var dataGenContext = (DataGenContext<TableFacet>)
143    store.get(DATA_GEN_CONTEXT, DataGenContext.class);
144   
145  8 return dataGenContext;
146    };
147    }
148    }