code: def validate_auto_threaded_json(pjson):
          
          # pjson should be a dict or unicode
          if not type(pjson) is dict:
              raise ParseError("Expected a JSON object/dictionary or a string representing a test. Instead got %s." 
                               % pjson)
  
          # Make sure that the 'tests' key is present 
          try:
              tests = pjson["tests"]
          except KeyError:
              raise KeyError("Test object requires 'tests' attribute.\nObject: %s" % 
                             json.dumps(pjson))
  
          # Verify that tests is a list
          if type(tests) is not list:
              raise ParseError(
                  "Expected 'tests' to be a list but got object of type %s.\nObject: %s" %
                  (type(tests), json.dumps(tests))
              )
  
          # Verify that 'options' is a dict if present
          options = pjson.get('options', {})
          if type(options) is not dict:
              raise ParseError('"options" attribute must be a dictionary')
  
          # Verify that 'environments' is a list of dicts if present
          environments = pjson.get('environments', [])
          is_list_of_dicts = lambda ls: len(ls) == len(filter(lambda d: type(d) is dict, ls))
          if type(environments) is not list or not is_list_of_dicts(environments):
              raise ParseError('"environments" attribute must be a list of dictionaries. Instead got %s.' % environments)
  
          for test in tests:
              if type(test) is unicode:
                  # Base case for recursion
                  pass
              else:
                  # Recur
                  ConfigurationValidator.validate_auto_threaded_json(test)
docs: Takes a parsed JSON dict representing a set of tests in the auto-threaded
          format and validates it, descending recursively if necessary.