@ -19,13 +19,11 @@ package org.springframework.test.context.cache;
@@ -19,13 +19,11 @@ package org.springframework.test.context.cache;
import org.junit.jupiter.api.BeforeEach ;
import org.junit.jupiter.api.Test ;
import org.springframework.context.ApplicationContext ;
import org.springframework.context.annotation.Configuration ;
import org.springframework.test.annotation.DirtiesContext.HierarchyMode ;
import org.springframework.test.context.ActiveProfiles ;
import org.springframework.test.context.ActiveProfilesResolver ;
import org.springframework.test.context.ContextConfiguration ;
import org.springframework.test.context.ContextHierarchy ;
import org.springframework.test.context.MergedContextConfiguration ;
import org.springframework.test.context.TestContext ;
import org.springframework.test.context.TestContextTestUtils ;
@ -52,7 +50,7 @@ class ContextCacheTests {
@@ -52,7 +50,7 @@ class ContextCacheTests {
@BeforeEach
void initialCacheState ( ) {
assertContextCacheStatistics ( contextCache , "initial state" , 0 , 0 , 0 ) ;
assertContextCacheStatistics ( contextCache , "initial state" , 0 , 0 , 0 , 0 ) ;
assertParentContextCount ( 0 ) ;
}
@ -64,38 +62,39 @@ class ContextCacheTests {
@@ -64,38 +62,39 @@ class ContextCacheTests {
return ( MergedContextConfiguration ) ReflectionTestUtils . getField ( testContext , "mergedConfig" ) ;
}
private ApplicationContext loadContext ( Class < ? > testClass ) {
private void loadCtxAndAssertStats ( Class < ? > testClass , int expectedSize , int expectedActiveContextsCount ,
int expectedHitCount , int expectedMissCount ) {
TestContext testContext = TestContextTestUtils . buildTestContext ( testClass , contextCache ) ;
return testContext . getApplicationContext ( ) ;
}
private void loadCtxAndAssertStats ( Class < ? > testClass , int expectedSize , int expectedHitCount , int expectedMissCount ) {
assertThat ( loadContext ( testClass ) ) . isNotNull ( ) ;
assertContextCacheStatistics ( contextCache , testClass . getName ( ) , expectedSize , expectedHitCount ,
expectedMissCount ) ;
assertThat ( testContext . getApplicationContext ( ) ) . isNotNull ( ) ;
assertContextCacheStatistics ( contextCache , testClass . getName ( ) , expectedSize , expectedActiveContextsCount ,
expectedHitCount , expectedMissCount ) ;
testContext . markApplicationContextUnused ( ) ;
}
@Test
void verifyCacheKeyIsBasedOnContextLoader ( ) {
loadCtxAndAssertStats ( AnnotationConfigContextLoaderTestCase . class , 1 , 0 , 1 ) ;
loadCtxAndAssertStats ( AnnotationConfigContextLoaderTestCase . class , 1 , 1 , 1 ) ;
loadCtxAndAssertStats ( CustomAnnotationConfigContextLoaderTestCase . class , 2 , 1 , 2 ) ;
loadCtxAndAssertStats ( CustomAnnotationConfigContextLoaderTestCase . class , 2 , 2 , 2 ) ;
loadCtxAndAssertStats ( AnnotationConfigContextLoaderTestCase . class , 2 , 3 , 2 ) ;
loadCtxAndAssertStats ( CustomAnnotationConfigContextLoaderTestCase . class , 2 , 4 , 2 ) ;
loadCtxAndAssertStats ( AnnotationConfigContextLoaderTestCase . class , 1 , 1 , 0 , 1 ) ;
loadCtxAndAssertStats ( AnnotationConfigContextLoaderTestCase . class , 1 , 1 , 1 , 1 ) ;
loadCtxAndAssertStats ( CustomAnnotationConfigContextLoaderTestCase . class , 2 , 1 , 1 , 2 ) ;
loadCtxAndAssertStats ( CustomAnnotationConfigContextLoaderTestCase . class , 2 , 1 , 2 , 2 ) ;
loadCtxAndAssertStats ( AnnotationConfigContextLoaderTestCase . class , 2 , 1 , 3 , 2 ) ;
loadCtxAndAssertStats ( CustomAnnotationConfigContextLoaderTestCase . class , 2 , 1 , 4 , 2 ) ;
}
@Test
void verifyCacheKeyIsBasedOnActiveProfiles ( ) {
int size = 0 , hit = 0 , miss = 0 ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , + + size , hit , + + miss ) ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , size , + + hit , miss ) ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , + + size , 1 , hit , + + miss ) ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , size , 1 , + + hit , miss ) ;
// Profiles {foo, bar} should not hash to the same as {bar,foo}
loadCtxAndAssertStats ( BarFooProfilesTestCase . class , + + size , hit , + + miss ) ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , size , + + hit , miss ) ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , size , + + hit , miss ) ;
loadCtxAndAssertStats ( BarFooProfilesTestCase . class , size , + + hit , miss ) ;
loadCtxAndAssertStats ( FooBarActiveProfilesResolverTestCase . class , size , + + hit , miss ) ;
loadCtxAndAssertStats ( BarFooProfilesTestCase . class , + + size , 1 , hit , + + miss ) ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , size , 1 , + + hit , miss ) ;
loadCtxAndAssertStats ( FooBarProfilesTestCase . class , size , 1 , + + hit , miss ) ;
loadCtxAndAssertStats ( BarFooProfilesTestCase . class , size , 1 , + + hit , miss ) ;
loadCtxAndAssertStats ( FooBarActiveProfilesResolverTestCase . class , size , 1 , + + hit , miss ) ;
}
@Test
@ -105,24 +104,24 @@ class ContextCacheTests {
@@ -105,24 +104,24 @@ class ContextCacheTests {
int misses = 0 ;
// Level 1
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel1TestCase . class , + + size , hits , + + misses ) ;
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel1TestCase . class , size , + + hits , misses ) ;
loadCtxAndAssertStats ( ContextHierarchyLevel1TestCase . class , + + size , 1 , hits , + + misses ) ;
loadCtxAndAssertStats ( ContextHierarchyLevel1TestCase . class , size , 1 , + + hits , misses ) ;
// Level 2
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel2TestCase . class , + + size /* L2 */ , + + hits /* L1 */ ,
loadCtxAndAssertStats ( ContextHierarchyLevel2TestCase . class , + + size /* L2 */ , 2 , + + hits /* L1 */ ,
+ + misses /* L2 */ ) ;
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel2TestCase . class , size , + + hits /* L2 */ , misses ) ;
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel2TestCase . class , size , + + hits /* L2 */ , misses ) ;
loadCtxAndAssertStats ( ContextHierarchyLevel2TestCase . class , size , 2 , + + hits /* L2 */ , misses ) ;
loadCtxAndAssertStats ( ContextHierarchyLevel2TestCase . class , size , 2 , + + hits /* L2 */ , misses ) ;
// Level 3-A
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel3aTestCase . class , + + size /* L3A */ , + + hits /* L2 */ ,
loadCtxAndAssertStats ( ContextHierarchyLevel3a1 TestCase . class , + + size /* L3A */ , 3 , + + hits /* L2 */ ,
+ + misses /* L3A */ ) ;
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel3aTestCase . class , size , + + hits /* L3A */ , misses ) ;
loadCtxAndAssertStats ( ContextHierarchyLevel3a1 TestCase . class , size , 3 , + + hits /* L3A */ , misses ) ;
// Level 3-B
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel3bTestCase . class , + + size /* L3B */ , + + hits /* L2 */ ,
loadCtxAndAssertStats ( ContextHierarchyLevel3bTestCase . class , + + size /* L3B */ , 3 , + + hits /* L2 */ ,
+ + misses /* L3B */ ) ;
loadCtxAndAssertStats ( ClassHierarchyC ontextHierarchyLevel3bTestCase . class , size , + + hits /* L3B */ , misses ) ;
loadCtxAndAssertStats ( ContextHierarchyLevel3bTestCase . class , size , 3 , + + hits /* L3B */ , misses ) ;
}
@Test
@ -130,23 +129,27 @@ class ContextCacheTests {
@@ -130,23 +129,27 @@ class ContextCacheTests {
// Load Level 3-A
TestContext testContext3a = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3aTestCase . class , contextCache ) ;
ContextHierarchyLevel3a1 TestCase . class , contextCache ) ;
testContext3a . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 3 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 3 , 0 , 3 ) ;
assertParentContextCount ( 2 ) ;
testContext3a . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 0 , 3 ) ;
// Load Level 3-B
TestContext testContext3b = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3bTestCase . class , contextCache ) ;
ContextHierarchyLevel3bTestCase . class , contextCache ) ;
testContext3b . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 3 , 1 , 4 ) ;
assertParentContextCount ( 2 ) ;
testContext3b . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 0 , 1 , 4 ) ;
// Remove Level 1
// Should also remove Levels 2, 3-A, and 3-B, leaving nothing.
contextCache . remove ( getMergedContextConfiguration ( testContext3a ) . getParent ( ) . getParent ( ) ,
HierarchyMode . CURRENT_LEVEL ) ;
assertContextCacheStatistics ( contextCache , "removed level 1" , 0 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 1" , 0 , 0 , 1 , 4 ) ;
assertParentContextCount ( 0 ) ;
}
@ -155,23 +158,27 @@ class ContextCacheTests {
@@ -155,23 +158,27 @@ class ContextCacheTests {
// Load Level 3-A
TestContext testContext3a = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3aTestCase . class , contextCache ) ;
ContextHierarchyLevel3a1 TestCase . class , contextCache ) ;
testContext3a . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 3 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 3 , 0 , 3 ) ;
assertParentContextCount ( 2 ) ;
testContext3a . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 0 , 3 ) ;
// Load Level 3-B
TestContext testContext3b = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3bTestCase . class , contextCache ) ;
ContextHierarchyLevel3bTestCase . class , contextCache ) ;
testContext3b . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 3 , 1 , 4 ) ;
assertParentContextCount ( 2 ) ;
testContext3b . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 0 , 1 , 4 ) ;
// Remove Level 1
// Should also remove Levels 2, 3-A, and 3-B, leaving nothing.
contextCache . remove ( getMergedContextConfiguration ( testContext3a ) . getParent ( ) . getParent ( ) ,
HierarchyMode . EXHAUSTIVE ) ;
assertContextCacheStatistics ( contextCache , "removed level 1" , 0 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 1" , 0 , 0 , 1 , 4 ) ;
assertParentContextCount ( 0 ) ;
}
@ -180,24 +187,28 @@ class ContextCacheTests {
@@ -180,24 +187,28 @@ class ContextCacheTests {
// Load Level 3-A
TestContext testContext3a = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3aTestCase . class , contextCache ) ;
ContextHierarchyLevel3a1 TestCase . class , contextCache ) ;
testContext3a . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 3 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 3 , 0 , 3 ) ;
assertParentContextCount ( 2 ) ;
testContext3a . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 0 , 3 ) ;
// Load Level 3-B
TestContext testContext3b = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3bTestCase . class , contextCache ) ;
ContextHierarchyLevel3bTestCase . class , contextCache ) ;
testContext3b . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 3 , 1 , 4 ) ;
assertParentContextCount ( 2 ) ;
testContext3b . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 0 , 1 , 4 ) ;
// Remove Level 2
// Should also remove Levels 3-A and 3-B, leaving only Level 1 as a context in the
// cache but also removing the Level 1 hierarchy since all children have been
// removed.
contextCache . remove ( getMergedContextConfiguration ( testContext3a ) . getParent ( ) , HierarchyMode . CURRENT_LEVEL ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 1 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 1 , 0 , 1 , 4 ) ;
assertParentContextCount ( 0 ) ;
}
@ -206,22 +217,26 @@ class ContextCacheTests {
@@ -206,22 +217,26 @@ class ContextCacheTests {
// Load Level 3-A
TestContext testContext3a = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3aTestCase . class , contextCache ) ;
ContextHierarchyLevel3a1 TestCase . class , contextCache ) ;
testContext3a . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 3 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 3 , 0 , 3 ) ;
assertParentContextCount ( 2 ) ;
testContext3a . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 0 , 3 ) ;
// Load Level 3-B
TestContext testContext3b = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3bTestCase . class , contextCache ) ;
ContextHierarchyLevel3bTestCase . class , contextCache ) ;
testContext3b . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 3 , 1 , 4 ) ;
assertParentContextCount ( 2 ) ;
testContext3b . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 0 , 1 , 4 ) ;
// Remove Level 2
// Should wipe the cache
contextCache . remove ( getMergedContextConfiguration ( testContext3a ) . getParent ( ) , HierarchyMode . EXHAUSTIVE ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 0 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 0 , 0 , 1 , 4 ) ;
assertParentContextCount ( 0 ) ;
}
@ -230,27 +245,31 @@ class ContextCacheTests {
@@ -230,27 +245,31 @@ class ContextCacheTests {
// Load Level 3-A
TestContext testContext3a = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3aTestCase . class , contextCache ) ;
ContextHierarchyLevel3a1 TestCase . class , contextCache ) ;
testContext3a . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 3 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 3 , 0 , 3 ) ;
assertParentContextCount ( 2 ) ;
testContext3a . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 0 , 3 ) ;
// Load Level 3-B
TestContext testContext3b = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3bTestCase . class , contextCache ) ;
ContextHierarchyLevel3bTestCase . class , contextCache ) ;
testContext3b . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 3 , 1 , 4 ) ;
assertParentContextCount ( 2 ) ;
testContext3b . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 0 , 1 , 4 ) ;
// Remove Level 3-A
contextCache . remove ( getMergedContextConfiguration ( testContext3a ) , HierarchyMode . CURRENT_LEVEL ) ;
assertContextCacheStatistics ( contextCache , "removed level 3-A" , 3 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 3-A" , 3 , 0 , 1 , 4 ) ;
assertParentContextCount ( 2 ) ;
// Remove Level 2
// Should also remove Level 3-B, leaving only Level 1.
contextCache . remove ( getMergedContextConfiguration ( testContext3b ) . getParent ( ) , HierarchyMode . CURRENT_LEVEL ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 1 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 1 , 0 , 1 , 4 ) ;
assertParentContextCount ( 0 ) ;
}
@ -259,29 +278,33 @@ class ContextCacheTests {
@@ -259,29 +278,33 @@ class ContextCacheTests {
// Load Level 3-A
TestContext testContext3a = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3aTestCase . class , contextCache ) ;
ContextHierarchyLevel3a1 TestCase . class , contextCache ) ;
testContext3a . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 3 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 3 , 0 , 3 ) ;
assertParentContextCount ( 2 ) ;
testContext3a . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A" , 3 , 0 , 0 , 3 ) ;
// Load Level 3-B
TestContext testContext3b = TestContextTestUtils . buildTestContext (
ClassHierarchyC ontextHierarchyLevel3bTestCase . class , contextCache ) ;
ContextHierarchyLevel3bTestCase . class , contextCache ) ;
testContext3b . getApplicationContext ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 3 , 1 , 4 ) ;
assertParentContextCount ( 2 ) ;
testContext3b . markApplicationContextUnused ( ) ;
assertContextCacheStatistics ( contextCache , "level 3, A and B" , 4 , 0 , 1 , 4 ) ;
// Remove Level 3-A
// Should wipe the cache.
contextCache . remove ( getMergedContextConfiguration ( testContext3a ) , HierarchyMode . EXHAUSTIVE ) ;
assertContextCacheStatistics ( contextCache , "removed level 3-A" , 0 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 3-A" , 0 , 0 , 1 , 4 ) ;
assertParentContextCount ( 0 ) ;
// Remove Level 2
// Should not actually do anything since the cache was cleared in the
// previous step. So the stats should remain the same.
contextCache . remove ( getMergedContextConfiguration ( testContext3b ) . getParent ( ) , HierarchyMode . EXHAUSTIVE ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 0 , 1 , 4 ) ;
assertContextCacheStatistics ( contextCache , "removed level 2" , 0 , 0 , 1 , 4 ) ;
assertParentContextCount ( 0 ) ;
}
@ -324,43 +347,4 @@ class ContextCacheTests {
@@ -324,43 +347,4 @@ class ContextCacheTests {
private static class FooBarActiveProfilesResolverTestCase {
}
@ContextHierarchy ( { @ContextConfiguration } )
private static class ClassHierarchyContextHierarchyLevel1TestCase {
@Configuration
static class Level1Config {
}
}
@ContextHierarchy ( { @ContextConfiguration } )
private static class ClassHierarchyContextHierarchyLevel2TestCase extends
ClassHierarchyContextHierarchyLevel1TestCase {
@Configuration
static class Level2Config {
}
}
@ContextHierarchy ( { @ContextConfiguration } )
private static class ClassHierarchyContextHierarchyLevel3aTestCase extends
ClassHierarchyContextHierarchyLevel2TestCase {
@Configuration
static class Level3aConfig {
}
}
@ContextHierarchy ( { @ContextConfiguration } )
private static class ClassHierarchyContextHierarchyLevel3bTestCase extends
ClassHierarchyContextHierarchyLevel2TestCase {
@Configuration
static class Level3bConfig {
}
}
}