diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/CachedSoqlExecutor.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/CachedSoqlExecutor.cls index e6c64ae341a..1f68b28a99e 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/CachedSoqlExecutor.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/CachedSoqlExecutor.cls @@ -12,7 +12,6 @@ public inherited sharing class CachedSoqlExecutor //NOPMD: incorrect report of t ICacheAdaptor cacheWrapper = new OrgCache(); // by default, configure the cache to use the org version - private final static String PARTITION_NAME = 'core'; private final static Integer CACHE_LIFESPAN_SECONDS = 28800; // TODO: soft setting / option /** @@ -118,30 +117,8 @@ public inherited sharing class CachedSoqlExecutor //NOPMD: incorrect report of t cacheWrapper.remove( generateKey( soql ) ); } - /** - * Clears the cached results for all cached SOQL - */ - public void clearAllCache() - { - String fullSoqlPartitionName = cacheWrapper.createFullyQualifiedPartitionName( PARTITION_NAME ); - for ( String thisKey : cacheWrapper.getKeys() ) - { - String qualifiedKey = qualifiedKey( thisKey ); - if ( cacheWrapper.contains( qualifiedKey ) ) - { - cacheWrapper.remove( qualifiedKey ); - } - } - } - private String generateKey( String soql ) { - String subkey = EncodingUtil.convertToHex( Crypto.generateDigest( 'SHA1', Blob.valueOf( soql ) ) ); - return qualifiedKey( subkey ); - } - - private String qualifiedKey( String subkey ) - { - return cacheWrapper.createFullyQualifiedKey( PARTITION_NAME, subkey ); + return EncodingUtil.convertToHex( Crypto.generateDigest( 'SHA1', Blob.valueOf( soql ) ) ); } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/ICacheAdaptor.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/ICacheAdaptor.cls index 512d3f5d0bc..75d4a510d9b 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/ICacheAdaptor.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/ICacheAdaptor.cls @@ -9,13 +9,10 @@ */ public interface ICacheAdaptor { - Boolean hasAccessToCache(); - Boolean isACache(); - Object get( String key ); - void put( String key, Object value, Integer lifespan ); - Set getKeys(); - Boolean contains( String key ); - void remove( String key ); - String createFullyQualifiedPartitionName( String partitionName ); - String createFullyQualifiedKey( String partitionName, String key ); + Boolean hasAccessToCache(); + Boolean isACache(); + Object get( String key ); + void put( String key, Object value, Integer lifespan ); + Boolean contains( String key ); + void remove( String key ); } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/NullCache.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/NullCache.cls index 0007e590817..db5db784508 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/NullCache.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/NullCache.cls @@ -5,48 +5,33 @@ * * All users are assumed to be allowed to use the cache, but it describes itself as 'not a cache' and effectively does nothing. */ -public class NullCache implements ICacheAdaptor +public inherited sharing class NullCache implements ICacheAdaptor { - public Boolean hasAccessToCache() - { - return true; - } - - public Boolean isACache() - { - return false; - } - - public Object get( String key ) - { - return null; - } - - public void put( String key, Object value, Integer lifespan ) // NOPMD: Intentionally left empty, as this should do nothing in a NullCache - { - } - - public Set getKeys() - { - return new Set(); - } - - public Boolean contains( String key ) - { - return false; - } - - public void remove( String key ) // NOPMD: Intentionally left empty, as this should do nothing in a NullCache - { - } - - public String createFullyQualifiedPartitionName( String partitionName ) - { - return partitionName; - } - - public String createFullyQualifiedKey( String partitionName, String subKey ) - { - return partitionName + '.' + subkey; - } + public Boolean hasAccessToCache() + { + return true; + } + + public Boolean isACache() + { + return false; + } + + public Object get( String key ) + { + return null; + } + + public void put( String key, Object value, Integer lifespan ) // NOPMD: Intentionally left empty, as this should do nothing in a NullCache + { + } + + public Boolean contains( String key ) + { + return false; + } + + public void remove( String key ) // NOPMD: Intentionally left empty, as this should do nothing in a NullCache + { + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/BulkObjectCache.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/ObjectCache.cls similarity index 85% rename from framework/default/ortoo-core/default/classes/fflib-extension/caching/BulkObjectCache.cls rename to framework/default/ortoo-core/default/classes/fflib-extension/caching/ObjectCache.cls index 4133a2d33a9..c7c4e9dd83b 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/BulkObjectCache.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/ObjectCache.cls @@ -8,7 +8,7 @@ * Note: The lifespan of a given object is reset whenever any object in that object's list is written. * That is, either the whole of the list is aged out, or none of it is. */ -public with sharing class BulkObjectCache +public with sharing class ObjectCache { // TODO: do we need to protect against 100kb limit // TODO: could implement a longest time since accessed, first out @@ -16,8 +16,6 @@ public with sharing class BulkObjectCache // TODO: could just ignore and invalidate the cache - check with the rest of the seniors // TODO: Docs on keys - // TODO: hide createFullyQualifiedPartitionName and createFullyQualifiedKey - public class InvalidIdentifierException extends Exceptions.DeveloperException {} public enum CacheScope { ORG, SESSION } @@ -80,7 +78,6 @@ public with sharing class BulkObjectCache ICacheAdaptor cacheWrapper = new OrgCache(); // by default, configure the cache to use the org version - private final static String PARTITION_NAME = 'core'; private final static Integer CACHE_LIFESPAN_SECONDS = 28800; // TODO: soft setting / option /** @@ -89,7 +86,7 @@ public with sharing class BulkObjectCache * @param CacheScope The scope of this cache instance. * @return CachedSoqlExecutor Itself, allowing for a fluent interface */ - public BulkObjectCache setScope( CacheScope scope ) + public ObjectCache setScope( CacheScope scope ) { Contract.requires( scope != null, 'setScope called with a null scope' ); @@ -122,7 +119,7 @@ public with sharing class BulkObjectCache CacheRetrieval values = new CacheRetrieval(); - Map cachedObjects = (Map)cacheWrapper.get( createFullyQualifiedKey( key ) ); + Map cachedObjects = (Map)cacheWrapper.get( key ); if ( cachedObjects == null ) { @@ -194,9 +191,9 @@ public with sharing class BulkObjectCache * * @param String The base key to put the objects into * @param List The SObjects to store - * @return BulkObjectCache Itself, allowing for a fluent interface + * @return ObjectCache Itself, allowing for a fluent interface */ - public BulkObjectCache put( String key, List sobjects ) + public ObjectCache put( String key, List sobjects ) { return put( key, 'Id', sobjects ); } @@ -208,9 +205,9 @@ public with sharing class BulkObjectCache * @param String The base key to put the objects into * @param String The field to get the individual SObject identifiers from (field value must be a non-null String) * @param List The SObjects to store - * @return BulkObjectCache Itself, allowing for a fluent interface + * @return ObjectCache Itself, allowing for a fluent interface */ - public BulkObjectCache put( String key, String idField, List sobjects ) + public ObjectCache put( String key, String idField, List sobjects ) { Contract.requires( idField != null, 'put called with a null idField' ); return put( key, new SobjectIdGetter( idField ), sobjects ); @@ -223,16 +220,15 @@ public with sharing class BulkObjectCache * @param String The base key to put the objects into * @param IdGetter The mechanism for getting the Id from each of the given objects * @param List The Objects to store - * @return BulkObjectCache Itself, allowing for a fluent interface + * @return ObjectCache Itself, allowing for a fluent interface */ - public BulkObjectCache put( String key, IdGetter idGetter, List objects ) + public ObjectCache put( String key, IdGetter idGetter, List objects ) { Contract.requires( key != null, 'put called with a null key' ); Contract.requires( idGetter != null, 'put called with a null idGetter' ); Contract.requires( objects != null, 'put called with a null objects' ); - String fullyQualifiedKey = createFullyQualifiedKey( key ); - Map cachedObjects = (Map)cacheWrapper.get( fullyQualifiedKey ); + Map cachedObjects = (Map)cacheWrapper.get( key ); if ( cachedObjects == null ) { @@ -247,7 +243,7 @@ public with sharing class BulkObjectCache Contract.assert( thisId != null, 'put called with an object that has a null Id: ' + thisObject ); cachedObjects.put( thisId, thisObject ); } - cacheWrapper.put( fullyQualifiedKey, cachedObjects, CACHE_LIFESPAN_SECONDS ); + cacheWrapper.put( key, cachedObjects, CACHE_LIFESPAN_SECONDS ); return this; } @@ -256,12 +252,12 @@ public with sharing class BulkObjectCache * Remove all the cached objects from the given base key. * * @param String The base key to remove the objects from. - * @return BulkObjectCache Itself, allowing for a fluent interface + * @return ObjectCache Itself, allowing for a fluent interface */ - public BulkObjectCache remove( String key ) + public ObjectCache remove( String key ) { Contract.requires( key != null, 'remove called with a null key' ); - cacheWrapper.remove( createFullyQualifiedKey( key ) ); + cacheWrapper.remove( key ); return this; } @@ -270,9 +266,9 @@ public with sharing class BulkObjectCache * * @param String The base key to remove the SObjects from. * @param Set The cache identifiers of the SObjects to remove. - * @return BulkObjectCache Itself, allowing for a fluent interface + * @return ObjectCache Itself, allowing for a fluent interface */ - public BulkObjectCache remove( String key, Set ids ) + public ObjectCache remove( String key, Set ids ) { Contract.requires( ids != null, 'remove called with a null ids' ); return remove( key, SetUtils.convertToSetOfStrings( ids ) ); @@ -283,29 +279,24 @@ public with sharing class BulkObjectCache * * @param String The base key to remove the objects from. * @param Set The cache identifiers of the objects to remove. - * @return BulkObjectCache Itself, allowing for a fluent interface + * @return ObjectCache Itself, allowing for a fluent interface */ - public BulkObjectCache remove( String key, Set ids ) + public ObjectCache remove( String key, Set ids ) { Contract.requires( key != null, 'remove called with a null key' ); Contract.requires( ids != null, 'remove called with a null ids' ); - Map cachedObjects = (Map)cacheWrapper.get( createFullyQualifiedKey( key ) ); + Map cachedObjects = (Map)cacheWrapper.get( key ); for ( String thisId : ids ) { Contract.assert( thisId != null, 'remove called with a null entry in ids' ); cachedObjects.remove( thisId ); } - cacheWrapper.put( createFullyQualifiedKey( key ), cachedObjects, CACHE_LIFESPAN_SECONDS ); + cacheWrapper.put( key, cachedObjects, CACHE_LIFESPAN_SECONDS ); return this; } - private String createFullyQualifiedKey( String key ) - { - return cacheWrapper.createFullyQualifiedKey( PARTITION_NAME, key ); - } - private class SobjectIdGetter implements IdGetter { String idField; diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/BulkObjectCache.cls-meta.xml b/framework/default/ortoo-core/default/classes/fflib-extension/caching/ObjectCache.cls-meta.xml similarity index 100% rename from framework/default/ortoo-core/default/classes/fflib-extension/caching/BulkObjectCache.cls-meta.xml rename to framework/default/ortoo-core/default/classes/fflib-extension/caching/ObjectCache.cls-meta.xml diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls index a4d17b4ba06..acb6eec3422 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls @@ -6,11 +6,14 @@ * * Attempting to access the cache without this permission will result in an OrgCache.AccessViolationException */ -public class OrgCache implements ICacheAdaptor +public inherited sharing class OrgCache implements ICacheAdaptor { + // TODO: clear all public class AccessViolationException extends Exceptions.DeveloperException {} // this looks like a config exception, but actually the system should be built // in such a way that it's never possible to get this exception + private final static String PARTITION_NAME = 'core'; + private Boolean hasAccessToCache { get @@ -65,7 +68,7 @@ public class OrgCache implements ICacheAdaptor .addContext( 'key', key ); } - return Cache.Org.get( key ); + return Cache.Org.get( createFullyQualifiedKey( key ) ); } /** @@ -93,26 +96,7 @@ public class OrgCache implements ICacheAdaptor .addContext( 'value', value ); } - Cache.Org.put( key, value, lifespan, Cache.Visibility.NAMESPACE, true ); // immutable outside of namespace - } - - /** - * Retrieve a set of the current keys of objects stored in this cache. - * - * If the user does not have access to the cache, will throw an AccessViolationException. - * - * @return Set The keys that currently exist in the cache - */ - public Set getKeys() - { - if ( ! hasAccessToCache ) - { - throw new AccessViolationException( Label.ortoo_core_org_cache_access_violation ) - .setErrorCode( FrameworkErrorCodes.CACHE_ACCESS_VIOLATION ) - .addContext( 'method', 'getKeys' ); - } - - return Cache.Org.getKeys(); + Cache.Org.put( createFullyQualifiedKey( key ), value, lifespan, Cache.Visibility.NAMESPACE, true ); // immutable outside of namespace } /** @@ -132,7 +116,7 @@ public class OrgCache implements ICacheAdaptor .addContext( 'method', 'contains' ) .addContext( 'key', key ); } - return Cache.Org.contains( key ); + return Cache.Org.contains( createFullyQualifiedKey( key ) ); } /** @@ -151,16 +135,16 @@ public class OrgCache implements ICacheAdaptor .addContext( 'method', 'remove' ) .addContext( 'key', key ); } - Cache.Org.remove( key ); + Cache.Org.remove( createFullyQualifiedKey( key ) ); } - public String createFullyQualifiedPartitionName( String partitionName ) + private String createFullyQualifiedPartitionName() { - return Cache.OrgPartition.createFullyQualifiedPartition( PackageUtils.NAMESPACE_PREFIX, partitionName ); + return Cache.OrgPartition.createFullyQualifiedPartition( PackageUtils.NAMESPACE_PREFIX, PARTITION_NAME ); } - public String createFullyQualifiedKey( String partitionName, String subKey ) + private String createFullyQualifiedKey( String key ) { - return Cache.OrgPartition.createFullyQualifiedKey( PackageUtils.NAMESPACE_PREFIX, partitionName, subkey ); + return Cache.OrgPartition.createFullyQualifiedKey( PackageUtils.NAMESPACE_PREFIX, PARTITION_NAME, key ); } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls index 4bfc5f4bfec..f65ceb5cd5c 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls @@ -3,8 +3,10 @@ * * All users are assumed to have access to the cache. */ -public class SessionCache implements ICacheAdaptor +public inherited sharing class SessionCache implements ICacheAdaptor { + private static final String PARTITION_NAME = 'core'; + /** * States if this user has access to the cache - which is always true * @@ -49,16 +51,6 @@ public class SessionCache implements ICacheAdaptor Cache.Session.put( key, value, lifespan, Cache.Visibility.NAMESPACE, true ); // immutable outside of namespace } - /** - * Retrieve a set of the current keys of objects stored in this cache. - * - * @return Set The keys that currently exist in the cache - */ - public Set getKeys() - { - return Cache.Session.getKeys(); - } - /** * States if the cache currently contains an object in the given key. * @@ -80,13 +72,13 @@ public class SessionCache implements ICacheAdaptor Cache.Session.remove( key ); } - public String createFullyQualifiedPartitionName( String partitionName ) + private String createFullyQualifiedPartitionName() { - return Cache.SessionPartition.createFullyQualifiedPartition( PackageUtils.NAMESPACE_PREFIX, partitionName ); + return Cache.SessionPartition.createFullyQualifiedPartition( PackageUtils.NAMESPACE_PREFIX, PARTITION_NAME ); } - public String createFullyQualifiedKey( String partitionName, String subKey ) + private String createFullyQualifiedKey( String key ) { - return Cache.SessionPartition.createFullyQualifiedKey( PackageUtils.NAMESPACE_PREFIX, partitionName, subkey ); + return Cache.SessionPartition.createFullyQualifiedKey( PackageUtils.NAMESPACE_PREFIX, PARTITION_NAME, key ); } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SobjectCache.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/SobjectCache.cls deleted file mode 100644 index 5d2b88601e3..00000000000 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SobjectCache.cls +++ /dev/null @@ -1,139 +0,0 @@ -// TODO: defunt -public with sharing class SobjectCache -{ - public class CacheAccessViolationException extends Exceptions.DeveloperException {} // this looks like a config exception, but actually the system should be built - // in such a way that it's never possible to get this exception - public enum CacheScope { ORG, SESSION } - - ICacheAdaptor cacheWrapper = new OrgCache(); // by default, configure the cache to use the org version - - private final static String PARTITION_NAME = 'soql'; // TODO: same partition? - private final static Integer CACHE_LIFESPAN_SECONDS = 28800; // TODO: soft setting / option - - private Boolean hasAccessToCache - { - get - { - if ( hasAccessToCache == null ) - { - hasAccessToCache = PermissionsService.hasAccessToCorePlatformCache(); - } - return hasAccessToCache; - } - set; - } - - public SobjectCache setScope( CacheScope scope ) - { - Contract.requires( scope != null, 'setScope called with a null scope' ); - - switch on scope - { - when ORG - { - cacheWrapper = new OrgCache(); - } - when SESSION - { - cacheWrapper = new SessionCache(); - } - } - - return this; - } - - public CacheRetrieval get( String key, Set ids ) - { - CacheRetrieval values = new CacheRetrieval(); - for ( Id thisId : ids ) - { - SObject thisValue = (SObject)cacheWrapper.get( createFullyQualifiedKey( key, thisId ) ); - if ( thisValue != null ) - { - values.addCacheHit( thisId, thisValue ); - } - else - { - values.addCacheMiss( thisId ); - } - } - return values; - } - - public SobjectCache put( String key, List sobjects ) - { - return put( key, 'Id', sobjects ); - } - - public SobjectCache put( String key, String idField, List sobjects ) - { - for ( Sobject thisSobject : sobjects ) - { - final String thisKey = createFullyQualifiedKey( key, (Id)thisSobject.get( idField ) ); - cacheWrapper.put( thisKey, thisSobject, CACHE_LIFESPAN_SECONDS ); - } - return this; - } - - public SobjectCache remove( String subkeyToRemove ) - { - Set keys = cacheWrapper.getKeys(); - - for ( String thisKey : keys ) - { - if ( isAKeyFor( thisKey, subkeyToRemove ) ) - { - cacheWrapper.remove( thisKey ); - } - } - return this; - } - - public SobjectCache remove( String key, Set ids ) - { - for ( Id thisId : ids ) - { - cacheWrapper.remove( createFullyQualifiedKey( key, thisId ) ); - } - return this; - } - - private Boolean isAKeyFor( String keyToCheck, String keyToCheckAgainst ) - { - return keyToCheck.startsWith( createKeyPrefix( keyToCheckAgainst ) ); - } - - private String createFullyQualifiedKey( String subKey, String id ) - { - return createKeyPrefix( subKey ) + id; - } - - private String createKeyPrefix( String subKey ) - { - return cacheWrapper.createFullyQualifiedKey( PARTITION_NAME, subkey ) + 'x'; - } - - public class CacheRetrieval - { - public Map cacheHits { get; private set; } - public Set cacheMisses { get; private set; } - - private CacheRetrieval() - { - cacheHits = new Map(); - cacheMisses = new Set(); - } - - private CacheRetrieval addCacheMiss( Id id ) - { - cacheMisses.add( id ); - return this; - } - - private CacheRetrieval addCacheHit( Id id, Sobject value ) - { - cacheHits.put( id, value ); - return this; - } - } -} diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SobjectCache.cls-meta.xml b/framework/default/ortoo-core/default/classes/fflib-extension/caching/SobjectCache.cls-meta.xml deleted file mode 100644 index dd61d1f917e..00000000000 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SobjectCache.cls-meta.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 52.0 - Active - diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/tests/CachedSoqlExecutorTest.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/tests/CachedSoqlExecutorTest.cls index 1ead66f5e98..f54244a8e4f 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/tests/CachedSoqlExecutorTest.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/tests/CachedSoqlExecutorTest.cls @@ -1,581 +1,429 @@ @isTest private without sharing class CachedSoqlExecutorTest { - @isTest - private static void query_whenCalledTwiceByAUserWithAccessToTheCache_onlyIssuesOneSoqlStatement() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void query_whenCalledTwiceByAUserWithAccessToTheCache_onlyIssuesOneSoqlStatement() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( true ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + CachedSoqlExecutor executor = new CachedSoqlExecutor(); - Test.startTest(); - List originalResults = executor.query( soqlStatement ); - List secondResults = executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + Test.startTest(); + List originalResults = executor.query( soqlStatement ); + List secondResults = executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with access to the cache, will only issue one SOQL statement' ); - System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with access to the cache, returns the same results in both calls' ); - } + System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with access to the cache, will only issue one SOQL statement' ); + System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with access to the cache, returns the same results in both calls' ); + } - @isTest - private static void query_org_whenCalledTwiceByAUserWithAccessToTheCache_onlyIssuesOneSoqlStatement() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void query_org_whenCalledTwiceByAUserWithAccessToTheCache_onlyIssuesOneSoqlStatement() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( true ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - Test.startTest(); - List originalResults = executor.query( soqlStatement ); - List secondResults = executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + Test.startTest(); + List originalResults = executor.query( soqlStatement ); + List secondResults = executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with access to the cache, will only issue one SOQL statement' ); - System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with access to the cache, returns the same results in both calls' ); - } + System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with access to the cache, will only issue one SOQL statement' ); + System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with access to the cache, returns the same results in both calls' ); + } - @isTest - private static void query_whenCalledTwiceByAUserWithoutAccessToTheCache_issuesTwoSoqlStatements() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void query_whenCalledTwiceByAUserWithoutAccessToTheCache_issuesTwoSoqlStatements() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( false ); + setupAccessToSoqlCache( false ); - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + CachedSoqlExecutor executor = new CachedSoqlExecutor(); - Test.startTest(); - List originalResults = executor.query( soqlStatement ); - List secondResults = executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + Test.startTest(); + List originalResults = executor.query( soqlStatement ); + List secondResults = executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - System.assertEquals( 2, soqlCalls, 'query, when called twice by a user with no access to the cache, will issue two SOQL statements' ); - System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with not access to the cache, returns the same results in both calls' ); - } + System.assertEquals( 2, soqlCalls, 'query, when called twice by a user with no access to the cache, will issue two SOQL statements' ); + System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with not access to the cache, returns the same results in both calls' ); + } - @isTest - private static void clearAllCache_willClearAllStatementsAndResultsFromTheCache() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void clearCacheFor_whenGivenASoqlStatementThatHasBeenExecuted_willClearTheCacheForThatStatement() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( true ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + CachedSoqlExecutor executor = new CachedSoqlExecutor(); - Test.startTest(); + executor.query( soqlStatement ); - executor.query( soqlStatement ); // executes SOQL - executor.clearAllCache(); + Test.startTest(); + executor.clearCacheFor( soqlStatement ); + executor.query( soqlStatement ); // should execute another soql + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - executor.query( soqlStatement ); // executes another SOQL - executor.query( soqlStatement ); - executor.query( soqlStatement ); + System.assertEquals( 1, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will clear that soql from the cache' ); + } + @isTest + private static void clearCacheFor_whenGivenASoqlStatementThatHasBeenExecuted_willNotClearTheCacheForOtherStatements() // NOPMD: Test method name format + { + String soqlStatement1 = 'SELECT Id FROM Account'; + String soqlStatement2 = 'SELECT Id FROM Account LIMIT 1'; - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + setupAccessToSoqlCache( true ); - System.assertEquals( 2, soqlCalls, 'clearAllCache, when called, will clear statements and results from the cache meaning that SOQL executions will need to be repeated when query is called' ); - } + CachedSoqlExecutor executor = new CachedSoqlExecutor(); - @isTest - private static void clearAllCache_whenThereIsNothingInTheCache_willNotThrowAnException() // NOPMD: Test method name format - { - setupAccessToSoqlCache( true ); + executor.query( soqlStatement1 ); + executor.query( soqlStatement2 ); - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + Test.startTest(); + executor.clearCacheFor( soqlStatement1 ); + executor.query( soqlStatement2 ); // should not execute another soql + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - Test.startTest(); - executor.clearAllCache(); - Test.stopTest(); + System.assertEquals( 0, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will not clear other soql from the cache' ); + } - System.assert( true, 'clearAllCache, when there is nothing in the cache, will not throw an exception' ); - } + @isTest + private static void clearCacheFor_whenGivenASoqlStatementThatHasNotBeenExecuted_willNotThrowAnException() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - @isTest - private static void clearAllCache_whenTheUserDoesNotHaveAccessToTheCache_throwsAnException() // NOPMD: Test method name format - { - setupAccessToSoqlCache( false ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + CachedSoqlExecutor executor = new CachedSoqlExecutor(); - Test.startTest(); - Exception exceptionThrown; - try - { - executor.clearAllCache(); - } - catch ( OrgCache.AccessViolationException e ) - { - exceptionThrown = e; - } - Test.stopTest(); + Test.startTest(); + executor.clearCacheFor( soqlStatement ); + Test.stopTest(); - ortoo_Asserts.assertContains( Label.ortoo_core_org_cache_access_violation, exceptionThrown?.getMessage(), 'clearAllCache, when the user does not have access to the cache, will throw an exception' ); - } + System.assert( true, 'clearCacheFor, when given a SOQL statement that has not been executed, will not throw an exception' ); + } - @isTest - private static void clearCacheFor_whenGivenASoqlStatementThatHasBeenExecuted_willClearTheCacheForThatStatement() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void clearCacheFor_whenTheUserDoesNotHaveAccessToTheCache_throwsAnException() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( true ); + setupAccessToSoqlCache( false ); - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + CachedSoqlExecutor executor = new CachedSoqlExecutor(); - executor.query( soqlStatement ); + Test.startTest(); + Exception exceptionThrown; + try + { + executor.clearCacheFor( soqlStatement ); + } + catch ( OrgCache.AccessViolationException e ) + { + exceptionThrown = e; + } + Test.stopTest(); - Test.startTest(); - executor.clearCacheFor( soqlStatement ); - executor.query( soqlStatement ); // should execute another soql - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + ortoo_Asserts.assertContains( Label.ortoo_core_org_cache_access_violation, exceptionThrown?.getMessage(), 'clearCacheFor, when the user does not have access to the cache, will throw an exception' ); + } - System.assertEquals( 1, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will clear that soql from the cache' ); - } + @isTest + private static void query_whenRanFor100Queries_willNotThrowAnException() + { + List soqlStatements = new List(); + for ( Integer i=1; i<=100; i++ ) + { + soqlStatements.add( 'SELECT Id FROM Account LIMIT ' + i ); + } - @isTest - private static void clearCacheFor_whenGivenASoqlStatementThatHasBeenExecuted_willNotClearTheCacheForOtherStatements() // NOPMD: Test method name format - { - String soqlStatement1 = 'SELECT Id FROM Account'; - String soqlStatement2 = 'SELECT Id FROM Account LIMIT 1'; + setupAccessToSoqlCache( true ); - setupAccessToSoqlCache( true ); + CachedSoqlExecutor executor = new CachedSoqlExecutor(); - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + Test.startTest(); - executor.query( soqlStatement1 ); - executor.query( soqlStatement2 ); + // Run each statement multiple times, one by one + for ( String thisSoqlStatement : soqlStatements ) + { + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + } - Test.startTest(); - executor.clearCacheFor( soqlStatement1 ); - executor.query( soqlStatement2 ); // should not execute another soql - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + // Then run each statement again + for ( String thisSoqlStatement : soqlStatements ) + { + executor.query( thisSoqlStatement ); + } - System.assertEquals( 0, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will not clear other soql from the cache' ); - } + Test.stopTest(); - @isTest - private static void clearCacheFor_whenGivenASoqlStatementThatHasNotBeenExecuted_willNotThrowAnException() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + System.assert( true, 'query, when run multiple times for 100 distinct queries, will not throw an exception' ); + } - setupAccessToSoqlCache( true ); + @isTest + private static void query_session_whenCalledTwiceByAUserWithAccessToTheCache_onlyIssuesOneSoqlStatement() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + setupAccessToSoqlCache( true ); - Test.startTest(); - executor.clearCacheFor( soqlStatement ); - Test.stopTest(); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - System.assert( true, 'clearCacheFor, when given a SOQL statement that has not been executed, will not throw an exception' ); - } + Test.startTest(); + List originalResults = executor.query( soqlStatement ); + List secondResults = executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - @isTest - private static void clearCacheFor_whenTheUserDoesNotHaveAccessToTheCache_throwsAnException() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with access to the cache, will only issue one SOQL statement' ); + System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with access to the cache, returns the same results in both calls' ); + } - setupAccessToSoqlCache( false ); + @isTest + private static void query_session_whenCalledTwiceByAUserWithoutAccessToTheCache_issuesOneSoqlStatement() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + setupAccessToSoqlCache( false ); - Test.startTest(); - Exception exceptionThrown; - try - { - executor.clearCacheFor( soqlStatement ); - } - catch ( OrgCache.AccessViolationException e ) - { - exceptionThrown = e; - } - Test.stopTest(); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - ortoo_Asserts.assertContains( Label.ortoo_core_org_cache_access_violation, exceptionThrown?.getMessage(), 'clearCacheFor, when the user does not have access to the cache, will throw an exception' ); - } + Test.startTest(); + List originalResults = executor.query( soqlStatement ); + List secondResults = executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - @isTest - private static void query_whenRanFor100Queries_willNotThrowAnException() - { - List soqlStatements = new List(); - for ( Integer i=1; i<=100; i++ ) - { - soqlStatements.add( 'SELECT Id FROM Account LIMIT ' + i ); - } + System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with no access to the org cache, will issue one SOQL statement' ); + System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with no access to the cache, returns the same results in both calls' ); + } - setupAccessToSoqlCache( true ); + @isTest + private static void clearCacheFor_session_whenGivenASoqlStatementThatHasBeenExecuted_willClearTheCacheForThatStatement() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - CachedSoqlExecutor executor = new CachedSoqlExecutor(); + setupAccessToSoqlCache( true ); - Test.startTest(); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - // Run each statement multiple times, one by one - for ( String thisSoqlStatement : soqlStatements ) - { - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - } + executor.query( soqlStatement ); - // Then run each statement again - for ( String thisSoqlStatement : soqlStatements ) - { - executor.query( thisSoqlStatement ); - } + Test.startTest(); + executor.clearCacheFor( soqlStatement ); + executor.query( soqlStatement ); // should execute another soql + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - Test.stopTest(); + System.assertEquals( 1, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will clear that soql from the cache' ); + } - System.assert( true, 'query, when run multiple times for 100 distinct queries, will not throw an exception' ); - } + @isTest + private static void clearCacheFor_session_whenGivenASoqlStatementThatHasBeenExecuted_willNotClearTheCacheForOtherStatements() // NOPMD: Test method name format + { + String soqlStatement1 = 'SELECT Id FROM Account'; + String soqlStatement2 = 'SELECT Id FROM Account LIMIT 1'; - @isTest - private static void query_session_whenCalledTwiceByAUserWithAccessToTheCache_onlyIssuesOneSoqlStatement() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + setupAccessToSoqlCache( true ); - setupAccessToSoqlCache( true ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); + executor.query( soqlStatement1 ); + executor.query( soqlStatement2 ); - Test.startTest(); - List originalResults = executor.query( soqlStatement ); - List secondResults = executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + Test.startTest(); + executor.clearCacheFor( soqlStatement1 ); + executor.query( soqlStatement2 ); // should not execute another soql + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with access to the cache, will only issue one SOQL statement' ); - System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with access to the cache, returns the same results in both calls' ); - } + System.assertEquals( 0, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will not clear other soql from the cache' ); + } - @isTest - private static void query_session_whenCalledTwiceByAUserWithoutAccessToTheCache_issuesOneSoqlStatement() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void clearCacheFor_session_whenGivenASoqlStatementThatHasNotBeenExecuted_willNotThrowAnException() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( false ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - Test.startTest(); - List originalResults = executor.query( soqlStatement ); - List secondResults = executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + Test.startTest(); + executor.clearCacheFor( soqlStatement ); + Test.stopTest(); - System.assertEquals( 1, soqlCalls, 'query, when called twice by a user with no access to the org cache, will issue one SOQL statement' ); - System.assertEquals( originalResults, secondResults, 'query, when called twice by a user with no access to the cache, returns the same results in both calls' ); - } + System.assert( true, 'clearCacheFor, when given a SOQL statement that has not been executed, will not throw an exception' ); + } - @isTest - private static void clearAllCache_session_willClearAllStatementsAndResultsFromTheCache() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void clearCacheFor_session_whenTheUserDoesNotHaveAccessToTheOrgCache_willNotThrowAnException() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( true ); + setupAccessToSoqlCache( false ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - Test.startTest(); + Test.startTest(); + executor.clearCacheFor( soqlStatement ); + Test.stopTest(); - executor.query( soqlStatement ); // executes SOQL - executor.clearAllCache(); - - executor.query( soqlStatement ); // executes another SOQL - executor.query( soqlStatement ); - executor.query( soqlStatement ); - - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); - - System.assertEquals( 2, soqlCalls, 'clearAllCache, when called, will clear statements and results from the cache meaning that SOQL executions will need to be repeated when query is called' ); - } - - @isTest - private static void clearAllCache_session_whenThereIsNothingInTheCache_willNotThrowAnException() // NOPMD: Test method name format - { - setupAccessToSoqlCache( true ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - - Test.startTest(); - executor.clearAllCache(); - Test.stopTest(); - - System.assert( true, 'clearAllCache, when there is nothing in the cache, will not throw an exception' ); - } - - @isTest - private static void clearAllCache_session_whenTheUserDoesNotHaveAccessToTheOrgCache_willNotThrowAnException() // NOPMD: Test method name format - { - setupAccessToSoqlCache( false ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - - Test.startTest(); - executor.clearAllCache(); - Test.stopTest(); - - System.assert( true, 'clearAllCache, when the user does not have access to the org cache, will not throw an exception' ); - } - - @isTest - private static void clearCacheFor_session_whenGivenASoqlStatementThatHasBeenExecuted_willClearTheCacheForThatStatement() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; - - setupAccessToSoqlCache( true ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - - executor.query( soqlStatement ); - - Test.startTest(); - executor.clearCacheFor( soqlStatement ); - executor.query( soqlStatement ); // should execute another soql - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); - - System.assertEquals( 1, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will clear that soql from the cache' ); - } - - @isTest - private static void clearCacheFor_session_whenGivenASoqlStatementThatHasBeenExecuted_willNotClearTheCacheForOtherStatements() // NOPMD: Test method name format - { - String soqlStatement1 = 'SELECT Id FROM Account'; - String soqlStatement2 = 'SELECT Id FROM Account LIMIT 1'; - - setupAccessToSoqlCache( true ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - - executor.query( soqlStatement1 ); - executor.query( soqlStatement2 ); - - Test.startTest(); - executor.clearCacheFor( soqlStatement1 ); - executor.query( soqlStatement2 ); // should not execute another soql - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); - - System.assertEquals( 0, soqlCalls, 'clearCacheFor, when given a SOQL statement that is already in the cache, will not clear other soql from the cache' ); - } - - @isTest - private static void clearCacheFor_session_whenGivenASoqlStatementThatHasNotBeenExecuted_willNotThrowAnException() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; - - setupAccessToSoqlCache( true ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - - Test.startTest(); - executor.clearCacheFor( soqlStatement ); - Test.stopTest(); - - System.assert( true, 'clearCacheFor, when given a SOQL statement that has not been executed, will not throw an exception' ); - } - - @isTest - private static void clearCacheFor_session_whenTheUserDoesNotHaveAccessToTheOrgCache_willNotThrowAnException() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; - - setupAccessToSoqlCache( false ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - - Test.startTest(); - executor.clearCacheFor( soqlStatement ); - Test.stopTest(); - - System.assert( true, 'clearCacheFor, when the user does not have access to the org cache, will not throw an exception' ); + System.assert( true, 'clearCacheFor, when the user does not have access to the org cache, will not throw an exception' ); } - @isTest - private static void query_session_whenRanFor100Queries_willNotThrowAnException() - { - List soqlStatements = new List(); - for ( Integer i=1; i<=100; i++ ) - { - soqlStatements.add( 'SELECT Id FROM Account LIMIT ' + i ); - } - - setupAccessToSoqlCache( true ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - - Test.startTest(); - - // Run each statement multiple times, one by one - for ( String thisSoqlStatement : soqlStatements ) - { - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - executor.query( thisSoqlStatement ); - } - - // Then run each statement again - for ( String thisSoqlStatement : soqlStatements ) - { - executor.query( thisSoqlStatement ); - } - - Test.stopTest(); - - System.assert( true, 'query, when run multiple times for 100 distinct queries, will not throw an exception' ); - } - - @isTest - private static void query_none_whenCalledTwiceByAUserWithAccessToTheCache_issuesTwoSoqlStatements() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; - - setupAccessToSoqlCache( true ); - - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); - - Test.startTest(); - List originalResults = executor.query( soqlStatement ); - List secondResults = executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); - - System.assertEquals( 2, soqlCalls, 'query against a NONE cache, when called twice by a user with access to the cache, will issue two SOQL statements' ); - } - - @isTest - private static void query_none_whenCalledTwiceByAUserWithoutAccessToTheCache_issuesTwoSoqlStatements() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void query_session_whenRanFor100Queries_willNotThrowAnException() + { + List soqlStatements = new List(); + for ( Integer i=1; i<=100; i++ ) + { + soqlStatements.add( 'SELECT Id FROM Account LIMIT ' + i ); + } - setupAccessToSoqlCache( false ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.SESSION ); - Test.startTest(); - List originalResults = executor.query( soqlStatement ); - List secondResults = executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + Test.startTest(); - System.assertEquals( 2, soqlCalls, 'query against a NONE cache, when called twice by a user with no access to the cache, will issue two SOQL statements' ); - } + // Run each statement multiple times, one by one + for ( String thisSoqlStatement : soqlStatements ) + { + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + executor.query( thisSoqlStatement ); + } - @isTest - private static void clearAllCache_none_willNotThrowAnException() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + // Then run each statement again + for ( String thisSoqlStatement : soqlStatements ) + { + executor.query( thisSoqlStatement ); + } - setupAccessToSoqlCache( true ); + Test.stopTest(); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); + System.assert( true, 'query, when run multiple times for 100 distinct queries, will not throw an exception' ); + } - Test.startTest(); + @isTest + private static void query_none_whenCalledTwiceByAUserWithAccessToTheCache_issuesTwoSoqlStatements() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - executor.query( soqlStatement ); - executor.clearAllCache(); + setupAccessToSoqlCache( true ); - executor.query( soqlStatement ); - executor.query( soqlStatement ); - executor.query( soqlStatement ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); + Test.startTest(); + List originalResults = executor.query( soqlStatement ); + List secondResults = executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + System.assertEquals( 2, soqlCalls, 'query against a NONE cache, when called twice by a user with access to the cache, will issue two SOQL statements' ); + } - System.assertEquals( 4, soqlCalls, 'clearAllCache against a none cache, when called, will not throw an exception and will not affect the number of SOQL statements issued' ); - } + @isTest + private static void query_none_whenCalledTwiceByAUserWithoutAccessToTheCache_issuesTwoSoqlStatements() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - @isTest - private static void clearAllCache_none_whenTheUserDoesNotHaveAccessToTheOrgCache_willNotThrowAnException() // NOPMD: Test method name format - { - setupAccessToSoqlCache( false ); + setupAccessToSoqlCache( false ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); - Test.startTest(); - executor.clearAllCache(); - Test.stopTest(); + Test.startTest(); + List originalResults = executor.query( soqlStatement ); + List secondResults = executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - System.assert( true, 'clearAllCache against a none cache, when called by a user that does not have access to the org cache, will not throw an exception' ); - } + System.assertEquals( 2, soqlCalls, 'query against a NONE cache, when called twice by a user with no access to the cache, will issue two SOQL statements' ); + } - @isTest - private static void clearCacheFor_none_doesNotAffectTheNumberOfSoqlStatementsIssued() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void clearCacheFor_none_doesNotAffectTheNumberOfSoqlStatementsIssued() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( true ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); - executor.query( soqlStatement ); + executor.query( soqlStatement ); - Test.startTest(); - executor.clearCacheFor( soqlStatement ); - executor.query( soqlStatement ); - Integer soqlCalls = Limits.getQueries(); - Test.stopTest(); + Test.startTest(); + executor.clearCacheFor( soqlStatement ); + executor.query( soqlStatement ); + Integer soqlCalls = Limits.getQueries(); + Test.stopTest(); - System.assertEquals( 1, soqlCalls, 'clearCacheFor against a none cache, does not affect the number of SOQL statements issued' ); - } + System.assertEquals( 1, soqlCalls, 'clearCacheFor against a none cache, does not affect the number of SOQL statements issued' ); + } - @isTest - private static void clearCacheFor_none_whenTheUserDoesNotHaveAccessToTheCache_throwsAnException() // NOPMD: Test method name format - { - String soqlStatement = 'SELECT Id FROM Account'; + @isTest + private static void clearCacheFor_none_whenTheUserDoesNotHaveAccessToTheCache_throwsAnException() // NOPMD: Test method name format + { + String soqlStatement = 'SELECT Id FROM Account'; - setupAccessToSoqlCache( false ); + setupAccessToSoqlCache( false ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); - Test.startTest(); - executor.clearCacheFor( soqlStatement ); - Test.stopTest(); + Test.startTest(); + executor.clearCacheFor( soqlStatement ); + Test.stopTest(); - System.assert( true, 'clearCacheFor against a none cache, when called by a user that does not have access to the org cache, will not throw an exception' ); - } + System.assert( true, 'clearCacheFor against a none cache, when called by a user that does not have access to the org cache, will not throw an exception' ); + } - @isTest - private static void query_none_whenRanFor100Queries_willNotThrowAnException() - { - List soqlStatements = new List(); - for ( Integer i=1; i<=100; i++ ) - { - soqlStatements.add( 'SELECT Id FROM Account LIMIT ' + i ); - } + @isTest + private static void query_none_whenRanFor100Queries_willNotThrowAnException() + { + List soqlStatements = new List(); + for ( Integer i=1; i<=100; i++ ) + { + soqlStatements.add( 'SELECT Id FROM Account LIMIT ' + i ); + } - setupAccessToSoqlCache( true ); + setupAccessToSoqlCache( true ); - CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); + CachedSoqlExecutor executor = new CachedSoqlExecutor().setScope( CachedSoqlExecutor.CacheScope.NONE ); - Test.startTest(); - // Run each statement once - this is the maximum we can do - for ( String thisSoqlStatement : soqlStatements ) - { - executor.query( thisSoqlStatement ); - } - Test.stopTest(); + Test.startTest(); + // Run each statement once - this is the maximum we can do + for ( String thisSoqlStatement : soqlStatements ) + { + executor.query( thisSoqlStatement ); + } + Test.stopTest(); - System.assert( true, 'query against a none cache, when run for 100 queries, will not throw an exception' ); - } + System.assert( true, 'query against a none cache, when run for 100 queries, will not throw an exception' ); + } - private static void setupAccessToSoqlCache( Boolean accessToCache ) - { - ApplicationMockRegistrar.registerMockService( IPermissionsService.class ) - .when( 'hasAccessToCorePlatformCache' ) - .returns( accessToCache ); - } + private static void setupAccessToSoqlCache( Boolean accessToCache ) + { + ApplicationMockRegistrar.registerMockService( IPermissionsService.class ) + .when( 'hasAccessToCorePlatformCache' ) + .returns( accessToCache ); + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/null-objects/NullAction.cls b/framework/default/ortoo-core/default/classes/null-objects/NullAction.cls index 233f6022f00..2fbc48b8fb0 100644 --- a/framework/default/ortoo-core/default/classes/null-objects/NullAction.cls +++ b/framework/default/ortoo-core/default/classes/null-objects/NullAction.cls @@ -1,7 +1,7 @@ /** * Provides the ability to perform no action in a Process Builder built process */ -public class NullAction +public inherited sharing class NullAction { /** * Allows a Process Builder or Flow action to 'Do Nothing' diff --git a/framework/default/ortoo-core/default/classes/null-objects/NullDomain.cls b/framework/default/ortoo-core/default/classes/null-objects/NullDomain.cls index 9a1a1b3998b..e6b29237397 100644 --- a/framework/default/ortoo-core/default/classes/null-objects/NullDomain.cls +++ b/framework/default/ortoo-core/default/classes/null-objects/NullDomain.cls @@ -1,7 +1,7 @@ /** * Is a Domain object that does nothing other than track that certain overridden methods have been called */ -public class NullDomain extends ortoo_SobjectDomain +public inherited sharing class NullDomain extends ortoo_SobjectDomain { public static Set methodsCalled = new Set();