File: //proc/self/root/usr/lib/ruby/site_ruby/1.8/puppet/vendor/rgen/test/transformer_test.rb
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
$:.unshift File.join(File.dirname(__FILE__),"..","test")
require 'test/unit'
require 'rgen/transformer'
require 'rgen/environment'
require 'rgen/util/model_comparator'
require 'metamodels/uml13_metamodel'
require 'testmodel/class_model_checker'
class TransformerTest < Test::Unit::TestCase
class ModelIn
attr_accessor :name
end
class ModelInSub < ModelIn
end
class ModelAIn
attr_accessor :name
attr_accessor :modelB
end
class ModelBIn
attr_accessor :name
attr_accessor :modelA
end
class ModelCIn
attr_accessor :number
end
class ModelOut
attr_accessor :name
end
class ModelAOut
attr_accessor :name
attr_accessor :modelB
end
class ModelBOut
attr_accessor :name
attr_accessor :modelA
end
class ModelCOut
attr_accessor :number
end
class MyTransformer < RGen::Transformer
attr_reader :modelInTrans_count
attr_reader :modelAInTrans_count
attr_reader :modelBInTrans_count
transform ModelIn, :to => ModelOut do
# aribitrary ruby code may be placed before the hash creating the output element
@modelInTrans_count ||= 0; @modelInTrans_count += 1
{ :name => name }
end
transform ModelAIn, :to => ModelAOut do
@modelAInTrans_count ||= 0; @modelAInTrans_count += 1
{ :name => name, :modelB => trans(modelB) }
end
transform ModelBIn, :to => ModelBOut do
@modelBInTrans_count ||= 0; @modelBInTrans_count += 1
{ :name => name, :modelA => trans(modelA) }
end
transform ModelCIn, :to => ModelCOut, :if => :largeNumber do
# a method can be called anywhere in a transformer block
{ :number => duplicateNumber }
end
transform ModelCIn, :to => ModelCOut, :if => :smallNumber do
{ :number => number / 2 }
end
method :largeNumber do
number > 1000
end
method :smallNumber do
number < 500
end
method :duplicateNumber do
number * 2;
end
end
class MyTransformer2 < RGen::Transformer
# check that subclasses are independent (i.e. do not share the rules)
transform ModelIn, :to => ModelOut do
{ :name => name }
end
end
def test_transformer
from = ModelIn.new
from.name = "TestName"
env_out = RGen::Environment.new
t = MyTransformer.new(:env_in, env_out)
assert t.trans(from).is_a?(ModelOut)
assert_equal "TestName", t.trans(from).name
assert_equal 1, env_out.elements.size
assert_equal env_out.elements.first, t.trans(from)
assert_equal 1, t.modelInTrans_count
end
def test_transformer_chain
from = ModelIn.new
from.name = "Test1"
from2 = ModelIn.new
from2.name = "Test2"
from3 = ModelIn.new
from3.name = "Test3"
env_out = RGen::Environment.new
elementMap = {}
t1 = MyTransformer.new(:env_in, env_out, elementMap)
assert t1.trans(from).is_a?(ModelOut)
assert_equal "Test1", t1.trans(from).name
assert_equal 1, t1.modelInTrans_count
# modifying the element map means that following calls of +trans+ will be affected
assert_equal( {from => t1.trans(from)}, elementMap )
elementMap.merge!({from2 => :dummy})
assert_equal :dummy, t1.trans(from2)
# second transformer based on the element map of the first
t2 = MyTransformer.new(:env_in, env_out, elementMap)
# second transformer returns same objects
assert_equal t1.trans(from).object_id, t2.trans(from).object_id
assert_equal :dummy, t2.trans(from2)
# and no transformer rule is evaluated at this point
assert_equal nil, t2.modelInTrans_count
# now transform a new object in second transformer
assert t2.trans(from3).is_a?(ModelOut)
assert_equal "Test3", t2.trans(from3).name
assert_equal 1, t2.modelInTrans_count
# the first transformer returns the same object without evaluation of a transformer rule
assert_equal t1.trans(from3).object_id, t2.trans(from3).object_id
assert_equal 1, t1.modelInTrans_count
end
def test_transformer_subclass
from = ModelInSub.new
from.name = "TestName"
t = MyTransformer.new
assert t.trans(from).is_a?(ModelOut)
assert_equal "TestName", t.trans(from).name
assert_equal 1, t.modelInTrans_count
end
def test_transformer_array
froms = [ModelIn.new, ModelIn.new]
froms[0].name = "M1"
froms[1].name = "M2"
env_out = RGen::Environment.new
t = MyTransformer.new(:env_in, env_out)
assert t.trans(froms).is_a?(Array)
assert t.trans(froms)[0].is_a?(ModelOut)
assert_equal "M1", t.trans(froms)[0].name
assert t.trans(froms)[1].is_a?(ModelOut)
assert_equal "M2", t.trans(froms)[1].name
assert_equal 2, env_out.elements.size
assert (t.trans(froms)-env_out.elements).empty?
assert_equal 2, t.modelInTrans_count
end
def test_transformer_cyclic
# setup a cyclic dependency between fromA and fromB
fromA = ModelAIn.new
fromB = ModelBIn.new
fromA.modelB = fromB
fromA.name = "ModelA"
fromB.modelA = fromA
fromB.name = "ModelB"
env_out = RGen::Environment.new
t = MyTransformer.new(:env_in, env_out)
# check that trans resolves the cycle correctly (no endless loop)
# both elements, fromA and fromB will be transformed with the transformation
# of the first element, either fromA or fromB
assert t.trans(fromA).is_a?(ModelAOut)
assert_equal "ModelA", t.trans(fromA).name
assert t.trans(fromA).modelB.is_a?(ModelBOut)
assert_equal "ModelB", t.trans(fromA).modelB.name
assert_equal t.trans(fromA), t.trans(fromA).modelB.modelA
assert_equal t.trans(fromB), t.trans(fromA).modelB
assert_equal 2, env_out.elements.size
assert (env_out.elements - [t.trans(fromA), t.trans(fromB)]).empty?
assert_equal 1, t.modelAInTrans_count
assert_equal 1, t.modelBInTrans_count
end
def test_transformer_conditional
froms = [ModelCIn.new, ModelCIn.new, ModelCIn.new]
froms[0].number = 100
froms[1].number = 1000
froms[2].number = 2000
env_out = RGen::Environment.new
t = MyTransformer.new(:env_in, env_out)
assert t.trans(froms).is_a?(Array)
assert_equal 2, t.trans(froms).size
# this one matched the smallNumber rule
assert t.trans(froms[0]).is_a?(ModelCOut)
assert_equal 50, t.trans(froms[0]).number
# this one did not match any rule
assert t.trans(froms[1]).nil?
# this one matched the largeNumber rule
assert t.trans(froms[2]).is_a?(ModelCOut)
assert_equal 4000, t.trans(froms[2]).number
# elements in environment are the same as the ones returned
assert_equal 2, env_out.elements.size
assert (t.trans(froms)-env_out.elements).empty?
end
class CopyTransformer < RGen::Transformer
include UML13
def transform
trans(:class => UML13::Package)
end
UML13.ecore.eClassifiers.each do |c|
copy c.instanceClass
end
end
MODEL_DIR = File.join(File.dirname(__FILE__),"testmodel")
include Testmodel::ClassModelChecker
include RGen::Util::ModelComparator
def test_copyTransformer
envIn = RGen::Environment.new
envOut = RGen::Environment.new
EASupport.instantiateUML13FromXMI11(envIn, MODEL_DIR+"/ea_testmodel.xml")
CopyTransformer.new(envIn, envOut).transform
checkClassModel(envOut)
assert modelEqual?(
envIn.find(:class => UML13::Model).first,
envOut.find(:class => UML13::Model).first)
end
end