-
Notifications
You must be signed in to change notification settings - Fork 11
Add AssessmentState file and max auto assessment interval #150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
46827bd
422411e
e412fae
43746ec
37eebc4
0c9ced6
32dc8c1
2abdba4
6101629
7b75a4e
b072bbe
8ab1270
05bc000
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,12 @@ | |
# limitations under the License. | ||
# | ||
# Requires Python 2.7+ | ||
|
||
import datetime | ||
import json | ||
import os | ||
import unittest | ||
|
||
from core.src.bootstrap.Constants import Constants | ||
from core.src.service_interfaces.TelemetryWriter import TelemetryWriter | ||
from core.tests.library.ArgumentComposer import ArgumentComposer | ||
from core.tests.library.RuntimeCompositor import RuntimeCompositor | ||
|
@@ -66,6 +68,88 @@ def test_assessment_telemetry_fail(self): | |
self.assertRaises(Exception, self.runtime.patch_assessor.start_assessment) | ||
self.runtime.patch_assessor.telemetry_writer = backup_telemetry_writer | ||
|
||
def test_assessment_state_file(self): | ||
# read_assessment_state creates a vanilla assessment state file if none exists | ||
assessment_state = self.runtime.patch_assessor.read_assessment_state() | ||
with open(self.runtime.patch_assessor.assessment_state_file_path, 'r') as file_handle: | ||
assessment_state_from_file = json.loads(file_handle.read())["assessmentState"] | ||
self.assessment_state_equals(assessment_state, assessment_state_from_file) | ||
|
||
# write and test again | ||
self.runtime.patch_assessor.write_assessment_state() | ||
assessment_state = self.runtime.patch_assessor.read_assessment_state() | ||
with open(self.runtime.patch_assessor.assessment_state_file_path, 'r') as file_handle: | ||
assessment_state_from_file = json.loads(file_handle.read())["assessmentState"] | ||
self.assessment_state_equals(assessment_state, assessment_state_from_file) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another way to validate write_assessment_state(), updated an existing AssessmentState.json will be to compare the lastHeartbeat before and after write_assessment_state(), i.e:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ben is aware of what to do here. Ack |
||
|
||
# Assessment state file is a directory | ||
if os.path.exists(self.runtime.patch_assessor.assessment_state_file_path): | ||
os.remove(self.runtime.patch_assessor.assessment_state_file_path) | ||
|
||
# Attempt to read when it does not exist - should create default assessment state file | ||
os.mkdir(self.runtime.patch_assessor.assessment_state_file_path) | ||
self.assertTrue(self.runtime.patch_assessor.read_assessment_state() is not None) | ||
|
||
if os.path.exists(self.runtime.patch_assessor.assessment_state_file_path): | ||
os.remove(self.runtime.patch_assessor.assessment_state_file_path) | ||
|
||
os.mkdir(self.runtime.patch_assessor.assessment_state_file_path) | ||
# Attempt to write when it does not exist - should also create default assessment state file | ||
self.runtime.patch_assessor.write_assessment_state() | ||
benank marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.assertTrue(self.runtime.patch_assessor.read_assessment_state() is not None) | ||
|
||
# Opening file throws exception | ||
backup_open = self.runtime.patch_assessor.env_layer.file_system.open | ||
self.runtime.patch_assessor.env_layer.file_system.open = lambda: self.raise_ex() | ||
self.assertRaises(Exception, self.runtime.patch_assessor.read_assessment_state) | ||
self.assertRaises(Exception, self.runtime.patch_assessor.write_assessment_state) | ||
self.runtime.patch_assessor.env_layer.file_system.open = backup_open | ||
|
||
def assessment_state_equals(self, state1, state2): | ||
self.assertEqual(state1["processIds"][0], state2["processIds"][0]) | ||
self.assertEqual(state1["lastHeartbeat"], state2["lastHeartbeat"]) | ||
self.assertEqual(state1["number"], state2["number"]) | ||
self.assertEqual(state1["autoAssessment"], state2["autoAssessment"]) | ||
self.assertEqual(state1["lastStartInSecondsSinceEpoch"], state2["lastStartInSecondsSinceEpoch"]) | ||
|
||
def test_should_auto_assessment_run(self): | ||
# First file write (since it does not exist on read) so it should succeed since last assessment time is 0 | ||
self.runtime.patch_assessor.read_assessment_state() | ||
self.assertTrue(self.runtime.patch_assessor.should_auto_assessment_run()) | ||
|
||
# Second file write, should fail now since minimum delay between assessments hasn't been met | ||
self.runtime.patch_assessor.write_assessment_state() | ||
self.assertFalse(self.runtime.patch_assessor.should_auto_assessment_run()) | ||
|
||
# It has been minimum delay time since last run | ||
assessment_state = self.runtime.patch_assessor.read_assessment_state() | ||
min_auto_assess_interval_in_seconds = self.runtime.patch_assessor.convert_iso8601_duration_to_total_seconds(Constants.MIN_AUTO_ASSESSMENT_INTERVAL) | ||
assessment_state["lastStartInSecondsSinceEpoch"] -= min_auto_assess_interval_in_seconds | ||
with open(self.runtime.patch_assessor.assessment_state_file_path, 'w+') as file_handle: | ||
file_handle.write(json.dumps({"assessmentState": assessment_state})) | ||
self.assertTrue(self.runtime.patch_assessor.should_auto_assessment_run()) | ||
|
||
# Time is in future, so run assessment and correct anomaly | ||
self.runtime.patch_assessor.write_assessment_state() | ||
assessment_state["lastStartInSecondsSinceEpoch"] += 5000000 | ||
with open(self.runtime.patch_assessor.assessment_state_file_path, 'w+') as file_handle: | ||
file_handle.write(json.dumps({"assessmentState": assessment_state})) | ||
self.assertTrue(self.runtime.patch_assessor.should_auto_assessment_run()) | ||
|
||
# Test exception case: exception is caught and assessment should run | ||
self.runtime.patch_assessor.read_assessment_state = lambda: self.raise_ex() | ||
self.assertTrue(self.runtime.patch_assessor.should_auto_assessment_run()) | ||
|
||
def test_convert_iso8601_duration_to_total_seconds(self): | ||
self.assertEqual(self.runtime.patch_assessor.convert_iso8601_duration_to_total_seconds('PT6H'), 21600) | ||
self.assertEqual(self.runtime.patch_assessor.convert_iso8601_duration_to_total_seconds('PT6H5M'), 21900) | ||
self.assertEqual(self.runtime.patch_assessor.convert_iso8601_duration_to_total_seconds('PT6H5M14S'), 21914) | ||
self.assertRaises(Exception, lambda: self.runtime.patch_assessor.convert_iso8601_duration_to_total_seconds('6H5M14S')) | ||
self.assertRaises(Exception, lambda: self.runtime.patch_assessor.convert_iso8601_duration_to_total_seconds('')) | ||
|
||
def raise_ex(self): | ||
raise Exception() | ||
|
||
def mock_refresh_repo(self): | ||
pass | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.