Add more OOM handling paths and refactor OOM tests
There were more cases where OOM wasn't being propagated correctly, or
even caught in the first place. This change makes all of those paths
report OOM to the application as is expected. One case was due to linux
sorting erroring out but then leaking memory, which wasn't caught because
the tests didn't create devices that supported PhysDevProps2.
Lastly, since the Allocation tests were taking much longer due to making
many more allocations, the MemoryTracker was rewritten to use
std::unordered_map to speed up insertion and lookup of allocations made.