File: test-req-promise.R

package info (click to toggle)
r-cran-httr2 1.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,604 kB
  • sloc: sh: 21; makefile: 2
file content (136 lines) | stat: -rw-r--r-- 4,817 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
test_that("checks its inputs", {
  req <- request_test("/status/:status", status = 200)

  expect_snapshot(error = TRUE, {
    req_perform_promise(1)
    req_perform_promise(req, path = 1)
    req_perform_promise(req, pool = "INVALID")
    req_perform_promise(req, verbosity = "INVALID")
  })
})

test_that("returns a promise that resolves", {
  p1 <- req_perform_promise(request_test("/delay/:secs", secs = 0.25))
  p2 <- req_perform_promise(request_test("/delay/:secs", secs = 0.25))
  expect_s3_class(p1, "promise")
  expect_s3_class(p2, "promise")
  p1_value <- extract_promise(p1)
  expect_equal(resp_status(p1_value), 200)
  p2_value <- extract_promise(p2)
  expect_equal(resp_status(p2_value), 200)
})

test_that("correctly prepares request", {
  req <- request_test("/post") %>% req_method("POST")
  prom <- req_perform_promise(req)
  expect_no_error(extract_promise(prom))
})

test_that("correctly prepares request", {
  req <- request_test("/get")
  expect_snapshot(
    . <- extract_promise(req_perform_promise(req, verbosity = 1)),
    transform = function(x) {
      gsub("(Date|Host|User-Agent|ETag|Content-Length|Accept-Encoding): .*", "\\1: <variable>", x)
    }
  )
})

test_that("can promise to download files", {
  req <- request_test("/json")
  path <- withr::local_tempfile()
  p <- req_perform_promise(req, path)
  expect_s3_class(p, "promise")
  p_value <- extract_promise(p)
  expect_equal(p_value$body, new_path(path))

  # And check that something was downloaded
  expect_gt(file.size(path), 0)
})

test_that("promises can retrieve from cache", {
  req <- request("http://example.com") %>% req_cache(tempfile())
  resp <- response(200,
                   headers = "Expires: Wed, 01 Jan 3000 00:00:00 GMT",
                   body = charToRaw("abc")
  )
  cache_set(req, resp)

  p <- req_perform_promise(req)
  expect_s3_class(p, "promise")
  p_value <- extract_promise(p)
  expect_equal(p_value, resp)
})

test_that("both curl and HTTP errors in promises are rejected", {
  expect_error(
    extract_promise(
      req_perform_promise(request_test("/status/:status", status = 404))
    ),
    class = "httr2_http_404"
  )
  expect_error(
    extract_promise(
      req_perform_promise(request("INVALID"))
    ),
    class = "httr2_failure"
  )
})

test_that("req_perform_promise doesn't leave behind poller", {
  skip_if_not(later::loop_empty(), "later::global_loop not empty when test started")
  p <- req_perform_promise(request_test("/delay/:secs", secs = 0.25))
  # Before promise is resolved, there should be an operation in our later loop
  expect_false(later::loop_empty())
  p_value <- extract_promise(p)
  # But now that that our promise is resolved, we shouldn't still be polling the pool
  expect_true(later::loop_empty())
})


test_that("req_perform_promise can use non-default pool", {
  custom_pool <- curl::new_pool()
  p1 <- req_perform_promise(request_test("/delay/:secs", secs = 0.25))
  p2 <- req_perform_promise(request_test("/delay/:secs", secs = 0.25), pool = custom_pool)
  expect_equal(length(curl::multi_list(custom_pool)), 1)
  p1_value <- extract_promise(p1)
  expect_equal(resp_status(p1_value), 200)
  p2_value <- extract_promise(p2)
  expect_equal(resp_status(p2_value), 200)
})

test_that("req_perform_promise uses the default loop", {
  # The main reason for temp loops is to allow an asynchronous operation to be
  # created, waited on, and resolved/rejected inside of a synchronous function,
  # all without affecting any asynchronous operations that existed before the
  # temp loop was created.

  # This can't proceed within the temp loop
  p1 <- req_perform_promise(request_test("/delay/:secs", secs = 0.25))

  later::with_temp_loop({
    # You can create an async response with explicit pool=NULL, but it can't
    # proceed until the temp loop is over
    p2 <- req_perform_promise(request_test("/get"), pool = NULL)

    # You can create an async response with explicit pool=pool, and it can
    # proceed as long as that pool was first used inside of the temp loop
    p3 <- req_perform_promise(request_test("/get"), pool = curl::new_pool())

    # You can't create an async response in the temp loop without explicitly
    # specifying a pool
    expect_snapshot(p4 <- req_perform_promise(request_test("/get")), error = TRUE)

    # Like I said, you can create this, but it won't work until we get back
    # outside the temp loop
    expect_null(extract_promise(p2, timeout = 1))

    # This works fine inside the temp loop, because its pool was first used
    # inside
    expect_equal(resp_status(extract_promise(p3, timeout = 1)), 200)
  })

  # These work fine now that we're back outside the temp loop
  expect_equal(resp_status(extract_promise(p1, timeout = 1)), 200)
  expect_equal(resp_status(extract_promise(p2, timeout = 1)), 200)
})