\n \n By clicking the Log In button above,
+ you are acknowledging that all Earthdata Login applications running in DAACs \n will have
+ access to my profile information. \n \n
\n
\n
\n \n
+ \ Protection and maintenance of user profile information is described
+ in\n NASA's
+ Web Privacy Policy.\n \n
\n
\n
\n
+ \
\n \n Protection and maintenance of user profile
+ information is described in\n NASA's
+ Web Privacy Policy.\n \n
\n
\n
\n
+ \ \n US Govt Property. Unauthorized use subject to prosecution.
+ Use subject to monitoring per\n NPD2810.\n
+ \ \n
\n
\n \n
\n
\n \n\n \n
+ \ \n \n
+ \ \n
+ \ \n
+ \ \n\n \n \n
+ \ \n\n \n \n\n"
+ headers:
+ Cache-Control:
+ - no-store
+ Connection:
+ - keep-alive
+ Content-Type:
+ - text/html; charset=utf-8
+ Date:
+ - Tue, 09 Apr 2024 21:58:55 GMT
+ ETag:
+ - W/"7af405988c901d45ff1b80e3d54e85fa"
+ Expires:
+ - Fri, 01 Jan 1990 00:00:00 GMT
+ Pragma:
+ - no-cache
+ Referrer-Policy:
+ - strict-origin-when-cross-origin
+ Server:
+ - nginx/1.22.1
+ Set-Cookie:
+ - _urs-gui_session=abd23c587ce267b8c84ef154346028b0; path=/; expires=Wed, 10
+ Apr 2024 21:58:55 GMT; HttpOnly
+ Strict-Transport-Security:
+ - max-age=31536000
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept
+ X-Content-Type-Options:
+ - nosniff
+ X-Download-Options:
+ - noopen
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Permitted-Cross-Domain-Policies:
+ - none
+ X-Request-Id:
+ - a5f4494f-83d0-40cc-a966-a45d47155163
+ X-Runtime:
+ - '0.012801'
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '9058'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Connection:
+ - keep-alive
+ method: GET
+ uri: https://cmr.earthdata.nasa.gov/search/granules.umm_json?short_name=SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205&temporal%5B%5D=2020-01-01T00:00:00Z,2022-01-01T00:00:00Z&page_size=0
+ response:
+ body:
+ string: '{"hits":147,"took":55,"items":[]}'
+ headers:
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - CMR-Hits, CMR-Request-Id, X-Request-Id, CMR-Scroll-Id, CMR-Search-After, CMR-Timed-Out,
+ CMR-Shapefile-Original-Point-Count, CMR-Shapefile-Simplified-Point-Count
+ CMR-Hits:
+ - '147'
+ CMR-Request-Id:
+ - c8f9b01d-a6a3-4809-8a65-e707f30b3d47
+ CMR-Took:
+ - '55'
+ Connection:
+ - keep-alive
+ Content-MD5:
+ - 376935be7b2a0e96352603908fe0dcd5
+ Content-SHA1:
+ - b02f8a240f36ad8cd6798334ce2455c338e6d55f
+ Content-Type:
+ - application/vnd.nasa.cmr.umm_results+json;version=1.6.5; charset=utf-8
+ Date:
+ - Tue, 09 Apr 2024 21:58:56 GMT
+ Server:
+ - ServerTokens ProductOnly
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept-Encoding, User-Agent
+ Via:
+ - 1.1 f300b5f0c0ff51593fb31953294424c0.cloudfront.net (CloudFront)
+ X-Amz-Cf-Id:
+ - 6UKqbnR1dCiMWGTDKFtLjE_KomjiZXUhp0ICfljulkAzPCeqJgb3cw==
+ X-Amz-Cf-Pop:
+ - PHL51-P1
+ X-Cache:
+ - Miss from cloudfront
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Request-Id:
+ - 6UKqbnR1dCiMWGTDKFtLjE_KomjiZXUhp0ICfljulkAzPCeqJgb3cw==
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '33'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Connection:
+ - keep-alive
+ method: GET
+ uri: https://cmr.earthdata.nasa.gov/search/granules.umm_json?short_name=SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205&temporal%5B%5D=2020-01-01T00:00:00Z,2022-01-01T00:00:00Z&page_size=1
+ response:
+ body:
+ string: '{"hits":147,"took":253,"items":[{"meta":{"concept-type":"granule","concept-id":"G2546526969-POCLOUD","revision-id":2,"native-id":"ssh_grids_v2205_2020010212","collection-concept-id":"C2270392799-POCLOUD","provider-id":"POCLOUD","format":"application/vnd.nasa.cmr.umm+json","revision-date":"2023-01-11T00:16:28.862Z"},"umm":{"TemporalExtent":{"RangeDateTime":{"EndingDateTime":"2020-01-02T00:00:00.000Z","BeginningDateTime":"2020-01-02T00:00:00.000Z"}},"MetadataSpecification":{"URL":"https://cdn.earthdata.nasa.gov/umm/granule/v1.6.5","Name":"UMM-G","Version":"1.6.5"},"GranuleUR":"ssh_grids_v2205_2020010212","ProviderDates":[{"Type":"Insert","Date":"2023-01-11T00:16:13.878Z"},{"Type":"Update","Date":"2023-01-11T00:16:13.878Z"}],"SpatialExtent":{"HorizontalSpatialDomain":{"Geometry":{"BoundingRectangles":[{"WestBoundingCoordinate":0.083,"SouthBoundingCoordinate":-79.917,"EastBoundingCoordinate":180,"NorthBoundingCoordinate":79.917},{"WestBoundingCoordinate":-180,"SouthBoundingCoordinate":-79.917,"EastBoundingCoordinate":-0.083,"NorthBoundingCoordinate":79.917}]}}},"DataGranule":{"ArchiveAndDistributionInformation":[{"SizeUnit":"MB","Size":9.246453285217285,"Checksum":{"Value":"9002febf17632e5921eba5b8f62237e6","Algorithm":"MD5"},"SizeInBytes":9695609,"Name":"ssh_grids_v2205_2020010212.nc"},{"SizeUnit":"MB","Size":6.008148193359375E-5,"Checksum":{"Value":"b0c271019f89f876b2d3c0a9c46b8f77","Algorithm":"MD5"},"SizeInBytes":63,"Name":"ssh_grids_v2205_2020010212.nc.md5"}],"DayNightFlag":"Unspecified","ProductionDateTime":"2022-10-30T20:57:22.377Z"},"CollectionReference":{"Version":"2205","ShortName":"SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205"},"RelatedUrls":[{"URL":"https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc.md5","Description":"Download
+ ssh_grids_v2205_2020010212.nc.md5","Type":"EXTENDED METADATA"},{"URL":"s3://podaac-ops-cumulus-public/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc.md5","Description":"This
+ link provides direct download access via S3 to the granule","Type":"EXTENDED
+ METADATA"},{"URL":"https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc","Description":"Download
+ ssh_grids_v2205_2020010212.nc","Type":"GET DATA"},{"URL":"s3://podaac-ops-cumulus-protected/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc","Description":"This
+ link provides direct download access via S3 to the granule","Type":"GET DATA
+ VIA DIRECT ACCESS"},{"URL":"https://archive.podaac.earthdata.nasa.gov/s3credentials","Description":"api
+ endpoint to retrieve temporary credentials valid for same-region direct s3
+ access","Type":"VIEW RELATED INFORMATION"},{"URL":"https://opendap.earthdata.nasa.gov/collections/C2270392799-POCLOUD/granules/ssh_grids_v2205_2020010212","Type":"USE
+ SERVICE API","Subtype":"OPENDAP DATA","Description":"OPeNDAP request URL"}]}}]}'
+ headers:
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - CMR-Hits, CMR-Request-Id, X-Request-Id, CMR-Scroll-Id, CMR-Search-After, CMR-Timed-Out,
+ CMR-Shapefile-Original-Point-Count, CMR-Shapefile-Simplified-Point-Count
+ CMR-Hits:
+ - '147'
+ CMR-Request-Id:
+ - 59762a2f-23b9-45a2-a99b-be84748be0e5
+ CMR-Search-After:
+ - '["pocloud",1577923200000,2546526969]'
+ CMR-Took:
+ - '254'
+ Connection:
+ - keep-alive
+ Content-MD5:
+ - 53cf1a1f972e393a32e3cd15ec36f700
+ Content-SHA1:
+ - 60c47f03299dda570448eaecfbd8b3ed10f7bd5a
+ Content-Type:
+ - application/vnd.nasa.cmr.umm_results+json;version=1.6.5; charset=utf-8
+ Date:
+ - Tue, 09 Apr 2024 21:58:56 GMT
+ Server:
+ - ServerTokens ProductOnly
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept-Encoding, User-Agent
+ Via:
+ - 1.1 f300b5f0c0ff51593fb31953294424c0.cloudfront.net (CloudFront)
+ X-Amz-Cf-Id:
+ - N9NqPFJ1jWMYiNKZDyuZ71_auV8xRiEL-06uHzn3q2PrTU66FCOKFA==
+ X-Amz-Cf-Pop:
+ - PHL51-P1
+ X-Cache:
+ - Miss from cloudfront
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Request-Id:
+ - N9NqPFJ1jWMYiNKZDyuZ71_auV8xRiEL-06uHzn3q2PrTU66FCOKFA==
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '3092'
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/tests/unit/fixtures/vcr_cassettes/MOD02QKM_2000.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get.yaml
similarity index 100%
rename from tests/unit/fixtures/vcr_cassettes/MOD02QKM_2000.yaml
rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get.yaml
diff --git a/tests/unit/fixtures/vcr_cassettes/TELLUS_GRAC.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_less_than_2k.yaml
similarity index 100%
rename from tests/unit/fixtures/vcr_cassettes/TELLUS_GRAC.yaml
rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_less_than_2k.yaml
diff --git a/tests/unit/fixtures/vcr_cassettes/CYGNSS.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_more_than_2k.yaml
similarity index 100%
rename from tests/unit/fixtures/vcr_cassettes/CYGNSS.yaml
rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_more_than_2k.yaml
diff --git a/tests/unit/fixtures/vcr_cassettes/MOD02QKM.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get_more_than_2000.yaml
similarity index 100%
rename from tests/unit/fixtures/vcr_cassettes/MOD02QKM.yaml
rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get_more_than_2000.yaml
diff --git a/tests/unit/test_results.py b/tests/unit/test_results.py
index 06f8256d..2113ada5 100644
--- a/tests/unit/test_results.py
+++ b/tests/unit/test_results.py
@@ -1,26 +1,15 @@
import logging
-import unittest
import earthaccess
-import vcr
from earthaccess.search import DataCollections
-my_vcr = vcr.VCR(
- record_mode="once",
- decode_compressed_response=True,
- # Header matching is not set by default, we need that to test the
- # search-after functionality is performing correctly.
- match_on=["method", "scheme", "host", "port", "path", "query", "headers"],
-)
+from vcr.unittest import VCRTestCase # type: ignore[import-untyped]
logging.basicConfig()
-vcr_log = logging.getLogger("vcr")
-vcr_log.setLevel(logging.ERROR)
+logging.getLogger("vcr").setLevel(logging.ERROR)
-headers_to_filters = ["authorization", "Set-Cookie", "User-Agent", "Accept-Encoding"]
-
-def assert_unique_results(results):
+def unique_results(results):
"""
When we invoke a search request multiple times we want to ensure that we don't
get the same results back. This is a one shot test as the results are preserved
@@ -30,7 +19,31 @@ def assert_unique_results(results):
return len(unique_concept_ids) == len(results)
-class TestResults(unittest.TestCase):
+class TestResults(VCRTestCase):
+ def _get_vcr(self, **kwargs):
+ myvcr = super(TestResults, self)._get_vcr(**kwargs)
+ myvcr.cassette_library_dir = "tests/unit/fixtures/vcr_cassettes"
+ myvcr.decode_compressed_response = True
+ # Header matching is not set by default, we need that to test the
+ # search-after functionality is performing correctly.
+ myvcr.match_on = [
+ "method",
+ "scheme",
+ "host",
+ "port",
+ "path",
+ "query",
+ "headers",
+ ]
+ myvcr.filter_headers = [
+ "Accept-Encoding",
+ "Authorization",
+ "Set-Cookie",
+ "User-Agent",
+ ]
+
+ return myvcr
+
def test_data_links(self):
granules = earthaccess.search_data(
short_name="SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205",
@@ -58,18 +71,12 @@ def test_get_more_than_2000(self):
then we expect multiple invocations of a cmr granule search and
to not fetch back more results than we ask for
"""
- with my_vcr.use_cassette(
- "tests/unit/fixtures/vcr_cassettes/MOD02QKM.yaml",
- filter_headers=headers_to_filters,
- ) as cass:
- granules = earthaccess.search_data(short_name="MOD02QKM", count=3000)
-
- self.assertEqual(len(granules), 4000)
+ granules = earthaccess.search_data(short_name="MOD02QKM", count=3000)
- # Assert that we performed one 'hits' search and two 'results' search queries
- self.assertEqual(len(cass), 3)
-
- assert_unique_results(granules)
+ # Assert that we performed one 'hits' search and two 'results' search queries
+ self.assertEqual(len(self.cassette), 3)
+ self.assertEqual(len(granules), 4000)
+ self.assertTrue(unique_results(granules))
def test_get(self):
"""
@@ -77,18 +84,12 @@ def test_get(self):
to get the maximum no. of granules from a single CMR call (2000)
in a single request
"""
- with my_vcr.use_cassette(
- "tests/unit/fixtures/vcr_cassettes/MOD02QKM_2000.yaml",
- filter_headers=headers_to_filters,
- ) as cass:
- granules = earthaccess.search_data(short_name="MOD02QKM", count=2000)
-
- self.assertEqual(len(granules), 2000)
-
- # Assert that we performed one 'hits' search and one 'results' search queries
- self.assertEqual(len(cass), 2)
+ granules = earthaccess.search_data(short_name="MOD02QKM", count=2000)
- assert_unique_results(granules)
+ # Assert that we performed one 'hits' search and one 'results' search queries
+ self.assertEqual(len(self.cassette), 2)
+ self.assertEqual(len(granules), 2000)
+ self.assertTrue(unique_results(granules))
def test_get_all_less_than_2k(self):
"""
@@ -96,20 +97,14 @@ def test_get_all_less_than_2k(self):
invocations of a cmr granule search and
to not fetch back more results than we ask for
"""
- with my_vcr.use_cassette(
- "tests/unit/fixtures/vcr_cassettes/TELLUS_GRAC.yaml",
- filter_headers=headers_to_filters,
- ) as cass:
- granules = earthaccess.search_data(
- short_name="TELLUS_GRAC_L3_JPL_RL06_LND_v04", count=2000
- )
-
- self.assertEqual(len(granules), 163)
-
- # Assert that we performed a hits query and one search results query
- self.assertEqual(len(cass), 2)
+ granules = earthaccess.search_data(
+ short_name="TELLUS_GRAC_L3_JPL_RL06_LND_v04", count=2000
+ )
- assert_unique_results(granules)
+ # Assert that we performed a hits query and one search results query
+ self.assertEqual(len(self.cassette), 2)
+ self.assertEqual(len(granules), 163)
+ self.assertTrue(unique_results(granules))
def test_get_all_more_than_2k(self):
"""
@@ -117,20 +112,14 @@ def test_get_all_more_than_2k(self):
invocations of a cmr granule search and
to not fetch back more results than we ask for
"""
- with my_vcr.use_cassette(
- "tests/unit/fixtures/vcr_cassettes/CYGNSS.yaml",
- filter_headers=headers_to_filters,
- ) as cass:
- granules = earthaccess.search_data(
- short_name="CYGNSS_NOAA_L2_SWSP_25KM_V1.2", count=3000
- )
-
- self.assertEqual(len(granules), 2520)
-
- # Assert that we performed a hits query and two search results queries
- self.assertEqual(len(cass), 3)
+ granules = earthaccess.search_data(
+ short_name="CYGNSS_NOAA_L2_SWSP_25KM_V1.2", count=3000
+ )
- assert_unique_results(granules)
+ # Assert that we performed a hits query and two search results queries
+ self.assertEqual(len(self.cassette), 3)
+ self.assertEqual(len(granules), 2520)
+ self.assertTrue(unique_results(granules))
def test_collections_less_than_2k(self):
"""
@@ -138,21 +127,14 @@ def test_collections_less_than_2k(self):
invocations of a cmr granule search and
to not fetch back more results than we ask for
"""
- with my_vcr.use_cassette(
- "tests/unit/fixtures/vcr_cassettes/PODAAC.yaml",
- filter_headers=headers_to_filters,
- ) as cass:
- query = DataCollections().daac("PODAAC").cloud_hosted(True)
- collections = query.get(20)
-
- self.assertEqual(len(collections), 20)
-
- # Assert that we performed a single search results query
- self.assertEqual(len(cass), 1)
+ query = DataCollections().daac("PODAAC").cloud_hosted(True)
+ collections = query.get(20)
- assert_unique_results(collections)
-
- self.is_using_search_after(cass)
+ # Assert that we performed a single search results query
+ self.assertEqual(len(self.cassette), 1)
+ self.assertEqual(len(collections), 20)
+ self.assertTrue(unique_results(collections))
+ self.assert_is_using_search_after(self.cassette)
def test_collections_more_than_2k(self):
"""
@@ -160,30 +142,21 @@ def test_collections_more_than_2k(self):
invocations of a cmr granule search and
to not fetch back more results than we ask for
"""
- with my_vcr.use_cassette(
- "tests/unit/fixtures/vcr_cassettes/ALL.yaml",
- filter_headers=headers_to_filters,
- ) as cass:
- query = DataCollections()
- collections = query.get(3000)
-
- self.assertEqual(len(collections), 4000)
-
- # Assert that we performed two search results queries
- self.assertEqual(len(cass), 2)
+ query = DataCollections()
+ collections = query.get(3000)
- assert_unique_results(collections)
+ # Assert that we performed two search results queries
+ self.assertEqual(len(self.cassette), 2)
+ self.assertEqual(len(collections), 4000)
+ self.assertTrue(unique_results(collections))
+ self.assert_is_using_search_after(self.cassette)
- self.is_using_search_after(cass)
-
- def is_using_search_after(self, cass):
- # Verify the page no. was not used
+ def assert_is_using_search_after(self, cass):
first_request = True
+
for request in cass.requests:
+ # Verify the page number was not used
self.assertTrue("page_num" not in request.uri)
# Verify that Search After was used in all requests except first
- if first_request:
- self.assertFalse("CMR-Search-After" in request.headers)
- else:
- self.assertTrue("CMR-Search-After" in request.headers)
+ self.assertEqual(first_request, "CMR-Search-After" not in request.headers)
first_request = False