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

Uri.base ignores IOOverrides which breaks paths package #39796

Closed
bsutton opened this issue Dec 14, 2019 · 2 comments
Closed

Uri.base ignores IOOverrides which breaks paths package #39796

bsutton opened this issue Dec 14, 2019 · 2 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io type-enhancement A request for a change that isn't a bug

Comments

@bsutton
Copy link

bsutton commented Dec 14, 2019

I'm using the 'path' package to write a library dcli.

https://pub.dev/packages/dcli

The library does path manipulation using the 'path' package as well as allowing a library user to modify the file system.

I'm trying to write unit tests for the dcli package.

To avoid possible damage of the file system I'm using a IOOverrides zone and providing a MemoryFileSystem.

Unit tests also run in parallel and as dcli has a shared cache directory I need the ability to isolate each unit test and as such each Unit test needs its own MemoryFileSystem.

The problem is that the path package calls Uri.base to determine the current working directory (cwd).

If you call Directory.current the IOOverrides zone behaves as expected by returning the IOOverrides MemoryFileSystem's cwd.

If you call Uri.base it utilizes _Directory._current which bypasses the IOOverride mechanism. The result is that Uri.base incorrectly returns the cwd of the root zone.

dart --version
Dart VM version: 2.7.0 (Unknown timestamp) on "linux_x64"

Unit test demonstrating the problem.

import 'dart:async';
import 'dart:io';

import 'package:file/memory.dart';
import 'package:test/test.dart';

void main() {
  // for some reason we don't start in the root zone. I'm assuming this is an artifact
  // of the unit test runner.
  var main = Zone.current;
  print('Directory.current = ${Directory.current}');
  print('MainZone: cwd:${Uri.base} Zone: ${main.hashCode}');
  test('zone 1', () {
    var _fs = MemoryFileSystem();
    print(
        'UnitTestZone: cwd:${Uri.base} Zone=${Zone.current.hashCode} Zone==Main: ${Zone.current == main}');

    IOOverrides.runZoned(() {
      print(
          'IOZone: cwd:${Uri.base} Zone=${Zone.current.hashCode} Zone==Main: ${Zone.current == main}');

      print('Note how Directory.current results in the override being called');
      print('Directory.current = ${Directory.current}');

      print('Note how Uri.base results in the override NOT being called');
      // the problem is that under the hood Uri.base calls _Directory._current rather than Directory.current.
      print('Uri.base = ${Uri.base}');

      // Uri.base should return the root of the MemoryFileSystem.
      expect(Uri.base.path, equals('/'));
    }, getCurrentDirectory: () {
      // print each time we are called
      print('Override called: getCurrentDirectory');
      return _fs.currentDirectory;
    }, setCurrentDirectory: (String path) {
      // print each time we are called
      print('Override called: setCurrentDirectory: $path');
      _fs.currentDirectory = path;
    });
  });
}

Edit: updated to reflect that the package dshell has been renamed to dcli.

@vsmenon vsmenon added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io labels Dec 16, 2019
@lrhn lrhn added the type-enhancement A request for a change that isn't a bug label Sep 29, 2020
@shyndman
Copy link

This as you might imagine extends to packages that use path, such as glob.

@lrhn
Copy link
Member

lrhn commented May 17, 2023

Uri cannot depend directly on IOOverrides since it exists on platforms that don't have dart:io.

It's definitely doing something to get a "base" location on those platforms, so whatever it's doing on the VM might be able to inspect IOOverrides as well.

(I consider Uri.base to be a fundamental mistake, same as any functionality that depends on isWindows for interpreting platform paths. The Uri class should have been self-contained, and not even know that there exists a "base" or a "platform path". Then other libraries could create Uris for concepts that they understand, like dart:io having a cwdAsUri. But that's not where we are, and probably hard to change by now. Not that I won't be willing to try if I can get extension static members!
Also, package:path should not have had the current functionality. That's outside of its scope. It should just work with paths that already exist. The best place to find the current directory would be the Directory class in dart:io, since we don't have a FileSystem class. Anyway!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

4 participants