docs: def _validate_dict_data(self, expected, actual):
          """Validate dictionary data.
  
             Compare expected dictionary data vs actual dictionary data.
             The values in the 'expected' dictionary can be strings, bools, ints,
             longs, or can be a function that evaluates a variable and returns a
             bool.
             """
          self.log.debug('actual: {}'.format(repr(actual)))
          self.log.debug('expected: {}'.format(repr(expected)))
  
          for k, v in six.iteritems(expected):
              if k in actual:
                  if (isinstance(v, six.string_types) or
                          isinstance(v, bool) or
                          isinstance(v, six.integer_types)):
                      # handle explicit values
                      if v != actual[k]:
                          return "{}:{}".format(k, actual[k])
                  # handle function pointers, such as not_null or valid_ip
                  elif not v(actual[k]):
                      return "{}:{}".format(k, actual[k])
              else:
                  return "key '{}' does not exist".format(k)
          return None