Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce VCR recordModes #1

Merged
merged 3 commits into from
Jun 17, 2021
Merged

Introduce VCR recordModes #1

merged 3 commits into from
Jun 17, 2021

Conversation

jairmyree
Copy link

These changes add a recordingMode variable that is used to enforce environment settings without obscuring DVR's logic.

@@ -134,7 +139,7 @@ open class Session: URLSession {
}

func finishTask(_ task: URLSessionTask, interaction: Interaction, playback: Bool) {
needsPersistence = needsPersistence || !playback
needsPersistence = (needsPersistence || !playback) && recordMode != .all
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if recordMode == .all then needsPersistence would be false, but if .all is effectively our re-record, then I don't see how this works.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.all isn't re-record. .all is live. .once is record (and re-record). It's based off when I originally asked you about VCR having 4 playback modes while our TEST_MODE environment variable only has 3.
.all = live
.once = record
.none = playback
.newEpisode isn't used since we only have 3 TEST_MODE options

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should re-think our TEST_MODE options

@@ -181,7 +186,7 @@ open class Session: URLSession {
}

private func addTask(_ task: URLSessionTask) {
let shouldRecord = !recording
let shouldRecord = !recording && (recordMode == .newEpisodes || recordMode == .once)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the descriptions in Azure/azure-sdk-for-ios#906 I should think that if recordMode is .all it should also record.

Comment on lines 190 to 192
if shouldRecord {
beginRecording()
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to preserve this behavior where if you don't call "beginRecording" yourself it does it automagically only for that one request? Does Python behave that way? It seems wonky to me.

Comment on lines 62 to 69
if cassette != nil {
fatalError("[DVR] Invalid request. The request was not found in the cassette.")
}

// Cassette is missing. Record.
if session.recordingEnabled == false {
fatalError("[DVR] Recording is disabled.")
// Cassette is missing. Record.
if session.recordingEnabled == false {
fatalError("[DVR] Recording is disabled.")
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this pretty hard to reason about. I would suggest:

// interaction not found
if cassette !=nil {
   fatalError(... request not in cassette)
} else {
  // if request not found and recording is not enabled, error
  if session.recordingEnabled == false {
    fatalError(...)
  }
}

Of course, this assumes recordingEnabled is set property based on the recordMode.

queue.async {
completion(interaction.responseData, interaction.response, nil)

if session.recordMode == .none {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this works for the general case. The only recordMode in which you don't need to check for a matching interaction is .all because that always records. This will skip looking for a matching interaction for .once and .newEpisodes.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole block probably needs to be refactored in terms of the four record modes based on whether there is a cassette and whether there is a match:

  • .once = YES cassette, NO match => error; NO cassette => record
  • .newEpisodes = YES cassette, NO match => record; NO cassette => record
  • .none = YES cassette, NO match => error, NO cassette => error
  • all = always record

@jairmyree
Copy link
Author

I redid the PR. DVR now conforms the playback mode expectations set in VCR.
.all records new live tests.
.none will only run recorded tests.
.once will record if no recording exists and otherwise play the recording.
.newEpisodes will use recording when request is present and run live and record when it is not.

.once will fail if a recording exists but doesn't contain the current request.
.new episodes will re-persist all interactions (recorded and live) if and only if new requests are detected.
.all ignores recordings always and persists live requests.
.none will fail if request isn't in recording or if recording doesn't exist.

@jairmyree jairmyree requested a review from tjprescott June 17, 2021 14:39
Comment on lines 107 to 117
struct DVRError : Error , CustomStringConvertible {
let description : String

init(_ desc : String) {
description = desc
}

func throwError() throws {
throw self
}
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you planning to use this somewhere? Typically, Swift errors are enums.

Copy link
Owner

@tjprescott tjprescott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Thanks @jairmyree!

@tjprescott tjprescott merged commit 775c8a7 into tjprescott:main Jun 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants