1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
|
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
$:.unshift File.join(File.dirname(__FILE__),"..","test")
require 'minitest/autorun'
require 'rgen/transformer'
require 'rgen/environment'
require 'rgen/util/model_comparator'
require 'metamodels/uml13_metamodel'
require 'testmodel/class_model_checker'
class TransformerTest < Minitest::Test
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_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
|