1 # Copyright (c) 2019 PANTHEON.tech s.r.o. All rights reserved.
3 # This program and the accompanying materials are made available under the
4 # terms of the Eclipse Public License v1.0 which accompanies this distribution,
5 # and is available at http://www.eclipse.org/legal/epl-v10.html
13 start_time = time.time()
18 java_home = os.environ['JAVA_HOME']
19 print(f"JAVA_HOME found: {java_home}")
21 print("JAVA_HOME not found, trying to get it from system.")
23 java_home = os.popen("(dirname $(dirname $(readlink -f $(which javac))))").read().split("\n")[0] + "/bin/java"
25 print("JAVA_HOME not found or java not installed, please install java or set JAVA_HOME first.")
28 # retrieve args from command
30 global log, models, validator
32 models = "/src/main/yang/"
35 opts, args = getopt.getopt(argv,"hl:m:v:",["help", "log=","models=", "validator="])
36 except getopt.GetoptError:
37 print("wrong usage type -h or --help for help")
40 if opt == '-h' or opt == '--help':
41 print("Usage: python3 yangtools_test.py [log] [models] [validator_version]")
42 print("[log]\n-l, --log=y/n for delete previous logs in ~/yangtools_csit_test/yang_validator_logs/ (omitting will not delete previous logs)")
43 print("[validator_version]\n-v, --validator=10.0.2 will download yang-model-validator-10.0.0-jar-with-dependencies.jar from nexus.opendaylight.org (omitting will build it locally")
44 print("[models]\n-m, --models=/path/to/models/ select directory for testing (omitting will test all models)")
45 print('''models option examples:
46 /src/main/yang/standard/
47 /src/main/yang/vendor/
48 /src/main/yang/standard/ietf/
49 /src/main/yang/standard/ieee/
50 /src/main/yang/standard/iana/
51 /src/main/yang/vendor/ciena/''')
53 elif opt in ("-l", "--log"):
55 elif opt in ("-m", "--models"):
57 elif opt in ("-v", "--validator"):
60 if __name__ == "__main__":
63 home_dir = str(os.path.expanduser('~')) # get home dir for local user
64 working_dir = (home_dir) + "/yangtools_csit_test"
65 logfile_path = f"{working_dir}/yang_validator_logs/"
67 def prepare_enviroment():
68 os.system(f"rm -rf target {working_dir}/src && mkdir -p {working_dir}/src/main")
69 os.system(f"cd {working_dir}/src/main && git clone --depth 10 {pytest_lib.YANGMODELS_REPO}")
70 os.system(f'mkdir {logfile_path}')
73 def delete_static_paths():
74 # delete logs from previous testing on locallhost
75 delete_logs = log.upper()
76 if delete_logs == "Y":
77 os.system(f"rm -rf {logfile_path}*")
78 # delete not tested models from pytest_lib.delete_static_paths_list
79 for file in pytest_lib.delete_static_paths_list:
80 print(f"rm -vrf {working_dir + file}")
81 os.system(f"rm -vrf {working_dir + file}")
84 def get_yang_files_to_validate():
85 # get full path to directories
86 yang_files_to_validate = os.popen(f'find {working_dir}{models}* -name "*.yang"').read().split("\n")[:-1]
87 print(f"Files to validate = {len(yang_files_to_validate)}\nFiles: {yang_files_to_validate}")
88 return (yang_files_to_validate)
92 global yang_path_option
93 yang_path_option = "--path "
94 for path in pytest_lib.yang_model_paths:
95 yang_path_option += (working_dir + path + " ")
97 def download_yang_model_validator():
98 global validator_file_name, validator
99 # check if validator argument received
101 # check if validator was build with maven or built it
102 if check_maven() and get_validator_file_name():
103 return validator_file_name
104 elif check_maven() and not get_validator_file_name():
105 print("building yang-validator with command 'cd ../ && mvn clean install -pl tools/yang-model-validator/'")
106 print(os.popen(f"cd ../ && mvn clean install -pl tools/yang-model-validator/").read())
107 get_validator_file_name()
109 print("MAVEN not found, please install MAVEN first and restart python command")
112 validator_file_name = f"yang-model-validator-{validator}-jar-with-dependencies.jar"
113 if validator_file_name in os.popen("ls -la").read():
114 print(f"file {validator_file_name} exist...")
116 print(f"downloading {validator_file_name}")
117 print(os.system(f"wget https://nexus.opendaylight.org/content/repositories/opendaylight.release/org/opendaylight/yangtools/yang-model-validator/{validator}/{validator_file_name}"))
121 def get_validator_file_name():
122 global validator_file_name, yang_target_dir
123 yang_target_dir = "../tools/yang-model-validator/target/"
124 get_dir_files = os.popen(f"ls {yang_target_dir}").read()
125 if "-SNAPSHOT-jar-with-dependencies.jar" in get_dir_files:
126 for line in get_dir_files.split("\n"):
127 if "-SNAPSHOT-jar-with-dependencies.jar" in line:
128 validator_file_name = line
132 if "Apache Maven" in os.popen("mvn --version").read():
136 def yang_files_loop(yang_files_to_validate):
137 global yang_path_option, yang_target_dir
139 effective_model_not_resolved, all_not_pass_yang_files, leaf_is_missing, mount_points, following_components = [],[],[],[],[]
140 leaf_list_is_missing, statement_has_to_be_present, augment_cannot_add_node_named, augment_target, other = [],[],[],[],[]
141 for x in range (0,len(yang_files_to_validate)):
143 print("Working on file: ", yang_files_to_validate[x])
144 print(f"Testing file {file_counter} from total {len(yang_files_to_validate)} files")
145 # update --path option for ietf/RFC/ models to shorten test duration
146 if "/src/main/yang/standard/ietf/RFC" in yang_files_to_validate[x]:
147 yang_path_option = f"--path {working_dir}/src/main/yang/standard/ietf/RFC {working_dir}/src/main/yang/standard/ieee/published/802.1 {working_dir}/src/main/yang/standard/ieee/published/802 {working_dir}/src/main/yang/vendor/ciena "
148 tool_options=f" {yang_path_option}-- {yang_files_to_validate[x]}"
149 # update command if argument --validator given
152 command = java_home + " -jar " + yang_target_dir + validator_file_name + tool_options
153 # generate name for log file
154 name = "yangtools-log"
155 date = datetime.datetime.today()
156 timestamp = str(date.timestamp())[:-3]
157 logfile = f"{name}.{timestamp}.log"
158 cmd = f"{command} > {logfile_path + logfile} 2>&1"
160 # copy log file and print error to console
161 if os.stat(logfile_path + logfile).st_size != 0:
162 print("java command: ", cmd)
163 with open(logfile_path + logfile) as f:
165 # add log name prefix for change name of file due to error
167 if 'Mount points may only be defined at either a container or a list' in text_log:
168 logname_prefix = "mount-points-"
169 mount_points.append(yang_files_to_validate[x])
170 elif "Leaf-list is missing a 'type' statement" in text_log:
171 logname_prefix = "Leaf-list-is-missing-"
172 leaf_list_is_missing.append(yang_files_to_validate[x])
173 elif "At least one enum statement has to be present" in text_log:
174 logname_prefix = "statement-has-to-be-present-"
175 statement_has_to_be_present.append(yang_files_to_validate[x])
176 elif "An augment cannot add node named" in text_log:
177 logname_prefix = "augment-cannot-add-node-named-"
178 augment_cannot_add_node_named.append(yang_files_to_validate[x])
179 elif "Augment target" in text_log:
180 logname_prefix = "Augment-target-"
181 augment_target.append(yang_files_to_validate[x])
182 elif 'Following components of unique statement argument refer to non-existent nodes:' in text_log:
183 logname_prefix = "following-components-"
184 following_components.append(yang_files_to_validate[x])
185 elif 'Leaf is missing a' not in text_log and "Some of EFFECTIVE_MODEL modifiers for statements were not resolved" in text_log:
186 logname_prefix = "effective-model-"
187 effective_model_not_resolved.append(yang_files_to_validate[x])
188 elif 'Leaf is missing a' in text_log:
189 logname_prefix = "leaf-"
190 leaf_is_missing.append(yang_files_to_validate[x])
192 logname_prefix = "others-"
193 other.append(yang_files_to_validate[x])
194 os.system(f"mv {logfile_path + logfile} {logfile_path + logname_prefix + logfile}")
195 print(40 * "*", f" ERROR IN YANG FILE {yang_files_to_validate[x]} ", 40 * "*")
196 print("LOG FILE = ", logfile_path + logname_prefix + logfile)
197 os.system(f"cat {logfile_path + logname_prefix + logfile}")
198 print(40 * "*", " ERROR ", 40 * "*")
199 all_not_pass_yang_files.append(yang_files_to_validate[x])
201 os.system(f"rm -vrf {logfile_path + logfile}")
202 print_files_name = ["all_not_pass_yang_files", "effective_model_not_resolved", "leaf_is_missing", "mount_points", "following_components",
203 "leaf_list_is_missing", "statement_has_to_be_present", "augment_cannot_add_node_named", "augment_target", "other"]
204 print_files_count = [all_not_pass_yang_files, effective_model_not_resolved, leaf_is_missing, mount_points, following_components,
205 leaf_list_is_missing, statement_has_to_be_present, augment_cannot_add_node_named, augment_target, other]
207 # print test result counts and save txt list with not pass files
208 print("\n\n\n",40 * "*", " TEST RESULTS ", 40 * "*")
209 print(f"All tested files: {len(yang_files_to_validate)}")
210 for x in range(0, len(print_files_count)):
211 if print_files_count[x]:
212 print(f"{print_files_name[x]} = {len(print_files_count[x])}")
213 with open(f'{logfile_path}_{print_files_name[x]}.txt', 'w') as f:
214 f.write(str(print_files_count[x]) + '\n')
215 print(f"Detailed LOGS here: {logfile_path}")
219 delete_static_paths()
220 download_yang_model_validator()
222 yang_files_loop(get_yang_files_to_validate())
223 print("test duration --- %s seconds ---" % (time.time() - start_time))