Граф коммитов

59 Коммитов

Автор SHA1 Сообщение Дата
Barret Rennie 1aee47ca69
Log to a file in fxrunner 2021-06-21 23:49:41 -04:00
Barret Rennie 1d346e50e7
Fix TestPerfProvider to return increasing cpu times
When `cpu_and_disk_idle()` was updated to compute the cpu idle time over
an interval, the tests were never updated to match. This fixes those
tests.
2021-06-21 21:57:18 -04:00
Barret Rennie bce6d3a52c
Remove debug logging of child handles 2021-05-11 13:22:45 -04:00
Barret Rennie ad5c9f8b01
Hide the cursor while the splash is shown
We move the cursor to the bottom of the screen when we show the splash
so that it does not interfere with visual metrics.
2021-05-11 13:22:45 -04:00
Barret Rennie f95c7b9c74
Detect CPU idle percentage over an interval
Previously we were using the overall CPU idle percentage since the
machine started, instead of measuring the idle percentage over an
interval (like we were already doing with disk IO counters). Now we
measure the CPU usage over the same interval that we measure IO counters
and use that for determining if we are idle.
2021-05-11 13:22:44 -04:00
Barret Rennie a8e362f263
Perform visual metrics analysis 2020-10-23 17:34:21 -04:00
Barret Rennie c486b7fad3
Paint the splash orange instead of red 2020-10-20 18:18:05 -04:00
Barret Rennie eb8bf59420
Unrefactor {fxrunner,fxrecorder}::main 2020-10-20 18:18:04 -04:00
Barret Rennie 4f52550351
Record Firefox execution
`fxrecorder` now starts a recording session via its `Recorder` and
requests `fxrunner` to start Firefox. After a delay, Firefox is shut
down and the recording stops.

Recorder and Splash mocks are also added for integration tests, but as
of yet they do nothing.
2020-09-29 15:55:25 -04:00
Barret Rennie 3cf57dccc8
Build a fake firefox.exe for integration-tests 2020-09-29 15:55:25 -04:00
Barret Rennie f62d658a48
Add path helpers to SessionInfo 2020-09-29 15:55:24 -04:00
Barret Rennie 46c047351b
Add a module for interacting with processes
The `libfxrunner::osapi::process` module provides some abstractions
around dealing with processes (i.e., HANDLEs to processes) on Windows,
namely opening processes, terminating processes, and iterating the
child processes of another process.

Child iteration is accomplished by the win32 ProcessSnapshot API.
Unfortunately, the winapi crate is missing some type definitions
(`PSS_HANDLE_ENTRY` and friends), so they are included (as part of the
`process::detail` module, since they are not exposed as part of the
`process` API).

We need these capabilities because on Windows, `firefox.exe` by default
will start the launcher process, which then starts the main Firefox
process. We can ask the launcher to wait until the main process exits,
but terminating the launcher will not terminate the main process. (We
can also sidestep the launcher and start the main process directly by
changing prefs, but the launcher does important work, like pre-loading
DLLs that Firefox will use).

Therefore we need a way to enumate the child processes of the launcher
process, so we can terminate the main Firefox process, which is what
this API provides.

There is one caveat to the implementation of this API, and that is if we
call `PssCaptureSnapshot()` too soon on a process handle opened via
`OpenProcess()` we fail inside a call to `memcpy`:

```
[0x0]   ntdll!memcpy + 0x92
[0x1]   ntdll!PsspHandleDumper + 0x1a1
[0x2]   ntdll!PsspWalkHandleTable + 0x21e
[0x3]   ntdll!PsspCaptureHandleInformation + 0x238
[0x4]   ntdll!PssNtCaptureSnapshot + 0x373
[0x5]   KERNELBASE!PssCaptureSnapshot + 0x1e
[0x6]   integration_tests_5e8edb1581cc8758!libfxrunner::osapi::process::ChildProcessIter::new + 0x9e
```

To work around this, we sleep for 500ms when calling
`ChildProcessIter::new()`, which in practice is called immediately after
`OpenProcess()`. Additionally, if we sleep for too short a duration,
e.g., 1ms, `ChildProcessIter::new()` ends up hanging forever inside the
tokio's thread parking implementation.
2020-09-29 15:55:23 -04:00
Barret Rennie ea5460cdd3
Add a Splash window
The Splash window paints the entire screen a solid colour so that the
Firefox window can be picked out of the recorded video.
2020-09-29 15:53:55 -04:00
Barret Rennie 141fbc0b8f
Wrap winapi calls with error checking
By their nature, winapi calls are not very rustic. They fall into three
common patterns:

1. Return a success vs non-success code (e.g. non-zero for success and
   zero for failure) and set a specific error code via `SetLastError`.
2. Return either a pointer value that may be null if an error occurred.
   In the error case, a specific error is set with `SetLastError`.
3. Returning an error code directly, with `ERROR_SUCCESS` representing
   the success case.

To handle these APIs, three new utilities have been added:

1. `fn check_nonzero<T>(T) -> Result<T, std::io::Error>`, which handles
   the success vs non-success case.
2. `fn check_nonnull<T>(*mut T) -> Result<*mut T, std::io::Error>`,
   which handles pointer returning functions (EXCEPT functions that
   return HANDLE -- those should use `Handle::TryFrom`, which compares
   against `INVALID_HANDLE_VALUE` instead of null).
3. `fn check_success(DOWRD) -> Result<(), std::io::Error>`, which
   handles functions that return error codes directly.
2020-09-28 16:03:19 -04:00
Barret Rennie b2ce664da6
Use TryFrom impl for Handle instead of From
`Handle` is now only constructible through a `TryFrom` impl, which
checks against the invalid handle value and returns the last Windows
error if it matches.

This also corrects the error checking we were doing while acquiring a
handle to the logical C:\ drive, as the invalid handle value is not a
null pointer.
2020-09-23 14:06:27 -04:00
Barret Rennie 549f6a56d3
Remove the WindowsError type
The `WindowsError` type can be completely replaced with `io::Error`.
2020-09-23 14:06:21 -04:00
Barret Rennie b1042e9b2e
Refactor Handle into a wrapper type 2020-09-01 01:45:51 -04:00
Barret Rennie e619f703c6
Namespace Windows API calls to their modules
Every non-type item imported from winapi has been rewritten to be
relative to its containing module, which makes for a more reasonable
import block at the top of Windows-specific files for code that is
just as readable.
2020-09-01 01:45:50 -04:00
Barret Rennie f64d4b2852
Use Display and Debug for error logging in runner 2020-09-01 01:45:50 -04:00
Barret Rennie 16bfe35c07
Remove incorrect comment
We aren't casting `name` to a `*mut c_char`.
2020-08-06 18:24:17 -04:00
Barret Rennie 3968746621
Depend on a stable version of winapi-rs
Fixes #11.
2020-08-06 17:19:49 -04:00
Barret Rennie 4fb152a2d8
Disable updates for downloaded Firefoxen
After downloading a build of Firefox, we disable the update via the
updater via the Policy Engine.
2020-07-23 16:13:49 -04:00
Barret Rennie 671c79af44
Rename requests to sessions
While updating the language, the main message from the recorder to the
runner (`Request`) is now an enum, instead of a struct containing an
enum as its only field.
2020-07-22 17:17:07 -04:00
Barret Rennie 00337ffbae
Do not debug print errors in logs
We now use the Display impl for all errors in all log statements.
2020-07-22 17:17:07 -04:00
Barret Rennie 66785a0bad
Handle requests that produce errors without exiting
The runner no longer exits when encountering an error after handling a
request that produced an error. This allows us to recover from, e.g.,
invalid requests, which are not fatal and should not cause the runner to
exit.
2020-07-20 15:11:25 -04:00
Barret Rennie f284398f87
Clean up all requests after serving resume requests
Requests are not intended to be served out of order. fxrunner must only
send a single new request followed by a corresponding resume request. We
now clean up the request directory after each resume request.
2020-07-20 15:11:25 -04:00
Barret Rennie f2d656a851
Cleanup completed resumed requests
The runner now will cleanup resumed requests as they are completed
(either successfully or unsucessfully). Additionally, the
`FsRequestManager` will cleanup any requests that it cannot resume.
2020-07-20 15:11:24 -04:00
Barret Rennie c24f5504cf
Clean up failed requests
If a request fails before the runner restarts, we now clean up any
downloaded files (Firefoxen, profiles, etc).
2020-07-20 15:11:24 -04:00
Barret Rennie d721ac8d49
Do not use a temporary directory for request state 2020-07-20 15:11:23 -04:00
Barret Rennie 9493e0dcf8
Use the RequestManager in the RunnerProto 2020-07-20 15:11:23 -04:00
Barret Rennie 72690be455
Add RequestManager for creating and resuming requests 2020-07-20 15:06:50 -04:00
Barret Rennie b67cbed24f
Propagate errors in profile creation to recorder 2020-07-17 15:30:19 -04:00
Barret Rennie c74be2de74
Fix cargo clippy lints 2020-07-07 19:09:15 -04:00
Barret Rennie 8ef6d8106a
Update fxunner to use thiserror 2020-06-29 23:32:16 -04:00
Barret Rennie 919b346aeb
Support not waiting for idle in protocol 2020-06-29 23:30:51 -04:00
Barret Rennie 2452dc1236
Pass directory into RunnerProto::handle_request
We pass the working directory into `RunnerProto::handle_request` so that
we can test the contents of the temporary directory before it is
removed.
2020-06-28 21:24:11 -04:00
Barret Rennie ccc54c6e4a
Rewrite Taskcluster as a Trait and impl
What was previously the `Taskcluster` struct is now the `Taskcluster`
trait and `FirefoxCi` struct, which implements that trait. This allows
us to only require testing the HTTP requests in our unit tests and
completely mock them out in integration tests, saving on test verbosity.

The `Taskcluster` trait is generic over an `Error` type, allowing for
easier mocking. The type that was `TaskclusterError` is now
`FirefoxCiError` (as it an implementation detail).

The `RunnerProtoError` is now generic over implementations of the
`Taskcluster` trait, again for easier mocking.
2020-06-28 21:24:11 -04:00
Barret Rennie 3244aec4b0
Expose only a static interface to RunnerProto
The RunnerProto only exposed only a single method: `handle_request`.
This interface has now been made a static function, replacing the
pattern of `RunnerProto::new().handle_request()` with
`RunnerProto::handle_request`.
2020-06-28 21:24:10 -04:00
Barret Rennie 4870a145c8
Make protocol less noisy
Instead of the recorder constantly sending messages to the runner, it
now sends a single `Request` message and receives a series of responses
from the runner.

Tests will be fixed in a later commit.

Received profiles, prefs, and Firefox builds are not presently persisted
through restarts. This will be fixed in an upcoming patch.

The protocol docs no longer match what happens, so they've been removed
for now.
2020-06-28 21:24:06 -04:00
Barret Rennie 83aa038edf
Wait for disk and CPU to become idle on fxrunner
As part of the protocol, fxrecorder will now wait for fxrunner's cpu and
disk to become idle before it starts Firefox.
2020-06-28 21:14:50 -04:00
Barret Rennie e3f6b27753
Parameterize RunnerProtoError over ShutdownProvider
Instead of being generic over `S: Error + 'static`, the
`RunnerProtoError` type is now generic over `S: ShutdownProvider` and we
can use `S::Error` inside its definition, instead of instantiating it
from the `RunnerProto<S>` with `S::Error` directly.

This is a little cleaner and more readable, but does have a side effect
that requires `ShutdownProvider: Debug`.

This is in preparation for adding another generic parameter to
`RunnerProtoError`, making it generic over errors from the
`PerfProvider`. Without this change, it would require being generic over
both of the `PerfProvider`'s error types (`PerfProvider::DiskIoError`
and `PerfProvider::CpuTimeError`), making the types longer and messier.
2020-06-28 21:14:50 -04:00
Barret Rennie ad51b08f31
Implement disk and CPU performance API
We can now wait for the disk and CPU to settle out to acceptable levels
for our performance tests. LIke the `ShutdownProvider` API, the
`PerformanceProvider` API is implemented as a trait so that it can be
replaced for integration tests.
2020-06-28 21:14:39 -04:00
Barret Rennie e713725461
Rename libfxrunner::shutdown to libfxrunner::osapi
The `shutdown` module has been lightly refactored into an `osapi`
module. The error utilities (`WindowsError` and `get_last_error`) have
been refactored into the `osapi::error` module and the `Handle` API has
been refactored into the `osapi::handle` module.
2020-06-25 01:22:04 -04:00
Barret Rennie ebb89065fd
Send prefs from the recorder to the runner
The recorder now accepts prefs via the command-line, which will be sent
to the runner. If a profile was sent to the runner, that profile's
`user.js` will be appended with these new prefs. Otherwise, a new
profile will be used and these prefs will be written to that profile's
`user.js` instead.
2020-06-25 01:20:32 -04:00
Barret Rennie d771f8362d
Send a profile from the recorder to the runner
The recorder can now specify a zipped Firefox profile for the runner to
use when running Firefox, which will be transferred from the recorder to
the runner.
2020-06-25 01:20:22 -04:00
Barret Rennie 66d61ecd99
Extract downloaded archives
The build artifacts from Taskcluster are zip archives, which are now
extracted as part of the download.
2020-06-24 19:50:10 -04:00
Barret Rennie 3795da5556
Request build downloads from Taskcluster
The recorder will now request the runner download a specific build of
Firefox. A Taskcluster task ID for a build task is accepted by the
recorder on the command-line, which is used to determine the task to
download.
2020-06-24 19:50:07 -04:00
Barret Rennie e217c1820e
Add an API for interacting with Taskcluster
The runner now has an API for interacting with Taskcluster. Network
requests are run against a local server during unit tests so that they
do not require Internet access (or a valid Taskcluster setup) to run.
2020-06-24 19:17:49 -04:00
Barret Rennie e61b0c7493
Thorougly test integration between runner and recorder
The interface between the `RunnerProto` and `RecorderProto` has been
more thoroughly tested for the handshake protocol. The infrastructure
added to accomplish this should make adding more tests easier as more of
the protocol is implemented.
2020-06-23 21:44:14 -04:00
Barret Rennie 73961e96c3
Use the Windows shutdown implementation when restarting
The fxrunner has a `--skip-restart` flag that is only provided in debug
builds that allows it to skip doing an actual restart for local
development and testing.
2020-06-23 21:44:14 -04:00