From b538576d075a6733b1792923f2d7f68857016507 Mon Sep 17 00:00:00 2001 From: Alex Moinet Date: Mon, 15 May 2023 11:20:31 +0100 Subject: [PATCH] Adapt Android RN test fixture to work with BitBar (#1957) * Add naive start of config file implementation * Move implementation into kotlin for simplicity * Slight refactor for testing * Cut pipeline right down for testing * Add missing imports and variables * Work around missing references * Add log import * Fix syntax error * Remove invalid log * Add debug log * Add more debugging * Add more debugging * Use proper async await to return maze-runner address * Naive implementation of cocoa file reading * More debugging * Don't pass address back up to JS * Remove superfluous function * Remove invalid import * Fix redeclaration error * Add general bridging header import * Add separate interface for config loader * Attempt to use seperate bridging header location * Remove config reading from iOS RN test fixtures due to build issues * Add feedback and extra guards against missing endpoints * Revert changes to buildkite pipeline --- .../fixtures/app/scenario_js/app/App.js | 16 +++--- .../fixtures/ios-module/BugsnagModule.h | 1 - .../fixtures/ios-module/BugsnagModule.m | 17 +++++-- .../ios-module/ConfigFileReader.swift | 51 +++++++++++++++++++ .../reactnative/module/BugsnagModule.java | 11 ++-- .../reactnative/module/ConfigFileReader.kt | 45 ++++++++++++++++ 6 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 test/react-native/features/fixtures/ios-module/ConfigFileReader.swift create mode 100644 test/react-native/features/fixtures/reactnative/module/ConfigFileReader.kt diff --git a/test/react-native/features/fixtures/app/scenario_js/app/App.js b/test/react-native/features/fixtures/app/scenario_js/app/App.js index 9747702722..5210022cec 100644 --- a/test/react-native/features/fixtures/app/scenario_js/app/App.js +++ b/test/react-native/features/fixtures/app/scenario_js/app/App.js @@ -17,8 +17,8 @@ export default class App extends Component { currentScenario: '', scenarioMetaData: '', apiKey: '12312312312312312312312312312312', - notifyEndpoint: 'http://bs-local.com:9339/notify', - sessionsEndpoint: 'http://bs-local.com:9339/sessions' + notifyEndpoint: '', + sessionsEndpoint: '' } } @@ -27,14 +27,18 @@ export default class App extends Component { } getConfiguration = () => { - return { + var config = { apiKey: this.state.apiKey, - endpoints: { + autoTrackSessions: false + } + + if (this.state.notifyEndpoint && this.state.sessionsEndpoint) { + config.endpoints = { notify: this.state.notifyEndpoint, sessions: this.state.sessionsEndpoint - }, - autoTrackSessions: false + } } + return config } setScenario = newScenario => { diff --git a/test/react-native/features/fixtures/ios-module/BugsnagModule.h b/test/react-native/features/fixtures/ios-module/BugsnagModule.h index 8d6ec2f75f..25a4de378c 100644 --- a/test/react-native/features/fixtures/ios-module/BugsnagModule.h +++ b/test/react-native/features/fixtures/ios-module/BugsnagModule.h @@ -17,5 +17,4 @@ BugsnagConfiguration *createConfiguration(NSDictionary * options); @end - #endif /* BugsnagModule_h */ diff --git a/test/react-native/features/fixtures/ios-module/BugsnagModule.m b/test/react-native/features/fixtures/ios-module/BugsnagModule.m index a2f55ced49..97887f8282 100644 --- a/test/react-native/features/fixtures/ios-module/BugsnagModule.m +++ b/test/react-native/features/fixtures/ios-module/BugsnagModule.m @@ -55,10 +55,21 @@ @implementation BugsnagModule NSLog(@"key: %@, value: %@ \n", key, [options objectForKey:key]); } BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:options[@"apiKey"]]; - NSDictionary *endpointsIn = options[@"endpoints"]; - NSString *notifyEndpoint = endpointsIn[@"notify"]; - NSString *sessionsEndpoint = endpointsIn[@"sessions"]; + NSString *notifyEndpoint; + NSString *sessionsEndpoint; + if (options[@"endpoints"] != nil && options[@"endpoints"][@"notify"] != nil && options[@"endpoints"][@"sessions"] != nil) { + NSDictionary *endpointsIn = options[@"endpoints"]; + notifyEndpoint = endpointsIn[@"notify"]; + sessionsEndpoint = endpointsIn[@"sessions"]; + } else { + NSString *baseAddress = @"bs-local.com:9339"; + notifyEndpoint = [NSString stringWithFormat:@"http://%@/notify", baseAddress]; + sessionsEndpoint = [NSString stringWithFormat:@"http://%@/sessions", baseAddress]; + } + NSLog(@"Notify endpoint set to: %@\n", notifyEndpoint); + NSLog(@"Sessions endpoint set to: %@\n", sessionsEndpoint); BugsnagEndpointConfiguration *endpoints = [[BugsnagEndpointConfiguration alloc] initWithNotify:notifyEndpoint sessions:sessionsEndpoint]; + [config setEndpoints:endpoints]; [config setAutoTrackSessions:[[options objectForKey:@"autoTrackSessions"]boolValue]]; config.enabledErrorTypes.ooms = NO; // Set by default, will add an override as required diff --git a/test/react-native/features/fixtures/ios-module/ConfigFileReader.swift b/test/react-native/features/fixtures/ios-module/ConfigFileReader.swift new file mode 100644 index 0000000000..c54ec252da --- /dev/null +++ b/test/react-native/features/fixtures/ios-module/ConfigFileReader.swift @@ -0,0 +1,51 @@ +// +// ConfigFileReader.swift +// reactnative +// +// Created by Alex Moinet on 04/05/2023. +// Copyright © 2023 Facebook. All rights reserved. +// + +import Foundation + +class FixtureConfig: Codable { + var maze_address: String +} + +class ConfigFileReader:NSObject { + func loadMazeRunnerAddress() -> String { + let bsAddress = "http://bs-local.com:9339" + + // Only iOS 12 and above will run on BitBar for now + if #available(iOS 12.0, *) {} else { + return bsAddress; + } + + for _ in 1...60 { + let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + + NSLog("Reading Maze Runner address from fixture_config.json") + do { + let fileUrl = URL(fileURLWithPath: "fixture_config", + relativeTo: documentsUrl).appendingPathExtension("json") + let savedData = try Data(contentsOf: fileUrl) + if let contents = String(data: savedData, encoding: .utf8) { + let decoder = JSONDecoder() + let jsonData = contents.data(using: .utf8) + let config = try decoder.decode(FixtureConfig.self, from: jsonData!) + let address = "http://" + config.maze_address + NSLog("Using Maze Runner address: " + address) + return address + } + } + catch let error as NSError { + NSLog("Failed to read fixture_config.json: \(error)") + } + NSLog("Waiting for fixture_config.json to appear") + sleep(1) + } + + NSLog("Unable to read from fixture_config.json, defaulting to BrowserStack environment") + return bsAddress; + } +} diff --git a/test/react-native/features/fixtures/reactnative/module/BugsnagModule.java b/test/react-native/features/fixtures/reactnative/module/BugsnagModule.java index 802d286536..2641ccbe25 100644 --- a/test/react-native/features/fixtures/reactnative/module/BugsnagModule.java +++ b/test/react-native/features/fixtures/reactnative/module/BugsnagModule.java @@ -123,12 +123,15 @@ private Configuration createConfiguration(ReadableMap options) { Configuration config = new Configuration(options.getString("apiKey")); config.setAutoTrackSessions(options.getBoolean("autoTrackSessions")); - if (options.hasKey("endpoint")) { - config.setEndpoints(new EndpointConfiguration(options.getString("endpoint"), options.getString("endpoint"))); - } - else if (options.hasKey("endpoints")) { + if (options.hasKey("endpoints")) { ReadableMap endpoints = options.getMap("endpoints"); config.setEndpoints(new EndpointConfiguration(endpoints.getString("notify"), endpoints.getString("sessions"))); + } else { + ConfigFileReader configReader = new ConfigFileReader(); + String mazeAddress = configReader.getMazeRunnerAddress(reactContext); + String notifyEndpoint = "http://" + mazeAddress + "/notify"; + String sessionEndpoint = "http://" + mazeAddress + "/sessions"; + config.setEndpoints(new EndpointConfiguration(notifyEndpoint, sessionEndpoint)); } if (options.hasKey("appVersion")) { diff --git a/test/react-native/features/fixtures/reactnative/module/ConfigFileReader.kt b/test/react-native/features/fixtures/reactnative/module/ConfigFileReader.kt new file mode 100644 index 0000000000..f1dbd4d592 --- /dev/null +++ b/test/react-native/features/fixtures/reactnative/module/ConfigFileReader.kt @@ -0,0 +1,45 @@ +package com.reactnative.module + +import android.content.Context +import android.util.Log +import org.json.JSONObject +import java.io.File +import java.io.IOException + +const val CONFIG_FILE_TIMEOUT = 5000 + +class ConfigFileReader { + + fun getMazeRunnerAddress(context: Context): String { + val externalFilesDir = context.getExternalFilesDir(null) + val configFile = File(externalFilesDir, "fixture_config.json") + var mazeAddress: String? = null + Log.i("Bugsnag", "Attempting to read Maze Runner address from config file ${configFile.path}") + + // Poll for the fixture config file + val pollEnd = System.currentTimeMillis() + CONFIG_FILE_TIMEOUT + while (System.currentTimeMillis() < pollEnd) { + if (configFile.exists()) { + val fileContents = configFile.readText() + val fixtureConfig = runCatching { JSONObject(fileContents) }.getOrNull() + mazeAddress = getStringSafely(fixtureConfig, "maze_address") + if (!mazeAddress.isNullOrBlank()) { + Log.i("Bugsnag", "Maze Runner address set from config file: $mazeAddress") + break + } + } + + Thread.sleep(250) + } + if (mazeAddress.isNullOrBlank()) { + Log.i("Bugsnag", "Failed to read Maze Runner address from config file, reverting to legacy address") + mazeAddress = "bs-local.com:9339" + } + return mazeAddress + } + + private fun getStringSafely(jsonObject: JSONObject?, key: String): String { + return jsonObject?.optString(key) ?: "" + } + +}