Skip to content

Commit

Permalink
Merge pull request #10 from tahiat/issue9
Browse files Browse the repository at this point in the history
honouring Specimin local path, error msg printing in log. PR for issue #9
  • Loading branch information
tahiat authored Feb 20, 2024
2 parents 96d9be8 + d7b8878 commit 74dfaf8
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 50 deletions.
45 changes: 26 additions & 19 deletions TestMain.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ class TestMain(unittest.TestCase):

@classmethod
def setUpClass(cls):
# cloning the specimin
main.clone_repository('https://github.com/kelloggm/specimin.git', 'resources')
cls.json_data = main.read_json_from_file('resources/test_data.json')[0]
cls.specimin_dir = "resources/specimin"
#TODO: previously used cf-1291 (index 0) fails when absolute path of the target is used. Will investigate it later.
#Currently using cf-6060
cls.json_data = main.read_json_from_file('resources/test_data.json')[3]
sp_env_var = main.get_specimin_env_var()
if sp_env_var is not None and os.path.exists(sp_env_var) and os.path.isdir(sp_env_var):
print("Local Specimin copy is being used")
cls.specimin_dir = sp_env_var
else:
print("Local Specimin not found. Cloning a Specimin copy")
main.clone_repository('https://github.com/kelloggm/specimin.git', 'resources')
cls.specimin_dir = os.path.abspath("resources/specimin")

@classmethod
def tearDownClass(cls):
Expand All @@ -20,7 +27,7 @@ def tearDownClass(cls):
shutil.rmtree('resources/specimin')
except Exception as e:
print(f"Error occurred {e}")
# removing any issue project cloned in resources
# removing any issue project cloned in resources
for root, dirs, files in os.walk('resources', topdown=False):
for dir_name in dirs:
if 'cf-' in dir_name:
Expand Down Expand Up @@ -56,9 +63,9 @@ def test_build_specimin_command(self):
"file": "IndexMode.java",
"package": 'org.apache.cassandra.index.sasi.conf'
}]
specimin_dir = 'user/specimin'
target_dir = 'user/ISSUES/cf-6077'
command = main.build_specimin_command(proj_name, target_dir, specimin_dir, root, targets)

target_dir = '/user/ISSUES/cf-6077'
command = main.build_specimin_command(proj_name, target_dir, root, targets)
target_command = ''
with open('resources/specimin_command_cf-6077.txt','r') as file:
target_command = file.read()
Expand All @@ -71,9 +78,9 @@ def test_build_specimin_command(self):
"file": "Avro2Confluent.java",
"package": 'com.fillmore_labs.kafka.sensors.serde.confluent.interop'
}]
specimin_dir = 'user/specimin'
target_dir = 'user/ISSUES/cf-6019'
command = main.build_specimin_command(proj_name, target_dir, specimin_dir, root, targets)

target_dir = '/user/ISSUES/cf-6019'
command = main.build_specimin_command(proj_name, target_dir, root, targets)
with open('resources/specimin_command_cf-6019.txt','r') as file:
target_command = file.read()
self.assertEqual(command, target_command)
Expand All @@ -82,15 +89,16 @@ def test_build_specimin_command(self):
# make
issue_name = self.json_data[JsonKeys.ISSUE_ID.value]
main.create_issue_directory('resources', issue_name)
self.assertTrue(os.path.exists('resources/cf-1291/input'))
main.clone_repository(self.json_data[JsonKeys.URL.value], f"resources/{issue_name}/input")

project_name = main.get_repository_name(self.json_data[JsonKeys.URL.value])
self.assertTrue(os.path.exists(f'resources/{issue_name}/input'))
main.clone_repository(self.json_data[JsonKeys.URL.value], f"resources/{issue_name}/input")

project_name = main.get_repository_name(self.json_data[JsonKeys.URL.value])
self.assertTrue(main.checkout_commit(self.json_data[JsonKeys.COMMIT_HASH.value],f"resources/{issue_name}/input/{project_name}"))
self.assertTrue(main.is_git_directory(f"resources/{issue_name}/input/{project_name}"))
main.change_branch(self.json_data[JsonKeys.BRANCH.value], f"resources/{issue_name}/input/{project_name}")

command = main.build_specimin_command(project_name, f"resources/{issue_name}", self.specimin_dir, self.json_data[JsonKeys.ROOT_DIR.value], self.json_data[JsonKeys.TARGETS.value])
#build_specimin_command accept absolute path of the root directory.
command = main.build_specimin_command(project_name, os.path.abspath(f"resources/{issue_name}"), self.json_data[JsonKeys.ROOT_DIR.value], self.json_data[JsonKeys.TARGETS.value])
print(command)
result = main.run_specimin(issue_name, command, self.specimin_dir)
self.assertEqual(result.status, "PASS")
Expand All @@ -103,11 +111,10 @@ def test_run_specimin(self):
"file": "Simple.java",
"package": "com.example"
}]
specimin_dir = 'resources/specimin'
target_dir = 'resources/onefilesimple'

command = main.build_specimin_command(proj_name, target_dir, specimin_dir, root, targets)
result = main.run_specimin(proj_name, command, 'resources/specimin')
command = main.build_specimin_command(proj_name, os.path.abspath(target_dir), root, targets)
result = main.run_specimin(proj_name, command, self.specimin_dir)
self.assertEqual(result.status, "PASS")


Expand Down
95 changes: 66 additions & 29 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
specimin_project_name = 'specimin'
specimin_source_url = 'https://github.com/kelloggm/specimin.git'
TIMEOUT_DURATION = 300
specimin_env_var = "SPECIMIN"

def read_json_from_file(file_path):
'''
Expand All @@ -34,6 +35,14 @@ def read_json_from_file(file_path):
print(f"File not found: {file_path}")
return None

def get_specimin_env_var():
'''
Check and returns the path of the Specimin program if defined
Retruns:
Path of the local Specimin program
'''
specimin_env_value = os.environ.get(specimin_env_var)
return specimin_env_value

def get_repository_name(github_ssh: str):
'''
Expand All @@ -60,8 +69,8 @@ def create_issue_directory(issue_container_dir, issue_id):
| |--- output
Parameters:
issue_container_dir (str): The directory where new directory is created
issue_id (str): Name of the directory to be created
issue_container_dir (str): Absolute path of the container directory containing all program directory.
issue_id (str): Name of the directory to be created inside container directory.
Returns:
specimin_input_dir (str): A target directory of SPECIMIN. (issue_container_dir/issue_id/input)
Expand Down Expand Up @@ -99,7 +108,7 @@ def clone_repository(url, directory):
directory (str): directory to clone in
'''
project_name = get_repository_name(url)
if (os.path.exists(f"{directory}/{project_name}")):
if (os.path.exists(os.path.join(directory, project_name))):
print(f"{project_name} repository already exists. Aborting cloning")
return
subprocess.run(["git", "clone", url], cwd=directory)
Expand Down Expand Up @@ -128,9 +137,11 @@ def checkout_commit(commit_hash, directory):
if not is_git_directory(directory):
raise ValueError(f"{directory} is not a valid git directory")

command = ["git", "checkout", commit_hash]
result = subprocess.run(command, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

if (commit_hash):
command = ["git", "checkout", commit_hash]
result = subprocess.run(command, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
else:
return True
if result.returncode == 0:
print(f"Successfully checked-out commit {commit_hash} in {directory}")
else:
Expand Down Expand Up @@ -163,8 +174,7 @@ def clone_specimin(path_to_clone, url):


def build_specimin_command(project_name: str,
issue_input_dir: str,
specimin_dir: str,
target_base_dir_path: str,
root_dir: str,
targets: list):
'''
Expand All @@ -180,19 +190,19 @@ def build_specimin_command(project_name: str,
Parameters:
project_name (str): Name of the target project. Example: daikon
issue_input_dir (str): path of the target project directory. Ex: ISSUES/cf-1291
specimin_dir (str): Specimin directory path
target_base_dir (str): path of the target project directory. Ex: ISSUES/cf-1291
root_dir (str): A directory path relative to the project base directory where java package stored.
targets ({'method': '', 'file': '', 'package': ''}) : target java file and method name data
Retruns:
command (str): The gradle command of SPECIMIN for the issue.
'''

if not os.path.isabs(target_base_dir_path):
raise ValueError("Invalid argument: target_base_dir_path must be an absolute path")

relative_path_of_target_dir = os.path.relpath(issue_input_dir, specimin_dir)

output_dir = os.path.join(relative_path_of_target_dir, specimin_output)
root_dir = os.path.join(relative_path_of_target_dir, specimin_input, project_name, root_dir)
output_dir = os.path.join(target_base_dir_path, specimin_output)
root_dir = os.path.join(target_base_dir_path, specimin_input, project_name, root_dir)
root_dir = root_dir.rstrip('/') + os.sep

target_file_list = []
Expand Down Expand Up @@ -243,20 +253,30 @@ def run_specimin(issue_name, command, directory) -> Result:
directory (str): The base directory of the specimin repository
Returns:
boolean: True/False based on successful execution of SPECIMIN
Result: execution result of Specimin
'''
print(f"{issue_name} executing...")
try:
result = subprocess.run(command, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, timeout=TIMEOUT_DURATION)
print(f"{issue_name} execution ends.")
if result.returncode == 0:
return Result(issue_name, "PASS", "")
else:
error_msg_file = os.path.join(issue_folder_dir, issue_name, f"{issue_name}_error.txt")
if os.path.exists(error_msg_file):
os.remove(error_msg_file)
with open(error_msg_file, 'w') as file:
file.write(result.stderr.decode("utf-8"))
error_msg_file = os.path.join(issue_folder_dir, issue_name, f"{issue_name}_error.txt") # not abs path. ISSUES/cf-1291/cf-1291_error.txt
try:
stderr_str = result.stderr.decode("utf-8") # this can fail.
stderr_lines = stderr_str.split('\n')[:5]
first_five_lines_stderr = '\n'.join(stderr_lines)
print(first_five_lines_stderr)
if os.path.exists(error_msg_file):
os.remove(error_msg_file)
with open(error_msg_file, 'w') as file:
file.write(stderr_str)
except UnicodeDecodeError as e:
print("Error decoding stderr:", e)
return Result(issue_name, "FAIL", f"{error_msg_file}")
except subprocess.TimeoutExpired:
print(f"{issue_name} execution ends. TIMEOUT")
return Result(issue_name, "FAIL", "Timeout")
except Exception as e:
return Result(issue_name, "FAIL", f"Unhandled exception occurred: {e}")
Expand All @@ -276,19 +296,27 @@ def performEvaluation(issue_data) -> Result:
branch = issue_data[JsonKeys.BRANCH.value]
commit_hash = issue_data[JsonKeys.COMMIT_HASH.value]

input_dir = create_issue_directory(issue_folder_dir, issue_id) # ../cf-12/input
clone_repository(url, input_dir) # TODO: check if clonning is successful.
issue_folder_abs_dir = os.path.abspath(issue_folder_dir)
input_dir = create_issue_directory(issue_folder_abs_dir, issue_id)
clone_repository(url, input_dir)
repo_name = get_repository_name(url)

if branch:
change_branch(branch, f"{input_dir}/{repo_name}")
change_branch(branch, os.path.join(input_dir, repo_name))

if commit_hash:
checkout_commit(commit_hash, f"{input_dir}/{repo_name}")

specimin_command = build_specimin_command(repo_name, os.path.join(issue_folder_dir, issue_id), os.path.join(issue_folder_dir, specimin_project_name),issue_data[JsonKeys.ROOT_DIR.value], issue_data[JsonKeys.TARGETS.value])

result = run_specimin(issue_id ,specimin_command, os.path.join(issue_folder_dir, specimin_project_name))
checkout_commit(commit_hash, os.path.join(input_dir, repo_name))

specimin_command = ""
result: Result = None
specimin_path = get_specimin_env_var()
if specimin_path is not None and os.path.exists(specimin_path):
specimin_command = build_specimin_command(repo_name, os.path.join(issue_folder_abs_dir, issue_id), issue_data[JsonKeys.ROOT_DIR.value], issue_data[JsonKeys.TARGETS.value])
result = run_specimin(issue_id ,specimin_command, specimin_path)
else:
specimin_command = build_specimin_command(repo_name, os.path.join(issue_folder_abs_dir, issue_id),issue_data[JsonKeys.ROOT_DIR.value], issue_data[JsonKeys.TARGETS.value])
result = run_specimin(issue_id ,specimin_command, os.path.join(issue_folder_abs_dir, specimin_project_name))

print(f"{result.name} - {result.status}")
return result

Expand All @@ -298,16 +326,25 @@ def main():
Main method of the script. It iterates over the json data and perform minimization for each cases.
'''
os.makedirs(issue_folder_dir, exist_ok=True) # create the issue holder directory
clone_specimin(issue_folder_dir, specimin_source_url)

specimin_path = get_specimin_env_var()
if specimin_path is not None and os.path.exists(specimin_path) and os.path.isdir(specimin_path):
print("Local Specimin copy is being used")
else:
print("Local Specimin not found. Cloning a Specimin copy")
clone_specimin(issue_folder_dir, specimin_source_url)

json_file_path = 'resources/test_data.json'
parsed_data = read_json_from_file(json_file_path)

evaluation_results = []
if parsed_data:
for issue in parsed_data:
issue_id = issue["issue_id"]
print(f"{issue_id} execution starts =========>")
result = performEvaluation(issue)
evaluation_results.append(result)
print((f"{issue_id} <========= execution Ends."))


report_generator = TableGenerator(evaluation_results)
Expand Down
2 changes: 1 addition & 1 deletion resources/specimin_command_cf-6019.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
./gradlew run --args='--root "../ISSUES/cf-6019/input/kafka-sensors/src/main/java/" --outputDirectory "../ISSUES/cf-6019/output" --targetFile "com/fillmore_labs/kafka/sensors/serde/confluent/interop/Avro2Confluent.java" --targetMethod "com.fillmore_labs.kafka.sensors.serde.confluent.interop.Avro2Confluent#transform(String, byte[])"'
./gradlew run --args='--root "/user/ISSUES/cf-6019/input/kafka-sensors/src/main/java/" --outputDirectory "/user/ISSUES/cf-6019/output" --targetFile "com/fillmore_labs/kafka/sensors/serde/confluent/interop/Avro2Confluent.java" --targetMethod "com.fillmore_labs.kafka.sensors.serde.confluent.interop.Avro2Confluent#transform(String, byte[])"'
2 changes: 1 addition & 1 deletion resources/specimin_command_cf-6077.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
./gradlew run --args='--root "../ISSUES/cf-6077/input/cassandra/src/java/" --outputDirectory "../ISSUES/cf-6077/output" --targetFile "org/apache/cassandra/index/sasi/conf/IndexMode.java" --targetMethod "org.apache.cassandra.index.sasi.conf.IndexMode#getMode(ColumnMetadata, Map<String, String>)"'
./gradlew run --args='--root "/user/ISSUES/cf-6077/input/cassandra/src/java/" --outputDirectory "/user/ISSUES/cf-6077/output" --targetFile "org/apache/cassandra/index/sasi/conf/IndexMode.java" --targetMethod "org.apache.cassandra.index.sasi.conf.IndexMode#getMode(ColumnMetadata, Map<String, String>)"'

0 comments on commit 74dfaf8

Please sign in to comment.