|
2 | 2 | import hashlib |
3 | 3 | import json |
4 | 4 | import xml.etree.ElementTree as ET |
| 5 | +from unittest.mock import MagicMock, patch |
5 | 6 | import boto3 |
6 | 7 | import pytest |
7 | 8 | from moto import mock_s3, mock_sts |
8 | 9 |
|
9 | 10 | import bignbit.utils |
10 | 11 | from bignbit.handle_big_result import ( |
| 12 | + _resolve_static_data_day, |
11 | 13 | construct_cnm, |
12 | 14 | create_metadata_xml, |
13 | 15 | generate_metadata, |
14 | 16 | get_mdxml_cnm_file_meta, |
| 17 | + IncompleteImageSetError, |
15 | 18 | process_harmony_results, |
16 | 19 | write_cnm_message |
17 | 20 | ) |
@@ -571,3 +574,102 @@ def test_write_cnm_message_nrt(): |
571 | 574 | assert '_NRT_' in cnm_message['collection'] or cnm_message['collection'].endswith('_NRT') |
572 | 575 |
|
573 | 576 |
|
| 577 | +# -------------------------------------------------------------------------------------- |
| 578 | +# Tests for _resolve_static_data_day |
| 579 | +# -------------------------------------------------------------------------------------- |
| 580 | + |
| 581 | +def test_resolve_static_data_day_no_strategy(): |
| 582 | + """Returns None when dataDayStrategy is absent.""" |
| 583 | + assert _resolve_static_data_day({}) is None |
| 584 | + |
| 585 | + |
| 586 | +def test_resolve_static_data_day_different_strategy(): |
| 587 | + """Returns None when dataDayStrategy is set to something other than 'single_day_of_year'.""" |
| 588 | + config = {'dataDayStrategy': 'some_other_strategy', 'singleDayNumber': 100} |
| 589 | + assert _resolve_static_data_day(config) is None |
| 590 | + |
| 591 | + |
| 592 | +def test_resolve_static_data_day_valid(): |
| 593 | + """Returns the configured day number when it is within the valid range.""" |
| 594 | + config = {'dataDayStrategy': 'single_day_of_year', 'singleDayNumber': 100} |
| 595 | + assert _resolve_static_data_day(config) == 100 |
| 596 | + |
| 597 | + |
| 598 | +def test_resolve_static_data_day_boundary_values(): |
| 599 | + """Returns 1 and 366 as valid boundary day numbers.""" |
| 600 | + assert _resolve_static_data_day({'dataDayStrategy': 'single_day_of_year', 'singleDayNumber': 1}) == 1 |
| 601 | + assert _resolve_static_data_day({'dataDayStrategy': 'single_day_of_year', 'singleDayNumber': 366}) == 366 |
| 602 | + |
| 603 | + |
| 604 | +def test_resolve_static_data_day_too_low(): |
| 605 | + """Returns 1 (fallback) when configured day is below the valid range.""" |
| 606 | + config = {'dataDayStrategy': 'single_day_of_year', 'singleDayNumber': 0} |
| 607 | + assert _resolve_static_data_day(config) == 1 |
| 608 | + |
| 609 | + |
| 610 | +def test_resolve_static_data_day_too_high(): |
| 611 | + """Returns 1 (fallback) when configured day exceeds 366.""" |
| 612 | + config = {'dataDayStrategy': 'single_day_of_year', 'singleDayNumber': 367} |
| 613 | + assert _resolve_static_data_day(config) == 1 |
| 614 | + |
| 615 | + |
| 616 | +def test_resolve_static_data_day_default_number(): |
| 617 | + """Returns 1 (default singleDayNumber) when the key is absent but strategy is set.""" |
| 618 | + config = {'dataDayStrategy': 'single_day_of_year'} |
| 619 | + assert _resolve_static_data_day(config) == 1 |
| 620 | + |
| 621 | + |
| 622 | +# -------------------------------------------------------------------------------------- |
| 623 | +# Additional tests for generate_metadata and process_harmony_results |
| 624 | +# -------------------------------------------------------------------------------------- |
| 625 | + |
| 626 | +def test_generate_metadata_raises_when_image_missing(): |
| 627 | + """IncompleteImageSetError is raised when the image_set has no image.""" |
| 628 | + image_set = ImageSet(name='empty_set', image={}) |
| 629 | + with pytest.raises(IncompleteImageSetError): |
| 630 | + generate_metadata(image_set, 'begin', 'mid', 'end', 'day', False, None) |
| 631 | + |
| 632 | + |
| 633 | +@mock_sts |
| 634 | +@mock_s3 |
| 635 | +@patch('bignbit.utils.get_harmony_client') |
| 636 | +def test_process_harmony_results_empty_result_urls(mock_get_harmony_client): |
| 637 | + """Returns an empty list when a valid Harmony job produces no result files.""" |
| 638 | + bignbit.utils.AWS_ACCOUNT_ID = None |
| 639 | + |
| 640 | + mock_harmony_client = MagicMock() |
| 641 | + mock_harmony_client.result_urls.return_value = iter([]) |
| 642 | + mock_get_harmony_client.return_value = mock_harmony_client |
| 643 | + |
| 644 | + harmony_job = {'job': 'valid-job-id', 'variable': 'temperature', 'output_crs': 'EPSG:4326'} |
| 645 | + result = process_harmony_results(harmony_job, 'UAT') |
| 646 | + assert result == [] |
| 647 | + |
| 648 | + |
| 649 | +@mock_sts |
| 650 | +@mock_s3 |
| 651 | +@patch('bignbit.utils.get_harmony_client') |
| 652 | +def test_process_harmony_results_all_variable_omitted(mock_get_harmony_client): |
| 653 | + """When variable is 'all', the 'variable' key is omitted from each file dict.""" |
| 654 | + bignbit.utils.AWS_ACCOUNT_ID = None |
| 655 | + |
| 656 | + s3_client = boto3.client('s3', region_name='us-west-2') |
| 657 | + bucket_name = 'test-harmony-bucket' |
| 658 | + s3_client.create_bucket( |
| 659 | + Bucket=bucket_name, |
| 660 | + CreateBucketConfiguration={'LocationConstraint': 'us-west-2'} |
| 661 | + ) |
| 662 | + image_key = 'path/to/result_image.png' |
| 663 | + s3_client.put_object(Bucket=bucket_name, Key=image_key, Body=b'fake image data') |
| 664 | + |
| 665 | + mock_harmony_client = MagicMock() |
| 666 | + mock_harmony_client.result_urls.return_value = iter([f's3://{bucket_name}/{image_key}']) |
| 667 | + mock_get_harmony_client.return_value = mock_harmony_client |
| 668 | + |
| 669 | + harmony_job = {'job': 'valid-job-id', 'variable': 'all', 'output_crs': 'EPSG:4326'} |
| 670 | + result = process_harmony_results(harmony_job, 'UAT') |
| 671 | + |
| 672 | + assert len(result) == 1 |
| 673 | + assert 'variable' not in result[0] |
| 674 | + assert result[0]['output_crs'] == 'EPSG:4326' |
| 675 | + assert result[0]['fileName'] == 'result_image.png' |
0 commit comments