#!/usr/bin/env python ################################################################################ # # CDDL HEADER START # # The contents of this file are subject to the terms of the Common Development # and Distribution License Version 1.0 (the "License"). # # You can obtain a copy of the license at # http:# www.opensource.org/licenses/CDDL-1.0. See the License for the # specific language governing permissions and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each file and # include the License file in a prominent location with the name LICENSE.CDDL. # If applicable, add the following below this CDDL HEADER, with the fields # enclosed by brackets "[]" replaced with your own identifying information: # # Portions Copyright (c) [yyyy] [name of copyright owner]. All rights reserved. # # CDDL HEADER END # # Copyright (c) 2017, Regents of the University of Minnesota. # All rights reserved. # # Contributor(s): # Ellad B. Tadmor # ################################################################################ # The docstring below is vc_description '''Check that the model has no memory leaks. This is tested using the Valgrind memory debugging tool (http://valgrind.org) by performing a series of energy and force calculations on a randomly distorted face-centered cubic (FCC) cube base structure for both non-periodic and periodic boundary conditions. Separate configurations are tested for each species supported by the model, as well as one containing a random distribution of all species. Configurations used for testing are provided as auxiliary files.''' # Python 2-3 compatible code issues from __future__ import print_function try: input = raw_input except NameError: pass import sys import kimvc from kimcalculator import KIMCalculator, KIM_get_supported_species_list from ase import Atoms import runner2 import subprocess import re __version__ = "000" __author__ = "Ellad Tadmor" vc_name = "vc-memory-leak" vc_description = kimvc.vc_stripall(__doc__) vc_category = "informational" vc_grade_basis = "passfail" vc_files = [] ################################################################################ # # FUNCTIONS # ################################################################################ ################################################################################ def do_vc(model, vc): ''' Do memory leak check ''' # call the code used to look for memory leaks durectky to generate # the output for the report runner2.memory_leaks_test_process(model, vc, vc_files) # call memory leaks test process using valigrind to look for leaks valgrind_out = subprocess.check_output(['valgrind', '--suppressions=./valgrind-python.supp', 'python', 'runner2.py', model], stderr=subprocess.STDOUT, universal_newlines=True) # print valgrind output to report dashwidth = 80 vc.rwrite('') vc.rwrite('='*dashwidth) vc.rwrite(' '*7 + 'VALGRIND OUTPUT') vc.rwrite('='*dashwidth) vc.rwrite('') vc.rwrite(valgrind_out) vc.rwrite('='*dashwidth) # determine grade vc.rwrite('') vc.rwrite('To pass this verification check the number of bytes that are ' '"definitely lost" ') vc.rwrite('or "indirectly lost" must be zero.') vc.rwrite('') vc.rwrite('NOTE that Valgrind will typically report non-zero ' '"possibly lost" bytes due to') vc.rwrite("Python's internal memory allocation and garbage collection " "that it does not monitor.") vc.rwrite('') definitely_lost = int(re.search('definitely lost: ([0-9]+)', valgrind_out).group(1)) indirectly_lost = int(re.search('indirectly lost: ([0-9]+)', valgrind_out).group(1)) leak_detected = definitely_lost > 0 or indirectly_lost > 0 # Run again and generate full valgrind output in aux file valgrind_out = subprocess.check_output(['valgrind', '--leak-check=full', '--show-leak-kinds=all', 'python', 'runner2.py', model], stderr=subprocess.STDOUT, universal_newlines=True) aux_file = 'valgrind.out' vc_files.append(aux_file) vc.write_aux_string(aux_file, valgrind_out) vc.rwrite('Full Valgrind output written to auxiliary file "{}"'. format(aux_file)) if leak_detected: vc.rwrite('(Search for the word "lost" in the file to identify ' 'memory leaks.)') vc.rwrite('') # report grade if not leak_detected: vc_grade = 'P' vc_comment = 'No memory leak detected.' else: vc_grade = 'F' vc_comment = 'Memory leak detected.' vc.rwrite('Grade: {}'.format(vc_grade)) vc.rwrite('') vc.rwrite('Comment: '+vc_comment) vc.rwrite('') return vc_grade, vc_comment ################################################################################ # # MAIN PROGRAM # ############################################################################### if __name__ == '__main__': # Get the model extended KIM ID: model = input("Model Extended KIM ID = ") # Define VC object and do verification check vc = kimvc.vc_object(vc_name, vc_description, __author__) with vc: # Perform verification check and get grade # try: vc_grade, vc_comment = do_vc(model, vc) # except: # vc_grade = "N/A" # vc_comment = "Unable to perform verification check due to an error." # sys.stderr.write('ERROR: Unable to perform verification check.\n') # Pack results in a dictionary and write VC property instance results = {"vc_name" : vc_name, "vc_description" : vc_description, "vc_category" : vc_category, "vc_grade_basis" : vc_grade_basis, "vc_grade" : vc_grade, "vc_comment" : vc_comment, "vc_files" : vc_files} vc.write_results(results)