# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for stack_parser."""
import os
import unittest
from unittest import mock

import parameterized
from pyfakefs import fake_filesystem_unittest

import stack_parser

# NOTE: This integration test relies on
# https://github.com/google/oss-fuzz/tree/master/projects/example project.
EXAMPLE_PROJECT = 'example'

# Location of data used for testing.
TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                              'test_data')


class ParseOutputTest(fake_filesystem_unittest.TestCase):
  """Tests parse_fuzzer_output."""

  def setUp(self):
    self.setUpPyfakefs()
    self.maxDiff = None  # pylint: disable=invalid-name

  @parameterized.parameterized.expand([('example_crash_fuzzer_output.txt',
                                        'example_crash_fuzzer_bug_summary.txt'),
                                       ('msan_crash_fuzzer_output.txt',
                                        'msan_crash_fuzzer_bug_summary.txt')])
  def test_parse_valid_output(self, fuzzer_output_file, bug_summary_file):
    """Checks that the parse fuzzer output can correctly parse output."""
    # Read the fuzzer output from disk.
    fuzzer_output_path = os.path.join(TEST_DATA_PATH, fuzzer_output_file)
    self.fs.add_real_file(fuzzer_output_path)
    with open(fuzzer_output_path, 'r') as fuzzer_output_handle:
      fuzzer_output = fuzzer_output_handle.read()
    bug_summary_path = '/bug-summary.txt'
    with mock.patch('logging.info') as mock_info:
      stack_parser.parse_fuzzer_output(fuzzer_output, bug_summary_path)
      mock_info.assert_not_called()

    with open(bug_summary_path) as bug_summary_handle:
      bug_summary = bug_summary_handle.read()

    # Compare the bug to the expected one.
    expected_bug_summary_path = os.path.join(TEST_DATA_PATH, bug_summary_file)
    self.fs.add_real_file(expected_bug_summary_path)
    with open(expected_bug_summary_path) as expected_bug_summary_handle:
      expected_bug_summary = expected_bug_summary_handle.read()

    self.assertEqual(expected_bug_summary, bug_summary)

  def test_parse_invalid_output(self):
    """Checks that no files are created when an invalid input was given."""
    artifact_path = '/bug-summary.txt'
    with mock.patch('logging.error') as mock_error:
      stack_parser.parse_fuzzer_output('not a valid output_string',
                                       artifact_path)
      assert mock_error.call_count
    self.assertFalse(os.path.exists(artifact_path))


if __name__ == '__main__':
  unittest.main()
