blob: 726624aac3e3ad9ae9704b78028ea265a2e9387c [file] [log] [blame]
package ioc.specs
import org.apache.tapestry5.ioc.internal.services.SymbolSourceImpl
import org.apache.tapestry5.ioc.services.SymbolProvider
import org.apache.tapestry5.ioc.services.SymbolSource
import spock.lang.Specification
class SymbolSourceImplSpec extends Specification {
def "expand symbols when no symbols are present in the input"() {
SymbolSource source = new SymbolSourceImpl([])
def input = "A jolly good time"
expect:
source.expandSymbols(input).is(input)
}
def "process simple expansions"() {
SymbolProvider provider = Mock()
SymbolSource source = new SymbolSourceImpl([provider])
when:
def expanded = source.expandSymbols('${barney} and ${dino}')
then:
expanded == "Barney and Dino"
1 * provider.valueForSymbol("barney") >> "Barney"
1 * provider.valueForSymbol("dino") >> "Dino"
}
def "providers are consulted in order"() {
SymbolProvider provider1 = Mock()
SymbolProvider provider2 = Mock()
SymbolSource source = new SymbolSourceImpl([provider1, provider2])
when:
def expanded = source.expandSymbols('${barney} and ${dino}')
then:
1 * provider1.valueForSymbol("barney") >> "Barney"
then:
1 * provider1.valueForSymbol("dino") >> null
then:
1 * provider2.valueForSymbol("dino") >> "Dino"
expanded == "Barney and Dino"
}
def "exception when no provider can expand a symbol"() {
SymbolProvider provider = Mock()
SymbolSource source = new SymbolSourceImpl([provider])
when:
source.expandSymbols('${barney} and ${dino}')
then:
RuntimeException e = thrown()
e.message == "Symbol 'barney' is not defined."
}
def "missing closing brace on symbol expansion"() {
SymbolSource source = new SymbolSourceImpl([]);
when:
source.expandSymbols('Unmatched ${this')
then:
RuntimeException e = thrown()
e.message == '''Input string 'Unmatched ${this' is missing a symbol closing brace.'''
}
def "missing closing brace from expanded value of symbol"() {
SymbolProvider provider = Mock()
SymbolSource source = new SymbolSourceImpl([provider]);
when:
source.valueForSymbol("barney")
then:
1 * provider.valueForSymbol("barney") >> '''Barney (whose friends are ${barney.friends})'''
1 * provider.valueForSymbol("barney.friends") >> '''${fred} and ${betty'''
1 * provider.valueForSymbol("fred") >> "Fred"
RuntimeException e = thrown()
e.message == '''Input string '${fred} and ${betty' is missing a symbol closing brace (in barney --> barney.friends).'''
}
def "expansion values may themselves contain further expansions"() {
SymbolProvider provider = Mock()
SymbolSource source = new SymbolSourceImpl([provider])
when:
def result = source.expandSymbols('''Fred's friends are ${fred.friends}.''')
then:
1 * provider.valueForSymbol("fred.friends") >> '''${barney} and ${dino}'''
1 * provider.valueForSymbol("barney") >> "Barney"
1 * provider.valueForSymbol("dino") >> "Dino"
result == '''Fred's friends are Barney and Dino.'''
}
def "unknown symbol when expanding a symbol value is properly tracked and reported"() {
SymbolProvider provider = Mock()
SymbolSource source = new SymbolSourceImpl([provider])
when:
def result = source.valueForSymbol("fred.message")
then:
1 * provider.valueForSymbol("fred.message") >> '''Fred's friends are ${fred.friends}.'''
1 * provider.valueForSymbol("fred.friends") >> '''${barney} and ${dino}'''
1 * provider.valueForSymbol("barney") >> "Barney"
RuntimeException e = thrown()
e.message == "Symbol 'dino' is not defined (in fred.message --> fred.friends --> dino)."
}
def "expanded values for symbols are cached"() {
SymbolProvider provider = Mock()
SymbolSource source = new SymbolSourceImpl([provider])
when:
def first = source.valueForSymbol("fred")
then:
1 * provider.valueForSymbol("fred") >> '''Fred's friends are ${barney} and ${dino}.'''
1 * provider.valueForSymbol("barney") >> "Barney"
1 * provider.valueForSymbol("dino") >> "Dino"
first == "Fred's friends are Barney and Dino."
when:
def second = source.valueForSymbol("fred")
then:
0 * _
second.is(first)
}
def "recursive expansions are identified and reported as an exception"() {
SymbolProvider provider = Mock()
SymbolSource source = new SymbolSourceImpl([provider])
when:
source.valueForSymbol("fred")
then:
1 * provider.valueForSymbol("fred") >> '''Fred's friends are ${fred.friends}.'''
1 * provider.valueForSymbol("fred.friends") >> '''${barney} and ${dino}'''
1 * provider.valueForSymbol("barney") >> '''Barney (whose friends are ${barney.friends})'''
1 * provider.valueForSymbol("barney.friends") >> '''${fred} and ${betty}'''
RuntimeException e = thrown()
e.message == "Symbol 'fred' is defined in terms of itself (fred --> fred.friends --> barney --> barney.friends --> fred)."
}
}