Commit graph

132 commits

Author SHA1 Message Date
chenhg
7d8880e50c Remove pstore case ibc.__pstore_append from CTS
BUG: 110118705
Change-Id: I946c645af0cfb3f3b0e9344c51940da226fd08ce
2018-06-21 16:04:10 -07:00
Elliott Hughes
6427c363df logd: remove failing test.
Bug: N/A
Test: ran tests manually
Change-Id: I3ebb97d757077acaab1b51809a1c2be90ceb1ad9
2018-06-19 15:06:53 -07:00
Mark Salyzyn
42fb2821cc liblog: expect content only if ro.logd.kernel is enabled
On svelte devices, CTS test liblog#android_logger_get_ fails on the
missing kernel buffer because it is not enabled to save space.

Test: gTest liblog_unit_tests
Bug: 109669791
Change-Id: Iaf46fe9713d3462a56885515a67db640544345ab
2018-06-05 07:43:15 -07:00
Mark Salyzyn
dc3c14720f liblog: clock_gettime, clock_getres and time benchmarks
Add local BM_time_clock_gettime_*, BM_time_clock_getres_* and
BM_time_time benchmarks.  Relates to the bionic benchmarks of
the same names, except adds CLOCK_MONOTONIC_RAW.  Added here for
developer convenience whenever updates to the liblog or logd
code base need integration testing.

ToDo: add liblog gTests that analyse the benchmark data to confirm
that the specified integrated device has vdso access to all the
pertinent clock sources.  Add liblog local benchmarks and tests to
measure the device clock drift of each possible liblog clock
source to help evaluate device configuration.

Test: liblog_benchmarks --benchmark_filter=BM_time*
Bug: 63737556
Bug: 69423514
Change-Id: Ibafe0880d976ef2b3885765f71e0ba6c99d56f2a
2018-01-16 08:11:59 -08:00
Mark Salyzyn
1520bd43b0 liblog: benchmarks use google-benchmark library
Remove our circa 2014 snapshot of the google benchmarking library, and
use the now very stable google-benchmark suite. Some porting effort,
and deal with some benchmarking saddle points that take too long to
sort out. Focus on minimal API changes, _odd_ new behaviors, and style.

Test: liblog_benchmarks, ensure results in about the same range
Bug: 69423514
Change-Id: I2add1df9cb664333bcf983b57121ae151b26935b
2018-01-16 08:11:26 -08:00
Julien Desprez
5b585791db Add suite component to test modules
Test: build
Bug: 65303193
Change-Id: I620c7034b9bdfa056dbde97c28bc5abc3375cc42
2017-12-18 18:08:53 +00:00
Xin Li
23e27db576 Merge commit 'a63ccea6abc7ea02e2d98e41c80793ca97237bd3' from
oc-mr1-dev-plus-aosp into stage-aosp-master

Change-Id: Ia33311cd1fd26dfaea59a69317b306fb91203c40
Merged-In: I03d06b10807e8a313c9654c2e1db36bfb59e3f99
2017-11-14 13:19:45 -08:00
Yao Chen
07320dc0a3 Allow stats buffer to be empty in liblog CTS.
Bug: 68205209
Test: CtsLiblogTestCases
Change-Id: I846c7cf72c54b02c2bc67c9c9e37b5cf4ae3da2b
2017-10-25 13:46:42 -07:00
Yoshitaka Seto
1d444319d7 Remove pstore related unit tests from CTS
am: 5dec8e22c3

Change-Id: Ifba13f9d714e58eaa3358a48246c71f90687629e
2017-09-21 23:25:34 +00:00
Yoshitaka Seto
5dec8e22c3 Remove pstore related unit tests from CTS
Pstore test cases should not belong to CTS.
The test cases should be a part of GTS if really required.

Test: manual
Bug: 66431569
Bug: 63969981
Bug: 63913130
Signed-off-by: Srinavasa Nagaraju <Srinavasa.Nagaraju@sony.com>
Signed-off-by: Yoshitaka Seto <yoshitaka.seto@sony.com>
Signed-off-by: Mark Salyzyn <salyzyn@google.com>
Tested-by: Srinavasa Nagaraju <Srinavasa.Nagaraju@sony.com>
Change-Id: Icd326403711ad268ce28a3863045fc9b2f211461
2017-09-21 13:37:50 -07:00
Alan Stokes
e0515d6dba Reading from logd in WRAP mode is expected to take a long time,
don't abort it after 30s.

Adds a new CTS test to verify the behaviour.

Bug: 64143705
Test: New and existing CTS tests pass. Manual testing with logcat.

(cherry picked from commit 64acdf77d6)

Change-Id: Ic2ec131a3aee293ee865c46e62566ddd82ec2507
2017-08-25 18:21:36 +01:00
Alan Stokes
e751059975 Merge "Small liblog test fixes & readability improvements." am: 332370d14d am: 511cc67633
am: 32636f0f4c

Change-Id: I5dd5e1b7267ff3f96aa264eede616dfb30b68884
2017-08-25 16:50:50 +00:00
Alan Stokes
332370d14d Merge "Small liblog test fixes & readability improvements." 2017-08-25 16:35:55 +00:00
Alan Stokes
328ba7c8e6 Merge "Reading from logd in WRAP mode is expected to take a long time, don't abort it after 30s." am: 974ab46561 am: 9181fe6427
am: 50289204e5

Change-Id: I88069714a32ec83f318a1a1dded0b0d8553be07f
2017-08-25 14:55:43 +00:00
Alan Stokes
81e63d0515 Small liblog test fixes & readability improvements.
liblog concurrent printf tests now check every write succeeds.
logd timeout_negative tests exits as soon as one run succeeds.

Test: CTS tests till pass.
Change-Id: I9a166a0abcb8b9aa5c055c35c5dccf30616a4e24
2017-08-25 14:53:21 +01:00
Alan Stokes
64acdf77d6 Reading from logd in WRAP mode is expected to take a long time,
don't abort it after 30s.

Adds a new CTS test to verify the behaviour.

Bug: 64143705
Test: New and existing CTS tests pass. Manual testing with logcat.
Change-Id: Ia67175701ed8c462083e14e26123ce8ddcb226bc
2017-08-25 11:40:49 +01:00
Chih-hung Hsieh
2f41895b90 Merge "Fix clang-tidy performance warnings in system/core." am: 69ff5009c7 am: 18f9c66823 am: b083ff4329
am: 36557667f3

Change-Id: I72bf60cf94547867f7eaf4aeddf60ff67c29dad5
2017-08-04 21:32:37 +00:00
Chih-hung Hsieh
18f9c66823 Merge "Fix clang-tidy performance warnings in system/core."
am: 69ff5009c7

Change-Id: I74373e9f0e7f83c9280f4700ea55b387c3384c2c
2017-08-04 21:14:30 +00:00
Chih-Hung Hsieh
e5d975c7cc Fix clang-tidy performance warnings in system/core.
* Use const reference parameter type to avoid unnecessary copy.
* Use more efficient overloaded string methods.

Bug: 30407689
Bug: 30411878
Test: build with WITH_TIDY=1
Change-Id: Ia5a00581e718d412255d6177e5a7c286cdfbec11
2017-08-03 13:58:05 -07:00
nickrose
653d49a245 Add logd CTS tests to VTS
Follow-up to  Change-Id: Id52ac1639447276171006c33bdfa7b4e6c874745

Test: make vts
Change-Id: Ibeb5082439ada49a6eccd6fb699e466ca71730c9
2017-07-10 11:17:38 -07:00
Guang Zhu
c2fbcf6f67 add component metadata tag to CTS liblog test acses
am: de29bf4884

Change-Id: I4bc7c46b9498227ccd19c558fd821d80974bd404
2017-06-06 19:28:39 +00:00
Guang Zhu
de29bf4884 add component metadata tag to CTS liblog test acses
Bug: 36140955
Bug: 35360169
Test: new unit test to ensure that all modules have this field
Change-Id: I352145965e8cd20371ccce3ba2b25f3a166bc3e8
Merged-In: Ifb7a14817265b4624f1dc6414b547c86aafcf4ac
2017-06-05 23:21:23 +00:00
Guang Zhu
44a4ab854e add component metadata tag to CTS liblog test acses
Bug: 36140955
Bug: 35360169
Test: new unit test to ensure that all modules have this field
Change-Id: Ifb7a14817265b4624f1dc6414b547c86aafcf4ac
2017-06-05 23:17:50 +00:00
Mark Salyzyn
067e8a0725 liblog: test: CTS: enoent does not qualify
Eliminate liblog@enoent CTS test as it is bypassed on "user" builds
in commit "liblog: test: enoent requires userdebug or eng to run".
This prevents time wasted running a test that bypasses during CTS.

Test: CtsLiblogTestCases_list --gtest_list_tests |
      (grep enoent && echo FAILED)
Bug: 62030441
Change-Id: Ia440db3e74dacdc5c311c640aab3a11844cc195a
2017-05-24 15:30:07 -07:00
Mark Salyzyn
558f2a166b liblog: test: android_logger_get_ "kernel" log buffer can be empty
(cherry picked from commit 37eaefa9a0)

If user build and for the "kernel" log buffer, allow an empty report.

Test: CTS: User: liblog#android_logger_get_
Test: remove ro.debuggable line from /default.prop,
      run liblog-unit-tests --gtest_filter=*.android_logger_get_
Bug: 62030309
Change-Id: I5f91af07608988f322b3c46574becc308e1d8b13
2017-05-24 12:50:38 -07:00
Mark Salyzyn
37eaefa9a0 liblog: test: android_logger_get_ "kernel" log buffer can be empty
If user build and for the "kernel" log buffer, allow an empty report.

Test: CTS: User: liblog#android_logger_get_
Test: remove ro.debuggable line from /default.prop,
      run liblog-unit-tests --gtest_filter=*.android_logger_get_
Bug: 62030309
Change-Id: I5f91af07608988f322b3c46574becc308e1d8b13
2017-05-24 12:45:41 -07:00
Mark Salyzyn
928e606d5a liblog: test: enoent requires userdebug or eng to run
(cherry picked from commit 38dad6c9e4)

Bypass test if we do not have all the prerequisites to run this check
of liblog failure propagation.  We need to be root, or be able to
call su, in order to temporarily stop logd to measure the error
response from liblog.  Basically a "user" build can not have the
levers to deny or fail the logger, preventing our ability to run the
liblog.enoent test.

Test: CTS: User: liblog#enoent
Test: remove ro.debuggable line from /default.prop,
      run liblog-unit-tests --gtest_filter=*.enoent
Bug: 62030441
Change-Id: I52177b8dd3c66d433bddf630e840ee088e13cddc
2017-05-24 09:15:27 -07:00
Mark Salyzyn
38dad6c9e4 liblog: test: enoent requires userdebug or eng to run
Bypass test if we do not have all the prerequisites to run this check
of liblog failure propagation.  We need to be root, or be able to
call su, in order to temporarily stop logd to measure the error
response from liblog.  Basically a "user" build can not have the
levers to deny or fail the logger, preventing our ability to run the
liblog.enoent test.

Test: CTS: User: liblog#enoent
Test: remove ro.debuggable line from /default.prop,
      run liblog-unit-tests --gtest_filter=*.enoent
Bug: 62030441
Change-Id: I52177b8dd3c66d433bddf630e840ee088e13cddc
2017-05-24 07:50:29 -07:00
Christopher Ferris
ac225780dd Move libc_logging to libasync_safe.
Move the name of the "private/libc_logging.h" header to <async_safe/log.h>.

For use of libc_malloc_debug_backtrace, remove the libc_logging library.
The library now includes the async safe log functions.

Remove the references to libc_logging.cpp in liblog, it isn't needed because
the code is already protected by a check of the __ANDROID__ define.

Test: Compiled and boot bullhead device.
Test: Run debuggerd unit tests.
Test: Run liblog unit tests on target and host.
Test: Run libmemunreachable unit tests (these tests are flaky though).
Change-Id: Ie79d7274febc31f210b610a2c4da958b5304e402
2017-05-02 18:38:46 -07:00
Mark Salyzyn
b7140c26d5 liblog: test: liblog.__security miscalculation
(cherry pick from commit b867beac56)

The gTest should not be able to set ro.device_owner, either as a unit
test or a CTS test.  The CTS test should not be able to set
persist.logd.security, the gTest may as it is run on userdebug with
root, so check if we are root to discern expectations.

Test: gTest liblog-unit-tests --gtest_filter=liblog.__security
Test: cts-tradefed run cts-dev -a armeabi-v7a -m CtsLiblogTestCases -t liblog#__security
Bug: 36480230
Change-Id: I1da88aae34da4e2fca8dd88d740eeb879d9c65bb
2017-04-21 08:20:56 -07:00
Mark Salyzyn
b867beac56 liblog: test: liblog.__security miscalculation
The gTest should not be able to set ro.device_owner, either as a unit
test or a CTS test.  The CTS test should not be able to set
persist.logd.security, the gTest may as it is run on userdebug with
root, so check if we are root to discern expectations.

Test: gTest liblog-unit-tests --gtest_filter=liblog.__security
Test: cts-tradefed run cts-dev -a armeabi-v7a -m CtsLiblogTestCases -t liblog#__security
Bug: 36480230
Change-Id: I1da88aae34da4e2fca8dd88d740eeb879d9c65bb
2017-04-20 13:26:12 -07:00
Rubin Xu
08c662c762 Fix liblog#__security failure
Update pid and gid value after calling setuid()

Bug: 36480230
Test: cts-tradefed run cts -m CtsLiblogTestCases -t liblog#__security_buffer
Change-Id: I707f7c724d64236ec17f2d978c85883a7b4f180f
Merges-In: I707f7c724d64236ec17f2d978c85883a7b4f180f
2017-04-05 11:30:06 +01:00
Rubin Xu
235cf8d729 Fix liblog#__security failure
Update pid and gid value after calling setuid()

Bug: 36480230
Test: cts-tradefed run cts -m CtsLiblogTestCases -t liblog#__security_buffer
Change-Id: I707f7c724d64236ec17f2d978c85883a7b4f180f
Merges-In: I707f7c724d64236ec17f2d978c85883a7b4f180f
2017-04-05 11:27:48 +01:00
Mark Salyzyn
fe8c96d152 liblog: benchmark add BM_log_event_overhead_42 for a well known tag
Measure the cost of using a known test event log tag from
system/core/logcat/event.logtags:

42    answer (to life the universe etc|3)

Test: liblog_benchmarks BM_log_event_overhead_42
Bug: 36683634
Change-Id: Ibd4be82bebfcedd381c84e8078cf6d05a636aa98
2017-03-31 13:25:36 -07:00
Mark Salyzyn
ef5d981977 liblog: tests: liblog.__security property failure
CTS tests are failing to set ro.device_owner property.

Test: gTest liblog_unit_tests --gtest_filter=liblog.__security
Bug: 36480230
Change-Id: Icafea9f7488ce9c4ea47d42dc08505bc0cf99a3e
2017-03-21 15:22:29 -07:00
Mark Salyzyn
5707524003 liblog: test: *.android_errorWriteWithinfoLog__android_logger_list_read__*
We would experience failures as test runs interfere with each other.
Create a unique tag for each test run signature.  Switch from using
TEST_PREFIX to TEST_LOGGER to identify the logger transport being
inspected and make that part of the signature.  Make sure 32 bit and
64 bit tests do not interfere.

Test: gTest liblog-unit-tests
      cts-tradefed run cts -m CtsLiblogTestCases
Bug: 36232924
Change-Id: I4d58242e5ef8e68e2d4b27cecf538938e17acf3f
2017-03-17 10:41:39 -07:00
Mark Salyzyn
58aaee8eb1 liblog: tests: __security and enoent failures
- __security test to allow 20ms resting time after setting ro.device_owner
- enoent test resort to using "su" command if we are not root to start
  and stop the logger.
- Add some instrumentation to guide us in the future if issues.

Test: gTest liblog-unit-tests
      cts-tradefed run cts -m CtsLiblogTestCases
Bug: 36232924
Change-Id: I6b926a1913497f7e6204493fc744ee6c454a5ce4
2017-03-17 09:11:45 -07:00
Mark Salyzyn
c500abb40b liblog: test: __android_log_btwrite__android_log_close precharge
TEST_PREFIX missing before operations on
liblog*.__android_log_btwrite__android_log_close tests

Test: gTest liblog-unit-tests
Bug: 27405083
Change-Id: Iaddc4e1b1f9afcfd8231c3921605fecefd2b56bf
2017-03-13 16:29:04 -07:00
Mark Salyzyn
81321a7980 liblog: replace "frontend" with "transport"
We still do not have any users of the 'frontend' interface, let's
right a wrong and rename it to 'transport' as it makes more sense.
Renames android_log_set_frontend, android_log_get_frontend and
include/log/log_frontend.h.

SideEffects: None
Test: gTest liblog-unit-tests
Bug: 27405083
Change-Id: I7c1c0f3dfdc7cf047285403e306edbd16ad1324d
2017-03-09 09:36:34 -08:00
Mark Salyzyn
2ed51d708e liblog: specify clang format
Switch coding style to match

SideEffects: None
Test: compile
Bug: 27405083
Change-Id: Id426d5c5e3b18f2ceec22b31bbc9781aabf6bcca
2017-03-09 09:36:19 -08:00
Mark Salyzyn
4d99c986d9 liblog: add LOGGER_STDERR frontend
Standalone, this logger provides no end-to-end capability.  Only
provides a writer, no reader transport.  All output goes, logcat-like,
into the stderr stream.  Output can be adjusted with environment
variables ANDROID_PRINTF_LOG and ANDROID_LOG_TAGS.

liblog_*.__android_log_bswrite_and_print___max print fails if a string
member is truncated with "Binary log entry conversion failed" and -1.
We expose the truncated content in the tests and in LOGGER_STDERR.

The purpose of this transport selection is for command-line tools,
providing a means to shunt the logs to be mixed in with the tool's
error stream.

Test: gTest liblog-unit-tests
Bug: 27405083
Change-Id: If344b6e3e67df2dc86ce317cfad8af8e857727b7
2017-03-08 07:17:31 -08:00
Mark Salyzyn
7100288532 liblog: add local_logger
- Create the local-only logger module
- Add LOGGER_LOCAL flag to android_set_log_frontend to enable
- Permit log reader for host compilation

android_set_log_frontend(LOGGER_LOCAL) will result in logs going
into application local memory.  logcat can not retrieve the data,
the user must utilize the log reading interface directly to
acquire their own logs.  Some local logger tests dropped as they
represent testing other liblog facilities.  Other local logger
tests dropped because we make the conscious decision to not
support LOG_ID_SECURITY logging.

ToDo: Some local logger tests dropped because of missing
      functionality associated with blocking reader.

Test: gTest libcutils-tests, logd-unit-tests, liblog-unit-tests,
      logcat-unit-tests, liblog-benchmarks and CtsLiblogTestCases_list
Bug: 27405083
Change-Id: Ia23b932af9e05756eaa60bab9139876b14faf72d
2017-02-08 15:07:06 -08:00
Mark Salyzyn
62d0d2d683 liblog: add logprint to host build
- cleanup of some style issues
- resolve a few minor bugs
- add -lrt for host so that clock_gettime can be issued
- enable write-only logging, logprint and event list
  handling tests for host consumption.

NB: CtsLiblogTestCases_list is only outlet for host testing of
    the interfaces, but it is not part of any automated testing

Test: gTest liblog-unit-tests, liblog-benchmarks and
      CtsLiblogTestCases_list && build mmma system/core/liblog
Bug: 27405083
Change-Id: I13db1f45f67569407587a5a909248de33809b8cf
2017-02-08 13:37:44 -08:00
Mark Salyzyn
8f2492f582 liblog: benchmark: Use local LOGGER_NULL frontend
Additional benchmarks to check the effects and performance of the
frontend changes.

Test: manual liblog-benchmarks
Bug: 27405083
Change-Id: I2a9dba81b70e9d71cdb8de1b35e8dff099ad6038
2017-02-08 13:37:44 -08:00
Mark Salyzyn
850d06e1c9 liblog: Add android_set_log_frontend
android_set_log_frontend allows one to select LOGGER_DEFAULT,
LOGGER_LOGD or LOGGER_NULL, the latter allows a runtime mechanism to
turn logging on or off.  LOGGER_DEFAULT is LOGGER_LOGD.

Test: gTest liblog-unit-tests notably liblog.android_set_log_frontend
      and liblog-benchmarks before and after.
Bug: 27405083
Change-Id: I365dbee9f7d83112da0ef8d1cace748d247773c8
2017-02-08 13:37:41 -08:00
Mark Salyzyn
c9e5f37166 liblog: add android_lookupEventTagNum
android_lookupEventTagNum added.  Adds support for creating a new
log tag at runtime, registered to the logd service.

Tested on Hikey, all services stopped, shell only access, CPUs not
locked (there is enough repeatability on this platform).

$ /data/nativetest64/liblog-benchmarks/liblog-benchmarks BM_lookupEventTagNum

                          iterations      ns/op
Precharge: start
Precharge: stop 231
NB: only Tag matching, linear lookup (as reference, before unordered_map)
BM_lookupEventTagNum         1000000       1017
NB: unordered_map with full Tag & Format lookup, but with Tag hashing
BM_lookupEventTagNum         2000000        683
NB: with full Tag & Format hash and lookup for matching
BM_lookupEventTagNum         2000000        814
NB: only Tag matching (Hail Mary path)
BM_lookupEventTagNum         5000000        471

Because the database can now be dynamic, we added reader/writer locks
which adds a 65ns (uncontended) premium on lookups, and switch to
check for an allocation adds 25ns (either open code, or using
string_view, no difference) which means our overall speed takes 90%
as long as the requests did before we switched to unordered_map.
Faster than before where we originally utilized binary lookup on
static content, but not by much.  Dynamic updates that are not cached
locally take the following times to acquire long path to logd to
generate.

BM_lookupEventTag           20000000         139
BM_lookupEventTag_NOT       20000000         87
BM_lookupEventFormat        20000000         139
BM_lookupEventTagNum_logd_new   5000         335936
BM_lookupEventTagNum_logd_existing 10000     249226

The long path pickups are mitigated by the built-in caching, and
the public mapping in /dev/event-log-tags.

SideEffects: Event tags and signal handlers do not mix
Test: liblog benchmarks
Bug: 31456426
Change-Id: I69e6489d899cf35cdccffcee0d8d7cad469ada0a
2017-02-02 15:21:15 -08:00
Mark Salyzyn
21de8aca67 liblog: add log/log_read.h
Move log reading definitions to their own home.

struct logger_entry
struct logger_entry_v2
struct logger_entry_v3
struct logger_entry_v4
LOGGER_ENTRY_MAX_PAYLOAD
LOGGER_ENTRY_MAX_LEN
struct log_msg
android_logger_get_id()
android_logger_clear()
android_logger_get_log_size()
android_logger_get_log_readable_size()
struct logger_list
android_logger_get_statistics()
android_logger_get_prune_list()
android_logger_set_prune_list()
android_logger_list_alloc()
android_logger_list_alloc_time()
android_logger_list_free()
android_logger_list_read()
android_logger_open()
android_logger_list_open()

Deal with a possible scenario where fcntl.h was not included at the
top of the source files, and log/log_read.h inclusion of fcntl.h
conflicts with a source file inclusion of sys/cdefs.h definition of
__unused macro.

Test: gTest liblog-unit-tests --gtest_filter=\
      liblog.__android_log_write__android_logger_list_read:\
      liblog.android_logger_get_
Bug: 34250038
Change-Id: Ib33544171563d6a351164754c254c4385686025b
2017-01-26 21:13:31 +00:00
Mark Salyzyn
52c140ca72 liblog: add log/log_time.h
Move log_time definitions to their own home.

struct log_time

Test: gTest liblog-unit-tests --gtest_filter=liblog.log_time
Bug: 34250038
Change-Id: I400cf4cc865d1c167699a4654ecb69455a18e604
2017-01-25 15:41:43 -08:00
Mark Salyzyn
dd61659e73 liblog: add log/log_system.h
Move SLOG logging macros to their own home.

SLOGV
SLOGV_IF
SLOGD
SLOGD_IF
SLOGI
SLOGI_IF
SLOGW
SLOGW_IF
SLOGE
SLOGE_IF

Test: gTest liblog-unit-tests --gtest_filter=liblog.SLOG
Bug: 34250038
Change-Id: I456c7ad23152dc1c7b39143d87401a8737e24d64
2017-01-25 15:41:43 -08:00
Mark Salyzyn
c89fea44ac liblog: add log/log_radio.h
Move RLOG logging macros to their own home.

RLOGV
RLOGV_IF
RLOGD
RLOGD_IF
RLOGI
RLOGI_IF
RLOGW
RLOGW_IF
RLOGE
RLOGE_IF

Test: gTest liblog-unit-tests --gtest_filter=liblog.RLOG
Bug: 34250038
Change-Id: Iad5b5abf23c7a537ff5293bb55a6633dce2e837d
2017-01-25 15:41:43 -08:00