From 3485eb0fbcfbb9d4ad227eb420730523cd081120 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn <> Date: Tue, 24 Mar 2009 18:36:55 -0700 Subject: Automated import from //branches/donutburger/...@140818,140818 --- tests/cpueater/NOTICE | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++ timeinfo/NOTICE | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 380 insertions(+) create mode 100644 tests/cpueater/NOTICE create mode 100644 timeinfo/NOTICE diff --git a/tests/cpueater/NOTICE b/tests/cpueater/NOTICE new file mode 100644 index 00000000..c5b1efa7 --- /dev/null +++ b/tests/cpueater/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/timeinfo/NOTICE b/timeinfo/NOTICE new file mode 100644 index 00000000..c5b1efa7 --- /dev/null +++ b/timeinfo/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + -- cgit v1.2.3 From 26c4c5f3205f521de9c6b420341fe67ec16810dc Mon Sep 17 00:00:00 2001 From: Dianne Hackborn <> Date: Fri, 27 Mar 2009 20:59:40 -0700 Subject: AI 143417: am: CL 143416 Quick and dirty backup command. This should only be included in dev builds. Original author: hackbod Merged from: //branches/cupcake/... Automated import of CL 143417 --- backup/Android.mk | 15 ++ backup/NOTICE | 190 +++++++++++++++ backup/backup.cpp | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 879 insertions(+) create mode 100644 backup/Android.mk create mode 100644 backup/NOTICE create mode 100644 backup/backup.cpp diff --git a/backup/Android.mk b/backup/Android.mk new file mode 100644 index 00000000..6a3d3fee --- /dev/null +++ b/backup/Android.mk @@ -0,0 +1,15 @@ +# Copyright 2009 The Android Open Source Project + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= backup.cpp + +LOCAL_SHARED_LIBRARIES := libcutils libc + +LOCAL_MODULE:= backup + +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := debug + +include $(BUILD_EXECUTABLE) diff --git a/backup/NOTICE b/backup/NOTICE new file mode 100644 index 00000000..c5b1efa7 --- /dev/null +++ b/backup/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/backup/backup.cpp b/backup/backup.cpp new file mode 100644 index 00000000..48f64eec --- /dev/null +++ b/backup/backup.cpp @@ -0,0 +1,674 @@ +// Copyright 2009 The Android Open Source Project + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#define FILE_VERSION 0xffff0001 + +namespace android { + +static char nameBuffer[PATH_MAX]; +static struct stat statBuffer; + +static char copyBuffer[8192]; + +#define SPECIAL_NO_TOUCH 0 +#define SPECIAL_NO_BACKUP 1 + +struct special_dir { + const char* path; + int type; +}; + +/* Directory paths that we will not backup/restore */ +static const struct special_dir SKIP_PATHS[] = { + { "/data/misc", SPECIAL_NO_TOUCH }, + { "/data/system/batterystats.bin", SPECIAL_NO_TOUCH }, + { "/data/system/location", SPECIAL_NO_TOUCH }, + { "/data/dalvik-cache", SPECIAL_NO_BACKUP }, + { NULL, 0 }, +}; + +/* This is just copied from the shell's built-in wipe command. */ +static int wipe (const char *path) +{ + DIR *dir; + struct dirent *de; + int ret; + int i; + + dir = opendir(path); + + if (dir == NULL) { + fprintf (stderr, "Error opendir'ing %s: %s\n", + path, strerror(errno)); + return 0; + } + + char *filenameOffset; + + strcpy(nameBuffer, path); + strcat(nameBuffer, "/"); + + filenameOffset = nameBuffer + strlen(nameBuffer); + + for (;;) { + de = readdir(dir); + + if (de == NULL) { + break; + } + + if (0 == strcmp(de->d_name, ".") + || 0 == strcmp(de->d_name, "..") + || 0 == strcmp(de->d_name, "lost+found") + ) { + continue; + } + + strcpy(filenameOffset, de->d_name); + bool noBackup = false; + + /* See if this is a path we should skip. */ + for (i = 0; SKIP_PATHS[i].path; i++) { + if (strcmp(SKIP_PATHS[i].path, nameBuffer) == 0) { + if (SKIP_PATHS[i].type == SPECIAL_NO_BACKUP) { + // In this case we aren't backing up the directory -- + // we do want to wipe its contents, but not the + // directory itself, since the restore file won't + // contain the directory. + noBackup = true; + } + break; + } + } + if (!noBackup && SKIP_PATHS[i].path != NULL) { + continue; + } + + ret = lstat (nameBuffer, &statBuffer); + + if (ret != 0) { + fprintf(stderr, "warning -- stat() error on '%s': %s\n", + nameBuffer, strerror(errno)); + continue; + } + + if(S_ISDIR(statBuffer.st_mode)) { + int i; + char *newpath; + + newpath = strdup(nameBuffer); + if (wipe(newpath) == 0) { + free(newpath); + closedir(dir); + return 0; + } + + if (!noBackup) { + ret = rmdir(newpath); + if (ret != 0) { + fprintf(stderr, "warning -- rmdir() error on '%s': %s\n", + newpath, strerror(errno)); + } + } + + free(newpath); + + strcpy(nameBuffer, path); + strcat(nameBuffer, "/"); + + } else { + ret = unlink(nameBuffer); + + if (ret != 0) { + fprintf(stderr, "warning -- unlink() error on '%s': %s\n", + nameBuffer, strerror(errno)); + } + } + } + + closedir(dir); + + return 1; +} + +static int write_int32(FILE* fh, int32_t val) +{ + int res = fwrite(&val, 1, sizeof(val), fh); + if (res != sizeof(val)) { + fprintf(stderr, "unable to write int32 (%d bytes): %s\n", res, strerror(errno)); + return 0; + } + + return 1; +} + +static int write_int64(FILE* fh, int64_t val) +{ + int res = fwrite(&val, 1, sizeof(val), fh); + if (res != sizeof(val)) { + fprintf(stderr, "unable to write int64 (%d bytes): %s\n", res, strerror(errno)); + return 0; + } + + return 1; +} + +static int copy_file(FILE* dest, FILE* src, off_t size, const char* destName, + const char* srcName) +{ + errno = 0; + + off_t origSize = size; + + while (size > 0) { + int amt = size > (off_t)sizeof(copyBuffer) ? sizeof(copyBuffer) : (int)size; + int readLen = fread(copyBuffer, 1, amt, src); + if (readLen <= 0) { + if (srcName != NULL) { + fprintf(stderr, "unable to read source (%d of %ld bytes) file '%s': %s\n", + amt, origSize, srcName, errno != 0 ? strerror(errno) : "unexpected EOF"); + } else { + fprintf(stderr, "unable to read buffer (%d of %ld bytes): %s\n", + amt, origSize, errno != 0 ? strerror(errno) : "unexpected EOF"); + } + return 0; + } + int writeLen = fwrite(copyBuffer, 1, readLen, dest); + if (writeLen != readLen) { + if (destName != NULL) { + fprintf(stderr, "unable to write file (%d of %d bytes) '%s': '%s'\n", + writeLen, readLen, destName, strerror(errno)); + } else { + fprintf(stderr, "unable to write buffer (%d of %d bytes): '%s'\n", + writeLen, readLen, strerror(errno)); + } + return 0; + } + size -= readLen; + } + return 1; +} + +#define TYPE_END 0 +#define TYPE_DIR 1 +#define TYPE_FILE 2 + +static int write_header(FILE* fh, int type, const char* path, const struct stat* st) +{ + int pathLen = strlen(path); + if (!write_int32(fh, type)) return 0; + if (!write_int32(fh, pathLen)) return 0; + if (fwrite(path, 1, pathLen, fh) != (size_t)pathLen) { + fprintf(stderr, "unable to write: %s\n", strerror(errno)); + return 0; + } + + if (!write_int32(fh, st->st_uid)) return 0; + if (!write_int32(fh, st->st_gid)) return 0; + if (!write_int32(fh, st->st_mode)) return 0; + if (!write_int64(fh, ((int64_t)st->st_atime)*1000*1000*1000)) return 0; + if (!write_int64(fh, ((int64_t)st->st_mtime)*1000*1000*1000)) return 0; + if (!write_int64(fh, ((int64_t)st->st_ctime)*1000*1000*1000)) return 0; + + return 1; +} + +static int backup_dir(FILE* fh, const char* srcPath) +{ + DIR *dir; + struct dirent *de; + char* fullPath = NULL; + int srcLen = strlen(srcPath); + int result = 1; + int i; + + dir = opendir(srcPath); + + if (dir == NULL) { + fprintf (stderr, "error opendir'ing '%s': %s\n", + srcPath, strerror(errno)); + return 0; + } + + for (;;) { + de = readdir(dir); + + if (de == NULL) { + break; + } + + if (0 == strcmp(de->d_name, ".") + || 0 == strcmp(de->d_name, "..") + || 0 == strcmp(de->d_name, "lost+found") + ) { + continue; + } + + if (fullPath == NULL) { + free(fullPath); + } + fullPath = (char*)malloc(srcLen + strlen(de->d_name) + 2); + strcpy(fullPath, srcPath); + fullPath[srcLen] = '/'; + strcpy(fullPath+srcLen+1, de->d_name); + + /* See if this is a path we should skip. */ + for (i = 0; SKIP_PATHS[i].path; i++) { + if (strcmp(SKIP_PATHS[i].path, fullPath) == 0) { + break; + } + } + if (SKIP_PATHS[i].path != NULL) { + continue; + } + + int ret = lstat(fullPath, &statBuffer); + + if (ret != 0) { + fprintf(stderr, "stat() error on '%s': %s\n", + fullPath, strerror(errno)); + result = 0; + goto done; + } + + if(S_ISDIR(statBuffer.st_mode)) { + printf("Processing dir %s...\n", fullPath); + + if (write_header(fh, TYPE_DIR, fullPath, &statBuffer) == 0) { + result = 0; + goto done; + } + if (backup_dir(fh, fullPath) == 0) { + result = 0; + goto done; + } + } else { + printf("Processing file %s...\n", fullPath); + + if (write_header(fh, TYPE_FILE, fullPath, &statBuffer) == 0) { + result = 0; + goto done; + } + + off_t size = statBuffer.st_size; + if (!write_int64(fh, size)) { + result = 0; + goto done; + } + + FILE* src = fopen(fullPath, "r"); + if (src == NULL) { + fprintf(stderr, "unable to open source file '%s': %s\n", + fullPath, strerror(errno)); + result = 0; + goto done; + } + + int copyres = copy_file(fh, src, size, NULL, fullPath); + fclose(src); + if (!copyres) { + result = 0; + goto done; + } + } + } + +done: + if (fullPath != NULL) { + free(fullPath); + } + + closedir(dir); + + return result; +} + +static int backup_data(const char* destPath) +{ + int res = -1; + + FILE* fh = fopen(destPath, "w"); + if (fh == NULL) { + fprintf(stderr, "unable to open destination '%s': %s\n", + destPath, strerror(errno)); + return -1; + } + + printf("Backing up /data to %s...\n", destPath); + + if (!write_int32(fh, FILE_VERSION)) goto done; + if (!backup_dir(fh, "/data")) goto done; + if (!write_int32(fh, 0)) goto done; + + res = 0; + +done: + if (fflush(fh) != 0) { + fprintf(stderr, "error flushing destination '%s': %s\n", + destPath, strerror(errno)); + res = -1; + goto donedone; + } + if (fsync(fileno(fh)) != 0) { + fprintf(stderr, "error syncing destination '%s': %s\n", + destPath, strerror(errno)); + res = -1; + goto donedone; + } + fclose(fh); + sync(); + +donedone: + return res; +} + +static int32_t read_int32(FILE* fh, int32_t defVal) +{ + int32_t val; + if (fread(&val, 1, sizeof(val), fh) != sizeof(val)) { + fprintf(stderr, "unable to read: %s\n", strerror(errno)); + return defVal; + } + + return val; +} + +static int64_t read_int64(FILE* fh, int64_t defVal) +{ + int64_t val; + if (fread(&val, 1, sizeof(val), fh) != sizeof(val)) { + fprintf(stderr, "unable to read: %s\n", strerror(errno)); + return defVal; + } + + return val; +} + +static int read_header(FILE* fh, int* type, char** path, struct stat* st) +{ + *type = read_int32(fh, -1); + if (*type == TYPE_END) { + return 1; + } + + if (*type < 0) { + fprintf(stderr, "bad token %d in restore file\n", *type); + return 0; + } + + int32_t pathLen = read_int32(fh, -1); + if (pathLen <= 0) { + fprintf(stderr, "bad path length %d in restore file\n", pathLen); + return 0; + } + char* readPath = (char*)malloc(pathLen+1); + if (fread(readPath, 1, pathLen, fh) != (size_t)pathLen) { + fprintf(stderr, "truncated path in restore file\n"); + free(readPath); + return 0; + } + readPath[pathLen] = 0; + *path = readPath; + + st->st_uid = read_int32(fh, -1); + if (st->st_uid == (uid_t)-1) { + fprintf(stderr, "bad uid in restore file at '%s'\n", readPath); + return 0; + } + st->st_gid = read_int32(fh, -1); + if (st->st_gid == (gid_t)-1) { + fprintf(stderr, "bad gid in restore file at '%s'\n", readPath); + return 0; + } + st->st_mode = read_int32(fh, -1); + if (st->st_mode == (mode_t)-1) { + fprintf(stderr, "bad mode in restore file at '%s'\n", readPath); + return 0; + } + int64_t ltime = read_int64(fh, -1); + if (ltime < 0) { + fprintf(stderr, "bad atime in restore file at '%s'\n", readPath); + return 0; + } + st->st_atime = (time_t)(ltime/1000/1000/1000); + ltime = read_int64(fh, -1); + if (ltime < 0) { + fprintf(stderr, "bad mtime in restore file at '%s'\n", readPath); + return 0; + } + st->st_mtime = (time_t)(ltime/1000/1000/1000); + ltime = read_int64(fh, -1); + if (ltime < 0) { + fprintf(stderr, "bad ctime in restore file at '%s'\n", readPath); + return 0; + } + st->st_ctime = (time_t)(ltime/1000/1000/1000); + + st->st_mode &= (S_IRWXU|S_IRWXG|S_IRWXO); + + return 1; +} + +static int restore_data(const char* srcPath) +{ + int res = -1; + + FILE* fh = fopen(srcPath, "r"); + if (fh == NULL) { + fprintf(stderr, "Unable to open source '%s': %s\n", + srcPath, strerror(errno)); + return -1; + } + + if (read_int32(fh, 0) != (int32_t)FILE_VERSION) { + fprintf(stderr, "Restore file has bad version\n"); + goto done; + } + + printf("Wiping contents of /data...\n"); + if (!wipe("/data")) { + goto done; + } + + printf("Restoring from %s to /data...\n", srcPath); + + while (1) { + int type; + char* path = NULL; + if (read_header(fh, &type, &path, &statBuffer) == 0) { + goto done; + } + if (type == 0) { + break; + } + + const char* typeName = "?"; + + if (type == TYPE_DIR) { + typeName = "dir"; + + printf("Processing dir %s...\n", path); + + if (mkdir(path, statBuffer.st_mode) != 0) { + if (errno != EEXIST) { + fprintf(stderr, "unable to create directory '%s': %s\n", + path, strerror(errno)); + free(path); + goto done; + } + } + + } else if (type == TYPE_FILE) { + typeName = "file"; + off_t size = read_int64(fh, -1); + if (size < 0) { + fprintf(stderr, "bad file size %ld in restore file\n", size); + free(path); + goto done; + } + + printf("Processing file %s...\n", path); + + FILE* dest = fopen(path, "w"); + if (dest == NULL) { + fprintf(stderr, "unable to open destination file '%s': %s\n", + path, strerror(errno)); + free(path); + goto done; + } + + int copyres = copy_file(dest, fh, size, path, NULL); + fclose(dest); + if (!copyres) { + free(path); + goto done; + } + + } else { + fprintf(stderr, "unknown node type %d\n", type); + goto done; + } + + // Do this even for directories, since the dir may have already existed + // so we need to make sure it gets the correct mode. + if (chmod(path, statBuffer.st_mode&(S_IRWXU|S_IRWXG|S_IRWXO)) != 0) { + fprintf(stderr, "unable to chmod destination %s '%s' to 0x%x: %s\n", + typeName, path, statBuffer.st_mode, strerror(errno)); + free(path); + goto done; + } + + if (chown(path, statBuffer.st_uid, statBuffer.st_gid) != 0) { + fprintf(stderr, "unable to chown destination %s '%s' to uid %d / gid %d: %s\n", + typeName, path, (int)statBuffer.st_uid, (int)statBuffer.st_gid, strerror(errno)); + free(path); + goto done; + } + + struct utimbuf timbuf; + timbuf.actime = statBuffer.st_atime; + timbuf.modtime = statBuffer.st_mtime; + if (utime(path, &timbuf) != 0) { + fprintf(stderr, "unable to utime destination %s '%s': %s\n", + typeName, path, strerror(errno)); + free(path); + goto done; + } + + + free(path); + } + + res = 0; + +done: + fclose(fh); + + return res; +} + +static void show_help(const char *cmd) +{ + fprintf(stderr,"Usage: %s [options] [backup-file-path]\n", cmd); + + fprintf(stderr, "options include:\n" + " -r Perform restore of previous backup.\n"); +} + +} /* namespace android */ + +int main (int argc, char **argv) +{ + int restore = 0; + + if (getuid() != AID_ROOT) { + fprintf(stderr, "error -- %s must run as root\n", argv[0]); + exit(-1); + } + + if (argc == 2 && 0 == strcmp(argv[1], "--help")) { + android::show_help(argv[0]); + exit(0); + } + + for (;;) { + int ret; + + ret = getopt(argc, argv, "r"); + + if (ret < 0) { + break; + } + + switch(ret) { + case 'r': + restore = 1; + break; + + default: + fprintf(stderr,"Unrecognized Option\n"); + android::show_help(argv[0]); + exit(-1); + break; + } + } + + const char* backupFile = "/sdcard/backup.dat"; + + if (argc > optind) { + backupFile = argv[optind]; + optind++; + if (argc != optind) { + fprintf(stderr, "Too many arguments\n"); + android::show_help(argv[0]); + exit(-1); + } + } + + printf("Stopping system...\n"); + property_set("ctl.stop", "runtime"); + property_set("ctl.stop", "zygote"); + sleep(1); + + int res; + if (restore) { + res = android::restore_data(backupFile); + if (res != 0) { + // Don't restart system, since the data partition is hosed. + return res; + } + printf("Restore complete! Restarting system, cross your fingers...\n"); + } else { + res = android::backup_data(backupFile); + if (res == 0) { + printf("Backup complete! Restarting system...\n"); + } else { + printf("Restarting system...\n"); + } + } + + property_set("ctl.start", "zygote"); + property_set("ctl.start", "runtime"); +} -- cgit v1.2.3 From 3cb2639f22f8aaf46852c9f03e825e05fc7e7362 Mon Sep 17 00:00:00 2001 From: Niko Catania <> Date: Mon, 30 Mar 2009 12:50:58 -0700 Subject: AI 143504: Completed cstddef to be non empty and similar to the gnu stl implementation. Even if we don't want to have a bloated stl implementation, having empty files around is probably not very good either. Added a test to make sure the header file compiles on host and kila-eng. QA Impact: In system/extras/test/bionic/libstdc++ build the tests using: mm BIONIC_TESTS=1 to build the host and target tests. BUG=1601432 Automated import of CL 143504 --- tests/bionic/libc/README.TXT | 2 +- tests/bionic/libstdc++/Android.mk | 66 +++++++++++++++++++++ tests/bionic/libstdc++/README.TXT | 14 +++++ tests/bionic/libstdc++/test_cstddef.cpp | 102 ++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 tests/bionic/libstdc++/Android.mk create mode 100644 tests/bionic/libstdc++/README.TXT create mode 100644 tests/bionic/libstdc++/test_cstddef.cpp diff --git a/tests/bionic/libc/README.TXT b/tests/bionic/libc/README.TXT index 5576b77b..7618f2b7 100644 --- a/tests/bionic/libc/README.TXT +++ b/tests/bionic/libc/README.TXT @@ -7,7 +7,7 @@ GNU Lesser General Public License (LGPL) You must define the BIONIC_TESTS environment variable to build these test programs. For example, do: - cd system/bionic-tests/ + cd system/extras/tests/bionic/libc mm BIONIC_TESTS=1 All test programs, except those in the 'other' directory, should exit diff --git a/tests/bionic/libstdc++/Android.mk b/tests/bionic/libstdc++/Android.mk new file mode 100644 index 00000000..fca89f6b --- /dev/null +++ b/tests/bionic/libstdc++/Android.mk @@ -0,0 +1,66 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Build control file for Bionic's test programs +# define the BIONIC_TESTS environment variable to build the test programs +# + +ifdef BIONIC_TESTS + +LOCAL_PATH:= $(call my-dir) + +# used to define a simple test program and build it as a standalone +# device executable. +# +# you can use EXTRA_CFLAGS to indicate additional CFLAGS to use +# in the build. the variable will be cleaned on exit +# +define device-test + $(foreach file,$(1), \ + $(eval include $(CLEAR_VARS)) \ + $(eval LOCAL_SRC_FILES := $(file)) \ + $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ + $(eval $(info LOCAL_MODULE=$(LOCAL_MODULE))) \ + $(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \ + $(eval LOCAL_MODULE_TAGS := tests) \ + $(eval include $(BUILD_EXECUTABLE)) \ + ) \ + $(eval EXTRA_CFLAGS :=) +endef + +# same as 'device-test' but builds a host executable instead +# you can use EXTRA_LDLIBS to indicate additional linker flags +# +define host-test + $(foreach file,$(1), \ + $(eval include $(CLEAR_VARS)) \ + $(eval LOCAL_SRC_FILES := $(file)) \ + $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ + $(eval $(info LOCAL_MODULE=$(LOCAL_MODULE) file=$(file))) \ + $(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \ + $(eval LOCAL_LDLIBS += $(EXTRA_LDLIBS)) \ + $(eval LOCAL_MODULE_TAGS := tests) \ + $(eval include $(BUILD_HOST_EXECUTABLE)) \ + ) \ + $(eval EXTRA_CFLAGS :=) \ + $(eval EXTRA_LDLIBS :=) +endef + +sources := \ + test_cstddef.cpp + +$(call host-test, $(sources)) +$(call device-test, $(sources)) + +endif # BIONIC_TESTS diff --git a/tests/bionic/libstdc++/README.TXT b/tests/bionic/libstdc++/README.TXT new file mode 100644 index 00000000..90d40ea9 --- /dev/null +++ b/tests/bionic/libstdc++/README.TXT @@ -0,0 +1,14 @@ +This directory contains a set of tests for Android's Bionic Standard C++ library. + +You must define the BIONIC_TESTS environment variable to build these +test programs. For example, do: + + cd system/extras/tests/bionic/libstdc++ + mm BIONIC_TESTS=1 + +All test programs should exit with a status code of 0 in case of success, and 1 +in case of failure. + +The directory layout is currently flat because there is one Bionic test. If you +want to add GNU STDC++ or benchmark tests, look in tests/bionic/libc as an +example how to structure your files. diff --git a/tests/bionic/libstdc++/test_cstddef.cpp b/tests/bionic/libstdc++/test_cstddef.cpp new file mode 100644 index 00000000..7526d3c5 --- /dev/null +++ b/tests/bionic/libstdc++/test_cstddef.cpp @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// Test that including cstddef works. This should be the only include in this +// file to make sure that we don't pick definitions without us knowing. +#include + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android { +// Dummy struct used to calculate offset of some of its fields. +struct Foo +{ + char field1; + char field2; +}; + +// Check various types are declared in the std namespace. +bool testTypesStd() +{ + // size_t should be defined in both namespaces + volatile ::size_t size_t_in_top_ns = 0; + volatile ::std::size_t size_t_in_std_ns = 0; + + if (sizeof(::size_t) != sizeof(::std::size_t)) + { + return false; + } + + // ptrdiff_t should be defined in both namespaces + volatile ::ptrdiff_t ptrdiff_t_in_top_ns = 0; + volatile ::std::ptrdiff_t ptrdiff_t_in_std_ns = 0; + + if (sizeof(::ptrdiff_t) != sizeof(::std::ptrdiff_t)) + { + return false; + } + // NULL is only in the top namespace + volatile int *null_is_defined = NULL; + return true; +} + +bool testOffsetOf() +{ +#ifndef offsetof +#error "offsetof is not a macro" +#endif + + // offsetof is only in the top namespace + volatile size_t offset = offsetof(struct Foo, field2); + return offset == 1; +} + +bool testNull() +{ +#ifndef NULL +#error "NULL is not a macro" +#endif + // If NULL is void* this will issue a warning. + volatile int null_is_not_void_star = NULL; + return true; +} + +} // android namespace + +int main(int argc, char **argv) +{ + FAIL_UNLESS(testTypesStd); + FAIL_UNLESS(testOffsetOf); + FAIL_UNLESS(testNull); + return kPassed; +} -- cgit v1.2.3 From 84011c7599ab8a4463cefda5e8ce8a59987640d8 Mon Sep 17 00:00:00 2001 From: Niko Catania <> Date: Thu, 2 Apr 2009 09:31:49 -0700 Subject: AI 144236: Added new C to stdc++ header files: cassert, cctype, climits, ctime. QA Impact:None BUG=1601432 Automated import of CL 144236 --- tests/bionic/libstdc++/Android.mk | 6 +- tests/bionic/libstdc++/test_cassert.cpp | 46 ++++++++++++++ tests/bionic/libstdc++/test_cctype.cpp | 96 +++++++++++++++++++++++++++++ tests/bionic/libstdc++/test_climits.cpp | 82 ++++++++++++++++++++++++ tests/bionic/libstdc++/test_cstddef.cpp | 1 - tests/bionic/libstdc++/test_ctime.cpp | 106 ++++++++++++++++++++++++++++++++ 6 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 tests/bionic/libstdc++/test_cassert.cpp create mode 100644 tests/bionic/libstdc++/test_cctype.cpp create mode 100644 tests/bionic/libstdc++/test_climits.cpp create mode 100644 tests/bionic/libstdc++/test_ctime.cpp diff --git a/tests/bionic/libstdc++/Android.mk b/tests/bionic/libstdc++/Android.mk index fca89f6b..4446c87f 100644 --- a/tests/bionic/libstdc++/Android.mk +++ b/tests/bionic/libstdc++/Android.mk @@ -58,7 +58,11 @@ define host-test endef sources := \ - test_cstddef.cpp + test_cassert.cpp \ + test_cctype.cpp \ + test_climits.cpp \ + test_cstddef.cpp \ + test_ctime.cpp $(call host-test, $(sources)) $(call device-test, $(sources)) diff --git a/tests/bionic/libstdc++/test_cassert.cpp b/tests/bionic/libstdc++/test_cassert.cpp new file mode 100644 index 00000000..efe73fe5 --- /dev/null +++ b/tests/bionic/libstdc++/test_cassert.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// Test that including cassert works. +#include + +namespace { +const int kPassed = 0; +} // anonymous namespace + +namespace android +{ +#ifndef assert +#error "assert must be a macro" +#endif +} // android namespace + +int main(int argc, char **argv) +{ + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_cctype.cpp b/tests/bionic/libstdc++/test_cctype.cpp new file mode 100644 index 00000000..ad6312b6 --- /dev/null +++ b/tests/bionic/libstdc++/test_cctype.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +namespace { +const int kPassed = 0; +} // anonymous namespace + +namespace android +{ +#ifdef isalnum +#error "should be a real function" +#endif +#ifdef isalpha +#error "should be a real function" +#endif +#ifdef iscntrl +#error "should be a real function" +#endif +#ifdef isdigit +#error "should be a real function" +#endif +#ifdef isgraph +#error "should be a real function" +#endif +#ifdef islower +#error "should be a real function" +#endif +#ifdef isprint +#error "should be a real function" +#endif +#ifdef ispunct +#error "should be a real function" +#endif +#ifdef isspace +#error "should be a real function" +#endif +#ifdef isupper +#error "should be a real function" +#endif +#ifdef isxdigit +#error "should be a real function" +#endif +#ifdef tolower +#error "should be a real function" +#endif +#ifdef toupper +#error "should be a real function" +#endif + +using std::isalnum; +using std::isdigit; +using std::isprint; +using std::isupper; +using std::tolower; +using std::isalpha; +using std::isgraph; +using std::ispunct; +using std::isxdigit; +using std::toupper; +using std::iscntrl; +using std::islower; +using std::isspace; + +} // namespace android + +int main(int argc, char **argv) +{ + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_climits.cpp b/tests/bionic/libstdc++/test_climits.cpp new file mode 100644 index 00000000..2e5c59ef --- /dev/null +++ b/tests/bionic/libstdc++/test_climits.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +bool testLimits() +{ + // char + volatile char c1 = CHAR_BIT; + volatile char c2 = CHAR_MAX; + volatile char c3 = CHAR_MIN; + + // int + volatile int i1 = INT_MAX; + volatile int i2 = INT_MIN; + + // short + volatile short s1 = SHRT_MAX; + volatile short s2 = SHRT_MIN; + + // long + volatile long l1 = LONG_MAX; + volatile long l2 = LONG_MIN; + + // long long + volatile long long ll1 = LLONG_MAX; + volatile long long ll2 = LLONG_MIN; + + volatile unsigned long mb = MB_LEN_MAX; + + // signed char + volatile signed char sc1 = SCHAR_MIN; + volatile signed char sc2 = SCHAR_MAX; + + // unsigned + volatile unsigned int ui = UINT_MAX; + volatile unsigned short us = USHRT_MAX; + volatile unsigned long ul = ULONG_MAX; + volatile unsigned long long ull = ULLONG_MAX; + + return true; +} + +} // namespace android + +int main(int argc, char **argv) +{ + FAIL_UNLESS(testLimits); + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_cstddef.cpp b/tests/bionic/libstdc++/test_cstddef.cpp index 7526d3c5..e918c589 100644 --- a/tests/bionic/libstdc++/test_cstddef.cpp +++ b/tests/bionic/libstdc++/test_cstddef.cpp @@ -1,4 +1,3 @@ -/* -*- c++ -*- */ /* * Copyright (C) 2009 The Android Open Source Project * All rights reserved. diff --git a/tests/bionic/libstdc++/test_ctime.cpp b/tests/bionic/libstdc++/test_ctime.cpp new file mode 100644 index 00000000..f812b312 --- /dev/null +++ b/tests/bionic/libstdc++/test_ctime.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +#ifndef CLOCKS_PER_SEC +#error "CLOCKS_PER_SEC must be a macro" +#endif + +#ifdef clock +#error "should be a real function" +#endif +#ifdef difftime +#error "should be a real function" +#endif +#ifdef mktime +#error "should be a real function" +#endif +#ifdef time +#error "should be a real function" +#endif +#ifdef asctime +#error "should be a real function" +#endif +#ifdef ctime +#error "should be a real function" +#endif +#ifdef gmtime +#error "should be a real function" +#endif +#ifdef localtime +#error "should be a real function" +#endif +#ifdef strftime +#error "should be a real function" +#endif + +using std::clock; +using std::difftime; +using std::mktime; +using std::time; +using std::asctime; +using std::ctime; +using std::gmtime; +using std::localtime; +using std::strftime; + +// Check various types are declared in the std namespace. +// This is a compilation test. +bool testTypesStd() +{ + volatile std::clock_t clock; + volatile std::time_t time; + volatile std::tm better_time; + return true; +} + +bool testGetClock() +{ + volatile std::clock_t clock1 = std::clock(); + volatile std::clock_t clock2 = std::clock(); + if (clock2 < clock1) return false; + return true; +} + +} // namespace android + +int main(int argc, char **argv) +{ + FAIL_UNLESS(testTypesStd); + FAIL_UNLESS(testGetClock); + return kPassed; +} -- cgit v1.2.3 From 1aa5708e437b96e04f31d9c9f167427411ba5510 Mon Sep 17 00:00:00 2001 From: Niko Catania <> Date: Wed, 8 Apr 2009 09:01:38 -0700 Subject: AI 145059: (Almost) final set of wrapper around the C headers for stdc++ and their tests. The only one left is cstring. * bionic/libstdc++/include/cstdlib: * bionic/libstdc++/include/cstdio: * bionic/libstdc++/include/cstdint: * bionic/libstdc++/include/csignal: * bionic/libstdc++/include/csetjmp: Added header file. Checks the bionic headers file were picked up instead of the host ones. Added test for new header files * system/extras/tests/bionic/libstdc++/Android.mk: Added tests for the new header files. EXTRA_CFLAGS: include the bionic header files. BUG=1601432 Automated import of CL 145059 --- tests/bionic/libstdc++/Android.mk | 8 ++ tests/bionic/libstdc++/README.TXT | 5 + tests/bionic/libstdc++/test_cassert.cpp | 5 +- tests/bionic/libstdc++/test_cctype.cpp | 4 + tests/bionic/libstdc++/test_climits.cpp | 6 ++ tests/bionic/libstdc++/test_csetjmp.cpp | 65 +++++++++++++ tests/bionic/libstdc++/test_csignal.cpp | 68 +++++++++++++ tests/bionic/libstdc++/test_cstddef.cpp | 6 +- tests/bionic/libstdc++/test_cstdint.cpp | 45 +++++++++ tests/bionic/libstdc++/test_cstdio.cpp | 166 ++++++++++++++++++++++++++++++++ tests/bionic/libstdc++/test_cstdlib.cpp | 49 ++++++++++ tests/bionic/libstdc++/test_ctime.cpp | 4 + 12 files changed, 428 insertions(+), 3 deletions(-) create mode 100644 tests/bionic/libstdc++/test_csetjmp.cpp create mode 100644 tests/bionic/libstdc++/test_csignal.cpp create mode 100644 tests/bionic/libstdc++/test_cstdint.cpp create mode 100644 tests/bionic/libstdc++/test_cstdio.cpp create mode 100644 tests/bionic/libstdc++/test_cstdlib.cpp diff --git a/tests/bionic/libstdc++/Android.mk b/tests/bionic/libstdc++/Android.mk index 4446c87f..2151676b 100644 --- a/tests/bionic/libstdc++/Android.mk +++ b/tests/bionic/libstdc++/Android.mk @@ -61,10 +61,18 @@ sources := \ test_cassert.cpp \ test_cctype.cpp \ test_climits.cpp \ + test_csetjmp.cpp \ + test_csignal.cpp \ test_cstddef.cpp \ + test_cstdint.cpp \ + test_cstdio.cpp \ + test_cstdlib.cpp \ test_ctime.cpp +EXTRA_CFLAGS := -I bionic/libstdc++/include $(call host-test, $(sources)) + +EXTRA_CFLAGS := -I bionic/libstdc++/include $(call device-test, $(sources)) endif # BIONIC_TESTS diff --git a/tests/bionic/libstdc++/README.TXT b/tests/bionic/libstdc++/README.TXT index 90d40ea9..aa7f8a46 100644 --- a/tests/bionic/libstdc++/README.TXT +++ b/tests/bionic/libstdc++/README.TXT @@ -6,9 +6,14 @@ test programs. For example, do: cd system/extras/tests/bionic/libstdc++ mm BIONIC_TESTS=1 +Preferably, to build and run you can use this: + + runtest_py libstdcpp + All test programs should exit with a status code of 0 in case of success, and 1 in case of failure. The directory layout is currently flat because there is one Bionic test. If you want to add GNU STDC++ or benchmark tests, look in tests/bionic/libc as an example how to structure your files. + diff --git a/tests/bionic/libstdc++/test_cassert.cpp b/tests/bionic/libstdc++/test_cassert.cpp index efe73fe5..67c96deb 100644 --- a/tests/bionic/libstdc++/test_cassert.cpp +++ b/tests/bionic/libstdc++/test_cassert.cpp @@ -26,8 +26,11 @@ * SUCH DAMAGE. */ -// Test that including cassert works. + #include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CASSERT__ +#error "Wrong header file included!!" +#endif namespace { const int kPassed = 0; diff --git a/tests/bionic/libstdc++/test_cctype.cpp b/tests/bionic/libstdc++/test_cctype.cpp index ad6312b6..bedb77fb 100644 --- a/tests/bionic/libstdc++/test_cctype.cpp +++ b/tests/bionic/libstdc++/test_cctype.cpp @@ -27,6 +27,10 @@ */ #include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CCTYPE__ +#error "Wrong header file included!!" +#endif + namespace { const int kPassed = 0; diff --git a/tests/bionic/libstdc++/test_climits.cpp b/tests/bionic/libstdc++/test_climits.cpp index 2e5c59ef..f3ce0232 100644 --- a/tests/bionic/libstdc++/test_climits.cpp +++ b/tests/bionic/libstdc++/test_climits.cpp @@ -25,7 +25,13 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + + #include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CLIMITS__ +#error "Wrong header file included!!" +#endif + namespace { const int kPassed = 0; diff --git a/tests/bionic/libstdc++/test_csetjmp.cpp b/tests/bionic/libstdc++/test_csetjmp.cpp new file mode 100644 index 00000000..9b314909 --- /dev/null +++ b/tests/bionic/libstdc++/test_csetjmp.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSETJMP__ +#error "Wrong header file included!!" +#endif + + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +#ifdef longjmp +#error "longjmp must not be a macro" +#endif + +#ifndef setjmp +#error "setjmp must be a macro" +#endif + +using std::longjmp; + +bool testJmpbuf() +{ + volatile std::jmp_buf jmpbuf; + return true; +} + +} // namespace android + +int main(int argc, char **argv) +{ + FAIL_UNLESS(testJmpbuf); + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_csignal.cpp b/tests/bionic/libstdc++/test_csignal.cpp new file mode 100644 index 00000000..22fa946f --- /dev/null +++ b/tests/bionic/libstdc++/test_csignal.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSIGNAL__ +#error "Wrong header file included!!" +#endif + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +#ifdef raise +#error "raise must not be a macro" +#endif + +#ifndef SIGABRT +#error "SIGABRT must be a macro" +#endif + +#ifndef SIGILL +#error "SIGILL must be a macro" +#endif + +using std::raise; +using std::signal; +bool testSigAtomicT() +{ + volatile std::sig_atomic_t s; + return true; +} + +} // namespace android + +int main(int argc, char **argv) +{ + FAIL_UNLESS(testSigAtomicT); + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_cstddef.cpp b/tests/bionic/libstdc++/test_cstddef.cpp index e918c589..19f9d422 100644 --- a/tests/bionic/libstdc++/test_cstddef.cpp +++ b/tests/bionic/libstdc++/test_cstddef.cpp @@ -26,9 +26,11 @@ * SUCH DAMAGE. */ -// Test that including cstddef works. This should be the only include in this -// file to make sure that we don't pick definitions without us knowing. #include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSTDDEF__ +#error "Wrong header file included!!" +#endif + namespace { const int kPassed = 0; diff --git a/tests/bionic/libstdc++/test_cstdint.cpp b/tests/bionic/libstdc++/test_cstdint.cpp new file mode 100644 index 00000000..8753cf7d --- /dev/null +++ b/tests/bionic/libstdc++/test_cstdint.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSTDINT__ +#error "Wrong header file included!!" +#endif + +namespace { +const int kPassed = 0; +} // anonymous namespace + +namespace android +{ +} // namespace android + +int main(int argc, char **argv) +{ + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_cstdio.cpp b/tests/bionic/libstdc++/test_cstdio.cpp new file mode 100644 index 00000000..573746dc --- /dev/null +++ b/tests/bionic/libstdc++/test_cstdio.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSTDIO__ +#error "Wrong header file included!!" +#endif + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +#ifndef BUFSIZ +#error "BUFSIZ must be a macro" +#endif + +#ifndef EOF +#error "EOF must be a macro" +#endif + +#ifndef FILENAME_MAX +#error "FILENAME_MAX must be a macro" +#endif + +#ifndef FOPEN_MAX +#error "FOPEN_MAX must be a macro" +#endif + +#ifndef L_tmpnam +#error "L_tmpnam must be a macro" +#endif + +#ifndef NULL +#error "NULL must be a macro" +#endif + +#ifndef SEEK_CUR +#error "SEEK_CUR must be a macro" +#endif + +#ifndef SEEK_END +#error "SEEK_END must be a macro" +#endif +#ifndef SEEK_SET +#error "SEEK_SET must be a macro" +#endif + +#ifndef TMP_MAX +#error "TMP_MAX must be a macro" +#endif + +#ifndef _IOFBF +#error "_IOFBF must be a macro" +#endif + +#ifndef _IOLBF +#error "_IOLBF must be a macro" +#endif + +#ifndef _IONBF +#error "_IONBF must be a macro" +#endif + +#ifndef stderr +#error "stderr must be a macro" +#endif + +#ifndef stdin +#error "stdin must be a macro" +#endif + +#ifndef stdout +#error "stdout must be a macro" +#endif + +using std::clearerr; +using std::fclose; +using std::feof; +using std::ferror; +using std::fflush; +using std::fgetc; +using std::fgetpos; +using std::fgets; +using std::fopen; +using std::fprintf; +using std::fputc; +using std::fputs; +using std::fread; +using std::freopen; +using std::fscanf; +using std::fseek; +using std::fsetpos; +using std::ftell; +using std::fwrite; +using std::getc; +using std::getchar; +using std::gets; +using std::perror; +using std::printf; +using std::putc; +using std::putchar; +using std::puts; +using std::remove; +using std::rename; +using std::rewind; +using std::scanf; +using std::setbuf; +using std::setvbuf; +using std::sprintf; +using std::sscanf; +using std::tmpfile; +using std::tmpnam; +using std::ungetc; +using std::vfprintf; +using std::vprintf; +using std::vsprintf; + +using std::snprintf; +using std::vfscanf; +using std::vscanf; +using std::vsnprintf; +using std::vsscanf; + +bool testTypesStd() +{ + volatile std::size_t size; + volatile std::FILE file; + volatile std::fpos_t fpos_t; + return true; +} +} // namespace android + +int main(int argc, char **argv) +{ + FAIL_UNLESS(testTypesStd); + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_cstdlib.cpp b/tests/bionic/libstdc++/test_cstdlib.cpp new file mode 100644 index 00000000..c5c914c4 --- /dev/null +++ b/tests/bionic/libstdc++/test_cstdlib.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSTDLIB__ +#error "Wrong header file included!!" +#endif + + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +} // namespace android + +int main(int argc, char **argv) +{ + // FAIL_UNLESS(testTypesStd); + return kPassed; +} diff --git a/tests/bionic/libstdc++/test_ctime.cpp b/tests/bionic/libstdc++/test_ctime.cpp index f812b312..72a13cb9 100644 --- a/tests/bionic/libstdc++/test_ctime.cpp +++ b/tests/bionic/libstdc++/test_ctime.cpp @@ -27,6 +27,10 @@ */ #include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CTIME__ +#error "Wrong header file included!!" +#endif + namespace { const int kPassed = 0; -- cgit v1.2.3 From 8c88d7d48dc60adcfef4c1e6b6ef6ac255cfc16d Mon Sep 17 00:00:00 2001 From: Niko Catania <> Date: Fri, 10 Apr 2009 10:51:56 -0700 Subject: AI 145714: Added cstring wrapper around string.h. In new, include cstddef which declares std::size_t. BUG=1601432 Automated import of CL 145714 --- tests/bionic/libstdc++/Android.mk | 1 + tests/bionic/libstdc++/test_cstring.cpp | 76 +++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 tests/bionic/libstdc++/test_cstring.cpp diff --git a/tests/bionic/libstdc++/Android.mk b/tests/bionic/libstdc++/Android.mk index 2151676b..b76949ef 100644 --- a/tests/bionic/libstdc++/Android.mk +++ b/tests/bionic/libstdc++/Android.mk @@ -67,6 +67,7 @@ sources := \ test_cstdint.cpp \ test_cstdio.cpp \ test_cstdlib.cpp \ + test_cstring.cpp \ test_ctime.cpp EXTRA_CFLAGS := -I bionic/libstdc++/include diff --git a/tests/bionic/libstdc++/test_cstring.cpp b/tests/bionic/libstdc++/test_cstring.cpp new file mode 100644 index 00000000..eab64a1e --- /dev/null +++ b/tests/bionic/libstdc++/test_cstring.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSTRING__ +#error "Wrong header file included!!" +#endif + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +using std::memchr; +using std::memcmp; +using std::memcpy; +using std::memmove; +using std::memset; +using std::strcat; +using std::strchr; +using std::strcmp; +using std::strcoll; +using std::strcpy; +using std::strcspn; +using std::strerror; +using std::strlen; +using std::strncat; +using std::strncmp; +using std::strncpy; +using std::strpbrk; +using std::strrchr; +using std::strspn; +using std::strstr; +using std::strtok; +using std::strxfrm; + +#ifndef NULL +#error "NULL must be a macro" +#endif + +volatile std::size_t size; + +} // namespace android + +int main(int argc, char **argv) +{ + return kPassed; +} -- cgit v1.2.3 From acbb5bc99bccf7e625cc73fb1aaa90355bedb733 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Thu, 30 Apr 2009 18:45:16 -0700 Subject: fb_test: Look for fbdev in several possible locations. Also, only try to set console graphics mode if we have an fbcon. This should make this utility a little more robust, and a hopefully more useful for bringup. Signed-off-by: Dima Zavin --- tests/framebuffer/fb_test.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/tests/framebuffer/fb_test.c b/tests/framebuffer/fb_test.c index 6fdbf3b3..3bd7e8e5 100644 --- a/tests/framebuffer/fb_test.c +++ b/tests/framebuffer/fb_test.c @@ -59,9 +59,12 @@ static int get_framebuffer(GGLSurface *fb) void *bits; fd = open("/dev/graphics/fb0", O_RDWR); - if(fd < 0) { - perror("cannot open fb0"); - return -1; + if (fd < 0) { + printf("cannot open /dev/graphics/fb0, retrying with /dev/fb0\n"); + if ((fd = open("/dev/fb0", O_RDWR)) < 0) { + perror("cannot open /dev/fb0"); + return -1; + } } if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { @@ -127,22 +130,26 @@ static void dumpinfo(struct fb_fix_screeninfo *fi, struct fb_var_screeninfo *vi) int gr_init(void) { - int fd; - + int fd = -1; - fd = open("/dev/tty0", O_RDWR | O_SYNC); - if(fd < 0) return -1; + if (!access("/dev/tty0", F_OK)) { + fd = open("/dev/tty0", O_RDWR | O_SYNC); + if(fd < 0) + return -1; - if(ioctl(fd, KDSETMODE, (void*) KD_GRAPHICS)) { - close(fd); - return -1; + if(ioctl(fd, KDSETMODE, (void*) KD_GRAPHICS)) { + close(fd); + return -1; + } } gr_fb_fd = get_framebuffer(gr_framebuffer); if(gr_fb_fd < 0) { - ioctl(fd, KDSETMODE, (void*) KD_TEXT); - close(fd); + if (fd >= 0) { + ioctl(fd, KDSETMODE, (void*) KD_TEXT); + close(fd); + } return -1; } @@ -160,9 +167,11 @@ void gr_exit(void) close(gr_fb_fd); gr_fb_fd = -1; - ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT); - close(gr_vt_fd); - gr_vt_fd = -1; + if (gr_vt_fd >= 0) { + ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT); + close(gr_vt_fd); + gr_vt_fd = -1; + } } int gr_fb_width(void) -- cgit v1.2.3 From ac6a88edbf65ff3f9e40d6e4bf1e55a002be6d6c Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Tue, 5 May 2009 15:54:39 +0200 Subject: Add a new test to check the behaviour of getaddrinfo() --- tests/bionic/libc/Android.mk | 1 + tests/bionic/libc/common/test_getaddrinfo.c | 44 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/bionic/libc/common/test_getaddrinfo.c diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk index 89d9ade2..c7e7305d 100644 --- a/tests/bionic/libc/Android.mk +++ b/tests/bionic/libc/Android.mk @@ -59,6 +59,7 @@ endef # First, the tests in 'common' sources := \ + common/test_getaddrinfo.c \ common/test_gethostbyname.c \ common/test_gethostname.c \ common/test_pthread_cleanup_push.c \ diff --git a/tests/bionic/libc/common/test_getaddrinfo.c b/tests/bionic/libc/common/test_getaddrinfo.c new file mode 100644 index 00000000..444bef8e --- /dev/null +++ b/tests/bionic/libc/common/test_getaddrinfo.c @@ -0,0 +1,44 @@ +/* this program is used to test that getaddrinfo() works correctly + * without a 'hints' argument + */ + +#include +#include +#include + +#include /* for printf */ +#include /* for memset */ +#include /* for IPPROTO_TCP */ + +#define SERVER_NAME "www.android.com" +#define PORT_NUMBER "9999" + +int main(void) +{ + struct addrinfo hints; + struct addrinfo* res; + int ret; + + /* first, try without any hints */ + ret = getaddrinfo( SERVER_NAME, PORT_NUMBER, NULL, &res); + if (ret != 0) { + printf("first getaddrinfo returned error: %s\n", gai_strerror(ret)); + return 1; + } + + freeaddrinfo(res); + + /* now try with the hints */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + ret = getaddrinfo( SERVER_NAME, PORT_NUMBER, &hints, &res ); + if (ret != 0) { + printf("second getaddrinfo returned error: %s\n", gai_strerror(ret)); + return 1; + } + + return 0; +} -- cgit v1.2.3 From fb96abdcfc53dc0c4ff0450c0afd192d6ba570c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Thu, 7 May 2009 20:48:46 -0700 Subject: Bring timetest back. --- tests/timetest/Android.mk | 19 ++++++++ tests/timetest/timetest.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 tests/timetest/Android.mk create mode 100644 tests/timetest/timetest.c diff --git a/tests/timetest/Android.mk b/tests/timetest/Android.mk new file mode 100644 index 00000000..918dea18 --- /dev/null +++ b/tests/timetest/Android.mk @@ -0,0 +1,19 @@ +# Copyright 2006 The Android Open Source Project + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= timetest.c + +LOCAL_MODULE:= timetest + +LOCAL_MODULE_TAGS := tests + +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) +LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) + +LOCAL_STATIC_LIBRARIES := libc + +include $(BUILD_EXECUTABLE) + diff --git a/tests/timetest/timetest.c b/tests/timetest/timetest.c new file mode 100644 index 00000000..baba36e2 --- /dev/null +++ b/tests/timetest/timetest.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + + + +long long nanotime(void) +{ + struct timespec t; + + if(clock_gettime(CLOCK_MONOTONIC, &t)) { + fprintf(stderr,"clock failure\n"); + exit(1); + } + + return (((long long) t.tv_sec) * 1000000000LL) + + ((long long) t.tv_nsec); +} + +static struct timespec ts_sub(struct timespec a, struct timespec b) +{ + struct timespec r; + r.tv_sec = a.tv_sec - b.tv_sec; + r.tv_nsec = a.tv_nsec - b.tv_nsec; + if(r.tv_nsec < 0) { + r.tv_sec--; + r.tv_nsec += 1000 * 1000 * 1000; + } + if(r.tv_sec < 0 && r.tv_nsec > 0) { + r.tv_sec++; + r.tv_nsec -= 1000 * 1000 * 1000; + } + return r; +} + +static struct timespec ts_min(struct timespec a, struct timespec b) +{ + if(a.tv_sec < b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_nsec < b.tv_nsec)) + return a; + else + return b; +} + +static struct timespec ts_max(struct timespec a, struct timespec b) +{ + if(a.tv_sec < b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_nsec < b.tv_nsec)) + return b; + else + return a; +} + +int main(int argc, char **argv) +{ + long long tnow, tlast; + struct timespec t1, dtmin, dtminp, dtmax; + int print_interval = 50000; + int print_countdown = 1; + int clock_id = CLOCK_MONOTONIC; + dtmin.tv_sec = INT_MAX; + dtmin.tv_nsec = 0; + dtminp.tv_sec = INT_MAX; + dtminp.tv_nsec = 0; + dtmax.tv_sec = 0; + dtmax.tv_nsec = 0; + tlast = 0; + + if(argc == 2) { + clock_id = atoi(argv[1]); + printf("using clock %d\n", clock_id); + } + clock_gettime(clock_id, &t1); + + for(;;) { + struct timespec t, dt; + clock_gettime(clock_id, &t); + dt = ts_sub(t, t1); + t1 = t; + dtmin = ts_min(dtmin, dt); + if(dt.tv_sec > 0 || dt.tv_nsec > 0) + dtminp = ts_min(dtminp, dt); + if(print_countdown != print_interval) + dtmax = ts_max(dtmax, dt); + if(--print_countdown == 0) { + fprintf(stderr,"%09ld.%09ld, dt %ld.%09ld, min %ld.%09ld, minp %ld.%09ld, max %ld.%09ld\n", + t.tv_sec, t.tv_nsec, dt.tv_sec, dt.tv_nsec, + dtmin.tv_sec, dtmin.tv_nsec, dtminp.tv_sec, dtminp.tv_nsec, + dtmax.tv_sec, dtmax.tv_nsec); + print_countdown = print_interval; + } + } + for(;;) { + tnow = nanotime(); + if(tnow < tlast) { +#if 0 + fprintf(stderr,"time went backwards: %lld -> %lld\n", + tlast, tnow); + exit(1); +#endif + fprintf(stderr,"%lld ROLLBACK\n", tnow); + } else { + fprintf(stderr,"%lld\n", tnow); + } + tlast = tnow; + } + + return 0; +} -- cgit v1.2.3 From 89f9b9118a393ca5ca16467ec9e5e3e4a84690b5 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Mon, 18 May 2009 11:15:24 -0700 Subject: showmap: Add support for 2.6.29 Signed-off-by: San Mehat --- showmap/showmap.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/showmap/showmap.c b/showmap/showmap.c index 4abd56a8..2a028eea 100644 --- a/showmap/showmap.c +++ b/showmap/showmap.c @@ -77,8 +77,11 @@ again: if(sscanf(line, "Private_Clean: %d kB", &mi->private_clean) != 1) goto oops; if(fgets(line, 1024, fp) == 0) goto oops; if(sscanf(line, "Private_Dirty: %d kB", &mi->private_dirty) != 1) goto oops; - if(fgets(line, 1024, fp) == 0) goto oops; - if(fgets(line, 1024, fp) == 0) goto oops; + + if(fgets(line, 1024, fp) == 0) goto oops; // Referenced + if(fgets(line, 1024, fp) == 0) goto oops; // Swap + if(fgets(line, 1024, fp) == 0) goto oops; // KernelPageSize + if(fgets(line, 1024, fp) == 0) goto oops; // MMUPageSize if(skip) { free(mi); -- cgit v1.2.3 From 4c0461001130e5ea3cd45997598863599837d9d8 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Mon, 18 May 2009 23:34:57 +0200 Subject: Add test --- tests/bionic/libstdc++/Android.mk | 1 + tests/bionic/libstdc++/test_cmath.cpp | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 tests/bionic/libstdc++/test_cmath.cpp diff --git a/tests/bionic/libstdc++/Android.mk b/tests/bionic/libstdc++/Android.mk index b76949ef..103b3274 100644 --- a/tests/bionic/libstdc++/Android.mk +++ b/tests/bionic/libstdc++/Android.mk @@ -61,6 +61,7 @@ sources := \ test_cassert.cpp \ test_cctype.cpp \ test_climits.cpp \ + test_cmath.cpp \ test_csetjmp.cpp \ test_csignal.cpp \ test_cstddef.cpp \ diff --git a/tests/bionic/libstdc++/test_cmath.cpp b/tests/bionic/libstdc++/test_cmath.cpp new file mode 100644 index 00000000..438fb649 --- /dev/null +++ b/tests/bionic/libstdc++/test_cmath.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CMATH__ +#error "Wrong header file included!!" +#endif + + +namespace { +const int kPassed = 0; +const int kFailed = 1; +#define FAIL_UNLESS(f) if (!android::f()) return kFailed; +} // anonymous namespace + +namespace android +{ +using ::cos; +using ::sin; +using ::tan; +using ::acos; +using ::asin; +using ::atan; +using ::atan2; + +using ::cosh; +using ::sinh; +using ::tanh; + +using ::exp; +using ::frexp; +using ::ldexp; +using ::log; +using ::log10; +using ::modf; + +using ::pow; +using ::sqrt; + +using ::ceil; +using ::fabs; +using ::floor; +using ::fmod; + +} // namespace android + +int main(int argc, char **argv) +{ + return kPassed; +} -- cgit v1.2.3 From 611cdccd9690a9083816f6d4746e998d58250a86 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Thu, 28 May 2009 17:37:31 +0200 Subject: Add a new unit test that checks that the static C++ constructors of shared libraries and dynamic executables are called only once, and in the correct order. --- tests/bionic/libc/Android.mk | 19 +++++++++++++++++ tests/bionic/libc/bionic/lib_static_init.cpp | 18 ++++++++++++++++ tests/bionic/libc/bionic/lib_static_init.h | 15 ++++++++++++++ tests/bionic/libc/bionic/test_static_init.cpp | 30 +++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 tests/bionic/libc/bionic/lib_static_init.cpp create mode 100644 tests/bionic/libc/bionic/lib_static_init.h create mode 100644 tests/bionic/libc/bionic/test_static_init.cpp diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk index c7e7305d..4e4bcc64 100644 --- a/tests/bionic/libc/Android.mk +++ b/tests/bionic/libc/Android.mk @@ -30,6 +30,7 @@ define device-test $(eval include $(CLEAR_VARS)) \ $(eval LOCAL_SRC_FILES := $(file)) \ $(eval LOCAL_MODULE := $(notdir $(file:%.c=%))) \ + $(eval LOCAL_MODULE := $(LOCAL_MODULE:%.cpp=%)) \ $(eval $(info LOCAL_MODULE=$(LOCAL_MODULE))) \ $(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \ $(eval LOCAL_MODULE_TAGS := tests) \ @@ -46,6 +47,7 @@ define host-test $(eval include $(CLEAR_VARS)) \ $(eval LOCAL_SRC_FILES := $(file)) \ $(eval LOCAL_MODULE := $(notdir $(file:%.c=%))) \ + $(eval LOCAL_MODULE := $(LOCAL_MODULE:%.cpp=%)) \ $(eval $(info LOCAL_MODULE=$(LOCAL_MODULE) file=$(file))) \ $(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \ $(eval LOCAL_LDLIBS += $(EXTRA_LDLIBS)) \ @@ -128,6 +130,23 @@ LOCAL_MODULE := test_relocs LOCAL_SHARED_LIBRARIES := libtest_relocs include $(BUILD_EXECUTABLE) +# This test tries to see if the static constructors in a +# shared library are only called once. We thus need to +# build a shared library, then call it from another +# program. +# +include $(CLEAR_VARS) +LOCAL_SRC_FILES := bionic/lib_static_init.cpp +LOCAL_MODULE := libtest_static_init +LOCAL_PRELINK_MODULE := false +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := bionic/test_static_init.cpp +LOCAL_MODULE := test_static_init +LOCAL_SHARED_LIBRARIES := libtest_static_init +include $(BUILD_EXECUTABLE) + # TODO: Add a variety of GLibc test programs too... # Hello World to test libstdc++ support diff --git a/tests/bionic/libc/bionic/lib_static_init.cpp b/tests/bionic/libc/bionic/lib_static_init.cpp new file mode 100644 index 00000000..d847110a --- /dev/null +++ b/tests/bionic/libc/bionic/lib_static_init.cpp @@ -0,0 +1,18 @@ +#include "lib_static_init.h" +#include + +Foo::Foo() +{ + /* increment the static variable */ + value = ++Foo::counter; + fprintf(stderr, "Foo::Foo for this=%p called (counter = %d)\n", this, counter); +} + +int Foo::getValue() +{ + return value; +} + +int Foo::counter; + +Foo theFoo; diff --git a/tests/bionic/libc/bionic/lib_static_init.h b/tests/bionic/libc/bionic/lib_static_init.h new file mode 100644 index 00000000..f455de8e --- /dev/null +++ b/tests/bionic/libc/bionic/lib_static_init.h @@ -0,0 +1,15 @@ +#ifndef _lib_static_init_h +#define _lib_static_init_h + +class Foo { +private: + int value; + static int counter; +public: + virtual int getValue(); + Foo(); +}; + +extern Foo theFoo; + +#endif /* _lib_static_init_h */ diff --git a/tests/bionic/libc/bionic/test_static_init.cpp b/tests/bionic/libc/bionic/test_static_init.cpp new file mode 100644 index 00000000..cbc4a59d --- /dev/null +++ b/tests/bionic/libc/bionic/test_static_init.cpp @@ -0,0 +1,30 @@ +#include +#include +#include "lib_static_init.h" + +Foo theFoo2; + +int main(int argc, char** argv) +{ + int c = theFoo.getValue(); + + /* check the counter on the library object + * it must have been called first, and only once + */ + if (c != 1) { + printf("KO (counter(shared) == %d, expected 1)\n", c); + return 1; + } + + /* check the counter on the executable object, + * it must have been called second, and only once + */ + c = theFoo2.getValue(); + if (c != 2) { + printf("KO (counter(executable) == %d, expected 2)\n", c); + return 1; + } + + printf("OK\n"); + return 0; +} -- cgit v1.2.3 From 39c016f875b793296a121f41de5775b88f6fa1c9 Mon Sep 17 00:00:00 2001 From: Nicolas Catania Date: Mon, 18 May 2009 16:08:12 -0700 Subject: Load test for the sdcard. Simulate loads on the sdcard for write, read and open operations using one or more process. The number of processes to run concurently can be specified on the command line. The size of the file and the number of iterations (for averaging result) are also a command line flag. The user can have summary of the performance plus the raw data for processing with a separate tool. There is a basic python script to help plotting the result. --- tests/sdcard/Android.mk | 37 +++ tests/sdcard/plot_sdcard.py | 200 +++++++++++++ tests/sdcard/sdcard_perf_test.cpp | 607 ++++++++++++++++++++++++++++++++++++++ tests/sdcard/stopwatch.cpp | 226 ++++++++++++++ tests/sdcard/stopwatch.h | 155 ++++++++++ tests/sdcard/sysutil.cpp | 604 +++++++++++++++++++++++++++++++++++++ tests/sdcard/sysutil.h | 146 +++++++++ tests/sdcard/testcase.cpp | 228 ++++++++++++++ tests/sdcard/testcase.h | 163 ++++++++++ 9 files changed, 2366 insertions(+) create mode 100644 tests/sdcard/Android.mk create mode 100755 tests/sdcard/plot_sdcard.py create mode 100644 tests/sdcard/sdcard_perf_test.cpp create mode 100644 tests/sdcard/stopwatch.cpp create mode 100644 tests/sdcard/stopwatch.h create mode 100644 tests/sdcard/sysutil.cpp create mode 100644 tests/sdcard/sysutil.h create mode 100644 tests/sdcard/testcase.cpp create mode 100644 tests/sdcard/testcase.h diff --git a/tests/sdcard/Android.mk b/tests/sdcard/Android.mk new file mode 100644 index 00000000..d1e06f25 --- /dev/null +++ b/tests/sdcard/Android.mk @@ -0,0 +1,37 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Build control file for Bionic's test programs +# define the BIONIC_TESTS environment variable to build the test programs +# + +ifdef SDCARD_TESTS + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES = \ + stopwatch.cpp \ + sysutil.cpp \ + sdcard_perf_test.cpp \ + testcase.cpp + +LOCAL_MODULE := sdcard_perf_test +LOCAL_MODULE_TAGS := eng tests +LOCAL_SHARED_LIBRARIES := libutils libhardware_legacy + +include $(BUILD_EXECUTABLE) + +endif # SDCARD_TESTS diff --git a/tests/sdcard/plot_sdcard.py b/tests/sdcard/plot_sdcard.py new file mode 100755 index 00000000..10ee00ba --- /dev/null +++ b/tests/sdcard/plot_sdcard.py @@ -0,0 +1,200 @@ +#!/usr/bin/python2.5 +# +# Copyright 2009 Google Inc. All Rights Reserved. + +"""plot_sdcard: A module to plot the results of an sdcard perf test. + +Requires Gnuplot python v 1.8 + +Typical usage: + +python +>>> import plot_sdcard as p +>>> (metadata, data) = p.parse('/tmp/data.txt') +>>> p.plotIterations(metadata, data) +>>> p.plotTimes(metadata, data) + +""" + +#TODO: provide a main so we can pipe the result from the run +#TODO: more comments... + +import Gnuplot +from numpy import * +import sys +import re +from itertools import izip + +class DataSet(object): + def __init__(self, line): + res = re.search('# StopWatch ([\w]+) total/cumulative duration ([0-9.]+)\. Samples: ([0-9]+)', line) + self.time = [] + self.data = [] + self.name = res.group(1) + self.duration = float(res.group(2)) + self.iteration = int(res.group(3)) + print "Name: %s Duration: %f Iterations: %d" % (self.name, self.duration, self.iteration) + self.summary = re.match('([a-z_]+)_total', self.name) + + def __repr__(self): + return str(zip(self.time, self.data)) + + def add(self, time, value): + self.time.append(time) + self.data.append(value) + + def rescaleTo(self, length): + factor = len(self.data) / length + + if factor > 1: + new_time = [] + new_data = [] + accum = 0.0 + idx = 1 + for t,d in izip(self.time, self.data): + accum += d + if idx % factor == 0: + new_time.append(t) + new_data.append(accum / factor) + accum = 0 + idx += 1 + self.time = new_time + self.data = new_data + + +class Metadata(object): + def __init__(self): + self.kernel = '' + self.command_line = '' + self.sched = '' + self.name = '' + self.fadvise = '' + self.iterations = 0 + self.duration = 0.0 + self.complete = False + + def parse(self, line): + if line.startswith('# Kernel:'): + self.kernel = re.search('Linux version ([0-9.]+-[0-9]+)', line).group(1) + elif line.startswith('# Command:'): + self.command_line = re.search('# Command: [/\w_]+ (.*)', line).group(1) + self.command_line = self.command_line.replace(' --', '-') + self.command_line = self.command_line.replace(' -d', '') + self.command_line = self.command_line.replace('--test=', '') + elif line.startswith('# Iterations'): + self.iterations = int(re.search('# Iterations: ([0-9]+)', line).group(1)) + elif line.startswith('# Fadvise'): + self.fadvise = int(re.search('# Fadvise: ([\w]+)', line).group(1)) + elif line.startswith("# Sched"): + self.sched = re.search('# Sched features: ([\w]+)', line).group(1) + self.complete = True + + def asTitle(self): + return "%s-duration:%f\\n-%s\\n%s" % (self.kernel, self.duration, self.command_line, self.sched) + + def updateWith(self, dataset): + self.duration = max(self.duration, dataset.duration) + self.name = dataset.name + + +def plotIterations(metadata, data): + gp = Gnuplot.Gnuplot(persist = 1) + gp('set data style lines') + gp.clear() + gp.xlabel("iterations") + gp.ylabel("duration in second") + gp.title(metadata.asTitle()) + styles = {} + line_style = 1 + + for dataset in data: + dataset.rescaleTo(metadata.iterations) + x = arange(len(dataset.data), dtype='int_') + if not dataset.name in styles: + styles[dataset.name] = line_style + line_style += 1 + d = Gnuplot.Data(x, dataset.data, + title=dataset.name, + with_='lines ls %d' % styles[dataset.name]) + else: # no need to repeat a title that exists already. + d = Gnuplot.Data(x, dataset.data, + with_='lines ls %d' % styles[dataset.name]) + + gp.replot(d) + gp.hardcopy('/tmp/%s-%s-%f.png' % (metadata.name, metadata.kernel, metadata.duration), terminal='png') + +def plotTimes(metadata, data): + gp = Gnuplot.Gnuplot(persist = 1) + gp('set data style impulses') + gp('set xtics 1') + gp.clear() + gp.xlabel("seconds") + gp.ylabel("duration in second") + gp.title(metadata.asTitle()) + styles = {} + line_style = 1 + + for dataset in data: + #dataset.rescaleTo(metadata.iterations) + x = array(dataset.time, dtype='float_') + if not dataset.name in styles: + styles[dataset.name] = line_style + line_style += 1 + d = Gnuplot.Data(x, dataset.data, + title=dataset.name, + with_='impulses ls %d' % styles[dataset.name]) + else: # no need to repeat a title that exists already. + d = Gnuplot.Data(x, dataset.data, + with_='impulses ls %d' % styles[dataset.name]) + + gp.replot(d) + gp.hardcopy('/tmp/%s-%s-%f.png' % (metadata.name, metadata.kernel, metadata.duration), terminal='png') + + +def parse(filename): + f = open(filename, 'r') + + metadata = Metadata() + data = [] # array of dataset + dataset = None + + for num, line in enumerate(f): + try: + line = line.strip() + if not line: continue + + if not metadata.complete: + metadata.parse(line) + continue + + if re.match('[a-z_]', line): + continue + + if line.startswith('# StopWatch'): # Start of a new dataset + if dataset: + if dataset.summary: + metadata.updateWith(dataset) + else: + data.append(dataset) + + dataset = DataSet(line) + continue + + if line.startswith('#'): + continue + + # must be data at this stage + try: + (time, value) = line.split(None, 1) + except ValueError: + print "skipping line %d: %s" % (num, line) + continue + + if dataset and not dataset.summary: + dataset.add(float(time), float(value)) + + except Exception, e: + print "Error parsing line %d" % num, sys.exc_info()[0] + raise + data.append(dataset) + return (metadata, data) diff --git a/tests/sdcard/sdcard_perf_test.cpp b/tests/sdcard/sdcard_perf_test.cpp new file mode 100644 index 00000000..28069b9a --- /dev/null +++ b/tests/sdcard/sdcard_perf_test.cpp @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stopwatch.h" +#include "sysutil.h" +#include "testcase.h" + +// Stress test for the sdcard. Use this to generate some load on the +// sdcard and collect performance statistics. The ouput is either a +// human readable report or the raw timing samples that can be +// processed using another tool. +// +// Needs debugfs: +// adb root; +// adb shell mount -t debugfs none /sys/kernel/debug +// +// The following tests are defined (value of the --test flag): +// write: Open a file write some random data and close. +// read: Open a file read it and close. +// read_write: Combine readers and writers. +// open_create: Open|create an non existing file. +// +// For each run you can control how many processes will run the test in +// parallel to simulate a real load (--procnb flag) +// +// For each process, the test selected will be executed many time to +// get a meaningful average/min/max (--iterations flag) +// +// Use --dump to also get the raw data. +// +// For read/write tests, size is the number of Kbytes to use. +// +// To build: mmm system/extras/tests/sdcard/Android.mk SDCARD_TESTS=1 +// +// Examples: +// adb shell /system/bin/sdcard_perf_test --test=read --size=1000 --chunk-size=100 --procnb=1 --iterations=10 --dump > /tmp/data.txt +// adb shell /system/bin/sdcard_perf_test --test=write --size=1000 --chunk-size=100 --procnb=1 --iterations=100 --dump > /tmp/data.txt +// +// To watch the memory: cat /proc/meminfo +// If the phone crashes, look at /proc/last_kmsg on reboot. +// +// TODO: It would be cool if we could play with various fadvise() +// strategies in here to see how tweaking read-ahead changes things. +// + +extern char *optarg; +extern int optind, opterr, optopt; + +// TODO: No clue where fadvise is. Disabled for now. +#define FADVISE(fd, off, len, advice) (void)0 + +#ifndef min +#define min(a,b) (((a)>(b))?(b):(a)) +#endif + +namespace { +using android::kernelVersion; +using android::kMinKernelVersionBufferSize; +using android::schedFeatures; +using android::kMinSchedFeaturesBufferSize; +using android_test::StopWatch; +using android::writePidAndWaitForReply; +using android::waitForChildrenAndSignal; +using android::waitForChildrenOrExit; +using android_test::TestCase; + +const char *kAppName = "sdcard_perf_test"; +const char *kTestDir = "/sdcard/perf"; +const bool kVerbose = false; + +// Used by getopt to parse the command line. +struct option long_options[] = { + {"size", required_argument, 0, 's'}, + {"chunk-size", required_argument, 0, 'S'}, + {"iterations", required_argument, 0, 'i'}, + {"procnb", required_argument, 0, 'p'}, + {"test", required_argument, 0, 't'}, + {"dump", no_argument, 0, 'd'}, + {"cpu-scaling", no_argument, 0, 'c'}, + {"sync", required_argument, 0, 'f'}, + {"truncate", no_argument, 0, 'e'}, + {"no-new-fair-sleepers", no_argument, 0, 'z'}, + {"no-normalized-sleepers", no_argument, 0, 'Z'}, + {"fadvise", required_argument, 0, 'a'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}, +}; + +void usage() +{ + printf("sdcard_perf_test --test=write|read|read_write|open_create [options]\n\n" + " -t --test: Select the test.\n" + " -s --size: Size in kbytes of the data.\n" + " -S --chunk-size: Size of a chunk. Default to size ie 1 chunk.\n" + " Data will be written/read using that chunk size.\n" + " -i --iterations: Number of time a process should carry its task.\n" + " -p --procnb: Number of processes to use.\n" + " -d --dump: Print the raw timing on stdout.\n" + " -c --cpu-scaling: Enable cpu scaling.\n" + " -s --sync: fsync|sync Use fsync or sync in write test. Default: no sync call.\n" + " -e --truncate: Truncate to size the file on creation.\n" + " -z --no-new-fair-sleepers: Turn them off. You need to mount debugfs.\n" + " -Z --no-normalized-sleepers: Turn them off. You need to mount debugfs.\n" + " -a --fadvise: Specify an fadvise policy (not supported).\n" + ); +} + +// Print command line, pid, kernel version, OOM adj and scheduler. +void printHeader(int argc, char **argv, const TestCase& testCase) +{ + printf("# Command: "); + for (int i = 0; i < argc; ++i) + { + printf("%s ", argv[i]); + } + printf("\n"); + + printf("# Pid: %d\n", getpid()); + + { + char buffer[kMinKernelVersionBufferSize] = {0, }; + if (kernelVersion(buffer, sizeof(buffer)) > 0) + { + printf("# Kernel: %s", buffer); + } + } + + // Earlier on, running this test was crashing the phone. It turned + // out that it was using too much memory but its oom_adj value was + // -17 which means disabled. -16 is the system_server and 0 is + // typically what applications run at. The issue is that adb runs + // at -17 and so is this test. We force oom_adj to 0 unless the + // oom_adj option has been used. + // TODO: We talked about adding an option to control oom_adj, not + // sure if we still need that. + int oomAdj = android::pidOutOfMemoryAdj(); + + printf("# Oom_adj: %d ", oomAdj); + if (oomAdj < 0) + { + android::setPidOutOfMemoryAdj(0); + printf("adjuted to %d", android::pidOutOfMemoryAdj()); + } + printf("\n"); + + { + char buffer[kMinSchedFeaturesBufferSize] = {0, }; + if (schedFeatures(buffer, sizeof(buffer)) > 0) + { + printf("# Sched features: %s", buffer); + } + } + printf("# Fadvise: %s\n", testCase.fadviseAsStr()); +} + +// Remove all the files under kTestDir and clear the caches. +void cleanup() { + android::resetDirectory(kTestDir); + android::syncAndDropCaches(); // don't pollute runs. +} + +// @param argc, argv have a wild guess. +// @param[out] testCase Structure built from the cmd line args. +void parseCmdLine(int argc, char **argv, TestCase *testCase)\ +{ + int c; + + while(true) + { + // getopt_long stores the option index here. + int option_index = 0; + + c = getopt_long (argc, argv, + "hS:s:i:p:t:dcf:ezZa:", + long_options, + &option_index); + // Detect the end of the options. + if (c == -1) break; + + switch (c) + { + case 's': + testCase->setDataSize(atoi(optarg) * 1024); + break; + case 'S': + testCase->setChunkSize(atoi(optarg) * 1024); + break; + case 'i': + testCase->setIter(atoi(optarg)); + printf("# Iterations: %d\n", testCase->iter()); + break; + case 'p': + testCase->setNproc(atoi(optarg)); + printf("# Proc nb: %d\n", testCase->nproc()); + break; + case 't': + testCase->setTypeFromName(optarg); + printf("# Test name %s\n", testCase->name()); + break; + case 'd': + testCase->setDump(); + break; + case 'c': + printf("# Cpu scaling is on\n"); + testCase->setCpuScaling(); + break; + case 'f': + if (strcmp("sync", optarg) == 0) { + testCase->setSync(TestCase::SYNC); + } else if (strcmp("fsync", optarg) == 0) { + testCase->setSync(TestCase::FSYNC); + } + break; + case 'e': // e for empty + printf("# Will truncate to size\n"); + testCase->setTruncateToSize(); + break; + case 'z': // no new fair sleepers + testCase->setNewFairSleepers(false); + break; + case 'Z': // no normalized sleepers + testCase->setNormalizedSleepers(false); + break; + case 'a': // fadvise + testCase->setFadvise(optarg); + break; + case 'h': + usage(); + exit(0); + default: + fprintf(stderr, "Unknown option %s\n", optarg); + exit(EXIT_FAILURE); + } + } +} + +// ---------------------------------------------------------------------- +// READ TEST + +// Read a file. We use a new file each time to avoid any caching +// effect that would happen if we were reading the same file each +// time. +// @param chunk buffer large enough where the chunk read are written. +// @param idx iteration number. +// @param testCase has all the timers and paramters to run the test. + +bool readData(char *const chunk, const int idx, TestCase *testCase) +{ + char filename[80] = {'\0',}; + + sprintf(filename, "%s/file-%d-%d", kTestDir, idx, getpid()); + + testCase->openTimer()->start(); + int fd = open(filename, O_RDONLY); + testCase->openTimer()->stop(); + + if (fd < 0) + { + fprintf(stderr, "Open read only failed."); + return false; + } + FADVISE(fd, 0, 0, testCase->fadvise()); + + size_t left = testCase->dataSize(); + pid_t *pid = (pid_t*)chunk; + while (left > 0) + { + char *dest = chunk; + size_t chunk_size = testCase->chunkSize(); + + if (chunk_size > left) + { + chunk_size = left; + left = 0; + } + else + { + left -= chunk_size; + } + + testCase->readTimer()->start(); + while (chunk_size > 0) + { + ssize_t s = read(fd, dest, chunk_size); + if (s < 0) + { + fprintf(stderr, "Failed to read.\n"); + close(fd); + return false; + } + chunk_size -= s; + dest += s; + } + testCase->readTimer()->stop(); + } + close(fd); + if (testCase->pid() != *pid) + { + fprintf(stderr, "Wrong pid found @ read block %x != %x\n", testCase->pid(), *pid); + return false; + } + else + { + return true; + } +} + + +bool testRead(TestCase *testCase) { + // Setup the testcase by writting some dummy files. + const size_t size = testCase->dataSize(); + size_t chunk_size = testCase->chunkSize(); + char *const chunk = new char[chunk_size]; + + memset(chunk, 0xaa, chunk_size); + *((pid_t *)chunk) = testCase->pid(); // write our pid at the beginning of each chunk + + size_t iter = testCase->iter(); + + // since readers are much faster we increase the number of + // iteration to last longer and have concurrent read/write + // thoughout the whole test. + if (testCase->type() == TestCase::READ_WRITE) + { + iter *= TestCase::kReadWriteFactor; + } + + for (size_t i = 0; i < iter; ++i) + { + char filename[80] = {'\0',}; + + sprintf(filename, "%s/file-%d-%d", kTestDir, i, testCase->pid()); + int fd = open(filename, O_RDWR | O_CREAT); + + size_t left = size; + while (left > 0) + { + if (chunk_size > left) + { + chunk_size = left; + } + ssize_t written = write(fd, chunk, chunk_size); + if (written < 0) + { + fprintf(stderr, "Write failed %d %s.", errno, strerror(errno)); + return false; + } + left -= written; + } + close(fd); + } + if (kVerbose) printf("Child %d all chunk written\n", testCase->pid()); + + android::syncAndDropCaches(); + testCase->signalParentAndWait(); + + // Start the read test. + testCase->testTimer()->start(); + for (size_t i = 0; i < iter; ++i) + { + if (!readData(chunk, i, testCase)) + { + return false; + } + } + testCase->testTimer()->stop(); + + delete [] chunk; + return true; +} + +// ---------------------------------------------------------------------- +// WRITE TEST + +bool writeData(const char *const chunk, const int idx, TestCase *testCase) { + char filename[80] = {'\0',}; + + sprintf(filename, "%s/file-%d-%d", kTestDir, idx, getpid()); + testCase->openTimer()->start(); + int fd = open(filename, O_RDWR | O_CREAT); // no O_TRUNC, see header comment + testCase->openTimer()->stop(); + + if (fd < 0) + { + fprintf(stderr, "Open write failed."); + return false; + } + FADVISE(fd, 0, 0, testCase->fadvise()); + + if (testCase->truncateToSize()) + { + testCase->truncateTimer()->start(); + ftruncate(fd, testCase->dataSize()); + testCase->truncateTimer()->stop(); + } + + size_t left = testCase->dataSize(); + while (left > 0) + { + const char *dest = chunk; + size_t chunk_size = testCase->chunkSize(); + + if (chunk_size > left) + { + chunk_size = left; + left = 0; + } + else + { + left -= chunk_size; + } + + + testCase->writeTimer()->start(); + while (chunk_size > 0) + { + ssize_t s = write(fd, dest, chunk_size); + if (s < 0) + { + fprintf(stderr, "Failed to write.\n"); + close(fd); + return false; + } + chunk_size -= s; + dest += s; + } + testCase->writeTimer()->stop(); + } + + if (TestCase::FSYNC == testCase->sync()) + { + testCase->syncTimer()->start(); + fsync(fd); + testCase->syncTimer()->stop(); + } + else if (TestCase::SYNC == testCase->sync()) + { + testCase->syncTimer()->start(); + sync(); + testCase->syncTimer()->stop(); + } + close(fd); + return true; +} + +bool testWrite(TestCase *testCase) +{ + const size_t size = testCase->dataSize(); + size_t chunk_size = testCase->chunkSize(); + char *data = new char[chunk_size]; + + memset(data, 0xaa, chunk_size); + // TODO: write the pid at the beginning like in the write + // test. Have a mode where we check the write was correct. + testCase->signalParentAndWait(); + + testCase->testTimer()->start(); + for (size_t i = 0; i < testCase->iter(); ++i) + { + if (!writeData(data, i, testCase)) + { + return false; + } + } + testCase->testTimer()->stop(); + delete [] data; + return true; +} + + +// ---------------------------------------------------------------------- +// READ WRITE + +// Mix of read and write test. Even PID run the write test. Odd PID +// the read test. Not fool proof but work most of the time. +bool testReadWrite(TestCase *testCase) +{ + if (getpid() & 0x1) { + return testRead(testCase); + } else { + return testWrite(testCase); + } +} + +// ---------------------------------------------------------------------- +// OPEN CREATE TEST + +bool testOpenCreate(TestCase *testCase) +{ + char filename[80] = {'\0',}; + + testCase->signalParentAndWait(); + testCase->testTimer()->start(); + + for (size_t i = 0; i < testCase->iter(); ++i) + { + sprintf(filename, "%s/file-%d-%d", kTestDir, i, testCase->pid()); + + int fd = open(filename, O_RDWR | O_CREAT); + FADVISE(fd, 0, 0, testCase->fadvise()); + + if (testCase->truncateToSize()) + { + ftruncate(fd, testCase->dataSize()); + } + if (fd < 0) + { + return false; + } + close(fd); + } + testCase->testTimer()->stop(); + return true; +} + +} // anonymous namespace + +int main(int argc, char **argv) +{ + android_test::TestCase testCase(kAppName); + + cleanup(); + + parseCmdLine(argc, argv, &testCase); + printHeader(argc, argv, testCase); + + printf("# File size %d kbytes\n", testCase.dataSize() / 1024); + printf("# Chunk size %d kbytes\n", testCase.chunkSize() / 1024); + printf("# Sync: %s\n", testCase.syncAsStr()); + + if (!testCase.cpuScaling()) + { + android::disableCpuScaling(); + } + + switch(testCase.type()) { + case TestCase::WRITE: + testCase.mTestBody = testWrite; + break; + case TestCase::READ: + testCase.mTestBody = testRead; + break; + case TestCase::OPEN_CREATE: + testCase.mTestBody = testOpenCreate; + break; + case TestCase::READ_WRITE: + testCase.mTestBody = testReadWrite; + break; + default: + fprintf(stderr, "Unknown test type %s", testCase.name()); + exit(EXIT_FAILURE); + } + + testCase.createTimers(); + + bool ok; + + ok = testCase.runTest(); + + cleanup(); + if (!ok) + { + printf("error %d %s", errno, strerror(errno)); + exit(EXIT_FAILURE); + } + else + { + exit(EXIT_SUCCESS); + } +} diff --git a/tests/sdcard/stopwatch.cpp b/tests/sdcard/stopwatch.cpp new file mode 100644 index 00000000..12fe8f1f --- /dev/null +++ b/tests/sdcard/stopwatch.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include "stopwatch.h" + +#define SNPRINTF_OR_RETURN(str, size, format, ...) { \ + int len = snprintf((str), (size), (format), ## __VA_ARGS__); \ + if (len < 0) return; \ + if (len > static_cast(size)) { \ + fprintf(stderr, "Not enough space\n"); \ + return; \ + } else { \ + (size) -= len; (str) += len; \ + } \ + } + +namespace { +const bool kVerbose = false; +bool printRaw = false; +} + +namespace android_test { + +StopWatch::StopWatch(const char *name, size_t capacity) + : mName(strdup(name)), mNum(0), mData(NULL), mDataLen(0), mCapacity(capacity * 2), + mSizeKbytes(0), mAlreadyPrinted(false), mPrintRaw(false), + mDuration(0.0), + mMinDuration(0.0), mMinIdx(0), + mMaxDuration(0.0), mMaxIdx(0), + mDeltas(NULL), mUsed(false) +{ + mStart.tv_sec = 0; + mStart.tv_nsec = 0; + mData = (Measurement *) malloc(mCapacity * sizeof(Measurement)); +} + +StopWatch::~StopWatch() +{ + if (mUsed && !mAlreadyPrinted) + { + fprintf(stderr, "Discarding data for %s\n", mName); + } + free(mData); + free(mName); + delete [] mDeltas; +} + +void StopWatch::start() +{ + checkCapacity(); + clock_gettime(CLOCK_MONOTONIC, &mData[mDataLen].mTime); + mData[mDataLen].mIsStart = true; + if (!mUsed) + { + mStart = mData[mDataLen].mTime; // mDataLen should be 0 + mUsed = true; + } + ++mNum; + ++mDataLen; +} + +void StopWatch::stop() +{ + checkCapacity(); + clock_gettime(CLOCK_MONOTONIC, &mData[mDataLen].mTime); + mData[mDataLen].mIsStart = false; + ++mDataLen; +} + +void StopWatch::setPrintRawMode(bool raw) +{ + printRaw = raw; +} + + +void StopWatch::sprint(char **str, size_t *size) +{ + if (kVerbose) fprintf(stderr, "printing\n"); + mAlreadyPrinted = true; + if (0 == mDataLen) + { + return; + } + if (mDataLen > 0 && mData[mDataLen - 1].mIsStart) + { + stop(); + } + if (kVerbose) SNPRINTF_OR_RETURN(*str, *size, "# Got %d samples for %s\n", mDataLen, mName); + processSamples(); + + SNPRINTF_OR_RETURN(*str, *size, "# StopWatch %s total/cumulative duration %f. Samples: %d\n", + mName, mDuration, mNum); + printThroughput(str, size); + printAverageMinMax(str, size); + + if (printRaw) + { + // print comment header and summary values. + + SNPRINTF_OR_RETURN(*str, *size, "# Name Iterations Duration Min MinIdx Max MaxIdx SizeMbytes\n"); + SNPRINTF_OR_RETURN(*str, *size, "%s %d %f %f %d %f %d %d\n", mName, mNum, mDuration, + mMinDuration, mMinIdx, mMaxDuration, mMaxIdx, mSizeKbytes); + // print each duration sample + for (size_t i = 0; i < mDataLen / 2; ++i) + { + long second = mData[i * 2].mTime.tv_sec - mStart.tv_sec; + long nano = mData[i * 2].mTime.tv_nsec - mStart.tv_nsec; + + SNPRINTF_OR_RETURN(*str, *size, "%f %f\n", double(second) + double(nano) / 1.0e9, mDeltas[i]); + } + } + +} + +// Normally we should have enough capacity but if we have to +// reallocate the measurement buffer (e.g start and stop called more +// than once in an iteration) we let the user know. She should provide +// a capacity when building the StopWatch. +void StopWatch::checkCapacity() +{ + if (mDataLen >= mCapacity) + { + mCapacity *= 2; + fprintf(stderr, "# Increased capacity to %d for %s. Measurement affected.\n", + mCapacity, mName); + mData = (Measurement *)realloc(mData, mCapacity * sizeof(Measurement)); + } +} + + +// Go over all the samples and compute the diffs between a start and +// stop pair. The diff is accumulated in mDuration and inserted in +// mDeltas. +// The min and max values for a diff are also tracked. +void StopWatch::processSamples() +{ + if (kVerbose) fprintf(stderr, "processing samples\n"); + mDeltas= new double[mDataLen / 2]; + + for (size_t i = 0; i < mDataLen; i += 2) // even: start odd: stop + { + long second = mData[i + 1].mTime.tv_sec - mData[i].mTime.tv_sec; + long nano = mData[i + 1].mTime.tv_nsec - mData[i].mTime.tv_nsec; + + mDeltas[i / 2] = double(second) + double(nano) / 1.0e9; + } + + for (size_t i = 0; i < mDataLen / 2; ++i) + { + if (0 == i) + { + mMinDuration = mMaxDuration = mDeltas[i]; + } + else + { + if (mMaxDuration < mDeltas[i]) + { + mMaxDuration = mDeltas[i]; + mMaxIdx = i; + } + if (mMinDuration > mDeltas[i]) + { + mMinDuration = mDeltas[i]; + mMinIdx = i; + } + } + mDuration += mDeltas[i]; + } +} + +double StopWatch::timespecToDouble(const struct timespec& time) +{ + double val = double(time.tv_nsec) / 1.0e9 + double(time.tv_sec); + return val < 0.0 ? -val : val; // sometimes 0.00 is -0.00 +} + + +// If we have only 2 values, don't bother printing anything. +void StopWatch::printAverageMinMax(char **str, size_t *size) +{ + if (mDataLen > 2) // if there is only one sample, avg, min, max are trivial. + { + SNPRINTF_OR_RETURN(*str, *size, "# Average %s duration %f s/op\n", mName, mDuration / mNum); + SNPRINTF_OR_RETURN(*str, *size, "# Min %s duration %f [%d]\n", mName, mMinDuration, mMinIdx); + SNPRINTF_OR_RETURN(*str, *size, "# Max %s duration %f [%d]\n", mName, mMaxDuration, mMaxIdx); + } +} + +void StopWatch::printThroughput(char **str, size_t *size) +{ + if (0 != mSizeKbytes) + { + SNPRINTF_OR_RETURN(*str, *size, "# Size: %d Kbytes Total: %d\n", mSizeKbytes, mNum); + SNPRINTF_OR_RETURN(*str, *size, "# Speed %f Kbyte/s\n", double(mSizeKbytes) * mNum / mDuration); + } +} +} // namespace android_test diff --git a/tests/sdcard/stopwatch.h b/tests/sdcard/stopwatch.h new file mode 100644 index 00000000..4d1a7949 --- /dev/null +++ b/tests/sdcard/stopwatch.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_ +#define ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_ + +#include +#include +#include + +namespace android_test { + +// StopWatch class to collect execution statistics. +// +// Once the watch has been created, start and stop can be called to +// capture an event duration. +// +// On completion, use 'sprint' to retrieve the data. +// +// If StopWatch::setPrintRawMode(true) has been called, the raw +// samples also are printed. +// The print method is thread safe to avoid mixing the result of +// watches on different threads. For processes, use different files +// that you concat after the run. +// +// If the time measure is associated with some volume of data, use +// setMbytes, the print method will compute the average throughput +// based on that value. +// +// To capture the time accurately and since the runs are not too long, +// we collect the raw start and stop time in an array that get +// processed once all the measurements have been done. +// +// Typical Usage: +// ============== +// +// StopWatch watch("my name", 20); +// +// for (int i = 0; i < 20; ++i) { +// watch.start(); +// doMyStuff(); +// watch.stop(); +// } +// char buffer[4096]; +// char *str = buffer; +// size_t size = sizeof(buffer); +// watch.sprint(&str, &size); +// + +class StopWatch { + public: + // Time of the snapshot and its nature (start of the interval or end of it). + struct Measurement { + struct timespec mTime; + bool mIsStart; + }; + static const size_t kUseDefaultCapacity = 20; + + // Create a stop watch. Default capacity == 2 * interval_nb + // @param name To be used when the results are displayed. No + // spaces, use _ instead. + // @param capacity Hint about the number of sampless that will be + // measured (1 sample == 1 start + 1 stop). Used + // to size the internal storage, when the capacity + // is reached, it is doubled. + StopWatch(const char *name, size_t capacity = kUseDefaultCapacity); + ~StopWatch(); + + // A StopWatch instance measures time intervals. Use setDataSize + // if some volume of data is processed during these intervals, to + // get the average throughput (in kbytes/s) printed. + void setDataSize(size_t size_in_bytes) { mSizeKbytes = size_in_bytes / 1000; } + + // Starts and stops the timer. The time between the 2 calls is an + // interval whose duration will be reported in sprint. + void start(); + void stop(); + + // Print a summary of the measurement and optionaly the raw data. + // The summary is commented out using a leading '#'. The raw data + // is a pair (time, duration). The 1st sample is always at time + // '0.0'. + // @param str[inout] On entry points to the begining of a buffer + // where to write the data. On exit points pass the last byte + // written. + // @param size[inout] On entry points to the size of the buffer + // pointed by *str. On exit *size is the amount of free space left + // in the buffer. If there was not enough space the data is truncated + // and a warning is printed. + void sprint(char **str, size_t *size); + + // @return true if at least one interval was timed. + bool used() const { return mUsed; } + + // Affects all the timers. Instructs all the timers to print the + // raw data as well as the summary. + static void setPrintRawMode(bool printRaw); + + private: + void checkCapacity(); + double timespecToDouble(const struct timespec& time); + void printAverageMinMax(char **str, size_t *size); + void printThroughput(char **str, size_t *size); + // Allocate mDeltas and fill it in. Search for the min and max. + void processSamples(); + + char *const mName; // Name of the test. + struct timespec mStart; + size_t mNum; // # of intervals == # of start() calls. + struct Measurement *mData; + size_t mDataLen; + size_t mCapacity; + int mSizeKbytes; + + bool mAlreadyPrinted; + bool mPrintRaw; + + double mDuration; + double mMinDuration; + size_t mMinIdx; + double mMaxDuration; + size_t mMaxIdx; + double *mDeltas; + + bool mUsed; +}; + +} // namespace android_test + +#endif // ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_ diff --git a/tests/sdcard/sysutil.cpp b/tests/sdcard/sysutil.cpp new file mode 100644 index 00000000..0182590a --- /dev/null +++ b/tests/sdcard/sysutil.cpp @@ -0,0 +1,604 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sysutil.h" + +namespace { +const int kError = -1; +// Max number of retries on EAGAIN and EINTR. Totally arbitrary. +const int kMaxAttempts = 8; + +// How long to wait after a cache purge. A few seconds (arbitrary). +const int kCachePurgeSleepDuration = 2; // seconds + +const bool kSilentIfMissing = false; + +const char *kKernelVersion = "/proc/version"; +const char *kScalingGovernorFormat = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor"; +const char *kDropCaches = "/proc/sys/vm/drop_caches"; +const char *kSchedFeatures = "/sys/kernel/debug/sched_features"; +const char *kNewFairSleepers = "NEW_FAIR_SLEEPERS"; +const char *kNoNewFairSleepers = "NO_NEW_FAIR_SLEEPERS"; +const char *kNormalizedSleepers = "NORMALIZED_SLEEPER"; // no 's' at the end +const char *kNoNormalizedSleepers = "NO_NORMALIZED_SLEEPER"; + +const char *kDebugfsWarningMsg = "Did you 'adb root; adb shell mount -t debugfs none /sys/kernel/debug' ?"; + +// TODO: Surely these file utility functions must exist already. A +// quick grep did not turn up anything. Look harder later. + +void printErrno(const char *msg, const char *filename) +{ + fprintf(stderr, "# %s %s %d %s\n", msg, filename, errno, strerror(errno)); +} + +// Read a C-string from a file. If the buffer is too short, an error +// message will be printed on stderr. +// @param filename Of the file to read. +// @param start Buffer where the data should be written to. +// @param size The size of the buffer pointed by str. Must be >= 1. +// @return The number of characters read (not including the trailing'\0' used +// to end the string) or -1 if there was an error. +int readStringFromFile(const char *filename, char *const start, size_t size, bool must_exist=true) +{ + if (NULL == start || size == 0) + { + return 0; + } + char *end = start; + int fd = open(filename, O_RDONLY); + + if (fd < 0) + { + if (ENOENT != errno || must_exist) + { + printErrno("Failed to open", filename); + } + return kError; + } + + bool eof = false; + bool error = false; + int attempts = 0; + + --size; // reserve space for trailing '\0' + + while (size > 0 && !error && !eof && attempts < kMaxAttempts) + { + ssize_t s; + + s = read(fd, end, size); + + if (s < 0) + { + error = EAGAIN != errno && EINTR != errno; + if (error) + { + printErrno("Failed to read", filename); + } + } + else if (0 == s) + { + eof = true; + } + else + { + end += s; + size -= s; + } + ++attempts; + } + + close(fd); + + if (error) + { + return kError; + } + else + { + *end = '\0'; + if (!eof) + { + fprintf(stderr, "Buffer too small for %s\n", filename); + } + return end - start; + } +} + +// Write a C string ('\0' terminated) to a file. +// +int writeStringToFile(const char *filename, const char *start, bool must_exist=true) +{ + int fd = open(filename, O_WRONLY); + + + if (fd < 0) + { + if (ENOENT != errno || must_exist) + { + printErrno("Failed to open", filename); + } + return kError; + } + + const size_t len = strlen(start); + size_t size = len; + bool error = false; + int attempts = 0; + + while (size > 0 && !error && attempts < kMaxAttempts) + { + ssize_t s = write(fd, start, size); + + if (s < 0) + { + error = EAGAIN != errno && EINTR != errno; + if (error) + { + printErrno("Failed to write", filename); + } + } + else + { + start += s; + size -= s; + } + ++attempts; + } + close(fd); + + if (error) + { + return kError; + } + else + { + if (size > 0) + { + fprintf(stderr, "Partial write to %s (%d out of %d)\n", + filename, size, len); + } + return len - size; + } +} + +int writeIntToFile(const char *filename, long value) +{ + char buffer[16] = {0,}; + sprintf(buffer, "%ld", value); + return writeStringToFile(filename, buffer); +} + +// @return a message describing the reason why the child exited. The +// message is in a shared buffer, not thread safe, erased by +// subsequent calls. +const char *reasonChildExited(int status) +{ + static char buffer[80]; + + if (WIFEXITED(status)) + { + snprintf(buffer, sizeof(buffer), "ok (%d)", WEXITSTATUS(status)); + } + else if (WIFSIGNALED(status)) + { + snprintf(buffer, sizeof(buffer), "signaled (%d %s)", WTERMSIG(status), strsignal(WTERMSIG(status))); + } + else + { + snprintf(buffer, sizeof(buffer), "stopped?"); + } + return buffer; +} + + +} // anonymous namespace + +namespace android { + +int kernelVersion(char *str, size_t size) +{ + return readStringFromFile(kKernelVersion, str, size); +} + +int pidOutOfMemoryAdj() +{ + char filename[FILENAME_MAX]; + + snprintf(filename, sizeof(filename), "/proc/%d/oom_adj", getpid()); + + char value[16]; + if (readStringFromFile(filename, value, sizeof(value)) == -1) + { + return -127; + } + else + { + return atoi(value); + } +} + +void setPidOutOfMemoryAdj(int level) +{ + char filename[FILENAME_MAX]; + + snprintf(filename, sizeof(filename), "/proc/%d/oom_adj", getpid()); + writeIntToFile(filename, level); +} + +void disableCpuScaling() +{ + for (int cpu = 0; cpu < 16; ++cpu) // 16 cores mobile phones, abestos pockets recommended. + { + char governor[FILENAME_MAX]; + sprintf(governor, kScalingGovernorFormat, cpu); + + if (writeStringToFile(governor, "performance", kSilentIfMissing) < 0) + { + if (cpu > 0 && errno == ENOENT) + { + break; // cpu1 or above not found, ok since we have cpu0. + } + fprintf(stderr, "Failed to write to scaling governor file for cpu %d: %d %s", + cpu, errno, strerror(errno)); + break; + } + } +} + +int schedFeatures(char *str, size_t size) +{ + return readStringFromFile(kSchedFeatures, str, size); +} + +bool newFairSleepers() +{ + char value[256] = {0,}; + + if (readStringFromFile(kSchedFeatures, value, sizeof(value)) == -1) + { + printErrno(kDebugfsWarningMsg, kSchedFeatures); + return false; + } + return strstr(value, "NO_NEW_FAIR_SLEEPERS") == NULL; +} + +void setNewFairSleepers(bool on) +{ + int retcode; + + if (on) + { + retcode = writeStringToFile(kSchedFeatures, kNewFairSleepers); + } + else + { + retcode = writeStringToFile(kSchedFeatures, kNoNewFairSleepers); + } + if (retcode < 0) + { + fprintf(stderr, "# %s\n", kDebugfsWarningMsg); + } +} + +bool normalizedSleepers() +{ + char value[256] = {0,}; + + if (readStringFromFile(kSchedFeatures, value, sizeof(value)) == -1) + { + printErrno(kDebugfsWarningMsg, kSchedFeatures); + return false; + } + return strstr(value, "NO_NEW_FAIR_SLEEPERS") == NULL; +} + +void setNormalizedSleepers(bool on) +{ + int retcode; + + if (on) + { + retcode = writeStringToFile(kSchedFeatures, kNormalizedSleepers); + } + else + { + retcode = writeStringToFile(kSchedFeatures, kNoNormalizedSleepers); + } + if (retcode < 0) + { + fprintf(stderr, "# %s\n", kDebugfsWarningMsg); + } +} + +pid_t forkOrExit() +{ + pid_t childpid = fork(); + + if (-1 == childpid) + { + fprintf(stderr, "Fork failed: %d %s", errno, strerror(errno)); + exit(EXIT_FAILURE); + } + return childpid; +} + +void waitForChildrenOrExit(int num) +{ + while (num > 0) + { + int status; + pid_t pid = wait(&status); + if (-1 == pid) + { + fprintf(stderr, "Wait failed\n"); + } + else + { + if (!WIFEXITED(status)) + { + fprintf(stderr, "Child pid %d did not exit cleanly %s\n", + pid, reasonChildExited(status)); + exit(EXIT_FAILURE); + } + } + --num; + } +} + +// Sync and cache cleaning functions. In the old hpux days I was told +// to always call *sync twice. The same advice seems to be still true +// today so *sync is called twice. +// Also we wait 'a little' to give a chance to background threads to +// purge their caches. +void syncAndDropCaches(int code) +{ + sync(); + sync(); + writeIntToFile(kDropCaches, code); + sleep(kCachePurgeSleepDuration); +} + + +void fsyncAndDropCaches(int fd, int code) +{ + fsync(fd); + fsync(fd); + writeIntToFile(kDropCaches, code); + sleep(kCachePurgeSleepDuration); +} + + +void resetDirectory(const char *directory) +{ + DIR *dir = opendir(directory); + + if (NULL != dir) + { + struct dirent *entry; + char name_buffer[PATH_MAX]; + + while((entry = readdir(dir))) + { + if (0 == strcmp(entry->d_name, ".") + || 0 == strcmp(entry->d_name, "..") + || 0 == strcmp(entry->d_name, "lost+found")) + { + continue; + } + strcpy(name_buffer, directory); + strcat(name_buffer, "/"); + strcat(name_buffer, entry->d_name); + unlink(name_buffer); + } + closedir(dir); + } else { + mkdir(directory, S_IRWXU); + } +} + + +// IPC +bool writePidAndWaitForReply(int writefd, int readfd) +{ + if (writefd > readfd) + { + fprintf(stderr, "Called with args in wrong order!!\n"); + return false; + } + pid_t pid = getpid(); + char *start = reinterpret_cast(&pid); + size_t size = sizeof(pid); + bool error = false; + int attempts = 0; + + while (size > 0 && !error && attempts < kMaxAttempts) + { + ssize_t s = write(writefd, start, size); + + if (s < 0) + { + error = EAGAIN != errno && EINTR != errno; + if (error) + { + printErrno("Failed to write", "parent"); + } + } + else + { + start += s; + size -= s; + } + ++attempts; + } + + if (error || 0 != size) + { + return false; + } + + bool eof = false; + char dummy; + size = sizeof(dummy); + error = false; + attempts = 0; + + while (size > 0 && !error && !eof && attempts < kMaxAttempts) + { + ssize_t s; + + s = read(readfd, &dummy, size); + + if (s < 0) + { + error = EAGAIN != errno && EINTR != errno; + if (error) + { + printErrno("Failed to read", "parent"); + } + } + else if (0 == s) + { + eof = true; + } + else + { + size -= s; + } + ++attempts; + } + if (error || 0 != size) + { + return false; + } + return true; +} + + + +bool waitForChildrenAndSignal(int mProcessNb, int readfd, int writefd) +{ + if (readfd > writefd) + { + fprintf(stderr, "Called with args in wrong order!!\n"); + return false; + } + + bool error; + int attempts; + size_t size; + + for (int p = 0; p < mProcessNb; ++p) + { + bool eof = false; + pid_t pid; + char *end = reinterpret_cast(&pid); + + error = false; + attempts = 0; + size = sizeof(pid); + + while (size > 0 && !error && !eof && attempts < kMaxAttempts) + { + ssize_t s; + + s = read(readfd, end, size); + + if (s < 0) + { + error = EAGAIN != errno && EINTR != errno; + if (error) + { + printErrno("Failed to read", "child"); + } + } + else if (0 == s) + { + eof = true; + } + else + { + end += s; + size -= s; + } + ++attempts; + } + + if (error || 0 != size) + { + return false; + } + } + + for (int p = 0; p < mProcessNb; ++p) + { + char dummy; + + error = false; + attempts = 0; + size = sizeof(dummy); + + while (size > 0 && !error && attempts < kMaxAttempts) + { + ssize_t s = write(writefd, &dummy, size); + + if (s < 0) + { + error = EAGAIN != errno && EINTR != errno; + if (error) + { + printErrno("Failed to write", "child"); + } + } + else + { + size -= s; + } + ++attempts; + } + + if (error || 0 != size) + { + return false; + } + } + return true; +} + +} // namespace android diff --git a/tests/sdcard/sysutil.h b/tests/sdcard/sysutil.h new file mode 100644 index 00000000..3df79c12 --- /dev/null +++ b/tests/sdcard/sysutil.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_SYSUTIL_H_ +#define ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_SYSUTIL_H_ + +#include +namespace android { + +// Collection of functions to access the system: +// .kernelVersion Retrieve the full kernel description. +// .pidOutOfMemoryAdj Get and set the OOM adj value. +// .setPidOutOfMemoryAdj +// .schedFeatures Manipulate the scheduler using debugfs. +// .newFairSleepers +// .setNewFairSleepers +// .disableCpuScaling Set cpu scaling to 'performance'. +// .forkOrExit Fork a child or exit. +// .syncAnddropCaches Call sync an drop page/dentries/inodes caches. +// .fsyncAnddropCaches Call fsync an drop page/dentries/inodes caches. +// .resetDirectory Delete (non-recursive) files in a directory. +// +// IPC function to synchonize a processes with their parent. +// .writePidAndWaitForReply To instruct the parent the child is ready. +// Blocks until the parent signals back. +// .waitForChildrenAndSignal Blocks until all the children have called +// writePidAndWaitForReply. +// Then unblock all the children. +// .waitForChildrenOrExit Wait and exit if a child exit with errors. +// + +// Minimum size for the buffer to retrieve the kernel version. +static const size_t kMinKernelVersionBufferSize = 256; + +// @param str points to the buffer where the kernel version should be +// added. Must be at least kMinKernelVersionBufferSize chars. +// @param size of the buffer pointed by str. +// @return If successful the number of characters inserted in the +// buffer (not including the trailing '\0' byte). -1 otherwise. +int kernelVersion(char *str, size_t size); + + +// Return the out of memory adj for this process. /proc//oom_adj. +// @return the oom_adj of the current process. Typically: +// 0: a regular process. Should die on OOM. +// -16: system_server level. +// -17: disable, this process will never be killed. +// -127: error. +int pidOutOfMemoryAdj(); +void setPidOutOfMemoryAdj(int level); + +// Disable cpu scaling. +void disableCpuScaling(); + + +// Minimum size for the buffer to retrieve the sched features. +static const size_t kMinSchedFeaturesBufferSize = 256; + +// @param str points to the buffer where the sched features should be +// added. Must be at least kMinSchedFeaturesBufferSize chars. +// @param size of the buffer pointed by str. +// @return If successful the number of characters inserted in the +// buffer (not including the trailing '\0' byte). -1 otherwise. +int schedFeatures(char *str, size_t size); + +// @return true if NEW_FAIR_SLEEPERS is set, false if NO_NEW_FAIR_SLEEPERS is set. +bool newFairSleepers(); + +// Turns NEW_FAIR_SLEEPERS on or off. +void setNewFairSleepers(bool on); + +// @return true if NORMALIZED_SLEEPERS is set, false if NO_NORMALIZED_SLEEPERS is set. +bool normalizedSleepers(); + +// Turns NORMALIZED_SLEEPERS on or off. +void setNormalizedSleepers(bool on); + +// Filesystem + +// Sync and drop caches. Sync is needed because dirty objects are not +// freable. +// @param code: +// * 1 To free pagecache. +// * 2 To free dentries and inodes. +// * 3 To free pagecache, dentries and inodes. +void syncAndDropCaches(int code = 3); + +// Fsync the given fd and drop caches. Fsync is needed because dirty +// objects are not freable. +// @param code: +// * 1 To free pagecache. +// * 2 To free dentries and inodes. +// * 3 To free pagecache, dentries and inodes. +void fsyncAndDropCaches(int fd, int code = 3); + +// Delete all the files in the given directory. If the directory does +// not exist, it is created. Use this at the beginning of a test to +// make sure you have a clean existing directory, previous run may +// have crashed and left clutter around. +void resetDirectory(const char *directory); + +// IPC + +// Try to fork. exit on failure. +pid_t forkOrExit(); + +// Signal our parent we are alive and ready by sending our pid. +// Then do a blocking read for parent's reply. +bool writePidAndWaitForReply(int writefd, int readfd); + +// Wait for all the children to report their pids. +// Then unblock them. +bool waitForChildrenAndSignal(int mProcessNb, int readfd, int writefd); + +// Wait for 'num' children to complete. +// If a child did not exit cleanly, exit. +void waitForChildrenOrExit(int num); + +} // namespace android + +#endif // ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_SYSUTIL_H_ diff --git a/tests/sdcard/testcase.cpp b/tests/sdcard/testcase.cpp new file mode 100644 index 00000000..0de436f7 --- /dev/null +++ b/tests/sdcard/testcase.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "testcase.h" +#include // wake lock +#include +#include +#include +#include + +namespace { +const bool kVerbose = false; +} + +namespace android_test { + +TestCase::TestCase(const char *appName) + : mTestBody(NULL), mAppName(appName), mDataSize(1000 * 1000), + mChunkSize(mDataSize), mIter(20), mNproc(1), + mType(UNKNOWN_TEST), mDump(false), mCpuScaling(false), + mSync(NO_SYNC), mFadvice(POSIX_FADV_NORMAL), mTruncateToSize(false), + mTestTimer(NULL) +{ + // Make sure the cpu and phone are fully awake. The + // FULL_WAKE_LOCK was used by java apps and don't do + // anything. Also the partial wake lock is a nop if the phone + // is plugged in via USB. + acquire_wake_lock(PARTIAL_WAKE_LOCK, mAppName); + mPid = getpid(); + setNewFairSleepers(true); + setNormalizedSleepers(true); + if (pipe(mIpc) < 0) + { + fprintf(stderr, "pipe failed\n"); + exit(1); + } + if (pipe(mIpc + 2) < 0) + { + fprintf(stderr, "pipe failed\n"); + exit(1); + } +} + +TestCase::~TestCase() +{ + release_wake_lock(mAppName); + for (int i = 0; i < 4; ++i) close(mIpc[i]); + delete mTestTimer; + delete mOpenTimer; +} + + +bool TestCase::runTest() +{ + if (UNKNOWN_TEST == mType) + { + fprintf(stderr, "No test set."); + return false; + } + for (size_t p = 0; p < mNproc; ++p) + { + pid_t childpid = android::forkOrExit(); + + if (0 == childpid) { // I am a child, run the test. + mPid = getpid(); + close(mIpc[READ_FROM_CHILD]); + close(mIpc[WRITE_TO_CHILD]); + + if (kVerbose) printf("Child pid: %d\n", mPid); + if (!mTestBody(this)) { + printf("Test failed\n"); + } + char buffer[32000] = {0,}; + char *str = buffer; + size_t size_left = sizeof(buffer); + + testTimer()->sprint(&str, &size_left); + if(openTimer()->used()) openTimer()->sprint(&str, &size_left); + if(readTimer()->used()) readTimer()->sprint(&str, &size_left); + if(writeTimer()->used()) writeTimer()->sprint(&str, &size_left); + if(syncTimer()->used()) syncTimer()->sprint(&str, &size_left); + if(truncateTimer()->used()) truncateTimer()->sprint(&str, &size_left); + + write(mIpc[TestCase::WRITE_TO_PARENT], buffer, str - buffer); + + + close(mIpc[WRITE_TO_PARENT]); + close(mIpc[READ_FROM_PARENT]); + exit(EXIT_SUCCESS); + } + } + // I am the parent process + close(mIpc[WRITE_TO_PARENT]); + close(mIpc[READ_FROM_PARENT]); + + // Block until all the children have reported for + // duty. Unblock them so they start the work. + if (!android::waitForChildrenAndSignal(mNproc, mIpc[READ_FROM_CHILD], mIpc[WRITE_TO_CHILD])) + { + exit(1); + } + + // Process the output of each child. + // TODO: handle EINTR + char buffer[32000] = {0,}; + while(read(mIpc[READ_FROM_CHILD], buffer, sizeof(buffer)) != 0) + { + printf("%s", buffer); + fflush(stdout); + memset(buffer, 0, sizeof(buffer)); + } + // Parent is waiting for children to exit. + android::waitForChildrenOrExit(mNproc); + return true; +} + +void TestCase::setIter(size_t iter) +{ + mIter = iter; +} + +void TestCase::createTimers() +{ + char total_time[80]; + + snprintf(total_time, sizeof(total_time), "%s_total", mName); + mTestTimer = new StopWatch(total_time, 1); + mTestTimer->setDataSize(dataSize()); + + mOpenTimer = new StopWatch("open", iter() * kReadWriteFactor); + + mReadTimer = new StopWatch("read", iter() * dataSize() / chunkSize() * kReadWriteFactor); + mReadTimer->setDataSize(dataSize()); + + mWriteTimer = new StopWatch("write", iter() * dataSize() / chunkSize()); + mWriteTimer->setDataSize(dataSize()); + + mSyncTimer = new StopWatch("sync", iter()); + + mTruncateTimer = new StopWatch("truncate", iter()); +} + +bool TestCase::setTypeFromName(const char *test_name) +{ + strcpy(mName, test_name); + if (strcmp(mName, "write") == 0) mType = WRITE; + if (strcmp(mName, "read") == 0) mType = READ; + if (strcmp(mName, "read_write") == 0) mType = READ_WRITE; + if (strcmp(mName, "open_create") == 0) mType = OPEN_CREATE; + + return UNKNOWN_TEST != mType; +} + +void TestCase::setSync(Sync s) +{ + mSync = s; +} + +const char *TestCase::syncAsStr() const +{ + return mSync == NO_SYNC ? "disabled" : (mSync == FSYNC ? "fsync" : "sync"); +} + +void TestCase::setFadvise(const char *advice) +{ + mFadvice = POSIX_FADV_NORMAL; + if (strcmp(advice, "sequential") == 0) + { + mFadvice = POSIX_FADV_SEQUENTIAL; + } + else if (strcmp(advice, "random") == 0) + { + mFadvice = POSIX_FADV_RANDOM; + } + else if (strcmp(advice, "noreuse") == 0) + { + mFadvice = POSIX_FADV_NOREUSE; + } + else if (strcmp(advice, "willneed") == 0) + { + mFadvice = POSIX_FADV_WILLNEED; + } + else if (strcmp(advice, "dontneed") == 0) + { + mFadvice = POSIX_FADV_DONTNEED; + } +} + +const char *TestCase::fadviseAsStr() const +{ + switch (mFadvice) { + case POSIX_FADV_NORMAL: return "fadv_normal"; + case POSIX_FADV_SEQUENTIAL: return "fadv_sequential"; + case POSIX_FADV_RANDOM: return "fadv_random"; + case POSIX_FADV_NOREUSE: return "fadv_noreuse"; + case POSIX_FADV_WILLNEED: return "fadv_willneed"; + case POSIX_FADV_DONTNEED: return "fadv_dontneed"; + default: return "fadvice_unknown"; + } +} + + +} // namespace android_test diff --git a/tests/sdcard/testcase.h b/tests/sdcard/testcase.h new file mode 100644 index 00000000..66af9d63 --- /dev/null +++ b/tests/sdcard/testcase.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef SYSTEM_EXTRAS_TESTS_SDCARD_TESTCASE_H_ +#define SYSTEM_EXTRAS_TESTS_SDCARD_TESTCASE_H_ + +#include +#include "stopwatch.h" +#include "sysutil.h" + +namespace android_test { + +// Class to group test parameters and implementation. +// Takes care of forking child processes and wait for them. + +class TestCase { + public: + enum Type {UNKNOWN_TEST, WRITE, READ, OPEN_CREATE, READ_WRITE}; + enum Pipe {READ_FROM_CHILD = 0, WRITE_TO_PARENT, READ_FROM_PARENT, WRITE_TO_CHILD}; + enum Sync {NO_SYNC, FSYNC, SYNC}; + + // Reads takes less time than writes. This is a basic + // approximation of how much longer the read tasks must run to + // terminate roughly at the same time as the write tasks. + const static int kReadWriteFactor = 5; + + TestCase(const char *appName); + + ~TestCase(); + + size_t iter() const { return mIter; } + void setIter(size_t iter); + + size_t nproc() const { return mNproc; } + void setNproc(size_t val) { mNproc = val; } + + size_t dataSize() const { return mDataSize; } + void setDataSize(size_t val) { mDataSize = val; } + + size_t chunkSize() const { return mChunkSize; } + void setChunkSize(size_t val) { mChunkSize = val; } + + bool newFairSleepers() const { return mNewFairSleepers; } + void setNewFairSleepers(bool val) { + mNewFairSleepers = val; + android::setNewFairSleepers(val); + } + + bool normalizedSleepers() const { return mNormalizedSleepers; } + void setNormalizedSleepers(bool val) { + mNormalizedSleepers = val; + android::setNormalizedSleepers(val); + } + + Sync sync() const { return mSync; } + void setSync(Sync s); + const char *syncAsStr() const; + + bool cpuScaling() const { return mCpuScaling; } + void setCpuScaling() { mCpuScaling = true; } + + bool truncateToSize() const { return mTruncateToSize; } + void setTruncateToSize() { mTruncateToSize = true; } + + int fadvise() { return mFadvice; } + void setFadvise(const char *advice); + const char *fadviseAsStr() const; + + // Print the samples. + void setDump() { StopWatch::setPrintRawMode(true); } + + StopWatch *testTimer() { return mTestTimer; } + StopWatch *openTimer() { return mOpenTimer; } + StopWatch *readTimer() { return mReadTimer; } + StopWatch *writeTimer() { return mWriteTimer; } + StopWatch *syncTimer() { return mSyncTimer; } + StopWatch *truncateTimer() { return mTruncateTimer; } + + // Fork the children, run the test and wait for them to complete. + bool runTest(); + + void signalParentAndWait() { + if (!android::writePidAndWaitForReply(mIpc[WRITE_TO_PARENT], mIpc[READ_FROM_PARENT])) { + exit(1); + } + } + + void createTimers(); + bool setTypeFromName(const char *test_name); + Type type() const { return mType; } + pid_t pid() const { return mPid; } + const char *name() const { return mName; } + + // This is set to the function that will actually do the test when + // the command line arguments have been parsed. The function will + // be run in one or more child(ren) process(es). + bool (*mTestBody)(TestCase *); +private: + const char *mAppName; + size_t mDataSize; + size_t mChunkSize; + size_t mIter; + size_t mNproc; + pid_t mPid; + char mName[80]; + Type mType; + + bool mDump; // print the raw values instead of a human friendly report. + bool mCpuScaling; // true, do not turn off cpu scaling. + Sync mSync; + int mFadvice; + // When new files are created, truncate them to the final size. + bool mTruncateToSize; + + bool mNewFairSleepers; + bool mNormalizedSleepers; + + // IPC + // Parent Child(ren) + // --------------------------------------- + // 0: read from child closed + // 1: closed write to parent + // 2: closed read from parent + // 3: write to child closed + int mIpc[4]; + + StopWatch *mTestTimer; // Used to time the test overall. + StopWatch *mOpenTimer; // Used to time the open calls. + StopWatch *mReadTimer; // Used to time the read calls. + StopWatch *mWriteTimer; // Used to time the write calls. + StopWatch *mSyncTimer; // Used to time the sync/fsync calls. + StopWatch *mTruncateTimer; // Used to time the ftruncate calls. +}; + +} // namespace android_test + +#endif // SYSTEM_EXTRAS_TESTS_SDCARD_TESTCASE_H_ -- cgit v1.2.3 From d6079c62819b4c022fe23e5101ca5382fbedb10f Mon Sep 17 00:00:00 2001 From: Nicolas Catania Date: Wed, 3 Jun 2009 11:08:47 -0700 Subject: Added main with command line args to plot the data. New shell script to generate scalability data. Fixed copyright notice. Fixed incomplete metadata issue when debugfs was not mounted. --- tests/sdcard/plot_sdcard.py | 295 +++++++++++++++++++++++++++++------------ tests/sdcard/profile_sdcard.sh | 64 +++++++++ tests/sdcard/stopwatch.cpp | 2 +- 3 files changed, 278 insertions(+), 83 deletions(-) create mode 100755 tests/sdcard/profile_sdcard.sh diff --git a/tests/sdcard/plot_sdcard.py b/tests/sdcard/plot_sdcard.py index 10ee00ba..19b83c3c 100755 --- a/tests/sdcard/plot_sdcard.py +++ b/tests/sdcard/plot_sdcard.py @@ -1,49 +1,70 @@ #!/usr/bin/python2.5 # -# Copyright 2009 Google Inc. All Rights Reserved. +# Copyright 2009, The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """plot_sdcard: A module to plot the results of an sdcard perf test. Requires Gnuplot python v 1.8 Typical usage: + -t x axis is time + -i x axis is iteration + -p profile data generated by profile_sdcard.sh + +./plot_sdcard.py -t /tmp/data.txt +./plot_sdcard.py -i /tmp/data.txt +./plot_sdcard.py -p -python +python interpreter >>> import plot_sdcard as p ->>> (metadata, data) = p.parse('/tmp/data.txt') ->>> p.plotIterations(metadata, data) ->>> p.plotTimes(metadata, data) +>>> (metadata, data) = p.Parse('/tmp/data.txt') +>>> p.PlotIterations(metadata, data) +>>> p.PlotTimes(metadata, data) """ -#TODO: provide a main so we can pipe the result from the run -#TODO: more comments... - -import Gnuplot -from numpy import * -import sys -import re +import getopt from itertools import izip +import re +import sys +import Gnuplot +import numpy + class DataSet(object): + """Dataset holds the summary and data (time,value pairs).""" + def __init__(self, line): - res = re.search('# StopWatch ([\w]+) total/cumulative duration ([0-9.]+)\. Samples: ([0-9]+)', line) + res = re.search(('# StopWatch ([\w]+) total/cumulative ' + 'duration ([0-9.]+). Samples: ([0-9]+)'), line) self.time = [] self.data = [] self.name = res.group(1) self.duration = float(res.group(2)) self.iteration = int(res.group(3)) - print "Name: %s Duration: %f Iterations: %d" % (self.name, self.duration, self.iteration) self.summary = re.match('([a-z_]+)_total', self.name) def __repr__(self): return str(zip(self.time, self.data)) - def add(self, time, value): + def Add(self, time, value): self.time.append(time) self.data.append(value) - def rescaleTo(self, length): + def RescaleTo(self, length): factor = len(self.data) / length if factor > 1: @@ -51,7 +72,7 @@ class DataSet(object): new_data = [] accum = 0.0 idx = 1 - for t,d in izip(self.time, self.data): + for t, d in izip(self.time, self.data): accum += d if idx % factor == 0: new_time.append(t) @@ -73,7 +94,7 @@ class Metadata(object): self.duration = 0.0 self.complete = False - def parse(self, line): + def Parse(self, line): if line.startswith('# Kernel:'): self.kernel = re.search('Linux version ([0-9.]+-[0-9]+)', line).group(1) elif line.startswith('# Command:'): @@ -84,74 +105,29 @@ class Metadata(object): elif line.startswith('# Iterations'): self.iterations = int(re.search('# Iterations: ([0-9]+)', line).group(1)) elif line.startswith('# Fadvise'): - self.fadvise = int(re.search('# Fadvise: ([\w]+)', line).group(1)) - elif line.startswith("# Sched"): + self.fadvise = re.search('# Fadvise: ([\w]+)', line).group(1) + elif line.startswith('# Sched'): self.sched = re.search('# Sched features: ([\w]+)', line).group(1) self.complete = True - def asTitle(self): - return "%s-duration:%f\\n-%s\\n%s" % (self.kernel, self.duration, self.command_line, self.sched) + def AsTitle(self): + return '%s-duration:%f\\n-%s\\n%s' % ( + self.kernel, self.duration, self.command_line, self.sched) - def updateWith(self, dataset): + def UpdateWith(self, dataset): self.duration = max(self.duration, dataset.duration) self.name = dataset.name -def plotIterations(metadata, data): - gp = Gnuplot.Gnuplot(persist = 1) - gp('set data style lines') - gp.clear() - gp.xlabel("iterations") - gp.ylabel("duration in second") - gp.title(metadata.asTitle()) - styles = {} - line_style = 1 - - for dataset in data: - dataset.rescaleTo(metadata.iterations) - x = arange(len(dataset.data), dtype='int_') - if not dataset.name in styles: - styles[dataset.name] = line_style - line_style += 1 - d = Gnuplot.Data(x, dataset.data, - title=dataset.name, - with_='lines ls %d' % styles[dataset.name]) - else: # no need to repeat a title that exists already. - d = Gnuplot.Data(x, dataset.data, - with_='lines ls %d' % styles[dataset.name]) - - gp.replot(d) - gp.hardcopy('/tmp/%s-%s-%f.png' % (metadata.name, metadata.kernel, metadata.duration), terminal='png') - -def plotTimes(metadata, data): - gp = Gnuplot.Gnuplot(persist = 1) - gp('set data style impulses') - gp('set xtics 1') - gp.clear() - gp.xlabel("seconds") - gp.ylabel("duration in second") - gp.title(metadata.asTitle()) - styles = {} - line_style = 1 - - for dataset in data: - #dataset.rescaleTo(metadata.iterations) - x = array(dataset.time, dtype='float_') - if not dataset.name in styles: - styles[dataset.name] = line_style - line_style += 1 - d = Gnuplot.Data(x, dataset.data, - title=dataset.name, - with_='impulses ls %d' % styles[dataset.name]) - else: # no need to repeat a title that exists already. - d = Gnuplot.Data(x, dataset.data, - with_='impulses ls %d' % styles[dataset.name]) +def Parse(filename): + """Parse a file with the collected data. - gp.replot(d) - gp.hardcopy('/tmp/%s-%s-%f.png' % (metadata.name, metadata.kernel, metadata.duration), terminal='png') + The data must be in 2 rows (x,y). + Args: + filename: Full path to the file. + """ -def parse(filename): f = open(filename, 'r') metadata = Metadata() @@ -164,16 +140,16 @@ def parse(filename): if not line: continue if not metadata.complete: - metadata.parse(line) + metadata.Parse(line) continue if re.match('[a-z_]', line): continue - if line.startswith('# StopWatch'): # Start of a new dataset + if line.startswith('# StopWatch'): # Start of a new dataset if dataset: if dataset.summary: - metadata.updateWith(dataset) + metadata.UpdateWith(dataset) else: data.append(dataset) @@ -187,14 +163,169 @@ def parse(filename): try: (time, value) = line.split(None, 1) except ValueError: - print "skipping line %d: %s" % (num, line) + print 'skipping line %d: %s' % (num, line) continue if dataset and not dataset.summary: - dataset.add(float(time), float(value)) + dataset.Add(float(time), float(value)) - except Exception, e: - print "Error parsing line %d" % num, sys.exc_info()[0] + except Exception: + print 'Error parsing line %d' % num, sys.exc_info()[0] raise data.append(dataset) + if not metadata.complete: + print """Error missing metadata. Did you mount debugfs? + [adb shell mount -t debugfs none /sys/kernel/debug]""" + sys.exit(1) return (metadata, data) + + +def PlotIterations(metadata, data): + """Plot the duration of the ops against iteration. + + If you are plotting data with widely different runtimes you probably want to + use PlotTimes instead. + + For instance when readers and writers are in the same mix, the + readers will go thru 100 iterations much faster than the + writers. The load test tries to be smart about that but the final + iterations of the writers will likely be done w/o any influence from + the readers. + + Args: + metadata: For the graph's title. + data: pair of to be plotted. + """ + + gp = Gnuplot.Gnuplot(persist=1) + gp('set data style lines') + gp.clear() + gp.xlabel('iterations') + gp.ylabel('duration in second') + gp.title(metadata.AsTitle()) + styles = {} + line_style = 1 + + for dataset in data: + dataset.RescaleTo(metadata.iterations) + x = numpy.arange(len(dataset.data), dtype='int_') + if not dataset.name in styles: + styles[dataset.name] = line_style + line_style += 1 + d = Gnuplot.Data(x, dataset.data, + title=dataset.name, + with_='lines ls %d' % styles[dataset.name]) + else: # no need to repeat a title that exists already. + d = Gnuplot.Data(x, dataset.data, + with_='lines ls %d' % styles[dataset.name]) + + gp.replot(d) + gp.hardcopy('/tmp/%s-%s-%f.png' % + (metadata.name, metadata.kernel, metadata.duration), + terminal='png') + + +def PlotTimes(metadata, data): + """Plot the duration of the ops against time elapsed. + + Args: + metadata: For the graph's title. + data: pair of to be plotted. + """ + + gp = Gnuplot.Gnuplot(persist=1) + gp('set data style impulses') + gp('set xtics 1') + gp.clear() + gp.xlabel('seconds') + gp.ylabel('duration in second') + gp.title(metadata.AsTitle()) + styles = {} + line_style = 1 + + for dataset in data: + x = numpy.array(dataset.time, dtype='float_') + if not dataset.name in styles: + styles[dataset.name] = line_style + line_style += 1 + d = Gnuplot.Data(x, dataset.data, + title=dataset.name, + with_='impulses ls %d' % styles[dataset.name]) + else: # no need to repeat a title that exists already. + d = Gnuplot.Data(x, dataset.data, + with_='impulses ls %d' % styles[dataset.name]) + + gp.replot(d) + gp.hardcopy('/tmp/%s-%s-%f.png' % + (metadata.name, metadata.kernel, metadata.duration), + terminal='png') + + +def PlotProfile(): + """Plot the time of a run against the number of processes.""" + (metadata, data) = Parse('/tmp/sdcard-scalability.txt') + gp = Gnuplot.Gnuplot(persist=1) + gp('set data style impulses') + gp('set xtics 1') + gp('set pointsize 2') + gp.clear() + gp.xlabel('writer process') + gp.ylabel('duration in second') + gp.title(metadata.AsTitle()) + + dataset = data[0] + x = numpy.array(dataset.time, dtype='int_') + d = Gnuplot.Data(x, dataset.data, + title=dataset.name, + with_='linespoints') + gp.replot(d) + gp.hardcopy('/tmp/%s-%s-%f.png' % + (metadata.name, metadata.kernel, metadata.duration), + terminal='png') + + +def Usage(): + """Print this module's usage.""" + print """ + To plot the result using the iter number of the x axis: + + plot_sdcard.py -i /tmp/data.txt + + To plot the result using time for the x axis: + + plot_sdcard.py -t /tmp/data.txt + + To plot the result from the profiler: + + profile_sdcard.sh + plot_sdcard.py -p + + """ + sys.exit(2) + + +def main(argv): + try: + (optlist, args) = getopt.getopt(argv[1:], + 'itp', ['iteration', 'time', 'profile']) + except getopt.GetoptError, err: + print str(err) + Usage() + + for flag, val in optlist: + if flag in ('-i', '--iteration'): + (metadata, data) = Parse(args[0]) + PlotIterations(metadata, data) + sys.exit(0) + elif flag in ('-t', '--time'): + (metadata, data) = Parse(args[0]) + PlotTimes(metadata, data) + sys.exit(0) + elif flag in ('-p', '--profile'): + PlotProfile() + sys.exit(0) + Usage() + + +if __name__ == '__main__': + main(sys.argv) diff --git a/tests/sdcard/profile_sdcard.sh b/tests/sdcard/profile_sdcard.sh new file mode 100755 index 00000000..4629c910 --- /dev/null +++ b/tests/sdcard/profile_sdcard.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Copyright 2009, The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Run a bunch of test on the sdcard to establish a performance profile. + +print_kernel() { + adb shell cat /proc/version +} +print_sched_features() { + adb shell cat /sys/kernel/debug/sched_features +} + +# Use dd to get the raw speed of the card +block_level() { + true +} + +# Time to run a test vs number of processes +scalability() { + local file="/tmp/sdcard-scalability.txt" + rm -f ${file} + echo "# Scalability tests" | tee -a ${file} + echo "# Kernel: $(print_kernel)" | tee -a ${file} + echo "# Sched features: $(print_sched_features)" | tee -a ${file} + echo "# StopWatch scalability total/cumulative duration 0.0 Samples: 1" | tee -a ${file} + echo "# Process Time" | tee -a ${file} + for p in $(seq 1 8); do + adb shell sdcard_perf_test --test=write --procnb=${p} --size=1000 --chunk-size=100 --iterations=50 >/tmp/tmp-sdcard.txt + local t=$(grep 'write_total' /tmp/tmp-sdcard.txt | tail -n 1 | cut -f 6 -d ' ') + echo "$p $t" | tee -a ${file} + done + +} + +# Readers and writers should not starve each others. +fairness() { + # Check readers finished before writers. + # Find the time of the last read op. + # Count how many writes and how many read happend + # during that period, do the ratio. + true +} + +####################################################################### +# MAIN + +echo "Make sure debugfs is mounted on the device." +block_level +scalability +fairness + + diff --git a/tests/sdcard/stopwatch.cpp b/tests/sdcard/stopwatch.cpp index 12fe8f1f..8207430d 100644 --- a/tests/sdcard/stopwatch.cpp +++ b/tests/sdcard/stopwatch.cpp @@ -117,7 +117,7 @@ void StopWatch::sprint(char **str, size_t *size) if (kVerbose) SNPRINTF_OR_RETURN(*str, *size, "# Got %d samples for %s\n", mDataLen, mName); processSamples(); - SNPRINTF_OR_RETURN(*str, *size, "# StopWatch %s total/cumulative duration %f. Samples: %d\n", + SNPRINTF_OR_RETURN(*str, *size, "# StopWatch %s total/cumulative duration %f Samples: %d\n", mName, mDuration, mNum); printThroughput(str, size); printAverageMinMax(str, size); -- cgit v1.2.3 From 32c21d90edce22f4c0b55effc527403a51be70f1 Mon Sep 17 00:00:00 2001 From: Chia-chi Yeh Date: Fri, 19 Jun 2009 15:52:11 +0800 Subject: fstest: Fix device, directory, and file permissions for VPN. --- tests/fstest/perm_checker.conf | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/fstest/perm_checker.conf b/tests/fstest/perm_checker.conf index fe253d7b..15485b84 100644 --- a/tests/fstest/perm_checker.conf +++ b/tests/fstest/perm_checker.conf @@ -60,7 +60,7 @@ /dev/pmem 660 660 system system graphics graphics /dev/pmem_adsp 660 660 system system audio audio /dev/pmem_camera 600 660 root system root camera -/dev/ppp 600 600 root root root root +/dev/ppp 660 660 radio radio vpn vpn /dev/psaux 600 600 root root root root /dev/ptmx 666 666 root root root root /dev/random 666 666 root root root root @@ -140,10 +140,8 @@ /system/etc/init.gprs-pppd 500 550 root root root shell /system/etc/init.testmenu 500 550 root root root root /system/etc/perm_checker.conf 000 777 root shell root shell -/system/etc/ppp/ 755 775 root system root system -/system/etc/ppp/chap-secrets 600 660 root system root system -/system/etc/ppp/ip-down 500 550 root system root system -/system/etc/ppp/ip-up 500 550 root system root system +/system/etc/ppp/ 755 755 root root root root +/system/etc/ppp/* 555 555 root root root root /system/etc/security/ 755 755 root root root root /system/etc/wifi/ 750 755 root system root system /system/lib/ 755 755 root root root root -- cgit v1.2.3 From 9c67529d7bec42a60136677195c46c1cfd995645 Mon Sep 17 00:00:00 2001 From: Sriram Raman Date: Mon, 22 Jun 2009 17:22:38 -0700 Subject: Remove sound, memtest, vibrator, timetest, cachetest from tests build --- sound/Android.mk | 2 +- tests/framebuffer/Android.mk | 4 ++-- tests/fstest/Android.mk | 4 ++-- tests/icachetest/Android.mk | 2 +- tests/memtest/Android.mk | 2 +- tests/timetest/Android.mk | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/Android.mk b/sound/Android.mk index 7a58998b..62174ccf 100644 --- a/sound/Android.mk +++ b/sound/Android.mk @@ -3,6 +3,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := sound LOCAL_SRC_FILES := playwav.c -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) diff --git a/tests/framebuffer/Android.mk b/tests/framebuffer/Android.mk index d6a8537d..4f789b9e 100644 --- a/tests/framebuffer/Android.mk +++ b/tests/framebuffer/Android.mk @@ -9,7 +9,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE:= test-fb-refresh -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional ifeq ($(TARGET_SIMULATOR),true) ifeq ($(HOST_OS),linux) @@ -26,7 +26,7 @@ ifneq ($(TARGET_SIMULATOR),true) include $(CLEAR_VARS) LOCAL_SRC_FILES := fb_test.c LOCAL_MODULE = test-fb-simple -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_STATIC_LIBRARIES := libc include $(BUILD_EXECUTABLE) diff --git a/tests/fstest/Android.mk b/tests/fstest/Android.mk index bf4f17c3..14c32aa0 100644 --- a/tests/fstest/Android.mk +++ b/tests/fstest/Android.mk @@ -22,7 +22,7 @@ LOCAL_SHARED_LIBRARIES := libc LOCAL_MODULE := perm_checker -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) @@ -32,7 +32,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := perm_checker.conf -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := ETC diff --git a/tests/icachetest/Android.mk b/tests/icachetest/Android.mk index fca07ee1..39d0016f 100644 --- a/tests/icachetest/Android.mk +++ b/tests/icachetest/Android.mk @@ -9,6 +9,6 @@ LOCAL_SHARED_LIBRARIES := libc LOCAL_MODULE:= icache -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) diff --git a/tests/memtest/Android.mk b/tests/memtest/Android.mk index 36f233c7..06e2304d 100644 --- a/tests/memtest/Android.mk +++ b/tests/memtest/Android.mk @@ -11,7 +11,7 @@ LOCAL_SHARED_LIBRARIES := libc LOCAL_MODULE:= memtest -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional ## LOCAL_CFLAGS += -fstack-protector-all LOCAL_CFLAGS += -fomit-frame-pointer diff --git a/tests/timetest/Android.mk b/tests/timetest/Android.mk index 918dea18..05e21fbe 100644 --- a/tests/timetest/Android.mk +++ b/tests/timetest/Android.mk @@ -7,7 +7,7 @@ LOCAL_SRC_FILES:= timetest.c LOCAL_MODULE:= timetest -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) -- cgit v1.2.3 From 360efc12dcfece46e5999505bd8042cba56a4289 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 29 Jun 2009 11:20:09 -0700 Subject: Rename backup command to rawbu. Rename the command to reflect that it is a low-level backup, since we are introducing a higher-level backup mechanism in the framework. Also change the syntax a little to make it less dangerous -- you now must explicitly specify a backup or restore, and if you don't do so it will abort with its help message. --- backup/Android.mk | 2 +- backup/backup.cpp | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/backup/Android.mk b/backup/Android.mk index 6a3d3fee..b5803905 100644 --- a/backup/Android.mk +++ b/backup/Android.mk @@ -7,7 +7,7 @@ LOCAL_SRC_FILES:= backup.cpp LOCAL_SHARED_LIBRARIES := libcutils libc -LOCAL_MODULE:= backup +LOCAL_MODULE:= rawbu LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) LOCAL_MODULE_TAGS := debug diff --git a/backup/backup.cpp b/backup/backup.cpp index 48f64eec..22c016d7 100644 --- a/backup/backup.cpp +++ b/backup/backup.cpp @@ -591,10 +591,21 @@ done: static void show_help(const char *cmd) { - fprintf(stderr,"Usage: %s [options] [backup-file-path]\n", cmd); + fprintf(stderr,"Usage: %s COMMAND [options] [backup-file-path]\n", cmd); + fprintf(stderr, "commands are:\n" + " help Show this help text.\n" + " backup Perform a backup of /data.\n" + " restore Perform a restore of /data.\n"); fprintf(stderr, "options include:\n" - " -r Perform restore of previous backup.\n"); + " -h Show this help text.\n"); + fprintf(stderr, "\nThe %s command allows you to perform low-level\n" + "backup and restore of the /data partition. This is\n" + "where all user data is kept, allowing for a fairly\n" + "complete restore of a device's state. Note that\n" + "because this is low-level, it will only work across\n" + "builds of the same (or very similar) device software.\n", + cmd); } } /* namespace android */ @@ -607,24 +618,39 @@ int main (int argc, char **argv) fprintf(stderr, "error -- %s must run as root\n", argv[0]); exit(-1); } - - if (argc == 2 && 0 == strcmp(argv[1], "--help")) { + + if (argc < 2) { + fprintf(stderr, "No command specified.\n"); + android::show_help(argv[0]); + exit(-1); + } + + if (0 == strcmp(argv[1], "restore")) { + restore = 1; + } else if (0 == strcmp(argv[1], "help")) { android::show_help(argv[0]); exit(0); + } else if (0 != strcmp(argv[1], "backup")) { + fprintf(stderr, "Unknown command: %s\n", argv[1]); + android::show_help(argv[0]); + exit(-1); } + optind = 2; + for (;;) { int ret; - ret = getopt(argc, argv, "r"); + ret = getopt(argc, argv, "h"); if (ret < 0) { break; } switch(ret) { - case 'r': - restore = 1; + case 'h': + android::show_help(argv[0]); + exit(0); break; default: -- cgit v1.2.3