diff --git a/.github/patches/apply_flutter_3.44_source_patches.sh b/.github/patches/apply_flutter_3.44_source_patches.sh index 2b4bfcc0d..0f40ddd5c 100644 --- a/.github/patches/apply_flutter_3.44_source_patches.sh +++ b/.github/patches/apply_flutter_3.44_source_patches.sh @@ -2,19 +2,22 @@ # Applies the Flutter 3.44-only source/pubspec changes on the fly, in CI only. # # Windows arm64 needs Flutter >= 3.44 (the first stable release shipping an arm64 Dart SDK + -# engine), which renamed DialogTheme/TabBarTheme -> *Data and needs newer extended_text/ -# google_fonts. Every other platform is still on Flutter 3.24.5, where the old names/versions -# are required, so these changes are kept OUT of the committed sources and applied here instead. +# engine), and macOS arm64 builds with 3.44 for its NSTextInputContext crash fix +# (https://github.com/rustdesk/rustdesk/issues/16817). 3.44 renamed DialogTheme/TabBarTheme -> +# *Data and needs newer extended_text/google_fonts. Every other platform is still on Flutter +# 3.24.5, where the old names/versions are required, so these changes are kept OUT of the +# committed sources and applied here instead. # -# Used by BOTH the Windows arm64 build (flutter-build.yml) and its dedicated bridge artifact -# (bridge.yml) so they share an identical 3.44 source state -- the generated *.freezed.dart must -# compile against the same Flutter/freezed version the arm64 build resolves. +# Used by BOTH arm64 builds (flutter-build.yml) and their shared bridge artifact (bridge.yml) so +# they share an identical 3.44 source state -- the generated *.freezed.dart must compile against +# the same Flutter/freezed version the arm64 builds resolve. # # Remove this script (and commit the changes) once upstream bumps Flutter across the board. # # Run from the repository root. sed is used (not a git-apply patch) because the checked-out # sources are CRLF on the windows-11-arm runner; the substitutions below are anchor-free and -# therefore CRLF-safe. +# therefore CRLF-safe. The calls are GNU sed (`sed -i` without a suffix); the macOS arm64 job +# puts GNU sed first on PATH because BSD sed rejects them. set -euo pipefail readonly NO_MATCHES=0 diff --git a/.github/workflows/bridge.yml b/.github/workflows/bridge.yml index 9d31399c8..940e1a332 100644 --- a/.github/workflows/bridge.yml +++ b/.github/workflows/bridge.yml @@ -25,7 +25,7 @@ jobs: flutter-version: "3.22.3", artifact-name: "bridge-artifact", } - # Dedicated bridge for the Windows arm64 build (Flutter 3.44); runs in parallel. + # Dedicated bridge for the Windows and macOS arm64 builds (Flutter 3.44); runs in parallel. - { target: x86_64-unknown-linux-gnu, os: ubuntu-22.04, @@ -92,8 +92,8 @@ jobs: # Default Flutter 3.22.3: extended_text 14 needs a newer Dart, so downgrade for resolution. sed -i -e 's/extended_text: 14.0.0/extended_text: 13.0.0/g' flutter/pubspec.yaml else - # Flutter 3.44 bridge for Windows arm64: match that build's source/pubspec state so the - # generated *.freezed.dart compiles against the same Flutter/freezed it resolves. + # Flutter 3.44 bridge for Windows/macOS arm64: match those builds' source/pubspec state so + # the generated *.freezed.dart compiles against the same Flutter/freezed they resolve. bash .github/patches/apply_flutter_3.44_source_patches.sh fi pushd flutter && flutter pub get && popd diff --git a/.github/workflows/flutter-build.yml b/.github/workflows/flutter-build.yml index 4850efd7b..964c11e9d 100644 --- a/.github/workflows/flutter-build.yml +++ b/.github/workflows/flutter-build.yml @@ -31,10 +31,15 @@ env: FLUTTER_VERSION: "3.24.5" ANDROID_FLUTTER_VERSION: "3.24.5" # Windows arm64 only: the first stable Flutter to ship a native arm64 Windows Dart SDK + - # engine is 3.44. Every other platform stays on FLUTTER_VERSION (3.24.5) until Windows 7 - # support is restored after the upstream-wide Flutter bump. The arm64 job patches the few - # 3.44-only source/pubspec changes on the fly (see "Patch RustDesk sources for Flutter 3.44"). + # engine is 3.44. Every other platform except macOS arm64 (below) stays on FLUTTER_VERSION + # (3.24.5) until Windows 7 support is restored after the upstream-wide Flutter bump. The 3.44 + # jobs patch the few 3.44-only source/pubspec changes on the fly (see "Patch RustDesk sources + # for Flutter 3.44"). FLUTTER_WINDOWS_ARM_VERSION: "3.44.9" + # macOS arm64 only: 3.24.5's engine crashes in attributedSubstringForProposedRange + # (https://github.com/rustdesk/rustdesk/issues/16817, https://github.com/flutter/flutter/issues/153157). + # x86_64 stays on FLUTTER_VERSION: 3.44's FlutterMacOS needs macOS 10.15 there, and it targets 10.14. + FLUTTER_MACOS_ARM_VERSION: "3.44.9" # for arm64 linux because official Dart SDK does not work FLUTTER_ELINUX_VERSION: "3.16.9" TAG_NAME: "${{ inputs.upload-tag }}" @@ -273,8 +278,9 @@ jobs: fi - name: Patch RustDesk sources for Flutter 3.44 (arm64) - # arm64 is the only target on Flutter 3.44; apply its source/pubspec deltas on the fly - # (shared with the 3.44 bridge job) so the committed sources stay on Flutter 3.24.5. + # arm64 is on Flutter 3.44 (as is macOS arm64); apply its source/pubspec deltas on the fly + # (shared with the macOS arm64 build and the 3.44 bridge job) so the committed sources + # stay on Flutter 3.24.5. # `flutter build` then runs `pub get`, regenerating pubspec.lock for the bumped deps. if: ${{ matrix.job.arch == 'aarch64' }} shell: bash @@ -1004,9 +1010,17 @@ jobs: uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 with: channel: "stable" - flutter-version: ${{ env.FLUTTER_VERSION }} + flutter-version: ${{ matrix.job.arch == 'aarch64' && env.FLUTTER_MACOS_ARM_VERSION || env.FLUTTER_VERSION }} + + - name: Keep CocoaPods for Flutter 3.44 (arm64) + # 3.44 turns on Swift Package Manager by default, which would migrate Runner.xcodeproj and + # move some plugins off CocoaPods; every plugin still ships a podspec. + if: ${{ matrix.job.arch == 'aarch64' }} + run: flutter config --no-enable-swift-package-manager - name: Patch flutter + # Flutter 3.44 (arm64) already has this dropdown fix. + if: ${{ matrix.job.arch == 'x86_64' }} run: | cd $(dirname $(dirname $(which flutter))) if [[ "3.24.5" == ${{env.FLUTTER_VERSION}} ]]; then @@ -1021,6 +1035,15 @@ jobs: sed -i -e 's/_setFramesEnabledState(false);/\/\/_setFramesEnabledState(false);/g' ../packages/flutter/lib/src/scheduler/binding.dart grep -n '_setFramesEnabledState(false);' ../packages/flutter/lib/src/scheduler/binding.dart + - name: Patch RustDesk sources for Flutter 3.44 (arm64) + # The script uses GNU `sed -i`, which macOS's BSD sed rejects. + if: ${{ matrix.job.arch == 'aarch64' }} + shell: bash + run: | + brew install gnu-sed + export PATH="$(brew --prefix gnu-sed)/libexec/gnubin:$PATH" + bash .github/patches/apply_flutter_3.44_source_patches.sh + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 with: @@ -1035,11 +1058,13 @@ jobs: - name: Restore bridge files uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: bridge-artifact + # arm64's *.freezed.dart must match the freezed it resolves under Flutter 3.44. + name: ${{ matrix.job.arch == 'aarch64' && 'bridge-artifact-flutter-3.44' || 'bridge-artifact' }} path: ./ - name: Run the Dart tests - if: ${{ !inputs.upload-artifact && matrix.job.arch == 'aarch64' }} + # x86_64 tests the Flutter 3.24.5 sources most platforms ship, arm64 the patched 3.44 ones. + if: ${{ !inputs.upload-artifact }} working-directory: flutter run: flutter test --timeout 60s diff --git a/Cargo.toml b/Cargo.toml index 100258694..4388fb062 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -273,7 +273,7 @@ os-version = "0.2" [dev-dependencies] hound = "3.5" docopt = "1.1" -tokio = "1.44" +tokio = { version = "1.44", features = ["test-util"] } [package.metadata.bundle] name = "RustDesk" diff --git a/src/common.rs b/src/common.rs index 53831cc5f..c5f0ec573 100644 --- a/src/common.rs +++ b/src/common.rs @@ -3087,7 +3087,6 @@ mod tests { self, time::{interval, interval_at, sleep, Duration, Instant, Interval}, }; - use std::collections::HashSet; #[test] fn parses_stable_rustdesk_release_url() { @@ -3135,16 +3134,6 @@ mod tests { } } - #[inline] - fn get_timestamp_secs() -> u128 { - (std::time::SystemTime::UNIX_EPOCH - .elapsed() - .unwrap() - .as_millis() - + 500) - / 1000 - } - fn interval_maker() -> Interval { interval(Duration::from_secs(1)) } @@ -3211,9 +3200,10 @@ mod tests { } } - // ThrottledInterval tick less times than tokio interval, if there're sleeps + // ThrottledInterval tick less times than tokio interval, if there're sleeps. + // The clock is paused, so a stalled runner cannot make two ticks look close together. #[allow(non_snake_case)] - #[tokio::test] + #[tokio::test(start_paused = true)] async fn test_RustDesk_interval_sleep() { let base_intervals = [interval_maker, interval_at_maker]; for (i, maker) in base_intervals.into_iter().enumerate() { @@ -3223,17 +3213,24 @@ mod tests { loop { tokio::select! { _ = timer.tick() => { - times.push(get_timestamp_secs()); + times.push(Instant::now()); if times.len() == 5 { break; } } } } - // No multiple ticks in the `interval` time. - // Values in "times" are unique and are less than normal tokio interval. - let times2: HashSet = HashSet::from_iter(times.clone()); - assert_eq!(times.len(), times2.len(), "test: {}", i); + // No multiple ticks in the `interval` time: tokio's interval bursts the missed ticks + // with no gap, ThrottledInterval keeps them at least 0.9 * period apart. + for pair in times.windows(2) { + let gap = pair[1] - pair[0]; + assert!( + gap >= Duration::from_millis(900), + "test: {}, gap: {:?}", + i, + gap + ); + } } }