mbt-gen 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/mbt-gen.rb +348 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4c7dc3614c0f3345b728127808e7bd517487298968c8edab06f6436b84d60c1
|
|
4
|
+
data.tar.gz: 780f4e406e9b84d112074106bb905e48a8eab8fac3e02936ab36f85087381c07
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 05d34d034b0aa1438c15f47969d8c9bd3d61545d2c9ade72efc0edfcee081e562c9fb3cc6f421e846319bbc43c0fe426b10bf81b8030b5ff560f97942405f5b7
|
|
7
|
+
data.tar.gz: 9f7b485dc1034d0529c3b8033633a862adb30c938899cfa8ceaaab95e130a10385c7d77c9e5859d31d8f5aeedf271e742e242e8699785ba8936b67df8f8f6b17
|
data/lib/mbt-gen.rb
CHANGED
|
@@ -18,6 +18,7 @@ DEFAULT_Z3_PATH = "z3"
|
|
|
18
18
|
|
|
19
19
|
CONFIG_FILE = "config.yml"
|
|
20
20
|
OUTPUT_FILE = "result.xml"
|
|
21
|
+
BASE_FILENAME = "doc-base.xml"
|
|
21
22
|
CONTINUATION_FILE = "continuation.log"
|
|
22
23
|
COMBINATION_LOG = "combinations.log"
|
|
23
24
|
VARS_LOG = "vars.log"
|
|
@@ -51,6 +52,19 @@ GENERATING A SINGLE MESSAGE:
|
|
|
51
52
|
-negate <validation_rule> - negates the named validation rule. This causes the resulting message to still satisfy all other validation rules, but to violate this one.
|
|
52
53
|
NOTE: the result can be found in #{OUTPUT_FILE}
|
|
53
54
|
|
|
55
|
+
GENERATING MESSAGES FOR SPECIAL REQUIREMENTS:
|
|
56
|
+
|
|
57
|
+
ruby #{$PROGRAM_NAME} -generate-max
|
|
58
|
+
- generates a message of maximum size. The message will be valid XML and will adhere to the schema, but it will
|
|
59
|
+
not neccessarily satisfy all validation rules. It will contain all structures, all optional fields and all lists of maximum size.
|
|
60
|
+
|
|
61
|
+
ruby #{$PROGRAM_NAME} -generate-equality-test-data
|
|
62
|
+
- generates a base message of maximum size (see -generate-max option) as well as the following test messages for each field and structure
|
|
63
|
+
- one test message in which the field contains a different value (only for fields)
|
|
64
|
+
- one test message in which the field/structure is empty in case it is optional
|
|
65
|
+
NOTE: all the other fields and structures will be the same as in the base message. This kind of test data is useful for
|
|
66
|
+
testing implementations of equality and comparison functionality on the specified messages.
|
|
67
|
+
|
|
54
68
|
GENERATING MESSAGES FOR ALL COMBINATIONS:
|
|
55
69
|
|
|
56
70
|
ruby #{$PROGRAM_NAME} -list-keys
|
|
@@ -772,6 +786,7 @@ def parse_field_value(fielddef, value)
|
|
|
772
786
|
when :enum
|
|
773
787
|
return solver_value_to_string(value)
|
|
774
788
|
when :date
|
|
789
|
+
puts "DEBUG: parsing date #{value.inspect}"
|
|
775
790
|
return Date.parse(value)
|
|
776
791
|
when :timestamp
|
|
777
792
|
return Time.new(value)
|
|
@@ -799,6 +814,91 @@ def format_solver_value(fielddef, solver_value)
|
|
|
799
814
|
end
|
|
800
815
|
end
|
|
801
816
|
|
|
817
|
+
def build_max_doc(progress, struct)
|
|
818
|
+
doc = Nokogiri::XML(XML_TEMPLATE)
|
|
819
|
+
add_max_struct_to_doc(progress, struct, doc)
|
|
820
|
+
return doc
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
def pick_solver_value_for_field(field_desc)
|
|
824
|
+
if field_desc[:datatype] == :int then
|
|
825
|
+
if field_desc[:min] then
|
|
826
|
+
field_desc[:min].to_s
|
|
827
|
+
elsif field_desc[:max] then
|
|
828
|
+
field_desc[:max].to_s
|
|
829
|
+
else
|
|
830
|
+
"0"
|
|
831
|
+
end
|
|
832
|
+
elsif field_desc[:datatype] == :string then
|
|
833
|
+
# TODO: when a string field has a :regexp, use the solver to find a value satisfying it
|
|
834
|
+
if field_desc[:maxLength] then
|
|
835
|
+
"a" * field_desc[:maxLength]
|
|
836
|
+
else
|
|
837
|
+
"default"
|
|
838
|
+
end
|
|
839
|
+
elsif field_desc[:datatype] == :enum then
|
|
840
|
+
field_desc[:values].first.to_s
|
|
841
|
+
elsif field_desc[:datatype] == :date then
|
|
842
|
+
Time.at(0).to_date.to_s
|
|
843
|
+
elsif field_desc[:datatype] == :timestamp then
|
|
844
|
+
Time.at(0).to_s
|
|
845
|
+
else
|
|
846
|
+
raise RuntimeError.new("encountered unknown :datatype #{field_desc[:datatype].inspect}")
|
|
847
|
+
end
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
def add_max_struct_to_doc(progress, struct, doc, prefix = nil)
|
|
851
|
+
struct.each do |key, value|
|
|
852
|
+
next if key == :validation_rules || key == :predicates || key == :parent_link || key == :struct_xpath_prefix || key == :additional_smtlib
|
|
853
|
+
if prefix then
|
|
854
|
+
xpath = "#{prefix}/#{key}"
|
|
855
|
+
else
|
|
856
|
+
xpath = key.to_s
|
|
857
|
+
end
|
|
858
|
+
if value[:type] == :field then
|
|
859
|
+
val = pick_solver_value_for_field(value)
|
|
860
|
+
fvalue_str = format_solver_value(value, val)
|
|
861
|
+
doc.add_child("<#{key}>#{fvalue_str}</#{key}>")
|
|
862
|
+
elsif value[:type] == :list then
|
|
863
|
+
node = doc.add_child("<#{key}></#{key}>")
|
|
864
|
+
if node.is_a?(Nokogiri::XML::NodeSet) then
|
|
865
|
+
node = node.first
|
|
866
|
+
end
|
|
867
|
+
xpath_element = value[:xpath_element]
|
|
868
|
+
if Integer(value[:model_maxLength]) > 0 then
|
|
869
|
+
Integer(value[:model_maxLength]).times do |i|
|
|
870
|
+
node.add_child("<#{xpath_element}>#{format_solver_value(value, pick_solver_value_for_field(value))}</#{xpath_element}>")
|
|
871
|
+
end
|
|
872
|
+
end
|
|
873
|
+
elsif value[:type] == :objlist then
|
|
874
|
+
node = doc.add_child("<#{key}></#{key}>")
|
|
875
|
+
if node.is_a?(Nokogiri::XML::NodeSet) then
|
|
876
|
+
node = node.first
|
|
877
|
+
end
|
|
878
|
+
xpath_element = value[:xpath_element]
|
|
879
|
+
value[:model_maxLength].times do |index|
|
|
880
|
+
cnode = node.add_child("<#{xpath_element}></#{xpath_element}>")
|
|
881
|
+
if cnode.is_a?(Nokogiri::XML::NodeSet) then
|
|
882
|
+
cnode = cnode.first
|
|
883
|
+
end
|
|
884
|
+
add_max_struct_to_doc(progress, value[:ref], cnode, "#{xpath}/#{index}")
|
|
885
|
+
end
|
|
886
|
+
elsif value[:type] == :structure then
|
|
887
|
+
unless value[:ref] then
|
|
888
|
+
raise RuntimeError.new("struct is broken: :structure #{key.inspect} does not have a :ref")
|
|
889
|
+
end
|
|
890
|
+
node = doc.add_child("<#{key}></#{key}>")
|
|
891
|
+
if node.is_a?(Nokogiri::XML::NodeSet) then
|
|
892
|
+
node = node.first
|
|
893
|
+
end
|
|
894
|
+
add_max_struct_to_doc(progress, value[:ref], node, xpath)
|
|
895
|
+
else
|
|
896
|
+
raise RuntimeError.new("struct is broken: encountered unknown :type #{value[:type].inspect}")
|
|
897
|
+
end
|
|
898
|
+
end
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
|
|
802
902
|
def build_document_from_model(progress, struct, model)
|
|
803
903
|
doc = Nokogiri::XML(XML_TEMPLATE)
|
|
804
904
|
add_model_struct_to_doc(progress, struct, doc, model)
|
|
@@ -888,6 +988,244 @@ def set_standard_options(progress, solver)
|
|
|
888
988
|
solver.to_solver(progress, "")
|
|
889
989
|
end
|
|
890
990
|
|
|
991
|
+
def each_structure_and_field_in(struct, prefix = nil, &block)
|
|
992
|
+
struct.each do |key, value|
|
|
993
|
+
next if key == :validation_rules || key == :predicates || key == :parent_link || key == :struct_xpath_prefix || key == :additional_smtlib
|
|
994
|
+
|
|
995
|
+
if prefix then
|
|
996
|
+
xpath = "#{prefix}/#{key}"
|
|
997
|
+
else
|
|
998
|
+
xpath = key
|
|
999
|
+
end
|
|
1000
|
+
|
|
1001
|
+
if value[:type] == :field then
|
|
1002
|
+
block.call(value, xpath)
|
|
1003
|
+
elsif value[:type] == :list then
|
|
1004
|
+
block.call(value, xpath)
|
|
1005
|
+
value[:model_maxLength].times do |i|
|
|
1006
|
+
cvalue = value.clone()
|
|
1007
|
+
cvalue[:element] = true
|
|
1008
|
+
block.call(cvalue, xpath + "/#{value[:xpath_element]}[#{i+1}]")
|
|
1009
|
+
end
|
|
1010
|
+
elsif value[:type] == :objlist then
|
|
1011
|
+
block.call(value, xpath)
|
|
1012
|
+
value[:model_maxLength].times do |i|
|
|
1013
|
+
cxpath = xpath + "/#{value[:xpath_element]}[#{i+1}]"
|
|
1014
|
+
cvalue = value.clone()
|
|
1015
|
+
cvalue[:element] = true
|
|
1016
|
+
block.call(cvalue, cxpath)
|
|
1017
|
+
each_structure_and_field_in(value[:ref], cxpath, &block)
|
|
1018
|
+
end
|
|
1019
|
+
elsif value[:type] == :structure then
|
|
1020
|
+
block.call(value, xpath)
|
|
1021
|
+
each_structure_and_field_in(value[:ref], xpath, &block)
|
|
1022
|
+
else
|
|
1023
|
+
raise RuntimeError.new("encountered unknown :type #{value[:type].inspect}")
|
|
1024
|
+
end
|
|
1025
|
+
end
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
def xpath_to_filename(xpath)
|
|
1029
|
+
xpath.gsub("/", "-").gsub(/\[\d*\]/) {|s| if s =~ /\[(\d*)\]/ then "-#{$1}-" else s end }
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
def generate_equality_test_data(progress, message, output_dir, config, options)
|
|
1033
|
+
unless Dir.exist?(output_dir)
|
|
1034
|
+
FileUtils.mkdir_p(output_dir)
|
|
1035
|
+
end
|
|
1036
|
+
|
|
1037
|
+
base_filename = "#{output_dir}/#{BASE_FILENAME}"
|
|
1038
|
+
generate_max_doc(progress, message, base_filename, config, options)
|
|
1039
|
+
|
|
1040
|
+
base_doc = Nokogiri::XML(File.read(base_filename))
|
|
1041
|
+
|
|
1042
|
+
each_structure_and_field_in(message) do |desc, xpath|
|
|
1043
|
+
if desc[:type] == :field then
|
|
1044
|
+
mutated_doc = base_doc.clone()
|
|
1045
|
+
node = mutated_doc.at_xpath(xpath)
|
|
1046
|
+
unless node then
|
|
1047
|
+
raise RuntimeError.new("xpath #{xpath.inspect} could not be found in base_doc")
|
|
1048
|
+
end
|
|
1049
|
+
node.inner_html = node.inner_html + "x"
|
|
1050
|
+
File.open("#{output_dir}/doc-mutated-#{xpath_to_filename(xpath)}.xml", "w") do |f|
|
|
1051
|
+
f.puts(mutated_doc.to_xml)
|
|
1052
|
+
end
|
|
1053
|
+
if desc[:optional] == true then
|
|
1054
|
+
mutated_doc = base_doc.clone()
|
|
1055
|
+
node = mutated_doc.at_xpath(xpath)
|
|
1056
|
+
unless node then
|
|
1057
|
+
raise RuntimeError.new("xpath #{xpath.inspect} could not be found in base_doc")
|
|
1058
|
+
end
|
|
1059
|
+
node.remove()
|
|
1060
|
+
File.open("#{output_dir}/doc-removed-#{xpath_to_filename(xpath)}.xml", "w") do |f|
|
|
1061
|
+
f.puts(mutated_doc.to_xml)
|
|
1062
|
+
end
|
|
1063
|
+
end
|
|
1064
|
+
elsif desc[:type] == :list then
|
|
1065
|
+
if desc[:element] then
|
|
1066
|
+
# list elements
|
|
1067
|
+
mutated_doc = base_doc.clone()
|
|
1068
|
+
node = mutated_doc.at_xpath(xpath)
|
|
1069
|
+
unless node then
|
|
1070
|
+
raise RuntimeError.new("xpath #{xpath.inspect} could not be found in base_doc")
|
|
1071
|
+
end
|
|
1072
|
+
node.inner_html = node.inner_html + "x"
|
|
1073
|
+
File.open("#{output_dir}/doc-mutated-#{xpath_to_filename(xpath)}.xml", "w") do |f|
|
|
1074
|
+
f.puts(mutated_doc.to_xml)
|
|
1075
|
+
end
|
|
1076
|
+
else
|
|
1077
|
+
# the list itself
|
|
1078
|
+
mutated_doc = base_doc.clone()
|
|
1079
|
+
node = mutated_doc.at_xpath(xpath)
|
|
1080
|
+
unless node then
|
|
1081
|
+
raise RuntimeError.new("xpath #{xpath.inspect} could not be found in base_doc")
|
|
1082
|
+
end
|
|
1083
|
+
node.remove()
|
|
1084
|
+
File.open("#{output_dir}/doc-removed-#{xpath_to_filename(xpath)}.xml", "w") do |f|
|
|
1085
|
+
f.puts(mutated_doc.to_xml)
|
|
1086
|
+
end
|
|
1087
|
+
end
|
|
1088
|
+
elsif desc[:type] == :objlist then
|
|
1089
|
+
if desc[:element] then
|
|
1090
|
+
# list elements
|
|
1091
|
+
# no additional test data neccessary as the element objects will contain fields that are modified already
|
|
1092
|
+
else
|
|
1093
|
+
# the list itself
|
|
1094
|
+
mutated_doc = base_doc.clone()
|
|
1095
|
+
node = mutated_doc.at_xpath(xpath)
|
|
1096
|
+
unless node then
|
|
1097
|
+
raise RuntimeError.new("xpath #{xpath.inspect} could not be found in base_doc")
|
|
1098
|
+
end
|
|
1099
|
+
node.remove()
|
|
1100
|
+
File.open("#{output_dir}/doc-removed-#{xpath_to_filename(xpath)}.xml", "w") do |f|
|
|
1101
|
+
f.puts(mutated_doc.to_xml)
|
|
1102
|
+
end
|
|
1103
|
+
end
|
|
1104
|
+
elsif desc[:type] == :structure then
|
|
1105
|
+
if desc[:optional] == true then
|
|
1106
|
+
mutated_doc = base_doc.clone()
|
|
1107
|
+
node = mutated_doc.at_xpath(xpath)
|
|
1108
|
+
unless node then
|
|
1109
|
+
raise RuntimeError.new("xpath #{xpath.inspect} could not be found in base_doc")
|
|
1110
|
+
end
|
|
1111
|
+
node.remove()
|
|
1112
|
+
File.open("#{output_dir}/doc-removed-#{xpath_to_filename(xpath)}.xml", "w") do |f|
|
|
1113
|
+
f.puts(mutated_doc.to_xml)
|
|
1114
|
+
end
|
|
1115
|
+
end
|
|
1116
|
+
else
|
|
1117
|
+
raise RuntimeError.new("encountered unknown :type #{desc[:type].inspect}")
|
|
1118
|
+
end
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1121
|
+
generate_equality_test(message, "#{output_dir}/test-equality.rb")
|
|
1122
|
+
end
|
|
1123
|
+
|
|
1124
|
+
def generate_equality_test(message, output_filename)
|
|
1125
|
+
|
|
1126
|
+
base_filename = BASE_FILENAME
|
|
1127
|
+
positive_tests = []
|
|
1128
|
+
positive_tests << "assert(equality('#{base_filename}', '#{base_filename}'), 'Equality implementation is not reflexive on file #{base_filename}')"
|
|
1129
|
+
each_structure_and_field_in(message) do |desc, xpath|
|
|
1130
|
+
if desc[:type] == :field then
|
|
1131
|
+
positive_tests << "assert(equality('doc-mutated-#{xpath_to_filename(xpath)}.xml', 'doc-mutated-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation is not reflexive on file doc-mutated-#{xpath_to_filename(xpath)}.xml')"
|
|
1132
|
+
if desc[:optional] == true then
|
|
1133
|
+
positive_tests << "assert(equality('doc-removed-#{xpath_to_filename(xpath)}.xml', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation is not reflexive on file doc-removed-#{xpath_to_filename(xpath)}.xml')"
|
|
1134
|
+
end
|
|
1135
|
+
elsif desc[:type] == :list then
|
|
1136
|
+
if desc[:element] then
|
|
1137
|
+
positive_tests << "assert(equality('doc-mutated-#{xpath_to_filename(xpath)}.xml', 'doc-mutated-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation is not reflexive on file doc-mutated-#{xpath_to_filename(xpath)}.xml')"
|
|
1138
|
+
else
|
|
1139
|
+
positive_tests << "assert(equality('doc-removed-#{xpath_to_filename(xpath)}.xml', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation is not reflexive on file doc-removed-#{xpath_to_filename(xpath)}.xml')"
|
|
1140
|
+
end
|
|
1141
|
+
elsif desc[:type] == :objlist then
|
|
1142
|
+
if desc[:element] then
|
|
1143
|
+
# list elements
|
|
1144
|
+
# no additional test data neccessary as the element objects will contain fields that are modified already
|
|
1145
|
+
else
|
|
1146
|
+
# the list itself
|
|
1147
|
+
positive_tests << "assert(equality('doc-removed-#{xpath_to_filename(xpath)}.xml', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation is not reflexive on file doc-removed-#{xpath_to_filename(xpath)}.xml')"
|
|
1148
|
+
end
|
|
1149
|
+
elsif desc[:type] == :structure then
|
|
1150
|
+
if desc[:optional] == true then
|
|
1151
|
+
positive_tests << "assert(equality('doc-removed-#{xpath_to_filename(xpath)}.xml', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation is not reflexive on file doc-removed-#{xpath_to_filename(xpath)}.xml')"
|
|
1152
|
+
end
|
|
1153
|
+
else
|
|
1154
|
+
raise RuntimeError.new("encountered unknown :type #{desc[:type].inspect}")
|
|
1155
|
+
end
|
|
1156
|
+
end
|
|
1157
|
+
|
|
1158
|
+
negative_tests = []
|
|
1159
|
+
each_structure_and_field_in(message) do |desc, xpath|
|
|
1160
|
+
if desc[:type] == :field then
|
|
1161
|
+
negative_tests << "assert(!equality('#{base_filename}', 'doc-mutated-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation seems not to take the field #{xpath} into account. It regards the files #{base_filename} and doc-mutated-#{xpath_to_filename(xpath)}.xml as equal.')"
|
|
1162
|
+
if desc[:optional] == true then
|
|
1163
|
+
negative_tests << "assert(!equality('#{base_filename}', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation seems not to take the existence of field #{xpath} into account. It regards the files #{base_filename} and doc-removed-#{xpath_to_filename(xpath)}.xml as equal.')"
|
|
1164
|
+
end
|
|
1165
|
+
elsif desc[:type] == :list then
|
|
1166
|
+
if desc[:element] then
|
|
1167
|
+
negative_tests << "assert(!equality('#{base_filename}', 'doc-mutated-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation seems not to take the list #{xpath} into account. It regards the files #{base_filename} and doc-mutated-#{xpath_to_filename(xpath)}.xml as equal.')"
|
|
1168
|
+
else
|
|
1169
|
+
negative_tests << "assert(!equality('#{base_filename}', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation seems not to take the existence of the list #{xpath} into account. It regards the files #{base_filename} and doc-removed-#{xpath_to_filename(xpath)}.xml as equal.')"
|
|
1170
|
+
end
|
|
1171
|
+
elsif desc[:type] == :objlist then
|
|
1172
|
+
if desc[:element] then
|
|
1173
|
+
# list elements
|
|
1174
|
+
# no additional test data neccessary as the element objects will contain fields that are modified already
|
|
1175
|
+
else
|
|
1176
|
+
# the list itself
|
|
1177
|
+
negative_tests << "assert(!equality('#{base_filename}', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation seems not to take the existence of objlist #{xpath} into account. It regards the files #{base_filename} and doc-removed-#{xpath_to_filename(xpath)}.xml as equal.')"
|
|
1178
|
+
end
|
|
1179
|
+
elsif desc[:type] == :structure then
|
|
1180
|
+
if desc[:optional] == true then
|
|
1181
|
+
negative_tests << "assert(!equality('#{base_filename}', 'doc-removed-#{xpath_to_filename(xpath)}.xml'), 'Equality implementation seems not to take the existence of structure #{xpath} into account. It regards the files #{base_filename} and doc-removed-#{xpath_to_filename(xpath)}.xml as equal.')"
|
|
1182
|
+
end
|
|
1183
|
+
else
|
|
1184
|
+
raise RuntimeError.new("encountered unknown :type #{desc[:type].inspect}")
|
|
1185
|
+
end
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
content = <<EOF
|
|
1190
|
+
#!/bin/ruby
|
|
1191
|
+
|
|
1192
|
+
require 'test/unit'
|
|
1193
|
+
|
|
1194
|
+
class EqualityTest < Test::Unit::TestCase
|
|
1195
|
+
|
|
1196
|
+
def equality(filename1, filename2)
|
|
1197
|
+
# TODO: call your equality implementation here.
|
|
1198
|
+
# This is just an example showing how to call an externally-provided implementation.
|
|
1199
|
+
system("diff", filename1, filename2)
|
|
1200
|
+
end
|
|
1201
|
+
|
|
1202
|
+
def test_equality_positive
|
|
1203
|
+
#{positive_tests.join("\n ")}
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1206
|
+
def test_equality_negative
|
|
1207
|
+
#{negative_tests.join("\n ")}
|
|
1208
|
+
end
|
|
1209
|
+
end
|
|
1210
|
+
EOF
|
|
1211
|
+
|
|
1212
|
+
File.open(output_filename, "w") do |f|
|
|
1213
|
+
f.puts(content)
|
|
1214
|
+
end
|
|
1215
|
+
|
|
1216
|
+
end
|
|
1217
|
+
|
|
1218
|
+
def generate_max_doc(progress, message, output_filename, config, options)
|
|
1219
|
+
result_doc = build_max_doc(progress, message)
|
|
1220
|
+
dir = File.dirname(output_filename)
|
|
1221
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
|
1222
|
+
File.open(output_filename, "w") do |f|
|
|
1223
|
+
f.puts result_doc.to_xml()
|
|
1224
|
+
end
|
|
1225
|
+
progress.print_line "DONE. Generated XML was written to #{output_filename}."
|
|
1226
|
+
return true
|
|
1227
|
+
end
|
|
1228
|
+
|
|
891
1229
|
def generate_doc(progress, message, output_filename, config, options)
|
|
892
1230
|
raise RuntimeError.new("option :solverFactory is required") unless options[:solverFactory]
|
|
893
1231
|
log = options[:log] || nil
|
|
@@ -2132,6 +2470,10 @@ def generate(message, argv, message_config_filename = nil)
|
|
|
2132
2470
|
else
|
|
2133
2471
|
options[:validate_files] = [argv.shift]
|
|
2134
2472
|
end
|
|
2473
|
+
elsif opt == '-generate-max' then
|
|
2474
|
+
options[:generate_max] = true
|
|
2475
|
+
elsif opt == '-generate-equality-test-data' then
|
|
2476
|
+
options[:generate_equality_test_data] = true
|
|
2135
2477
|
else
|
|
2136
2478
|
puts "FATAL: unknown option #{opt.inspect}."
|
|
2137
2479
|
puts USAGE
|
|
@@ -2192,6 +2534,12 @@ def generate(message, argv, message_config_filename = nil)
|
|
|
2192
2534
|
list_fields_and_structures(message, options[:list])
|
|
2193
2535
|
elsif options[:list_validation_rules] then
|
|
2194
2536
|
list_validation_rules(message)
|
|
2537
|
+
elsif options[:generate_max] then
|
|
2538
|
+
validate_model(message)
|
|
2539
|
+
generate_max_doc(progress, message, OUTPUT_FILE, config, options)
|
|
2540
|
+
elsif options[:generate_equality_test_data] then
|
|
2541
|
+
validate_model(message)
|
|
2542
|
+
generate_equality_test_data(progress, message, OUTPUT_DIR, config, options)
|
|
2195
2543
|
else
|
|
2196
2544
|
progress.print_line "using #{options[:date_now]} as [Date.now]"
|
|
2197
2545
|
progress.print_line "using #{options[:timestamp_now]} as [Timestamp.now]"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mbt-gen
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- FM-enthusiast
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|