def setUp(self):
   super(ProvStoreConverterTestCase, self).setUp()
   self.provstore = ProvStoreConverter()
   self.in_file = None
   self.out_file = None
   self.config = {}  
   self.config[ProvStoreConverter.URL] = \
       "https://" + self.__class__.__name__
   self.config[ProvStoreConverter.AUTHORIZATION] = "ApiKey user:12345"
   self.config[ProvStoreConverter.INPUT_FORMATS] = standards.FORMATS
   self.config[ProvStoreConverter.OUTPUT_FORMATS] = standards.FORMATS
class ProvStoreConverterTestCase(unittest.TestCase):

  def setUp(self):
    super(ProvStoreConverterTestCase, self).setUp()
    self.provstore = ProvStoreConverter()
    self.in_file = None
    self.out_file = None
    self.config = {}  
    self.config[ProvStoreConverter.URL] = \
        "https://" + self.__class__.__name__
    self.config[ProvStoreConverter.AUTHORIZATION] = "ApiKey user:12345"
    self.config[ProvStoreConverter.INPUT_FORMATS] = standards.FORMATS
    self.config[ProvStoreConverter.OUTPUT_FORMATS] = standards.FORMATS

  def tearDown(self):
    super(ProvStoreConverterTestCase, self).tearDown()
    for f in [self.in_file, self.out_file]:
      if f != None and os.path.isfile(f):
        os.remove(f)

  def test_init(self):
    self.assertEqual("", self.provstore.url)
    self.assertEqual("", self.provstore.authorization)
    self.assertEqual([], self.provstore.input_formats)
    self.assertEqual([], self.provstore.output_formats)

  def test_configure(self):
    self.provstore.configure(self.config)
    self.assertEqual(self.config[ProvStoreConverter.URL],
                     self.provstore.url)
    self.assertEqual(self.config[ProvStoreConverter.AUTHORIZATION],
                     self.provstore.authorization)
    self.assertEqual(self.config[ProvStoreConverter.INPUT_FORMATS],
                     self.provstore.input_formats)
    self.assertEqual(self.config[ProvStoreConverter.OUTPUT_FORMATS],
                     self.provstore.output_formats)

  def test_configure_no_authorization(self):
    del(self.config[ProvStoreConverter.AUTHORIZATION])
    with self.assertRaises(ConfigError):
      self.provstore.configure(self.config)

  def test_convert_missing_input_file(self):
    self.provstore.configure(self.config)
    self.in_file = "nosuchfile.json"
    self.out_file = "convert_missing_input_file." + standards.JSON
    with self.assertRaises(ConversionError):
      self.provstore.convert(self.in_file, self.out_file)

  def test_convert_invalid_input_format(self):
    self.provstore.configure(self.config)
    (_, self.in_file) = tempfile.mkstemp(suffix=".nosuchformat")
    self.out_file = "convert_invalid_input_format." + standards.PROVX
    with self.assertRaises(ConversionError):
      self.provstore.convert(self.in_file, self.out_file)

  def test_convert_invalid_output_format(self):
    self.provstore.configure(self.config)
    (_, self.in_file) = tempfile.mkstemp(suffix="." + standards.JSON)
    self.out_file = "convert_invalid_output_format.nosuchformat"
    with self.assertRaises(ConversionError):
      self.provstore.convert(self.in_file, self.out_file)

  def register_post(self, mocker, content_type, doc_id, 
                    status_code = requests.codes.created):
    headers={http.CONTENT_TYPE: content_type,
             http.ACCEPT: ProvStoreConverter.CONTENT_TYPES[standards.JSON],
             http.AUTHORIZATION: self.config[ProvStoreConverter.AUTHORIZATION]}
    mocker.register_uri("POST", 
                        self.config[ProvStoreConverter.URL],
                        json={"id": doc_id},
                        request_headers=headers,
                        status_code=status_code)

  def register_get(self, mocker, content_type, doc_id, doc, format,
                   status_code = requests.codes.ok):
    doc_url = self.config[ProvStoreConverter.URL] + str(doc_id)
    headers={http.ACCEPT: content_type}
    mocker.register_uri("GET", 
                        doc_url + "." + format,
                        request_headers=headers,
                        text=doc,
                        status_code=status_code)

  def register_delete(self, mocker, doc_id, 
                      status_code=requests.codes.no_content):
    doc_url = self.config[ProvStoreConverter.URL] + str(doc_id)
    headers={http.AUTHORIZATION: self.config[ProvStoreConverter.AUTHORIZATION]}
    mocker.register_uri("DELETE", 
                        doc_url,
                        request_headers=headers,
                        status_code=status_code)

  @parameterized.expand(standards.FORMATS)
  def test_convert(self, format):
    content_type = ProvStoreConverter.CONTENT_TYPES[format]
    self.provstore.configure(self.config)
    (_, self.in_file) = tempfile.mkstemp(suffix="." + format)
    (_, self.out_file) = tempfile.mkstemp(suffix="." + format)
    doc = "mockdocument"
    doc_id = 123
    # Set up mock service response.
    with requests_mock.Mocker(real_http=False) as mocker:
      self.register_post(mocker, content_type, doc_id)
      self.register_get(mocker, content_type, doc_id, doc, format)
      self.register_delete(mocker, doc_id)
      self.provstore.convert(self.in_file, self.out_file)
      with open(self.out_file, 'r') as f:
        self.assertEqual(doc, f.read(), "Unexpected output file content")

  def test_convert_post_server_error(self):
    self.provstore.configure(self.config)
    format = standards.JSON
    (_, self.in_file) = tempfile.mkstemp(suffix="." + format)
    (_, self.out_file) = tempfile.mkstemp(suffix="." + format)
    content_type = ProvStoreConverter.CONTENT_TYPES[format]
    # Set up mock service response with POST causing server error.
    with requests_mock.Mocker(real_http=False) as mocker:
      self.register_post(mocker, 
                         content_type,
                         123,
                         status_code=requests.codes.internal_server_error)
      with self.assertRaises(ConversionError):
        self.provstore.convert(self.in_file, self.out_file)

  def test_convert_get_server_error(self):
    self.provstore.configure(self.config)
    format = standards.JSON
    (_, self.in_file) = tempfile.mkstemp(suffix="." + format)
    (_, self.out_file) = tempfile.mkstemp(suffix="." + format)
    content_type = ProvStoreConverter.CONTENT_TYPES[format]
    doc = "mockDocument"
    doc_id = 123
    # Set up mock service response with GET causing server error.
    with requests_mock.Mocker(real_http=False) as mocker:
      self.register_post(mocker, content_type, doc_id)
      self.register_get(mocker, content_type, doc_id, doc, format,
                        status_code=requests.codes.internal_server_error)
      with self.assertRaises(ConversionError):
        self.provstore.convert(self.in_file, self.out_file)

  def test_convert_delete_server_error(self):
    self.provstore.configure(self.config)
    format = standards.JSON
    (_, self.in_file) = tempfile.mkstemp(suffix="." + format)
    (_, self.out_file) = tempfile.mkstemp(suffix="." + format)
    content_type = ProvStoreConverter.CONTENT_TYPES[format]
    doc = "mockDocument"
    doc_id = 123
    # Set up mock service response with DELETE causing server error.
    with requests_mock.Mocker(real_http=False) as mocker:
      self.register_post(mocker, content_type, doc_id)
      self.register_get(mocker, content_type, doc_id, doc, format)
      self.register_delete(mocker, doc_id,
                           status_code=requests.codes.internal_server_error)
      with self.assertRaises(ConversionError):
        self.provstore.convert(self.in_file, self.out_file)