---
# System prepended metadata

title: ScopedPathOverride
tags: [Chromium-General, elkurin-daily-note]

---

# ScopedPathOverride
baseディレクトリを読もうの会。  
今日のテーマは[base::ScopedPathOverride](https://source.chromium.org/chromium/chromium/src/+/main:base/test/scoped_path_override.h;l=19;drc=3e815ef723d2b1a4b467fff93e16a177ebae1626)。  

## Overview

ScopedPathOverrideは[PathService](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.h;l=21;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)の特定のkeyを一時的にtemp pathで上書きする。  
Scopedと名前にある通り、constructorの中でregisterしdestructorの中で最初の状態に戻す処理が自動で行われる。  

ここでOverrideするパスは、`path`や`dir`でoverrideしたい場所を指定することもできるし、何も渡さなければconstructorの中でtemp dirの中に実体が作られる。  

testの中でのみ使われることを想定されている。

### PathServiceとは
PathServiceとは、パスをuniqueなkeyのenumと対応させることでコードの中ではenumを指定するだけで取ってこれるシングルトン。  
keyに指定しておけばかんたんにChromiumすべてのコードでのパスを上書きできるので、上記のようなテスト時にありがたい。  
より詳しくは[PathService in Chromium](https://github.com/elkurin/elkurin-daily-notes/blob/main/docs/day83.md)で。

## 実装
constructorは3種類。
- [ScopedPathOverride(int key)](https://source.chromium.org/chromium/chromium/src/+/main:base/test/scoped_path_override.h;l=22;drc=3e815ef723d2b1a4b467fff93e16a177ebae1626): overrideしたい`key`だけ指定し、そのパスはScopedPathOverrideの中で作成
- [ScopedPathOverride(int key, const FilePath& dir)](https://source.chromium.org/chromium/chromium/src/+/main:base/test/scoped_path_override.h;l=25;drc=3e815ef723d2b1a4b467fff93e16a177ebae1626): userが指定した`dir`で`key`をoverrideする
- [ScopedPathOverride(int kay, const FilePath& path, bool is_absolute, bool create)](https://source.chromium.org/chromium/chromium/src/+/main:base/test/scoped_path_override.h;l=28;drc=3e815ef723d2b1a4b467fff93e16a177ebae1626): 上のやつの[PathService::OverrideAndCreateIfNeeded](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.h;l=55;drc=9d69367493326eeb650386198de90b220824702b)版


一番使い勝手の良い`ScopedPathOverride(int key)`を見てみる。
```cpp=
ScopedPathOverride::ScopedPathOverride(int key) : key_(key) {
  SaveOriginal();
  bool result = temp_dir_.CreateUniqueTempDir();
  CHECK(result);
  result = PathService::Override(key, temp_dir_.GetPath());
  CHECK(result);
}
```
[ScopedTempDir::CreateUniqueTempDir](https://source.chromium.org/chromium/chromium/src/+/main:base/files/scoped_temp_dir.cc;l=36;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)でディレクトリを作りそれでPathServiceをoverrideしている。  
Overrideする前には[SaveOriginal](https://source.chromium.org/chromium/chromium/src/+/main:base/test/scoped_path_override.cc;l=40;drc=9d69367493326eeb650386198de90b220824702b)が呼ばれている。  
これはoptional型である`original_override_`の中に元のファイルの値を保存しておき、destructorの中で復元するために用いられる。  
なお、このoriginalとは正しいregisterされた値ではなく、以前にoverrideされている値。例えば、親クラスのテストでoverrideしているようなケース。  
正しい値とoverrideはPathServiceの中では別の場所に保存されている。  
Overrideは[PathData::overrides](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.cc;l=308;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)の中にmapとして保存され、正規のパスでRegisterされるものは各[PathProvider](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.h;l=71;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)ごとまるっと[PathData::providers](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.cc;l=152;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)に保存される。

その他の2つのconstructorでも最後は復元するのでSaveOriginalが呼ばれている。  
また、共通して使われる[PathService::Override](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.cc;l=314;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)は`create = true`で[OverrideAndCreateIfNeeded](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.cc;l=277;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)を呼んでおり、つまりもし指定したパスが空っぽだったらOverrideの中で勝手に用意してくれている。

## Note
PathServiceの中では真面目に非同期でのコールをサポートしている。  
[PathData](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.cc;l=148;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)というオブジェクトは`lock`を持っており、[RegisterProvider](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.cc;l=343;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)中や[Override](https://source.chromium.org/chromium/chromium/src/+/main:base/path_service.cc;l=302;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)中は[AutoLock](https://source.chromium.org/chromium/chromium/src/+/main:base/synchronization/lock.h;l=116;drc=7dc3003765c74daa4bb49e4463e3a7963d8c7ea1)をかけて読み書きブロックをしている。