Bläddra i källkod

Fix 9.0.0 Functions Error Code Regressions (#9862)

Paul Beusterien 3 år sedan
förälder
incheckning
1658c4051e

+ 5 - 0
FirebaseFunctions/Backend/index.js

@@ -108,6 +108,11 @@ exports.httpErrorTest = functions.https.onRequest((request, response) => {
   response.status(400).send();
 });
 
+// Regression test for https://github.com/firebase/firebase-ios-sdk/issues/9855
+exports.throwTest = functions.https.onCall((data) => {
+  throw new functions.https.HttpsError('invalid-argument', 'Invalid test requested.');
+});
+
 exports.timeoutTest = functions.https.onRequest((request, response) => {
   // Wait for longer than 500ms.
   setTimeout(() => response.send({data: true}), 500);

+ 1 - 0
FirebaseFunctions/Backend/start.sh

@@ -53,6 +53,7 @@ FUNCTIONS_BIN="./node_modules/.bin/functions"
 "${FUNCTIONS_BIN}" deploy unknownErrorTest --trigger-http
 "${FUNCTIONS_BIN}" deploy explicitErrorTest --trigger-http
 "${FUNCTIONS_BIN}" deploy httpErrorTest --trigger-http
+"${FUNCTIONS_BIN}" deploy throwTest --trigger-http
 "${FUNCTIONS_BIN}" deploy timeoutTest --trigger-http
 
 if [ "$1" != "synchronous" ]; then

+ 3 - 0
FirebaseFunctions/CHANGELOG.md

@@ -1,3 +1,6 @@
+# 9.2.0
+- [fixed] Fixed regressions in error code processing introduced in 9.0.0. (#9855)
+
 # 9.0.0
 - [changed] The FirebaseFunctionsSwift library has been removed. All of its APIs are now included
   in the FirebaseFunctions library. Please remove references to FirebaseFunctionsSwift from Podfiles

+ 6 - 8
FirebaseFunctions/Sources/FunctionsError.swift

@@ -143,11 +143,11 @@ extension FunctionsErrorCode {
   static func errorCode(forName name: String) -> FunctionsErrorCode {
     switch name {
     case "OK": return .OK
-    case "CANELLED": return .cancelled
-    case "UNKOWN": return .unknown
-    case "INVLID_ARGUMENT": return .invalidArgument
-    case "DEALINE_EXCEEDED": return .deadlineExceeded
-    case "NOTFOUND": return .notFound
+    case "CANCELLED": return .cancelled
+    case "UNKNOWN": return .unknown
+    case "INVALID_ARGUMENT": return .invalidArgument
+    case "DEADLINE_EXCEEDED": return .deadlineExceeded
+    case "NOT_FOUND": return .notFound
     case "ALREADY_EXISTS": return .notFound
     case "PERMISSION_DENIED": return .permissionDenied
     case "RESOURCE_EXHAUSTED": return .resourceExhausted
@@ -158,9 +158,7 @@ extension FunctionsErrorCode {
     case "INTERNAL": return .internal
     case "UNAVAILABLE": return .unavailable
     case "DATA_LOSS": return .dataLoss
-    case "UNATHENTICATED": return .unauthenticated
-    // TODO(review): The docs originally say that unknown should be returned if it doesn't match,
-    // but the implementation doesn't do that, it's optional. Let's make this internal.
+    case "UNAUTHENTICATED": return .unauthenticated
     default: return .internal
     }
   }

+ 56 - 0
FirebaseFunctions/Tests/Integration/IntegrationTests.swift

@@ -647,6 +647,62 @@ class IntegrationTests: XCTestCase {
     }
   #endif
 
+  func testThrowError() {
+    let byName = functions.httpsCallable(
+      "throwTest",
+      requestAs: [Int].self,
+      responseAs: Int.self
+    )
+    let byURL = functions.httpsCallable(
+      emulatorURL("throwTest"),
+      requestAs: [Int].self,
+      responseAs: Int.self
+    )
+    for function in [byName, byURL] {
+      let expectation = expectation(description: #function)
+      XCTAssertNotNil(function)
+      function.call([]) { result in
+        do {
+          _ = try result.get()
+        } catch {
+          let error = error as NSError
+          XCTAssertEqual(FunctionsErrorCode.invalidArgument.rawValue, error.code)
+          XCTAssertEqual(error.localizedDescription, "Invalid test requested.")
+          expectation.fulfill()
+          return
+        }
+        XCTFail("Failed to throw error for missing result")
+      }
+      waitForExpectations(timeout: 5)
+    }
+  }
+
+  #if compiler(>=5.5.2) && canImport(_Concurrency)
+    @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
+    func testThrowErrorAsync() async {
+      let byName = functions.httpsCallable(
+        "throwTest",
+        requestAs: [Int].self,
+        responseAs: Int.self
+      )
+      let byURL = functions.httpsCallable(
+        emulatorURL("throwTest"),
+        requestAs: [Int].self,
+        responseAs: Int.self
+      )
+      for function in [byName, byURL] {
+        do {
+          _ = try await function.call([])
+          XCTAssertFalse(true, "Failed to throw error for missing result")
+        } catch {
+          let error = error as NSError
+          XCTAssertEqual(FunctionsErrorCode.invalidArgument.rawValue, error.code)
+          XCTAssertEqual(error.localizedDescription, "Invalid test requested.")
+        }
+      }
+    }
+  #endif
+
   func testTimeout() {
     let byName = functions.httpsCallable(
       "timeoutTest",

+ 14 - 0
FirebaseFunctions/Tests/ObjCIntegration/FIRIntegrationTests.m

@@ -261,6 +261,20 @@ static NSString *const kDefaultProjectID = @"functions-integration-test";
   [self waitForExpectations:@[ expectation ] timeout:10];
 }
 
+// Regression test for https://github.com/firebase/firebase-ios-sdk/issues/9855
+- (void)testThrowTest {
+  XCTestExpectation *expectation = [[XCTestExpectation alloc] init];
+  FIRHTTPSCallable *function = [_functions HTTPSCallableWithName:@"throwTest"];
+  [function callWithObject:@{}
+                completion:^(FIRHTTPSCallableResult *_Nullable result, NSError *_Nullable error) {
+                  XCTAssertNotNil(error);
+                  XCTAssertEqual(FIRFunctionsErrorCodeInvalidArgument, error.code);
+                  XCTAssertEqualObjects(error.localizedDescription, @"Invalid test requested.");
+                  [expectation fulfill];
+                }];
+  [self waitForExpectations:@[ expectation ] timeout:10];
+}
+
 - (void)testTimeout {
   XCTestExpectation *expectation = [[XCTestExpectation alloc] init];
   FIRHTTPSCallable *function = [_functions HTTPSCallableWithName:@"timeoutTest"];