#!/usr/bin/env python3 ################################################################################ # # 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) 2019, 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 kim_python_utils.vc as kim_vc_utils import runner2 import subprocess import re __version__ = "002" __author__ = "Ellad Tadmor" ################################################################################ # # FUNCTIONS # ################################################################################ ################################################################################ def do_vc(model, vc): """ Do memory leak check """ # call the code used to look for memory leaks directly to generate # the output for the report runner2.memory_leaks_test_process(model, vc) # call memory leaks test process using valgrind to look for leaks try: valgrind_out = subprocess.check_output( [ "valgrind", "--suppressions=./valgrind-python.supp", "python", "runner2.py", model, ], stderr=subprocess.STDOUT, universal_newlines=True, ) except subprocess.CalledProcessError: raise RuntimeError("Failed to run valgrind; check that it is installed.") # 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 try: valgrind_out = subprocess.check_output( [ "valgrind", "--leak-check=full", "--show-leak-kinds=all", "python", "runner2.py", model, ], stderr=subprocess.STDOUT, universal_newlines=True, ) except subprocess.CalledProcessError: raise RuntimeError("Failed to run valgrind; check that it is installed.") aux_file = "valgrind.out" vc.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." return vc_grade, vc_comment ################################################################################ # # MAIN PROGRAM # ############################################################################### if __name__ == "__main__": vcargs = { "vc_name": "vc-memory-leak", "vc_author": __author__, "vc_description": kim_vc_utils.vc_stripall(__doc__), "vc_category": "informational", "vc_grade_basis": "passfail", "vc_files": [], "vc_debug": False, # Set to True to get exception traceback info } # Get the model extended KIM ID: model = input("Enter a model name:\n") # Execute VC kim_vc_utils.setup_and_run_vc(do_vc, model, **vcargs)