Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(745)

Issue 2747023002: Cleanup machine based on the state in configuration file for mini installer test.

Created:
3 years, 9 months ago by zmin
Modified:
3 years, 9 months ago
Reviewers:
grt (UTC plus 2)
CC:
chromium-reviews
Target Ref:
refs/heads/master
Project:
chromium
Visibility:
Public.

Description

Cleanup machine based on the state in configuration file for mini installer test. RunCleanCommand in test_installer now will reset the machine if |force_clean| is True after running uninstaller. The resetting is based on the state in config.config and assoicated .prop file. The state for the initial cleanup before all test cases is 'clean'. The state for the tearDown is the last state of each test case. Cleanup only supports deleting directory and registry key now. Both of them will always be executed recursively. BUG=6698997

Patch Set 1 #

Patch Set 2 : fixup #

Total comments: 9

Patch Set 3 : refactor #

Patch Set 4 : fix gni file #

Total comments: 1

Patch Set 5 : refactor to use visitor pattern #

Unified diffs Side-by-side diffs Delta from patch set Stats (+417 lines, -267 lines) Patch
A chrome/test/mini_installer/cleaner_visitor.py View 1 2 3 4 1 chunk +50 lines, -0 lines 0 comments Download
A chrome/test/mini_installer/entry.py View 1 2 3 4 1 chunk +8 lines, -0 lines 0 comments Download
A chrome/test/mini_installer/file.py View 1 2 3 4 1 chunk +31 lines, -0 lines 0 comments Download
M chrome/test/mini_installer/file_verifier.py View 1 2 1 chunk +0 lines, -31 lines 0 comments Download
M chrome/test/mini_installer/mini_installer_test.gni View 1 2 3 4 1 chunk +16 lines, -5 lines 0 comments Download
A chrome/test/mini_installer/process.py View 1 2 3 4 1 chunk +32 lines, -0 lines 0 comments Download
D chrome/test/mini_installer/process_verifier.py View 1 2 1 chunk +0 lines, -33 lines 0 comments Download
A chrome/test/mini_installer/registry.py View 1 2 3 4 1 chunk +132 lines, -0 lines 0 comments Download
M chrome/test/mini_installer/registry_verifier.py View 1 2 1 chunk +0 lines, -112 lines 0 comments Download
A chrome/test/mini_installer/state_walker.py View 1 2 3 4 1 chunk +45 lines, -0 lines 0 comments Download
M chrome/test/mini_installer/test_installer.py View 1 2 3 4 13 chunks +32 lines, -46 lines 0 comments Download
M chrome/test/mini_installer/variable_expander.py View 2 chunks +3 lines, -3 lines 0 comments Download
M chrome/test/mini_installer/verifier.py View 1 chunk +9 lines, -0 lines 0 comments Download
M chrome/test/mini_installer/verifier_runner.py View 1 2 1 chunk +0 lines, -37 lines 0 comments Download
A chrome/test/mini_installer/verifier_visitor.py View 1 2 3 4 1 chunk +59 lines, -0 lines 0 comments Download

Messages

Total messages: 27 (19 generated)
zmin
Hi Greg, Can you please take a look this CL please? Owen
3 years, 9 months ago (2017-03-13 21:42:38 UTC) #7
grt (UTC plus 2)
This is a great start. See below for a proposal to make it a bit ...
3 years, 9 months ago (2017-03-14 09:19:44 UTC) #8
zmin
I have refactor the code and I'll try to test for it with more test ...
3 years, 9 months ago (2017-03-14 23:13:00 UTC) #12
grt (UTC plus 2)
i think this can be simplified further. will this work? ---- visitor.py --- class Visitor: ...
3 years, 9 months ago (2017-03-15 09:00:08 UTC) #19
zmin
On 2017/03/15 09:00:08, grt (UTC plus 1) wrote: > i think this can be simplified ...
3 years, 9 months ago (2017-03-15 20:37:23 UTC) #20
grt (UTC plus 2)
On 2017/03/15 20:37:23, zmin wrote: > Ah, guess i didn't see the keyword 'pattern' yesterday ...
3 years, 9 months ago (2017-03-16 08:36:22 UTC) #21
zmin
I refactor the code to use the visitor pattern.
3 years, 9 months ago (2017-03-22 23:25:21 UTC) #24
grt (UTC plus 2)
3 years, 9 months ago (2017-03-23 10:26:09 UTC) #27
Hi Owen. I don't understand the design here, perhaps because I'm still mentally
stuck on a classical Visitor pattern. I envision a clear separation of concerns
like this:

- StateWalker does nothing more than walk the property dict, evaluate
conditions, and then dispatch to the type-specific method on the Visitor it is
given. It doesn't know what the Visitor is going to do and doesn't need to know
about any type-specific implementation (i.e., File, Process, Registry classes).

- Concrete Visitor types dispatch type-specific methods to the appropriate
behavior.

So rather than:

Walk -> create entry (File, Registry, Process) -> entry.Check -> visitor.Visit

we would have:

Walk -> visitor.Visit -> (somehow the operation is done)

Referring to my proposal in comment 19, here's one possibility for VisitFile for
each type of visitor:

--- verifier_visitor.py ---

import file_handler

class VerifierVisitor(Visitor):
  def __init__(self):
    self._file_handler = file_handler.FileHandler()
    self._process_handler = ...

  def VisitFile(self, variable_expander, expectation_name, expectation):
    self._file_handler.Verify(variable_expander, expectation_name, expectation)

--- cleaner_visitor.py ---

import file_handler

class CleanerVisitor(Visitor):
  def __init__(self):
    self._file_handler = file_handler.FileHandler()
    self._process_handler = ...

  def VisitFile(self, variable_expander, expectation_name, expectation):
    self._file_handler.Clean(variable_expander, expectation_name, expectation)

--- file_handler.py ---

class FileHandler:
  def Verify(variable_expander, expectation_name, expectation):
    file_path = variable_expander.Expand(expectation_name)
    file_exists = os.path.exists(file_path)
    assert expectation['exists'] == file_exists, \
        ('File %s exists' % file_path) if file_exists else \
        ('File %s is missing' % file_path)

  def Clean(variable_expander, expectation_name, expectation):
    """Delete files and directories that would cause a non-existence
       expectation to fail."""
    # Nothing to do if the expectation is that the file should exist.
    if expectation['exists']:
      return
    file_path = variable_expander.Expand(expectation_name)
    if os.path.exists(file_path):
      ...delete file_path...

Alternatively, if that seems like too much hoop jumping (Walker ->
OperationVisitor -> TypeHandler), you could do away with the visitor and more
tightly couple the walking with the operation by baking the visitor into the
Walker and indicating the operation via an in param or something:

class StateWalker:
  _type_to_handler = {
    'Files': file_handler.FileHandler(),
    'Processes': process_handler.ProcessHandler(),
    'RegistryEntries': registry_entry_handler.RegistryEntryHandler(),
  }

  def Walk(self, variable_expander, property_dict, operation):
    """Traverses |property_dict|, invoking the relevant handler's |operation|
       ('Verify' or 'Clean') method for each expectation."""
    for type_name, expectations in property_dict.iteritems():
      for expectation_name, expectation_dict in expectations.iteritems():
        # Skip over expectations with conditions that aren't satisfied.
        if 'condition' in expectation_dict:
          condition = variable_expander.Expand(expectation_dict['condition'])
          if not self._EvaluateCondition(condition):
            continue
        getattr(StateWalker._type_to_handler[type_name], operation)(
          variable_expander, expectation_name, expectation)

Does this make sense? I'm totally fine if you want to keep things simple and
skip the Visitor classes.

Powered by Google App Engine
This is Rietveld 408576698