2017-12-04 19:52:07 +00:00
// For these tests we use a fake DBus daemon to verify powerMonitor module
// interaction with the system bus. This requires python-dbusmock installed and
// running (with the DBUS_SYSTEM_BUS_ADDRESS environment variable set).
2018-09-27 05:49:02 +00:00
// script/spec-runner.js will take care of spawning the fake DBus daemon and setting
2017-12-04 19:52:07 +00:00
// DBUS_SYSTEM_BUS_ADDRESS when python-dbusmock is installed.
//
// See https://pypi.python.org/pypi/python-dbusmock for more information about
// python-dbusmock.
2020-03-20 20:28:31 +00:00
import { expect } from 'chai' ;
import * as dbus from 'dbus-native' ;
import { ifdescribe } from './spec-helpers' ;
import { promisify } from 'util' ;
2017-12-04 19:52:07 +00:00
2018-10-09 05:32:19 +00:00
describe ( 'powerMonitor' , ( ) = > {
2020-03-20 20:28:31 +00:00
let logindMock : any , dbusMockPowerMonitor : any , getCalls : any , emitSignal : any , reset : any ;
2017-12-04 19:52:07 +00:00
2019-10-28 22:12:35 +00:00
// TODO(deepak1556): Enable on arm64 after upgrade, it crashes at the moment.
ifdescribe ( process . platform === 'linux' && process . arch !== 'arm64' && process . env . DBUS_SYSTEM_BUS_ADDRESS != null ) ( 'when powerMonitor module is loaded with dbus mock' , ( ) = > {
2018-03-14 05:42:08 +00:00
before ( async ( ) = > {
2020-03-20 20:28:31 +00:00
const systemBus = dbus . systemBus ( ) ;
const loginService = systemBus . getService ( 'org.freedesktop.login1' ) ;
const getInterface = promisify ( loginService . getInterface . bind ( loginService ) ) ;
logindMock = await getInterface ( '/org/freedesktop/login1' , 'org.freedesktop.DBus.Mock' ) ;
getCalls = promisify ( logindMock . GetCalls . bind ( logindMock ) ) ;
emitSignal = promisify ( logindMock . EmitSignal . bind ( logindMock ) ) ;
reset = promisify ( logindMock . Reset . bind ( logindMock ) ) ;
} ) ;
2018-03-14 05:42:08 +00:00
2018-10-09 05:32:19 +00:00
after ( async ( ) = > {
2020-03-20 20:28:31 +00:00
await reset ( ) ;
} ) ;
2018-03-14 05:42:08 +00:00
2019-08-28 20:54:50 +00:00
function onceMethodCalled ( done : ( ) = > void ) {
2017-12-04 19:52:07 +00:00
function cb ( ) {
2020-03-20 20:28:31 +00:00
logindMock . removeListener ( 'MethodCalled' , cb ) ;
2017-12-04 19:52:07 +00:00
}
2020-03-20 20:28:31 +00:00
done ( ) ;
return cb ;
2017-12-04 19:52:07 +00:00
}
2018-08-31 20:52:32 +00:00
before ( done = > {
2020-03-20 20:28:31 +00:00
logindMock . on ( 'MethodCalled' , onceMethodCalled ( done ) ) ;
2017-12-04 19:52:07 +00:00
// lazy load powerMonitor after we listen to MethodCalled mock signal
2020-03-20 20:28:31 +00:00
dbusMockPowerMonitor = require ( 'electron' ) . powerMonitor ;
} ) ;
2017-12-04 19:52:07 +00:00
2020-03-24 16:03:29 +00:00
it ( 'should call Inhibit to delay suspend once a listener is added' , async ( ) = > {
// No calls to dbus until a listener is added
{
const calls = await getCalls ( ) ;
expect ( calls ) . to . be . an ( 'array' ) . that . has . lengthOf ( 0 ) ;
}
// Add a dummy listener to engage the monitors
dbusMockPowerMonitor . on ( 'dummy-event' , ( ) = > { } ) ;
try {
let retriesRemaining = 3 ;
// There doesn't seem to be a way to get a notification when a call
// happens, so poll `getCalls` a few times to reduce flake.
let calls : any [ ] = [ ] ;
while ( retriesRemaining -- > 0 ) {
calls = await getCalls ( ) ;
if ( calls . length > 0 ) break ;
await new Promise ( resolve = > setTimeout ( resolve , 1000 ) ) ;
}
expect ( calls ) . to . be . an ( 'array' ) . that . has . lengthOf ( 1 ) ;
expect ( calls [ 0 ] . slice ( 1 ) ) . to . deep . equal ( [
'Inhibit' , [
[ [ { type : 's' , child : [ ] } ] , [ 'sleep' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'electron' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'Application cleanup before suspend' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'delay' ] ]
]
] ) ;
} finally {
dbusMockPowerMonitor . removeAllListeners ( 'dummy-event' ) ;
}
2020-03-20 20:28:31 +00:00
} ) ;
2017-12-04 19:52:07 +00:00
describe ( 'when PrepareForSleep(true) signal is sent by logind' , ( ) = > {
it ( 'should emit "suspend" event' , ( done ) = > {
2020-03-20 20:28:31 +00:00
dbusMockPowerMonitor . once ( 'suspend' , ( ) = > done ( ) ) ;
2017-12-04 19:52:07 +00:00
emitSignal ( 'org.freedesktop.login1.Manager' , 'PrepareForSleep' ,
2020-03-20 20:28:31 +00:00
'b' , [ [ 'b' , true ] ] ) ;
} ) ;
2017-12-04 19:52:07 +00:00
describe ( 'when PrepareForSleep(false) signal is sent by logind' , ( ) = > {
2018-08-31 20:52:32 +00:00
it ( 'should emit "resume" event' , done = > {
2020-03-20 20:28:31 +00:00
dbusMockPowerMonitor . once ( 'resume' , ( ) = > done ( ) ) ;
2017-12-04 19:52:07 +00:00
emitSignal ( 'org.freedesktop.login1.Manager' , 'PrepareForSleep' ,
2020-03-20 20:28:31 +00:00
'b' , [ [ 'b' , false ] ] ) ;
} ) ;
2017-12-04 19:52:07 +00:00
it ( 'should have called Inhibit again' , async ( ) = > {
2020-03-20 20:28:31 +00:00
const calls = await getCalls ( ) ;
expect ( calls ) . to . be . an ( 'array' ) . that . has . lengthOf ( 2 ) ;
2018-08-31 20:52:32 +00:00
expect ( calls [ 1 ] . slice ( 1 ) ) . to . deep . equal ( [
2017-12-04 19:52:07 +00:00
'Inhibit' , [
2018-09-13 16:10:51 +00:00
[ [ { type : 's' , child : [ ] } ] , [ 'sleep' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'electron' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'Application cleanup before suspend' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'delay' ] ]
2017-12-04 19:52:07 +00:00
]
2020-03-20 20:28:31 +00:00
] ) ;
} ) ;
} ) ;
} ) ;
2017-12-12 17:06:45 +00:00
describe ( 'when a listener is added to shutdown event' , ( ) = > {
before ( async ( ) = > {
2020-03-20 20:28:31 +00:00
const calls = await getCalls ( ) ;
expect ( calls ) . to . be . an ( 'array' ) . that . has . lengthOf ( 2 ) ;
dbusMockPowerMonitor . once ( 'shutdown' , ( ) = > { } ) ;
} ) ;
2017-12-12 17:06:45 +00:00
it ( 'should call Inhibit to delay shutdown' , async ( ) = > {
2020-03-20 20:28:31 +00:00
const calls = await getCalls ( ) ;
expect ( calls ) . to . be . an ( 'array' ) . that . has . lengthOf ( 3 ) ;
2018-08-31 20:52:32 +00:00
expect ( calls [ 2 ] . slice ( 1 ) ) . to . deep . equal ( [
2017-12-12 17:06:45 +00:00
'Inhibit' , [
2018-09-13 16:10:51 +00:00
[ [ { type : 's' , child : [ ] } ] , [ 'shutdown' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'electron' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'Ensure a clean shutdown' ] ] ,
[ [ { type : 's' , child : [ ] } ] , [ 'delay' ] ]
2017-12-12 17:06:45 +00:00
]
2020-03-20 20:28:31 +00:00
] ) ;
} ) ;
2017-12-12 17:06:45 +00:00
describe ( 'when PrepareForShutdown(true) signal is sent by logind' , ( ) = > {
2018-08-31 20:52:32 +00:00
it ( 'should emit "shutdown" event' , done = > {
2020-03-20 20:28:31 +00:00
dbusMockPowerMonitor . once ( 'shutdown' , ( ) = > { done ( ) ; } ) ;
2017-12-12 17:06:45 +00:00
emitSignal ( 'org.freedesktop.login1.Manager' , 'PrepareForShutdown' ,
2020-03-20 20:28:31 +00:00
'b' , [ [ 'b' , true ] ] ) ;
} ) ;
} ) ;
} ) ;
} ) ;
2018-03-14 05:42:08 +00:00
describe ( 'when powerMonitor module is loaded' , ( ) = > {
2019-11-01 20:37:02 +00:00
// eslint-disable-next-line no-undef
2020-03-20 20:28:31 +00:00
let powerMonitor : typeof Electron . powerMonitor ;
2018-03-14 05:42:08 +00:00
before ( ( ) = > {
2020-03-20 20:28:31 +00:00
powerMonitor = require ( 'electron' ) . powerMonitor ;
} ) ;
2019-02-27 20:54:01 +00:00
describe ( 'powerMonitor.getSystemIdleState' , ( ) = > {
it ( 'gets current system idle state' , ( ) = > {
// this function is not mocked out, so we can test the result's
// form and type but not its value.
2020-03-20 20:28:31 +00:00
const idleState = powerMonitor . getSystemIdleState ( 1 ) ;
expect ( idleState ) . to . be . a ( 'string' ) ;
const validIdleStates = [ 'active' , 'idle' , 'locked' , 'unknown' ] ;
expect ( validIdleStates ) . to . include ( idleState ) ;
} ) ;
2019-02-27 20:54:01 +00:00
it ( 'does not accept non positive integer threshold' , ( ) = > {
expect ( ( ) = > {
2020-03-20 20:28:31 +00:00
powerMonitor . getSystemIdleState ( - 1 ) ;
} ) . to . throw ( /must be greater than 0/ ) ;
2019-02-27 20:54:01 +00:00
expect ( ( ) = > {
2020-03-20 20:28:31 +00:00
powerMonitor . getSystemIdleState ( NaN ) ;
} ) . to . throw ( /conversion failure/ ) ;
2019-02-27 20:54:01 +00:00
expect ( ( ) = > {
2020-03-20 20:28:31 +00:00
powerMonitor . getSystemIdleState ( 'a' as any ) ;
} ) . to . throw ( /conversion failure/ ) ;
} ) ;
} ) ;
2019-02-27 20:54:01 +00:00
describe ( 'powerMonitor.getSystemIdleTime' , ( ) = > {
it ( 'notify current system idle time' , ( ) = > {
2020-03-20 20:28:31 +00:00
const idleTime = powerMonitor . getSystemIdleTime ( ) ;
expect ( idleTime ) . to . be . at . least ( 0 ) ;
} ) ;
} ) ;
} ) ;
} ) ;