Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
34467289
Unverified
Commit
34467289
authored
Jul 08, 2019
by
Jonah Williams
Committed by
GitHub
Jul 08, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add timer checking and Fake http client to testbed (#35392)
parent
49cce984
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
327 additions
and
20 deletions
+327
-20
context.dart
packages/flutter_tools/lib/src/base/context.dart
+2
-0
testbed.dart
packages/flutter_tools/test/src/testbed.dart
+293
-20
testbed_test.dart
packages/flutter_tools/test/testbed_test.dart
+32
-0
No files found.
packages/flutter_tools/lib/src/base/context.dart
View file @
34467289
...
...
@@ -142,6 +142,7 @@ class AppContext {
String
name
,
Map
<
Type
,
Generator
>
overrides
,
Map
<
Type
,
Generator
>
fallbacks
,
ZoneSpecification
zoneSpecification
,
})
async
{
final
AppContext
child
=
AppContext
.
_
(
this
,
...
...
@@ -152,6 +153,7 @@ class AppContext {
return
await
runZoned
<
Future
<
V
>>(
()
async
=>
await
body
(),
zoneValues:
<
_Key
,
AppContext
>{
_Key
.
key
:
child
},
zoneSpecification:
zoneSpecification
,
);
}
...
...
packages/flutter_tools/test/src/testbed.dart
View file @
34467289
...
...
@@ -3,8 +3,12 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:flutter_tools/src/base/context.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
...
...
@@ -25,7 +29,9 @@ export 'package:flutter_tools/src/base/context.dart' show Generator;
// - More TBD.
final
Map
<
Type
,
Generator
>
_testbedDefaults
=
<
Type
,
Generator
>{
// Keeps tests fast by avoid actual file system.
FileSystem:
()
=>
MemoryFileSystem
(
style:
platform
.
isWindows
?
FileSystemStyle
.
windows
:
FileSystemStyle
.
posix
),
FileSystem:
()
=>
MemoryFileSystem
(
style:
platform
.
isWindows
?
FileSystemStyle
.
windows
:
FileSystemStyle
.
posix
),
Logger:
()
=>
BufferLogger
(),
// Allows reading logs and prevents stdout.
OutputPreferences:
()
=>
OutputPreferences
(
showColor:
false
),
// configures BufferLogger to avoid color codes.
Usage:
()
=>
NoOpUsage
(),
// prevent addition of analytics from burdening test mocks
...
...
@@ -67,9 +73,8 @@ class Testbed {
/// `setup` may be provided to apply mocks within the tool managed zone,
/// including any specified overrides.
Testbed
({
FutureOr
<
void
>
Function
()
setup
,
Map
<
Type
,
Generator
>
overrides
})
:
_setup
=
setup
,
_overrides
=
overrides
;
:
_setup
=
setup
,
_overrides
=
overrides
;
final
Future
<
void
>
Function
()
_setup
;
final
Map
<
Type
,
Generator
>
_overrides
;
...
...
@@ -88,21 +93,42 @@ class Testbed {
};
// Cache the original flutter root to restore after the test case.
final
String
originalFlutterRoot
=
Cache
.
flutterRoot
;
return
runInContext
<
T
>(()
{
return
context
.
run
<
T
>(
name:
'testbed'
,
overrides:
testOverrides
,
body:
()
async
{
Cache
.
flutterRoot
=
''
;
if
(
_setup
!=
null
)
{
await
_setup
();
}
await
test
();
Cache
.
flutterRoot
=
originalFlutterRoot
;
return
null
;
}
);
});
// Track pending timers to verify that they were correctly cleaned up.
final
Map
<
Timer
,
StackTrace
>
timers
=
<
Timer
,
StackTrace
>{};
return
HttpOverrides
.
runZoned
(()
{
return
runInContext
<
T
>(()
{
return
context
.
run
<
T
>(
name:
'testbed'
,
overrides:
testOverrides
,
zoneSpecification:
ZoneSpecification
(
createTimer:
(
Zone
self
,
ZoneDelegate
parent
,
Zone
zone
,
Duration
duration
,
void
Function
()
timer
)
{
final
Timer
result
=
parent
.
createTimer
(
zone
,
duration
,
timer
);
timers
[
result
]
=
StackTrace
.
current
;
return
result
;
},
createPeriodicTimer:
(
Zone
self
,
ZoneDelegate
parent
,
Zone
zone
,
Duration
period
,
void
Function
(
Timer
)
timer
)
{
final
Timer
result
=
parent
.
createPeriodicTimer
(
zone
,
period
,
timer
);
timers
[
result
]
=
StackTrace
.
current
;
return
result
;
}
),
body:
()
async
{
Cache
.
flutterRoot
=
''
;
if
(
_setup
!=
null
)
{
await
_setup
();
}
await
test
();
Cache
.
flutterRoot
=
originalFlutterRoot
;
for
(
MapEntry
<
Timer
,
StackTrace
>
entry
in
timers
.
entries
)
{
if
(
entry
.
key
.
isActive
)
{
throw
StateError
(
'A Timer was active at the end of a test:
${entry.value}
'
);
}
}
return
null
;
});
});
},
createHttpClient:
(
SecurityContext
c
)
=>
FakeHttpClient
());
}
}
...
...
@@ -135,12 +161,259 @@ class NoOpUsage implements Usage {
void
sendCommand
(
String
command
,
{
Map
<
String
,
String
>
parameters
})
{}
@override
void
sendEvent
(
String
category
,
String
parameter
,
{
Map
<
String
,
String
>
parameters
})
{}
void
sendEvent
(
String
category
,
String
parameter
,
{
Map
<
String
,
String
>
parameters
})
{}
@override
void
sendException
(
dynamic
exception
,
StackTrace
trace
)
{}
@override
void
sendTiming
(
String
category
,
String
variableName
,
Duration
duration
,
{
String
label
})
{}
}
class
FakeHttpClient
implements
HttpClient
{
@override
bool
autoUncompress
;
@override
Duration
connectionTimeout
;
@override
Duration
idleTimeout
;
@override
int
maxConnectionsPerHost
;
@override
String
userAgent
;
@override
void
addCredentials
(
Uri
url
,
String
realm
,
HttpClientCredentials
credentials
)
{}
@override
void
addProxyCredentials
(
String
host
,
int
port
,
String
realm
,
HttpClientCredentials
credentials
)
{}
@override
set
authenticate
(
Future
<
bool
>
Function
(
Uri
url
,
String
scheme
,
String
realm
)
f
)
{}
@override
set
authenticateProxy
(
Future
<
bool
>
Function
(
String
host
,
int
port
,
String
scheme
,
String
realm
)
f
)
{}
@override
set
badCertificateCallback
(
bool
Function
(
X509Certificate
cert
,
String
host
,
int
port
)
callback
)
{}
@override
void
close
({
bool
force
=
false
})
{}
@override
Future
<
HttpClientRequest
>
delete
(
String
host
,
int
port
,
String
path
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
deleteUrl
(
Uri
url
)
async
{
return
FakeHttpClientRequest
();
}
@override
set
findProxy
(
String
Function
(
Uri
url
)
f
)
{}
@override
Future
<
HttpClientRequest
>
get
(
String
host
,
int
port
,
String
path
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
getUrl
(
Uri
url
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
head
(
String
host
,
int
port
,
String
path
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
headUrl
(
Uri
url
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
open
(
String
method
,
String
host
,
int
port
,
String
path
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
openUrl
(
String
method
,
Uri
url
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
patch
(
String
host
,
int
port
,
String
path
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
patchUrl
(
Uri
url
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
post
(
String
host
,
int
port
,
String
path
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
postUrl
(
Uri
url
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
put
(
String
host
,
int
port
,
String
path
)
async
{
return
FakeHttpClientRequest
();
}
@override
Future
<
HttpClientRequest
>
putUrl
(
Uri
url
)
async
{
return
FakeHttpClientRequest
();
}
}
class
FakeHttpClientRequest
implements
HttpClientRequest
{
FakeHttpClientRequest
();
@override
bool
bufferOutput
;
@override
int
contentLength
;
@override
Encoding
encoding
;
@override
bool
followRedirects
;
@override
int
maxRedirects
;
@override
bool
persistentConnection
;
@override
void
add
(
List
<
int
>
data
)
{}
@override
void
addError
(
Object
error
,
[
StackTrace
stackTrace
])
{}
@override
Future
<
void
>
addStream
(
Stream
<
List
<
int
>>
stream
)
async
{}
@override
Future
<
HttpClientResponse
>
close
()
async
{
return
FakeHttpClientResponse
();
}
@override
HttpConnectionInfo
get
connectionInfo
=>
null
;
@override
List
<
Cookie
>
get
cookies
=>
<
Cookie
>[];
@override
Future
<
HttpClientResponse
>
get
done
=>
null
;
@override
Future
<
void
>
flush
()
{
return
Future
<
void
>.
value
();
}
@override
HttpHeaders
get
headers
=>
null
;
@override
String
get
method
=>
null
;
@override
Uri
get
uri
=>
null
;
@override
void
write
(
Object
obj
)
{}
@override
void
writeAll
(
Iterable
<
Object
>
objects
,
[
String
separator
=
''
])
{}
@override
void
writeCharCode
(
int
charCode
)
{}
@override
void
writeln
([
Object
obj
=
''
])
{}
}
class
FakeHttpClientResponse
extends
Stream
<
Uint8List
>
implements
HttpClientResponse
{
final
Stream
<
List
<
int
>>
_content
=
const
Stream
<
List
<
int
>>.
empty
();
@override
X509Certificate
get
certificate
=>
null
;
@override
HttpClientResponseCompressionState
get
compressionState
=>
null
;
@override
HttpConnectionInfo
get
connectionInfo
=>
null
;
@override
int
get
contentLength
=>
0
;
@override
List
<
Cookie
>
get
cookies
=>
<
Cookie
>[];
@override
Future
<
Socket
>
detachSocket
()
async
{
return
null
;
}
@override
HttpHeaders
get
headers
=>
null
;
@override
bool
get
isRedirect
=>
null
;
@override
StreamSubscription
<
Uint8List
>
listen
(
void
Function
(
Uint8List
event
)
onData
,
{
Function
onError
,
void
Function
()
onDone
,
bool
cancelOnError
})
{
return
_content
.
listen
(
onData
,
onError:
onError
,
onDone:
onDone
,
cancelOnError:
cancelOnError
);
}
@override
bool
get
persistentConnection
=>
false
;
@override
String
get
reasonPhrase
=>
null
;
@override
Future
<
HttpClientResponse
>
redirect
(
[
String
method
,
Uri
url
,
bool
followLoops
])
{
return
null
;
}
@override
List
<
RedirectInfo
>
get
redirects
=>
const
<
RedirectInfo
>[];
@override
int
get
statusCode
=>
HttpStatus
.
badRequest
;
void
sendTiming
(
String
category
,
String
variableName
,
Duration
duration
,
{
String
label
})
{}
}
...
...
packages/flutter_tools/test/testbed_test.dart
View file @
34467289
...
...
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:io'
;
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/base/context.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
...
...
@@ -50,6 +53,35 @@ void main() {
expect
(
instance
,
isA
<
B
>());
});
test
(
'provides a mocked http client'
,
()
async
{
final
Testbed
testbed
=
Testbed
();
await
testbed
.
run
(()
async
{
final
HttpClient
client
=
HttpClient
();
final
HttpClientRequest
request
=
await
client
.
getUrl
(
null
);
final
HttpClientResponse
response
=
await
request
.
close
();
expect
(
response
.
statusCode
,
HttpStatus
.
badRequest
);
expect
(
response
.
contentLength
,
0
);
});
});
test
(
'Throws StateError if Timer is left pending'
,
()
async
{
final
Testbed
testbed
=
Testbed
();
expect
(
testbed
.
run
(()
async
{
Timer
.
periodic
(
const
Duration
(
seconds:
1
),
(
Timer
timer
)
{
});
}),
throwsA
(
isInstanceOf
<
StateError
>()));
});
test
(
'Doesnt throw a StateError if Timer is left cleaned up'
,
()
async
{
final
Testbed
testbed
=
Testbed
();
testbed
.
run
(()
async
{
final
Timer
timer
=
Timer
.
periodic
(
const
Duration
(
seconds:
1
),
(
Timer
timer
)
{
});
timer
.
cancel
();
});
});
});
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment