├── .gitignore
├── .travis.yml
├── LICENSE
├── NOTICE
├── README.md
├── VERSION
├── bash-dtf
├── dtf.bash
├── dtf_core.sh
└── dtf_log.sh
├── build.gradle
├── deb-scripts
├── postinstall
└── postuninstall
├── dtf-binding
└── dtfbinder
├── dtf-client-app
├── .gitignore
├── LICENSE
├── app
│ ├── build.gradle
│ ├── keys
│ │ └── .gitignore
│ ├── proguard-rules.txt
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── assets
│ │ ├── busybox-arm
│ │ └── busybox-i686
│ │ ├── java
│ │ └── com
│ │ │ └── dtf
│ │ │ └── client
│ │ │ ├── BootReceiver.java
│ │ │ ├── HelperService.java
│ │ │ ├── InitializeService.java
│ │ │ ├── NotificationService.java
│ │ │ ├── ShellExecutor.java
│ │ │ ├── SocketService.java
│ │ │ └── Utils.java
│ │ └── res
│ │ ├── drawable-hdpi
│ │ ├── ic_build_white_48dp.png
│ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ ├── ic_build_white_48dp.png
│ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ ├── ic_build_white_48dp.png
│ │ └── ic_launcher.png
│ │ ├── drawable-xxhdpi
│ │ ├── ic_build_white_48dp.png
│ │ └── ic_launcher.png
│ │ ├── values-v11
│ │ └── styles.xml
│ │ ├── values-v14
│ │ └── styles.xml
│ │ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── dtf-included
├── .gitignore
├── Makefile
└── build
│ └── included.tar
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── installscript
└── install.sh
├── man
├── dtf-archive.ronn
├── dtf-binary.ronn
├── dtf-binding.ronn
├── dtf-check.ronn
├── dtf-client.ronn
├── dtf-init.ronn
├── dtf-library.ronn
├── dtf-local.ronn
├── dtf-module.ronn
├── dtf-package.ronn
├── dtf-pm.ronn
├── dtf-project.ronn
├── dtf-prop.ronn
├── dtf-reset.ronn
├── dtf-status.ronn
├── dtf-upgrade.ronn
└── dtf.ronn
├── python-dtf
├── .coveragerc
├── .gitignore
├── MANIFEST.in
├── README.rst
├── dtf
│ ├── __init__.py
│ ├── adb.py
│ ├── checker.py
│ ├── client.py
│ ├── colors.py
│ ├── constants.py
│ ├── core
│ │ ├── __init__.py
│ │ ├── autoconfig.py
│ │ ├── cmds
│ │ │ ├── __init__.py
│ │ │ ├── archive.py
│ │ │ ├── binding.py
│ │ │ ├── client.py
│ │ │ ├── init.py
│ │ │ ├── local.py
│ │ │ ├── pm.py
│ │ │ ├── prop.py
│ │ │ ├── reset.py
│ │ │ ├── status.py
│ │ │ └── upgrade.py
│ │ ├── compat.py
│ │ ├── item.py
│ │ ├── manifestparser.py
│ │ ├── packagemanager.py
│ │ └── utils.py
│ ├── exceptions.py
│ ├── globals.py
│ ├── included.py
│ ├── launcher.py
│ ├── library.py
│ ├── logging.py
│ ├── module.py
│ ├── packages.py
│ ├── properties.py
│ └── testutils.py
├── generate_coverage.sh
├── pylint.config
├── setup.cfg
├── setup.py
└── tests
│ ├── data-files
│ ├── hello-world.apk
│ ├── integration_client_upload_data
│ ├── integration_module_invalid_noclass
│ ├── integration_module_invalid_noexecargs
│ ├── integration_module_valid_kraise
│ ├── integration_module_valid_mod
│ ├── integration_module_valid_raise
│ ├── integration_module_valid_subs
│ ├── integration_pm_binary_install
│ ├── integration_pm_install_library.dz
│ ├── integration_pm_install_package.dz
│ ├── integration_pm_module_install_bash
│ ├── integration_pm_valid_zip.zip
│ ├── nexus_5x
│ └── valid_android_manifest.xml
│ ├── integration-device
│ └── client
│ │ ├── test_client.py
│ │ ├── test_client_download.py
│ │ ├── test_client_execute.py
│ │ ├── test_client_install.py
│ │ ├── test_client_remove.py
│ │ ├── test_client_restart.py
│ │ ├── test_client_status.py
│ │ └── test_client_upload.py
│ ├── integration
│ ├── archive
│ │ └── test_archive.py
│ ├── binding
│ │ └── test_binding.py
│ ├── local
│ │ └── test_local.py
│ ├── module
│ │ └── test_module.py
│ ├── pm
│ │ ├── test_pm.py
│ │ ├── test_pm_delete.py
│ │ ├── test_pm_export.py
│ │ ├── test_pm_install.py
│ │ ├── test_pm_list.py
│ │ ├── test_pm_purge.py
│ │ └── test_pm_repo.py
│ ├── prop
│ │ ├── test_prop.py
│ │ ├── test_prop_del.py
│ │ ├── test_prop_dump.py
│ │ ├── test_prop_get.py
│ │ ├── test_prop_set.py
│ │ └── test_prop_test.py
│ ├── reset
│ │ └── test_reset.py
│ └── test_dtf.py
│ └── unit
│ ├── test_colors.py
│ ├── test_included.py
│ ├── test_log.py
│ └── test_prop.py
├── release
└── android-dtf_all.deb
├── requirements.txt
├── uninstall_1_3.sh
└── wait_for_emulator
/.gitignore:
--------------------------------------------------------------------------------
1 | # Some dtf stuff shouldn't be added.
2 | .dtf*
3 | .gradle
4 | build/
5 | man/*.[0-9]
6 |
7 | # OS generated files #
8 | ######################
9 | .DS_Store
10 | .DS_Store?
11 | ._*
12 | .Spotlight-V100
13 | .Trashes
14 | ehthumbs.db
15 | Thumbs.db
16 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "2.7"
4 | - "3.3"
5 |
6 | before_install:
7 | # apt-get packages first.
8 | - sudo apt-get -qq update
9 | - sudo apt-get install -y lintian devscripts shellcheck
10 | - if [ `uname -m` = x86_64 ]; then sudo apt-get install -qq libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 lib32z1 libreadline6-dev:i386 libncurses5-dev:i386; fi
11 |
12 | - if test ! -e $HOME/android-sdk-dl/sdk-tools.zip ; then curl https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip > $HOME/android-sdk-dl/sdk-tools.zip ; fi
13 | - unzip -qq -n $HOME/android-sdk-dl/sdk-tools.zip -d $HOME/android-sdk
14 |
15 | # Install or update Android SDK components (will not do anything if already up to date thanks to the cache mechanism)
16 | - echo y | $HOME/android-sdk/tools/bin/sdkmanager 'tools' > /dev/null
17 | - echo y | $HOME/android-sdk/tools/bin/sdkmanager 'platform-tools' > /dev/null
18 | - echo y | $HOME/android-sdk/tools/bin/sdkmanager 'build-tools;26.0.2' > /dev/null
19 | - echo y | $HOME/android-sdk/tools/bin/sdkmanager 'platforms;android-22' > /dev/null
20 | - echo y | $HOME/android-sdk/tools/bin/sdkmanager 'system-images;android-22;default;armeabi-v7a' > /dev/null
21 | - export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
22 | - export JAVA_HOME=/usr/lib/jvm/java-8-oracle
23 |
24 | # Create and start a AVD
25 | - echo no | $HOME/android-sdk/tools/bin/avdmanager create avd --force -n test -k "system-images;android-22;default;armeabi-v7a"
26 | - $HOME/android-sdk/emulator/emulator -avd test -no-audio -no-window &
27 |
28 | install:
29 | - pip install -r "requirements.txt"
30 | - pip install setuptools==28.7.1
31 |
32 | before_script:
33 | # Wait for emulator
34 | - ./wait_for_emulator
35 |
36 | script: ./gradlew --no-daemon buildDebugApk doCoverage
37 |
38 | branches:
39 | only:
40 | - dev
41 |
42 | git:
43 | depth: 5
44 |
45 | before_cache:
46 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
47 | - rm -rf $HOME/.gradle/caches/*/plugin-resolution/
48 |
49 | cache:
50 | directories:
51 | # Android SDK
52 | - $HOME/android-sdk-dl
53 | - $HOME/android-sdk
54 |
55 | # Gradle dependencies
56 | - $HOME/.gradle/caches/
57 | - $HOME/.gradle/wrapper/
58 |
59 | # Android build cache (see http://tools.android.com/tech-docs/build-cache)
60 | - $HOME/.android/build-cache
61 |
62 | # pip caching.
63 | - $HOME/.cache/pip
64 |
65 | env:
66 | - ANDROID_HOME=$HOME/android-sdk
67 |
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Android Device Testing Framework (dtf)
2 | ======================================
3 |
4 | [](https://travis-ci.org/jakev/dtf)
5 |
6 | About
7 | -----
8 | The Android Device Testing Framework (`dtf`) is a data collection and analysis framework to help individuals search for vulnerabilities on mobile devices. `dtf` _is not_ a:
9 |
10 | * Vulnerability scanner or explitation framework for mobile devices
11 | * An application assessment tool
12 | * A "turn your phone into a hacking device" tool
13 |
14 | Instead, `dtf` aims to allow testers to obtain information from their Android device, process this information into databases, and then start searching for vulnerabilities (all without requiring root privileges). These modules help you focus on changes made to AOSP components such as applications, frameworks, system services, as well as lower-level components such as binaries, libraries, and device drivers. In addition, you'll be able to analyze new functionality implemented by the OEMs and other parties to find vulnerabilities.
15 |
16 | ### Key Features
17 | * 30+ modules for collecting, processing, and interacting with a device
18 | * Builtin API for interfacing with your target device
19 | * Python and shell bindings for creating modules
20 | * Per-project property sub-system and logging/auditing
21 | * Bundled versions of numerous Android tools (think apktool/smali/dex2jar)
22 |
23 | Installing
24 | ----------
25 | `dtf` is offically supported on Ubuntu, particularly versions 14 through 16. At this time there is no support for Windows or OS X.
26 |
27 | ### Manual Prerequisites
28 | The only manual installation requirement for `dtf` is the Android SDK (`dtf` relies on the `adb` utility). It is recommended that you install [Android Studio](https://developer.android.com/studio/install.html), and add `adb` to your `$PATH`.
29 |
30 | ### Installation Script
31 | To install `dtf` on Ubuntu (or update the framework), run the following commands:
32 |
33 | $ curl -sSL thecobraden.com/getdtf > install.sh
34 | $ chmod u+x install.sh
35 | $ ./install.sh
36 |
37 | If you're one of those people who doesn't trust the whole `curl|bash` model, just download the script from the [GitHub](https://github.com/android-dtf/dtf/blob/dev/installscript/install.sh) page.
38 |
39 | ### Managing Installed Content
40 | During installation, `dtf` will automatically configure itself to pull from the stable feed of core content. It is a good idea to routinely run the following command to ensure `dtf` remains up-to-date:
41 |
42 | $ dtf pm upgrade
43 |
44 | ### Upgrading from 1.3.0
45 | If you previously installed `dtf` version 1.3.0, you can use the uninstall script to ensure there are no conflicts:
46 |
47 | $ sudo ./uninstall_1_3.sh
48 |
49 | Note that `dtf` version 1.3.1 *does not* require any changes to a user's `$PATH`, so you should remove any `$PATH` changes related to `dtf`.
50 |
51 | Using dtf
52 | ---------
53 | Before using `dtf`, you'll need to enable USB debugging on your target device. If you're unsure of what this is, `dtf` is probably not the tool for you. Once it's enabled, update all Play applications, and connect the device to your PC. Assuming `adb` sees your device, we can create our project with the `init` built-in command:
54 |
55 | $ mkdir MyProject
56 | $ cd MyProject
57 | $ dtf init
58 |
59 | From here, you'll want to read up on each of the many modules that `dtf` supports. See the project Wiki for additional details on using `dtf`.
60 |
61 | Licenses
62 | --------
63 | `dtf` is licensed under the Apache License, Version 2.0, but contains additional code from other projects. Check the NOTICE file for additional projects and licensing.
64 |
65 | Contributing & Building
66 | -----------------------
67 | If you're interested in building your own instance of `dtf`, you'll need a couple of dependences:
68 |
69 | $ sudo apt-get install lintian python2.7 openjdk-8-jdk python-pip devscripts shellcheck
70 | $ sudo pip install flake8 pylint pytest pytest-runner wheel
71 |
72 | You can now build the project, which is currently limited to Debian '.deb' packages. To build `dtf`, run the following command from the project root:
73 |
74 | $ ./gradlew clean useDebugApk makeDeb
75 |
76 | ### Creating Content
77 | The `dtf` `man` pages are a great place to start. The `man` pages for `dtf-module(7)`, `dtf-binary(7)`, `dtf-library(7)` and `dtf-package(7)` will provide additional insight on the structure of `dtf` content. If you're creating a module, it's a good idea to ensure that it passes all the checks with the `dtf_check` utility. More information can be found in the `man` pages for `dtf-check(1)`. To check your new module:
78 |
79 | $ dtf_check -sa my_cool_module
80 |
81 | Questions & Comments
82 | --------------------
83 | Please use the project's GitHub issue tracker for reporting bugs. For bugs related to a specific module, please use the issue tracker for that particular git repo.
84 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 1.3.2
2 |
--------------------------------------------------------------------------------
/bash-dtf/dtf.bash:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | # Bash Completion Script
17 |
18 | getroot () {
19 |
20 | if [ -f .dtfini ]; then echo "$PWD" && return; fi
21 |
22 | test / == "$PWD" && return || test -e "$1" && echo "$PWD" && return || cd .. && upsearch ".dtfini"
23 | }
24 |
25 | upsearch () {
26 | test / == "$PWD" && return || test -e "$1" && echo "$PWD" && return || cd .. && upsearch "$1"
27 | }
28 |
29 | _dtf()
30 | {
31 | MAIN_DB=~/.dtf/main.db
32 |
33 | local cur prev opts
34 | COMPREPLY=()
35 | cur="${COMP_WORDS[COMP_CWORD]}"
36 | prev="${COMP_WORDS[COMP_CWORD-1]}"
37 | opts=""
38 |
39 | TOP=$(getroot)
40 |
41 | CORE="archive binding client help init local modules pm prop reset status version"
42 | MODULES=$(dtf pm list modules -q 2>/dev/null|tr '\n' ' ')
43 | LOCAL_MODULES=$(ls "${TOP}/local_modules" 2>/dev/null)
44 |
45 | opts="${CORE} ${MODULES} ${LOCAL_MODULES}"
46 |
47 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
48 | COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
49 | return 0
50 | else
51 | COMPREPLY=( $(compgen -W "`ls`" -- ${cur}) )
52 | return 0
53 | fi
54 |
55 |
56 | }
57 | complete -F _dtf dtf
58 |
--------------------------------------------------------------------------------
/bash-dtf/dtf_core.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Android Device Testing Framework ("dtf")
3 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Modules that want to take advantage of built-in functionality should source this file.
18 |
19 | # This allows modules to access dtf resources
20 | DTF_DIR=~/.dtf
21 | DTF_BINS=${DTF_DIR}/binaries
22 | DTF_LIBS=${DTF_DIR}/libraries
23 | DTF_MODULES=${DTF_DIR}/modules
24 | DTF_PACKAGES=${DTF_DIR}/packages
25 | DTF_INCLUDED=${DTF_DIR}/included
26 |
27 | export DTF_BINS DTF_LIBS DTF_MODULES DTF_PACKAGES DTF_INCLUDED
28 |
29 | # API Levels for quick references.
30 | export API_1=1
31 | export API_2=2
32 | export API_CUPCAKE=3
33 | export API_DONUT=4
34 | export API_ECLAIR=5
35 | export API_ECLAIR_R1=6
36 | export API_ECLAIR_R2=7
37 | export API_FROYO=8
38 | export API_GINGERBREAD=9
39 | export API_GINGERBREAD_R1=10
40 | export API_HONEYCOMB=11
41 | export API_HONEYCOMB_R1=12
42 | export API_HONEYCOMB_R2=13
43 | export API_ICE_CREAM_SANDWICH=14
44 | export API_ICE_CREAM_SANDWICH_R1=15
45 | export API_JELLY_BEAN=16
46 | export API_JELLY_BEAN_R1=17
47 | export API_JELLY_BEAN_R2=18
48 | export API_KITKAT=19
49 | export API_WEAR=20
50 | export API_LOLLIPOP=21
51 | export API_LOLLIPOP_R1=22
52 | export API_MARSHMALLOW=23
53 | export API_NOUGAT=24
54 |
55 | # In the case of $TOP not being set, you can use this to obtain the project
56 | # path. Chances are that you won't ever need to call this.
57 | getroot () {
58 |
59 | if [ -f .dtfini ]; then echo "$PWD" && return; fi
60 |
61 | test / = "$PWD" && return || test -e "$1" && echo "$PWD" && return || cd .. && upsearch ".dtfini"
62 | }
63 |
64 | # Helper for obtaining project root. Not meant to be called (unless you wanted
65 | # to?)
66 | upsearch () {
67 | test / = "$PWD" && return || test -e "$1" && echo "$PWD" && return || cd .. && upsearch "$1"
68 | }
69 |
70 | # Top of the project.
71 | export TOP
72 | TOP=$(upsearch .dtfini)
73 |
74 | # Change back to the launch directory
75 | dtf_reset_dir() {
76 |
77 | cd "$LAUNCH_DIR" || exit 1
78 | }
79 |
80 | # Method to check if device is connected.
81 | # returns 1 if connected, 0 if not connected.
82 | dtf_device_connected ()
83 | {
84 | state=$(adb get-state)
85 |
86 | if [ "$state" = "device" ]; then
87 | return 0
88 | fi
89 |
90 | return 1
91 | }
92 |
93 | # Check if a module is installed.
94 | dtf_has_module ()
95 | {
96 | module_name=$1
97 |
98 | if dtf pm list modules -q |grep "\b${module_name}$" > /dev/null; then
99 | return 0
100 | else
101 | return 1
102 | fi
103 | }
104 |
105 | # Check if a binary is installed.
106 | dtf_has_binary ()
107 | {
108 | binary_name=$1
109 |
110 | if dtf pm list binaries -q |grep "\b${binary_name}$" > /dev/null; then
111 | return 0
112 | else
113 | return 1
114 | fi
115 | }
116 |
117 | # Check if a library is installed.
118 | dtf_has_library ()
119 | {
120 | library_name=$1
121 |
122 | if dtf pm list libraries -q |grep "\b${library_name}$" > /dev/null; then
123 | return 0
124 | else
125 | return 1
126 | fi
127 | }
128 |
129 | # Check if a package is installed.
130 | dtf_has_package ()
131 | {
132 | package_name=$1
133 |
134 | if dtf pm list packages -q |grep "\b${package_name}$" > /dev/null; then
135 | return 0
136 | else
137 | return 1
138 | fi
139 | }
140 |
--------------------------------------------------------------------------------
/bash-dtf/dtf_log.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Android Device Testing Framework ("dtf")
3 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Modules may source this file to use dtf's logging capabilities.
18 |
19 | # Taken from: https://gist.github.com/bcap/5682077#file-terminal-control-sh
20 | # Terminal output control (http://www.termsys.demon.co.uk/vtansi.htm)
21 |
22 |
23 | # Feel free to override these in your module.
24 | LOG_FILE=.dtflog
25 | LOG_LEVEL=4
26 | LOG_TO_STDOUT=1
27 | LOG_TO_FILE=1
28 |
29 | # Don't override the global logging.
30 | if [ -z "$GLOG_LEVEL" ]; then
31 | GLOG_LEVEL=$LOG_LEVEL
32 | fi
33 |
34 | #########################
35 | # Format Notes:
36 | #[2013-01-02T12:00:31] testmodule/E - This is an error!
37 | # [], E, W, I, V, D
38 | # 0, 1, 2, 3, 4, 5
39 | #########################
40 |
41 | COLOR_ERROR=$(tput setaf 1)
42 | COLOR_WARN=$(tput setaf 3)
43 | COLOR_INFO=$(tput setaf 2)
44 | COLOR_VERB=$(tput setaf 6)
45 | COLOR_DEB=$(tput setaf 5)
46 | COLOR_RST=$(tput sgr0)
47 |
48 |
49 | # Internal low-level logger
50 | _log()
51 | {
52 | date="[$(date)]"
53 | color=$1
54 | app=$2
55 | shift
56 | shift
57 | message=$*
58 |
59 | if [ "${LOG_TO_FILE}" -eq "1" ]; then
60 | echo "${date} ${app} - ${message}" >> ${LOG_FILE};
61 | fi
62 |
63 | if [ "${LOG_TO_STDOUT}" -eq "1" ]; then
64 | printf "%s %s - %s\n" "${color}${date}" "${app}" "${message}${COLOR_RST}"
65 | fi
66 | }
67 |
68 | # Print an error message
69 | log_e()
70 | {
71 | LOG_LEVEL=$GLOG_LEVEL
72 | if [ "${LOG_LEVEL}" -ge 1 ]; then
73 | caller=$(basename "${0}")
74 | _log "${COLOR_ERROR}" "${caller}/E" "$@"
75 | fi
76 | }
77 |
78 | # Print a warning message
79 | log_w()
80 | {
81 | LOG_LEVEL=$GLOG_LEVEL
82 | if [ "${LOG_LEVEL}" -ge 2 ]; then
83 | caller=$(basename "${0}")
84 | _log "${COLOR_WARN}" "${caller}/W" "$@"
85 | fi
86 | }
87 |
88 | # Print an informational message
89 | log_i()
90 | {
91 | LOG_LEVEL=$GLOG_LEVEL
92 | if [ "${LOG_LEVEL}" -ge 3 ]; then
93 | caller=$(basename "${0}")
94 | _log "${COLOR_INFO}" "${caller}/I" "$@"
95 | fi
96 | }
97 |
98 | # Print a verbose message
99 | log_v()
100 | {
101 | LOG_LEVEL=$GLOG_LEVEL
102 | if [ "${LOG_LEVEL}" -ge 4 ]; then
103 | caller=$(basename "${0}")
104 | _log "${COLOR_VERB}" "${caller}/V" "$@"
105 | fi
106 | }
107 |
108 | # Print a debugging message
109 | log_d()
110 | {
111 | LOG_LEVEL=$GLOG_LEVEL
112 | if [ "${LOG_LEVEL}" -ge 5 ]; then
113 | caller=$(basename "${0}")
114 | _log "${COLOR_DEB}" "${caller}/D" "$@"
115 | fi
116 | }
117 |
--------------------------------------------------------------------------------
/deb-scripts/postinstall:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | case "$1" in
4 | configure)
5 | pip install /tmp/dtf-*.whl
6 | ;;
7 | esac
8 |
--------------------------------------------------------------------------------
/deb-scripts/postuninstall:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | case "$1" in
4 | remove)
5 | pip uninstall -y dtf
6 | ;;
7 | purge)
8 | rm -rf ~/.dtf
9 | ;;
10 | esac
11 |
--------------------------------------------------------------------------------
/dtf-binding/dtfbinder:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Android Device Testing Framework ("dtf")
3 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Central point for dtf bindings
18 |
19 | # Helpers
20 |
21 |
22 |
23 | # This determines the real serial based on the current mode
24 | get_connection_serial ()
25 | {
26 | mode=$(dtf prop get Client mode)
27 |
28 | if [ "$mode" = "usb" ]; then
29 | serial=$(dtf prop get Info serial)
30 | echo "$serial"
31 | elif [ "$mode" = "wifi" ]; then
32 | ip_addr=$(dtf prop get Client ip-addr)
33 | port=$(dtf prop get Client port)
34 | echo "${ip_addr}:${port}"
35 | fi
36 | }
37 |
38 | launch_shell()
39 | {
40 | ANDROID_SERIAL=$(get_connection_serial) adb shell "$@"
41 |
42 | return 0
43 | }
44 |
45 | launch_busybox()
46 | {
47 | busybox=$(dtf prop get Info busybox)
48 | serial=$(get_connection_serial)
49 |
50 | adb -s "${serial}" shell run-as com.dtf.client "${busybox}" "$@"
51 | }
52 |
53 | launch_aapt()
54 | {
55 | aapt_file=$(dtf binding dtf_aapt)
56 | if [ ! -r "$aapt_file" ]; then
57 | echo "dtf_aapt: can't find $aapt_file"
58 | return 1
59 | fi
60 |
61 | $aapt_file "$@"
62 | return $?
63 | }
64 |
65 |
66 | launch_abe()
67 | {
68 | jarfile=$(dtf binding dtf_abe)
69 | if [ ! -r "$jarfile" ]; then
70 | echo "dtf_abe: can't find $jarfile"
71 | return 1
72 | fi
73 |
74 | javaOpts="-Xmx256M"
75 |
76 | while expr "x$1" : 'x-J' >/dev/null; do
77 | opt=$(expr "$1" : '-J\(.*\)')
78 | javaOpts="${javaOpts} -${opt}"
79 | shift
80 | done
81 |
82 | jarpath="$jarfile"
83 |
84 | java "$javaOpts" -jar "$jarpath" "$@"
85 |
86 | return $?
87 | }
88 |
89 | launch_apktool()
90 | {
91 | jarfile=$(dtf binding dtf_apktool)
92 | if [ ! -r "$jarfile" ]; then
93 | echo "dtf_apktool: can't find $jarfile"
94 | return 1
95 | fi
96 |
97 | javaOpts="-Xmx256M"
98 |
99 | while expr "x$1" : 'x-J' >/dev/null; do
100 | opt=$(expr "$1" : '-J\(.*\)')
101 | javaOpts="${javaOpts} -${opt}"
102 | shift
103 | done
104 |
105 | jarpath="$jarfile"
106 |
107 | java "$javaOpts" -jar "$jarpath" "$@"
108 |
109 | return $?
110 | }
111 |
112 | launch_axmlprinter2()
113 | {
114 | jarfile=$(dtf binding dtf_axmlprinter2)
115 | if [ ! -r "$jarfile" ]; then
116 | echo "dtf_axmlprinter2: can't find $jarfile"
117 | return 1
118 | fi
119 |
120 | javaOpts="-Xmx256M"
121 |
122 | while expr "x$1" : 'x-J' >/dev/null; do
123 | opt=$(expr "$1" : '-J\(.*\)')
124 | javaOpts="${javaOpts} -${opt}"
125 | shift
126 | done
127 |
128 | jarpath="$jarfile"
129 |
130 | java "$javaOpts" -jar "$jarpath" "$@"
131 |
132 | return $?
133 | }
134 |
135 | launch_baksmali()
136 | {
137 | jarfile=$(dtf binding dtf_baksmali)
138 | if [ ! -r "$jarfile" ]; then
139 | echo "dtf_baksmali: can't find $jarfile"
140 | return 1
141 | fi
142 |
143 | javaOpts="-Xmx256M"
144 |
145 | while expr "x$1" : 'x-J' >/dev/null; do
146 | opt=$(expr "$1" : '-J\(.*\)')
147 | javaOpts="${javaOpts} -${opt}"
148 | shift
149 | done
150 |
151 | jarpath="$jarfile"
152 |
153 | java "$javaOpts" -jar "$jarpath" "$@"
154 | return $?
155 | }
156 |
157 | launch_smali()
158 | {
159 | jarfile=$(dtf binding dtf_smali)
160 | if [ ! -r "$jarfile" ]; then
161 | echo "dtf_smali: can't find $jarfile"
162 | return 1
163 | fi
164 |
165 | javaOpts="-Xmx256M"
166 |
167 | while expr "x$1" : 'x-J' >/dev/null; do
168 | opt=$(expr "$1" : '-J\(.*\)')
169 | javaOpts="${javaOpts} -${opt}"
170 | shift
171 | done
172 |
173 | jarpath="$jarfile"
174 |
175 | java "$javaOpts" -jar "$jarpath" "$@"
176 |
177 | return $?
178 | }
179 |
180 | # Main
181 | calling_bind=$(basename "$0")
182 |
183 | case $calling_bind in
184 | dtf_shell)
185 | launch_shell "$@"
186 | return 0 ;;
187 | dtf_busybox)
188 | launch_busybox "$@"
189 | return 0 ;;
190 | dtf_aapt)
191 | launch_aapt "$@"
192 | return $? ;;
193 | dtf_abe)
194 | launch_abe "$@"
195 | return $? ;;
196 | dtf_apktool)
197 | launch_apktool "$@"
198 | return $? ;;
199 | dtf_axmlprinter2)
200 | launch_axmlprinter2 "$@"
201 | return $? ;;
202 | dtf_baksmali)
203 | launch_baksmali "$@"
204 | return $? ;;
205 | dtf_smali)
206 | launch_smali "$@"
207 | return $? ;;
208 | # Don't call directly!
209 | dtfbinder) echo "Don't call binder directly!";;
210 |
211 | # Other...
212 | *) echo "Binding not found!" ;;
213 | esac
214 |
--------------------------------------------------------------------------------
/dtf-client-app/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | app/build/
3 | app/src/main/bin/
4 | app/src/main/gen/
5 | build/
6 | .idea/
7 | .gradle
8 | /local.properties
9 | .DS_Store
10 | captures/
11 | gen/
12 |
--------------------------------------------------------------------------------
/dtf-client-app/app/build.gradle:
--------------------------------------------------------------------------------
1 | import groovy.swing.SwingBuilder
2 |
3 | apply plugin: 'com.android.application'
4 | apply plugin: 'findbugs'
5 |
6 | System.setProperty('java.awt.headless', 'false')
7 |
8 | android {
9 | compileSdkVersion 25
10 | buildToolsVersion '26.0.2'
11 |
12 | defaultConfig {
13 | applicationId PACKAGE_NAME
14 | minSdkVersion 10
15 | targetSdkVersion 25
16 | versionCode VERSION_CODE.toInteger()
17 | versionName VERSION_NAME
18 | }
19 |
20 | signingConfigs {
21 | release {
22 | storeFile file("keys/ReleaseKeys.jks")
23 | keyAlias 'dtfReleaseKeys'
24 | storePassword "X"
25 | keyPassword "X"
26 | }
27 | }
28 |
29 | buildTypes {
30 | release {
31 | debuggable true
32 | minifyEnabled true
33 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
34 | signingConfig signingConfigs.release
35 |
36 | applicationVariants.all { variant ->
37 | variant.outputs.all { output ->
38 |
39 | outputFileName = "${PACKAGE_NAME}-${variant.versionName}-${variant.versionCode}.apk"
40 | }
41 | }
42 |
43 | }
44 | }
45 |
46 | lintOptions {
47 | abortOnError true
48 | }
49 |
50 | task findBugs(type: FindBugs, dependsOn: "assembleDebug") {
51 |
52 | description 'Run findbugs'
53 | group 'verification'
54 |
55 | classes = fileTree('build/intermediates/classes/debug/')
56 | source = fileTree('com/dtf/client')
57 | classpath = files()
58 |
59 | effort = 'max'
60 | reportLevel = 'high'
61 |
62 | reports {
63 | html.enabled = true
64 | xml.enabled = false
65 | }
66 | }
67 | }
68 |
69 | task askForPasswords << {
70 |
71 | def console = System.console()
72 | def storePw
73 | def keyPw
74 |
75 | if (console) {
76 | storePw = new String(console.readPassword("\nKeystore password: "))
77 | keyPw = new String(console.readPassword("Key password: "))
78 | } else {
79 | // Gradle is running as a daemon - prompt user to enter passwords via popup UI (#770)
80 | new SwingBuilder().edt {
81 | dialog(modal: true, title: 'Enter credentials', alwaysOnTop: true, resizable: true,
82 | locationRelativeTo: null, pack: true, show: true
83 | ) {
84 | vbox {
85 | label(text: "Keystore passphrase:")
86 | textField id: "storeText", input = passwordField()
87 | label(text: "Key passphrase:")
88 | textField id: "keyText", input = passwordField()
89 | button(defaultButton: true, text: 'OK', actionPerformed: {
90 | storePw = storeText.text;
91 | keyPw = keyText.text;
92 | dispose();
93 | })
94 | }
95 | }
96 | }
97 | }
98 |
99 | android.signingConfigs.release.storePassword = storePw
100 | android.signingConfigs.release.keyPassword = keyPw
101 | }
102 |
103 | // Tricks for password prompt
104 | tasks.whenTaskAdded { theTask ->
105 | if (theTask.name.matches("packageRelease")) {
106 | theTask.dependsOn "askForPasswords"
107 | }
108 | }
109 |
110 | dependencies {
111 | compile "com.android.support:support-core-utils:25.4.0"
112 | }
113 |
114 | afterEvaluate {
115 | assembleRelease.dependsOn findBugs
116 | }
117 |
--------------------------------------------------------------------------------
/dtf-client-app/app/keys/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
5 |
--------------------------------------------------------------------------------
/dtf-client-app/app/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
35 |
36 |
40 |
41 |
42 |
43 |
44 |
45 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/assets/busybox-arm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/assets/busybox-arm
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/assets/busybox-i686:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/assets/busybox-i686
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/java/com/dtf/client/BootReceiver.java:
--------------------------------------------------------------------------------
1 | package com.dtf.client;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | public class BootReceiver extends BroadcastReceiver {
8 |
9 | public BootReceiver() {
10 | }
11 |
12 | @Override
13 | public void onReceive(Context context, Intent intent) {
14 |
15 | if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
16 |
17 | /* Start the notification banner */
18 | context.startService(new Intent(context, NotificationService.class));
19 |
20 | /* Start the LocalSocketServer */
21 | context.startService(new Intent(context, SocketService.class));
22 | }
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/java/com/dtf/client/HelperService.java:
--------------------------------------------------------------------------------
1 | package com.dtf.client;
2 |
3 | import android.app.IntentService;
4 | import android.content.Intent;
5 | import android.util.Log;
6 |
7 |
8 | public class HelperService extends IntentService {
9 |
10 | private static final String ACTION_RESTART_SOCKET = "com.dtf.action.name.RESTART_SOCKET";
11 |
12 | private static final String TAG = "DtfHelperService";
13 |
14 | public HelperService() {
15 | super("HelperService");
16 | }
17 |
18 | @Override
19 | protected void onHandleIntent(Intent intent) {
20 | if (intent != null) {
21 | final String action = intent.getAction();
22 |
23 | if (ACTION_RESTART_SOCKET.equals(action)) {
24 | handleActionRestartSocket();
25 | }
26 | }
27 | }
28 |
29 | private void handleActionRestartSocket() {
30 |
31 | if (SocketService.isRunning) {
32 |
33 | // First stop the socket service.
34 | Log.d(TAG, "Stopping the socket service...");
35 |
36 | this.stopService(new Intent(this, SocketService.class));
37 |
38 | } else {
39 | Log.d(TAG, "Socket service is not running, skipping...");
40 | }
41 |
42 | // Give it 2 seconds to cool down
43 | try {
44 | Thread.sleep(2000);
45 | } catch (InterruptedException e) {
46 | e.printStackTrace();
47 | }
48 |
49 | // Now start it!
50 | Log.d(TAG, "Starting socket service!");
51 | this.startService(new Intent(this, SocketService.class));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/java/com/dtf/client/InitializeService.java:
--------------------------------------------------------------------------------
1 | /* Android Device Testing Framework ("dtf")
2 | * Copyright 2013-2014 Jake Valletta (@jake_valletta)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.dtf.client;
18 |
19 | import android.app.IntentService;
20 | import android.content.Intent;
21 | import android.content.res.AssetManager;
22 | import android.util.Log;
23 |
24 | import java.io.File;
25 | import java.io.FileOutputStream;
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 | import java.io.OutputStream;
29 |
30 | public class InitializeService extends IntentService {
31 |
32 | private final String TAG = "DtfInitializeService";
33 |
34 | public InitializeService() {
35 | super("InitializeService");
36 | }
37 |
38 | @Override
39 | protected void onHandleIntent(Intent intent) {
40 |
41 | Log.d(TAG, "Copying assets...");
42 | int resp = copyAssets();
43 | Log.d(TAG, "Copy completed: " + resp);
44 |
45 | Log.d(TAG, "Setting file directory as executable...");
46 | resp = setExecutable();
47 | Log.d(TAG, "Set complete: " + resp);
48 |
49 | /* Start the notification banner */
50 | this.startService(new Intent(this, NotificationService.class));
51 |
52 | /* Start the LocalSocketServer */
53 | this.startService(new Intent(this, SocketService.class));
54 |
55 | }
56 |
57 | private int copyAssets() {
58 |
59 | String busyboxFile = "";
60 | if (Utils.isArm()) {
61 | busyboxFile = "busybox-arm";
62 | }
63 | else if (Utils.isIntel()) {
64 | busyboxFile = "busybox-i686";
65 | }
66 |
67 | else {
68 | Log.e(TAG, "Unable to determine CPU type!");
69 | }
70 |
71 | AssetManager assetManager = getAssets();
72 | String[] files = null;
73 |
74 | try {
75 | files = assetManager.list("");
76 | } catch (IOException e) {
77 | Log.e("tag", "Failed to get asset file list.", e);
78 | return -1;
79 | }
80 |
81 | for(String filename : files) {
82 | if (filename.equals(busyboxFile)) {
83 |
84 | Log.d(TAG, "Copying asset: " + busyboxFile);
85 |
86 | InputStream in = null;
87 | OutputStream out = null;
88 |
89 | try {
90 | in = assetManager.open(busyboxFile);
91 | File outFile = new File(this.getFilesDir()+"/", "busybox");
92 |
93 | out = new FileOutputStream(outFile);
94 | copyFile(in, out);
95 | in.close();
96 | in = null;
97 | out.flush();
98 | out.close();
99 | out = null;
100 |
101 | // Make it world executable.
102 | outFile.setExecutable(true, false);
103 |
104 | } catch(IOException e) {
105 | Log.e("tag", "Failed to copy asset file: " + filename, e);
106 | return -2;
107 | }
108 | }
109 | }
110 | return 0;
111 | }
112 |
113 | private int setExecutable() {
114 |
115 | Process p = null;
116 | try {
117 | p = Runtime.getRuntime().exec("chmod 777 /data/data/com.dtf.client/files");
118 | p.waitFor();
119 | } catch (InterruptedException e) {
120 | Log.e(TAG, "Unable to open permissions on files directory!");
121 | return -1;
122 | } catch (IOException e) {
123 | Log.e(TAG, "Unable to open permissions on files directory!");
124 | return -2;
125 | }
126 |
127 | return 0;
128 | }
129 |
130 | private void copyFile(InputStream in, OutputStream out) throws IOException {
131 | byte[] buffer = new byte[1024];
132 | int read;
133 | while((read = in.read(buffer)) != -1){
134 | out.write(buffer, 0, read);
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/java/com/dtf/client/NotificationService.java:
--------------------------------------------------------------------------------
1 | package com.dtf.client;
2 |
3 | import android.app.IntentService;
4 | import android.app.Notification;
5 | import android.app.NotificationManager;
6 | import android.app.PendingIntent;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.graphics.BitmapFactory;
10 | import android.net.Uri;
11 | import android.os.Build;
12 | import android.support.v4.app.NotificationCompat;
13 | import android.util.Log;
14 |
15 |
16 | public class NotificationService extends IntentService {
17 |
18 | NotificationManager notificationManager;
19 | private static final int NOTIFICATION_ID = 1;
20 | private static final String TAG = "NotificationService";
21 |
22 | public NotificationService() {
23 | super("NotificationService");
24 | }
25 |
26 | @Override
27 | protected void onHandleIntent(Intent intent) {
28 | stickyNotification();
29 | }
30 |
31 | private void stickyNotification() {
32 |
33 | Log.d(TAG, "Creating our sticky notification!");
34 |
35 | notificationManager =
36 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
37 |
38 | Intent i = new Intent();
39 | i.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
40 | i.setData(Uri.parse("package:com.dtf.client"));
41 |
42 | PendingIntent pendingIntent = PendingIntent.getActivity(this,
43 | NOTIFICATION_ID, i, PendingIntent.FLAG_UPDATE_CURRENT);
44 |
45 | Notification n;
46 |
47 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
48 |
49 | NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
50 | .setContentTitle("dtfClient is Installed!")
51 | .setContentText("Click here to uninstall")
52 | .setContentIntent(pendingIntent)
53 | .setSmallIcon(R.drawable.ic_build_white_48dp)
54 | .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
55 |
56 | n = builder.build();
57 | } else {
58 |
59 | Notification.Builder builder = new Notification.Builder(this)
60 | .setContentTitle("dtfClient is Installed!")
61 | .setContentText("Click here to uninstall")
62 | .setContentIntent(pendingIntent)
63 | .setSmallIcon(R.drawable.ic_build_white_48dp)
64 | .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
65 | n = builder.build();
66 | }
67 |
68 | n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
69 | notificationManager.notify(NOTIFICATION_ID, n);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/java/com/dtf/client/ShellExecutor.java:
--------------------------------------------------------------------------------
1 | package com.dtf.client;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 | import java.nio.charset.Charset;
6 |
7 | public class ShellExecutor {
8 |
9 | public ShellExecutor() {
10 |
11 | }
12 |
13 | public String execute(String command) {
14 |
15 | StringBuffer output = new StringBuffer();
16 |
17 | Process p;
18 | try {
19 | p = Runtime.getRuntime().exec(command);
20 | p.waitFor();
21 | BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream(),
22 | Charset.forName("UTF-8")));
23 |
24 | String line;
25 | while ((line = reader.readLine())!= null) {
26 | output.append(line + "\n");
27 | }
28 |
29 | } catch (Exception e) {
30 | e.printStackTrace();
31 | }
32 | String response = output.toString();
33 | return response;
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/java/com/dtf/client/Utils.java:
--------------------------------------------------------------------------------
1 | package com.dtf.client;
2 |
3 |
4 | import android.os.Build;
5 |
6 | public class Utils {
7 |
8 | static String cpu = Build.CPU_ABI;
9 |
10 | static boolean isIntel() {
11 |
12 | if (cpu.startsWith("x86")) {
13 | return true;
14 | }
15 | return false;
16 | }
17 |
18 | static boolean isArm() {
19 |
20 | if (cpu.startsWith("arm")) {
21 | return true;
22 | }
23 | return false;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-hdpi/ic_build_white_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-hdpi/ic_build_white_48dp.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-mdpi/ic_build_white_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-mdpi/ic_build_white_48dp.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-xhdpi/ic_build_white_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-xhdpi/ic_build_white_48dp.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-xxhdpi/ic_build_white_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-xxhdpi/ic_build_white_48dp.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | dtf Client
4 |
5 |
6 |
--------------------------------------------------------------------------------
/dtf-client-app/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/dtf-client-app/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | google()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.0.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | jcenter()
15 | google()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/dtf-client-app/gradle.properties:
--------------------------------------------------------------------------------
1 | PACKAGE_NAME=com.dtf.client
2 | VERSION_NAME=1.0
3 | VERSION_CODE=4
4 |
--------------------------------------------------------------------------------
/dtf-client-app/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-client-app/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/dtf-client-app/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Nov 11 12:41:45 PST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/dtf-client-app/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/dtf-client-app/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/dtf-client-app/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/dtf-included/.gitignore:
--------------------------------------------------------------------------------
1 | src/
2 | out/
3 |
--------------------------------------------------------------------------------
/dtf-included/Makefile:
--------------------------------------------------------------------------------
1 | setup:
2 | mkdir -p src/
3 | mkdir -p out/
4 |
5 | abe: setup
6 | git clone https://github.com/nelenkov/android-backup-extractor.git src/abe
7 | cd src/abe; \
8 | wget https://www.bouncycastle.org/download/bcprov-jdk15on-158.jar -O lib/bcprov-jdk15on-158.jar; \
9 | ./gradlew build shadowJar; \
10 | cp ./build/libs/abe-all.jar ../../out/abe.jar
11 |
12 | apktool: setup
13 | git clone git://github.com/iBotPeaches/Apktool.git src/apktool
14 | cd src/apktool; \
15 | ./gradlew build shadowJar; \
16 | cp ./brut.apktool/apktool-cli/build/libs/apktool-cli-all.jar ../../out/apktool.jar; \
17 | cp ./brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt ../../out/aapt
18 |
19 | axmlprinter: setup
20 | git clone https://github.com/rednaga/axmlprinter src/axmlprinter2
21 | cd src/axmlprinter2; \
22 | ./gradlew jar; \
23 | cp ./build/libs/axmlprinter*.jar ../../out/axmlprinter2.jar
24 |
25 | smali: setup
26 | git clone https://github.com/JesusFreke/smali.git src/smali
27 | cd src/smali; \
28 | ./gradlew build; \
29 | cp ./smali/build/libs/smali.jar ../../out/smali.jar; \
30 | cp ./baksmali/build/libs/baksmali.jar ../../out/baksmali.jar
31 |
32 | version:
33 | echo $(shell date +%Y-%m-%d) > out/VERSION
34 |
35 | tar: version
36 | cd out; \
37 | tar -cf ../build/included.tar ./*
38 |
39 | fatTar: abe apktool axmlprinter smali tar
40 |
41 | clean:
42 | rm -rf src/
43 | rm -rf out/
44 | rm -rf build/*
45 |
--------------------------------------------------------------------------------
/dtf-included/build/included.tar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/dtf-included/build/included.tar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
6 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/man/dtf-archive.ronn:
--------------------------------------------------------------------------------
1 | dtf-archive(1) -- Create a ZIP archive for your project
2 | =======================================================
3 |
4 | ## SYNOPSIS
5 | dtf archive [subcommand] []
6 |
7 | Subcommands:
8 | create Archive the current project.
9 |
10 | ## DESCRIPTION
11 | dtf-archive(1) is used to create a ZIP file containing all files for a given dtf(1) project for archiving purposes. By default, it uses the version string set by dtf-init(1).
12 |
13 | ## EXAMPLES
14 | Create an archive using the default version string:
15 | $ dtf archive create
16 |
17 | Create an archive called :
18 | $ dtf archive create my_archive.zip
19 |
20 | ## AUTHOR
21 | Jake Valletta
22 |
23 | ## DTF
24 | Part of the dtf(1) suite.
25 |
--------------------------------------------------------------------------------
/man/dtf-binary.ronn:
--------------------------------------------------------------------------------
1 | dtf-binary(7) -- dtf binary documentation
2 | =========================================
3 |
4 | ## DESCRIPTION
5 | A dtf-binary(7) is an executable file that is needed by a module. Currently, there is no support for architectures or versions of Linux. Use with caution. A dtf-binary(7) is installed using dtf-pm(1).
6 |
7 | ## EXAMPLES
8 | A dtf-binary(7) can be launched using a python-based dtf-module(7) using the **dtf.package** class:
9 |
10 | import dtf.package as pm
11 |
12 | ...
13 |
14 | # Launch executable
15 | pm.launch_binary('somebin')
16 |
17 | # Using the launcher= to specify how to load
18 | pm.launch_binary('some_java_bin', launcher='java -jar')
19 |
20 | ## AUTHOR
21 | Jake Valletta
22 |
23 | ## DTF
24 | Part of the dtf(1) suite.
25 |
26 | ## SEE ALSO
27 | dtf-pm(1), dtf-local(1), dtf-library(7), dtf-module(7), dtf-package(7)
28 |
--------------------------------------------------------------------------------
/man/dtf-binding.ronn:
--------------------------------------------------------------------------------
1 | dtf-binding(1) -- View bindings for built-in tools
2 | ==================================================
3 |
4 | ## SYNOPSIS
5 | dtf binding []
6 |
7 | ## DESCRIPTION
8 | dtf-binding(1) prints a single dtf binding or all bindings for built-in tools. This lets a modules use the **dtf.included** python class and **dtf_\*** helpers to invoke Android tools such as aapt and apktool.
9 |
10 | ## EXAMPLES
11 | To print all bindings, run dtf-binding(1) with no arguments:
12 |
13 | $ dtf binding
14 |
15 | To print a single binding, supply it as argument 1:
16 |
17 | $ dtf binding dtf_apktool
18 |
19 | The purpose of this system is to allow hotswapping of built-in tools. For example, suppose a specific version of smali is desired for a given project. You can edit the file "~/.dtf/included/globals.ini" to reflect this. Now, when using dtf(1), this new tool will be used.
20 |
21 | ## AUTHOR
22 | Jake Valletta
23 |
24 | ## DTF
25 | Part of the dtf(1) suite.
26 |
--------------------------------------------------------------------------------
/man/dtf-check.ronn:
--------------------------------------------------------------------------------
1 | dtf-check(1) -- Check a dtf Module for errors and style
2 | =======================================================
3 |
4 | ## SYNOPSIS
5 | dtf check -s -a []
6 |
7 | ## DESCRIPTION
8 | dtf-check(1) checks a dtf-module(7) for syntax and style weaknesses. Those who wish to contribute to dtf(1) should use this utility to ensure they are introducing robust and readadble code. Since dtf-check(1) uses the same functions used by dtf(1) to load modules, it ensures the specified module:
9 | - Will be detected as a python or bash module
10 | - Will pass all autoparse checks
11 | - Contains only best practice values in autoparse
12 | - Will pass `pylint` and `flake8` checks (optional)
13 |
14 | ## EXAMPLES
15 | dtf-check(1) takes a **file_name** argument:
16 |
17 | $ dtf_check mynewmodule
18 |
19 | To run dtf-check(1) will all checks, use the all (**-a**) argument:
20 |
21 | $ dtf_check -a mynewmodule
22 |
23 | If you want to treat warnings as errors (recommended), use the strict (**-s**) argument:
24 |
25 | $ dtf_check -sa mynewmodule
26 |
27 | For more information on creating modules, see dtf-module(7).
28 |
29 | ## AUTHOR
30 | Jake Valletta
31 |
32 | ## DTF
33 | Part of the dtf(1) suite.
34 |
--------------------------------------------------------------------------------
/man/dtf-client.ronn:
--------------------------------------------------------------------------------
1 | dtf-client(1) -- Interact with dtfClient on device
2 | ==================================================
3 |
4 | ## SYNOPSIS
5 | dtf client [subcommand] []
6 |
7 | Subcommands:
8 | download Download a file using dtfClient.
9 | execute Execute a command using dtfClient.
10 | install Install the dtf client on device.
11 | status Print the install status of the client.
12 | remove Uninstall the dtf client.
13 | restart Restart dtfClient's socket service.
14 | upload Upload file using dtfClient.
15 |
16 | ## DESCRIPTION
17 | dtf-client(1) is used to interact with the dtfClient ("com.dtf.client") installed on your project device.
18 |
19 | ## EXAMPLES
20 | Determine if a device has the dtfClient application installed:
21 | $ dtf client status
22 |
23 | Install the dtfClient on a test device:
24 | $ dtf client install
25 |
26 | Restart any dtfClient services (useful for troubleshooting):
27 | $ dtf client restart
28 |
29 | Upload a file to the dtfClient's data directory:
30 | $ dtf client upload some_file.txt
31 |
32 | Download a file from the dtfClient's data directory and rename:
33 | $ dtf client download some.db --path ./users.db
34 |
35 | Execute a command using the dtfClient:
36 | $ dtf client execute ls /mnt/sdcard
37 |
38 | Remove the dtfClient application:
39 | $ dtf client remove
40 |
41 | ## AUTHOR
42 | Jake Valletta
43 |
44 | ## DTF
45 | Part of the dtf(1) suite.
46 |
--------------------------------------------------------------------------------
/man/dtf-init.ronn:
--------------------------------------------------------------------------------
1 | dtf-init(1) -- Initialize a dtf project
2 | =======================================
3 |
4 | ## SYNOPSIS
5 | dtf init
6 |
7 | ## DESCRIPTION
8 | dtf-init(1) creates an dtf(1) project in the current directory. It will install the dtfClient onto a test device, and create a boilerplate directory structure (see dtf-project(7) for more information on what emcompasses a dtf project).
9 |
10 | ## EXAMPLES
11 | In order to use dtf(1), you'll need to initialize a project. Before doing so, make sure that USB debugging is enabled on your test device, the device is connected, and your test machine's RSA keys are trusted. Once all of these are met, you can create your project with dtf-init(1):
12 |
13 | $ mkdir new_project
14 | $ cd new_project
15 | $ dtf init
16 |
17 | See dtf-reset(1) deleting a dtf project.
18 |
19 | ## AUTHOR
20 | Jake Valletta
21 |
22 | ## DTF
23 | Part of the dtf(1) suite.
24 |
--------------------------------------------------------------------------------
/man/dtf-library.ronn:
--------------------------------------------------------------------------------
1 | dtf-library(7) -- dtf library documentation
2 | ===========================================
3 |
4 | ## DESCRIPTION
5 | A dtf-library(7) is a collection of python files used by a dtf-module(7). A dtf-library(7) is installed using dtf-pm(1).
6 |
7 | ## AUTHOR
8 | Jake Valletta
9 |
10 | ## DTF
11 | Part of the dtf(1) suite.
12 |
13 | ## SEE ALSO
14 | dtf-pm(1), dtf-local(1), dtf-binary(7), dtf-module(7), dtf-package(7)
15 |
--------------------------------------------------------------------------------
/man/dtf-local.ronn:
--------------------------------------------------------------------------------
1 | dtf-local(1) -- Print all local (non-global) modules
2 | ====================================================
3 |
4 | ## SYNOPSIS
5 | dtf local
6 |
7 | ## DESCRIPTION
8 | dtf-local(1) prints all local (non-global) modules. Note that a local module will take precedence over a global module.
9 |
10 | ## EXAMPLES
11 | dtf-local(1) does not take any arguments, and does not have any subcommands. To print local modules:
12 |
13 | $ cd my_project
14 | $ dtf local
15 |
16 | Local modules are parsed the same as global modules. The only difference is that local modules exist in the _local_modules/_ directory of a project (they do not need to be installed with dtf-pm(1)). See dtf-project(7) for more information about a dtf(1) project structure.
17 |
18 | ## AUTHOR
19 | Jake Valletta
20 |
21 | ## DTF
22 | Part of the dtf(1) suite.
23 |
--------------------------------------------------------------------------------
/man/dtf-module.ronn:
--------------------------------------------------------------------------------
1 | dtf-module(7) -- dtf module documentation
2 | =========================================
3 |
4 | ## DESCRIPTION
5 | A dtf-module(7) can be either a python class or shell script. A module performs a single task or mulitple tasks. A dtf-module(7) can import a dtf-library(7), and can execute a dtf-binary(7).
6 |
7 | ## PYTHON MODULES
8 | Python modules must extend the **dtf.Module** class, where the class name is the same as the file name. The entry point to a dtf-module(7) is the **execute(self, args)** method, and must be implemented. Python modules can take advantage of a dtf-library(7) using **import**. Python modules also use functionality exposed by **dtf.\***. The use of **dtf.core.\*** classes are strongly discouraged.
9 |
10 | ## BASH MODULES
11 | Bash modules do not contain nearly as much functionality as a python-based dtf-module(7). A bash dtf-module(7) is designed to perform simple tasks or for prototyping. Bash modules must have a supported shebang, starting in "#!" and ending with "sh", such as "#!/usr/bin/ksh". Bash modules can source API's from the **DTF_CORE** and **DTF_LOG** environment variables as follows:
12 | \. $DTF_CORE
13 | \. $DTF_LOG
14 |
15 | ## MODULE PROPERTIES
16 | Each module can be installed with dtf-pm(1), or tested/executed locally from a project's _local_modules_ directory with dtf-local(1). dtf-pm(1) supports installing packages with metadata. The following metadata fields are supported (Python|Bash):
17 |
18 | about|About = A one sentence description of the module.
19 | author|Author = The author of the module.
20 | name|N/A = The name of the module (should match name of class.
21 | version|Version - The version of the module, in semantic version format.
22 |
23 | Python modules can also take advantage of the following properties (no Bash support):
24 |
25 | min_sdk = The minimum required SDK.
26 | requires = A list of command-line utilities required.
27 |
28 | ## PYTHON EXAMPLE
29 | A trival python dtf-module(7) example called newmodule is:
30 |
31 | from dtf.module import Module
32 |
33 | class newmodule(Module):
34 |
35 | about = "A new, fun module"
36 | author = "Some Hacker (mygithub)"
37 | name = "newmodule"
38 | version = "1.3.0"
39 |
40 | def execute(self, args):
41 |
42 | print "Hello, world!"
43 |
44 | ## BASH EXAMPLE
45 | A trival bash dtf-module(7) example called newmodule is:
46 |
47 | #!/usr/bin/bash
48 |
49 | \. $DTF_CORE
50 | \. $DTF_LOG
51 |
52 | log_i "Hello world!"`
53 |
54 | ## AUTHOR
55 | Jake Valletta
56 |
57 | ## DTF
58 | Part of the dtf(1) suite.
59 |
60 | ## SEE ALSO
61 | dtf-pm(1), dtf-local(1), dtf-binary(7), dtf-library(7), dtf-package(7)
62 |
--------------------------------------------------------------------------------
/man/dtf-package.ronn:
--------------------------------------------------------------------------------
1 | dtf-package(7) -- dtf package documentation
2 | ===========================================
3 |
4 | ## DESCRIPTION
5 | A dtf-package(7) is collection of files avaiable to modules. Use with caution. A dtf-package(7) is installed using dtf-pm(1).
6 |
7 | ## AUTHOR
8 | Jake Valletta
9 |
10 | ## DTF
11 | Part of the dtf(1) suite.
12 |
13 | ## SEE ALSO
14 | dtf-pm(1), dtf-local(1), dtf-binary(7), dtf-library(7), dtf-module(7)
15 |
--------------------------------------------------------------------------------
/man/dtf-pm.ronn:
--------------------------------------------------------------------------------
1 | dtf-pm(1) -- The dtf package manager
2 | ====================================
3 |
4 | ## SYNOPSIS
5 | dtf pm [subcommand] []
6 |
7 | Subcommands:
8 | delete Delete an item from main database.
9 | export Export entire main database to dtf ZIP.
10 | install Install a dtf ZIP or single item.
11 | list List all installed items.
12 | purge Purge all installed items, reset DB.
13 |
14 | ## DESCRIPTION
15 | dtf-pm(1) is the global package manager for dtf(1). It is used to install, remove, and export installed content. There are currently 4 types of content: binaries, libraries, modules, and packages. Additional information about these can be found within:
16 | dtf-binary(7)
17 | dtf-library(7)
18 | dtf-module(7)
19 | dtf-package(7)
20 |
21 | ## EXAMPLES
22 | Installing a single module with auto parsing:
23 | $ dtf pm install --single module --name my_module --auto
24 |
25 | List all installed modules with verbose information:
26 | $ dtf pm list modules -v
27 |
28 | Removing a single module:
29 | $ dtf pm delete --type module --name my_module
30 |
31 | Install a ZIP archive containing content:
32 | $ dtf pm install --zip new_content.zip
33 |
34 | Export all currently installed content to a ZIP:
35 | $ dtf pm export exported.zip
36 |
37 | Removing all globally installed content:
38 | $ dtf pm purge
39 |
40 | ## AUTHOR
41 | Jake Valletta
42 |
43 | ## DTF
44 | Part of the dtf(1) suite.
45 |
46 | ## SEE ALSO
47 | dtf-module(7), dtf-package(7), dtf-library(7), dtf-binary(7)
48 |
--------------------------------------------------------------------------------
/man/dtf-project.ronn:
--------------------------------------------------------------------------------
1 | dtf-project(7) -- Information on dtf project structure
2 | ======================================================
3 |
4 | ## KEY FILES & DIRECTORIES
5 | local_modules/ - The local modules directory contains non-global modules accessible to only the given project.
6 | reports/ - Used by modules to store reports.
7 | .dbs/ - Directory used by modules for database storage.
8 | .dtfini - Property information stored by dtf-prop(1) for the current project.
9 | .dtflog - Saved logs generated by dtf(1) or installed content.
10 |
11 | Generally speaking, properties stored by dtf-prop(1) will reside in either the "Info" or "Local" section. By convention, these should be alphanumeric and '-':
12 | $ dtf prop set Local system-apps "system-apps"
13 |
14 | ## PROJECT LIFECYCLE
15 | Each major software release of a device should have its own project. To create a new project, we use dtf-init(1):
16 | $ mkdir new_project
17 | $ cd new_project
18 | $ dtf init
19 |
20 | This configs any infiguration needed to begin testing your device. At some point, you may want to move on. At this point, you can use dtf-archive(1) to save some space:
21 | $ dtf archive
22 |
23 | You may also want to purge information about your test device (not actual data!) using dtf-reset(1):
24 | $ dtf reset
25 |
26 | ## AUTHOR
27 | Jake Valletta
28 |
29 | ## SEE ALSO
30 | dtf-archive(1), dtf-init(1), dtf-local(1), dtf-prop(1), dtf-reset(1)
31 |
--------------------------------------------------------------------------------
/man/dtf-prop.ronn:
--------------------------------------------------------------------------------
1 | dtf-prop(1) -- The dtf property manager
2 | =======================================
3 |
4 | ## SYNOPSIS
5 | dtf prop [subcommand] []
6 |
7 | Subcommands:
8 | get [sec] [prop] Get a property.
9 | set [sec] [prop] [val] Set a property.
10 | del [sec] [prop] Delete a property.
11 | dump Dump current properties.
12 | test [sec] [prop] Test if a value is set.
13 |
14 | ## DESCRIPTION
15 | dtf-prop(1) is used to set and get properties for a dtf(1) project. Properties are stored by section. Currently, two sections are utilized:
16 | Info - Information about a device set primarily by dtf(1).
17 | Local - Local directory information used by modules.
18 |
19 | ## EXAMPLES
20 | Set a property in the section Info called serial:
21 | $ dtf prop set Info serial 123456
22 |
23 | Check if a property is set (1 = set, 0 = not set):
24 | $ dtf prop test Info serial
25 |
26 | Get the value of a property:
27 | $ dtf prop get Info sdk
28 |
29 | Delete a property:
30 | $ dtf prop del Info version-string
31 |
32 | Dump all properties:
33 | $ dtf prop dump
34 |
35 | ## AUTHOR
36 | Jake Valletta
37 |
38 | ## DTF
39 | Part of the dtf(1) suite.
40 |
41 | ## SEE ALSO
42 | dtf-project(1)
43 |
--------------------------------------------------------------------------------
/man/dtf-reset.ronn:
--------------------------------------------------------------------------------
1 | dtf-reset(1) -- Reset a dtf project's configuration
2 | ===================================================
3 |
4 | ## SYNOPSIS
5 | dtf reset
6 |
7 | ## DESCRIPTION
8 | dtf-reset(1) is used to remove the dtf(1) configuration for a given project. It is not reversible.
9 |
10 | ## EXAMPLES
11 | dtf-reset(1) does not take any arguments, and does not have any subcommands. To remove the dtf(1) configuration file for the current project:
12 |
13 | $ cd old_project
14 | $ dtf reset
15 |
16 | Note: this does not remove project data. It only removes data contained in dtf(1) configuration file.
17 |
18 | ## AUTHOR
19 | Jake Valletta
20 |
21 | ## DTF
22 | Part of the dtf(1) suite.
23 |
--------------------------------------------------------------------------------
/man/dtf-status.ronn:
--------------------------------------------------------------------------------
1 | dtf-status(1) -- Determine if a project device is connected
2 | ===========================================================
3 |
4 | ## SYNOPSIS
5 | dtf status
6 |
7 | ## DESCRIPTION
8 | dtf-status(1) prints whether or not a project device is connected.
9 |
10 | ## EXAMPLES
11 | dtf-status(1) does not take any arguments, and does not have any subcommands. To print the status of a connected device:
12 | $ cd my_project
13 | $ dtf status
14 |
15 | ## AUTHOR
16 | Jake Valletta
17 |
18 | ## DTF
19 | Part of the dtf(1) suite.
20 |
--------------------------------------------------------------------------------
/man/dtf-upgrade.ronn:
--------------------------------------------------------------------------------
1 | dtf-uograde(1) -- Update components of dtf(1)
2 | =============================================
3 |
4 | ## SYNOPSIS
5 | dtf upgrade [subcommand] []
6 |
7 | Subcommands:
8 | core Update dtf framework.
9 | included Update just the bundled TAR.
10 |
11 | ## DESCRIPTION
12 | dtf-upgrade(1) is used to keep dtf(1) up-to-date.
13 |
14 | ## EXAMPLES
15 | Update the included TAR and reconfigure dtf(1)'s bindings:
16 | $ dtf upgrade included
17 |
18 | Download the install/upgrade script to update dtf(1):
19 | $ dtf upgrade core
20 |
21 | ## AUTHOR
22 | Jake Valletta
23 |
24 | ## DTF
25 | Part of the dtf(1) suite.
26 |
--------------------------------------------------------------------------------
/man/dtf.ronn:
--------------------------------------------------------------------------------
1 | dtf(1) -- Module-based framework for discovering vulnerabilities on Android devices
2 | ===================================================================================
3 |
4 | ## SYNOPSIS
5 | _dtf_ [module|command] []
6 |
7 |
8 | ## DESCRIPTION
9 | dtf(1) is a module-based framework that enables a user to interact with an Android device and discover vulnerabilities. Some features provided by dtf(1) are:
10 |
11 | 1. Package management
12 | 2. Project property subsystem
13 | 3. Client application to interface with Android device
14 | 4. Python APIs to interact with a Android device
15 | 5. Bindings to incorporate with existing Android tools
16 |
17 | ## EXAMPLES
18 | Run the module **apkget** with arguments "-p" and "com.android.mms":
19 |
20 | $ dtf apkget -p com.android.mms
21 |
22 | Run the built-in package manager and list installed modules:
23 |
24 | $ dtf pm list modules
25 |
26 | For examples of built-in commands, see the section [SEE ALSO][].
27 |
28 | ## ENVIRONMENT VARIABLES
29 | _GLOG_LEVEL_ - Manually specify a module's logging level. Valid levels are 0 (no logging) - 5 (full).
30 |
31 | ## AUTHOR
32 | Jake Valletta
33 |
34 | ## COPYRIGHT
35 | dtf(1) is copyright (c) 2013-2017, Jake Valletta (@jake_valletta). Released under the Apache License, Version 2.0.
36 | license.
37 |
38 | ## SEE ALSO
39 | dtf-archive(1), dtf-binding(1), dtf-client(1), dtf-init(1), dtf-local(1), dtf-pm(1), dtf-prop(1), dtf-reset(1), dtf-status(1), dtf-upgrade(1), dtf-check(1), dtf-project(7), dtf-binary(7), dtf-library(7), dtf-module(7), dtf-package(7)
40 |
--------------------------------------------------------------------------------
/python-dtf/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | branch = True
3 | parallel = True
4 | concurrency = multiprocessing
5 | source = dtf/
6 |
--------------------------------------------------------------------------------
/python-dtf/.gitignore:
--------------------------------------------------------------------------------
1 | dtf/VERSION
2 |
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # Distribution / packaging
9 | .Python
10 | env/
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | *.egg-info/
23 | .installed.cfg
24 | *.egg
25 | .gradle
26 |
27 | # Coverage
28 | .coverage
29 | .cache
30 | htmlcov
31 | # virtualenv stuff
32 | venv/
33 |
--------------------------------------------------------------------------------
/python-dtf/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include dtf/VERSION
2 |
--------------------------------------------------------------------------------
/python-dtf/README.rst:
--------------------------------------------------------------------------------
1 | Android Device Testing Framework (dtf)
2 | ======================================
3 |
4 | About
5 | -----
6 | The Android Device Testing Framework ("dtf") is a data collection and analysis framework to help individuals answer the question: "Where are the vulnerabilities on this mobile device?" Dtf provides a modular approach and built-in APIs that allows testers to quickly create scripts to interact with their Android devices. By default, dtf does not include any modules, but a collection of testing modules is made available on the [Cobra Den website](www.thecobraden.com/projects/dtf/). These modules allow testers to obtain information from their Android device, process this information into databases, and then start searching for vulnerabilities (all without requiring root privileges). These modules help you focus on changes made to AOSP components such as applications, frameworks, system services, as well as lower-level components such as binaries, libraries, and device drivers. In addition, you'll be able to analyze new functionality implemented by the OEMs and other parties to find vulnerabilities.
7 |
--------------------------------------------------------------------------------
/python-dtf/dtf/__init__.py:
--------------------------------------------------------------------------------
1 | """Main dtf Module"""
2 |
3 | from __future__ import absolute_import
4 | import pkg_resources
5 |
6 | # Here we use the installed version as version number. For tests,
7 | # this may not exist so we just fake it and return unknown.
8 | # pylint: disable=maybe-no-member
9 | try:
10 | __version__ = pkg_resources.get_distribution('dtf').version
11 | except pkg_resources.DistributionNotFound:
12 | __version__ = "???"
13 |
--------------------------------------------------------------------------------
/python-dtf/dtf/colors.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Wrapper API for using colors in dtf modules"""
17 |
18 | from __future__ import absolute_import
19 | from colored import fg, attr
20 |
21 | import dtf.globals as glbl
22 |
23 | COLOR_ERR = fg(1)
24 | COLOR_WARN = fg(3)
25 | COLOR_INFO = fg(2)
26 | COLOR_VERB = fg(6)
27 | COLOR_DEB = fg(5)
28 |
29 |
30 | def __use_colors():
31 |
32 | """Check if colors should be used"""
33 |
34 | return bool(glbl.get_generic_global('Config', 'use_colors') == '1')
35 |
36 |
37 | def error(message):
38 |
39 | """Color format a message for errors"""
40 |
41 | if __use_colors():
42 | return "%s%s%s" % (COLOR_ERR, message, attr(0))
43 | else:
44 | return message
45 |
46 |
47 | def warning(message):
48 |
49 | """Color format a message for warnings"""
50 |
51 | if __use_colors():
52 | return "%s%s%s" % (COLOR_WARN, message, attr(0))
53 | else:
54 | return message
55 |
56 |
57 | def info(message):
58 |
59 | """Color format a message for informational messages"""
60 |
61 | if __use_colors():
62 | return "%s%s%s" % (COLOR_INFO, message, attr(0))
63 | else:
64 | return message
65 |
66 |
67 | def verbose(message):
68 |
69 | """Color format a message for verbose messages"""
70 |
71 | if __use_colors():
72 | return "%s%s%s" % (COLOR_VERB, message, attr(0))
73 | else:
74 | return message
75 |
76 |
77 | def debug(message):
78 |
79 | """Color format a message for debugging"""
80 |
81 | if __use_colors():
82 | return "%s%s%s" % (COLOR_DEB, message, attr(0))
83 | else:
84 | return message
85 |
86 |
87 | def bold(message):
88 |
89 | """Format a bold message"""
90 |
91 | if __use_colors():
92 | return "%s%s%s" % (attr('bold'), message, attr(0))
93 | else:
94 | return message
95 |
--------------------------------------------------------------------------------
/python-dtf/dtf/constants.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """dtf Constants"""
17 |
18 | from __future__ import absolute_import
19 | import dtf
20 |
21 | VERSION = dtf.__version__
22 |
23 | DTF_CLIENT = "com.dtf.client"
24 |
25 | # API Constants
26 | API_1 = 1
27 | API_2 = 2
28 | API_CUPCAKE = 3
29 | API_DONUT = 4
30 | API_ECLAIR = 5
31 | API_ECLAIR_R1 = 6
32 | API_ECLAIR_R2 = 7
33 | API_FROYO = 8
34 | API_GINGERBREAD = 9
35 | API_GINGERBREAD_R1 = 10
36 | API_HONEYCOMB = 11
37 | API_HONEYCOMB_R1 = 12
38 | API_HONEYCOMB_R2 = 13
39 | API_ICE_CREAM_SANDWICH = 14
40 | API_ICE_CREAM_SANDWICH_R1 = 15
41 | API_JELLY_BEAN = 16
42 | API_JELLY_BEAN_R1 = 17
43 | API_JELLY_BEAN_R2 = 18
44 | API_KITKAT = 19
45 | API_WEAR = 20
46 | API_LOLLIPOP = 21
47 | API_LOLLIPOP_R1 = 22
48 | API_MARSHMALLOW = 23
49 | API_NOUGAT = 24
50 | API_NOUGAT_R1 = 25
51 |
52 | # Max Supported
53 | API_MAX = API_NOUGAT_R1
54 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/__init__.py:
--------------------------------------------------------------------------------
1 | """Core (internal) dtf functionality"""
2 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/__init__.py:
--------------------------------------------------------------------------------
1 | """Built-in dtf commands"""
2 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/archive.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Built-in module for archiving a project"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 | import os
21 | import zipfile
22 |
23 | import dtf.properties as prop
24 | import dtf.logging as log
25 | from dtf.module import Module
26 |
27 |
28 | class archive(Module): # pylint: disable=invalid-name
29 |
30 | """Module class for archiving a project"""
31 |
32 | @classmethod
33 | def usage(cls):
34 |
35 | """Module usage"""
36 |
37 | print('dtf Archiver')
38 | print('')
39 | print('Subcommands:')
40 | print(' create Archive the current project.')
41 | print('')
42 |
43 | return 0
44 |
45 | def make_zip(self, zip_name):
46 |
47 | """Make a ZIP file"""
48 |
49 | zip_f = None
50 |
51 | try:
52 | zip_f = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED)
53 | except RuntimeError:
54 | log.e(self.name, "ZIP_DEFLATE not available!")
55 | return -1
56 |
57 | # pylint: disable=unused-variable
58 | for root, dirs, files in os.walk(os.getcwd()):
59 | for file_to_add in files:
60 | zip_f.write(os.path.join(root, file_to_add))
61 |
62 | zip_f.close()
63 |
64 | return 0
65 |
66 | def do_create(self, args):
67 |
68 | """Create the archive"""
69 |
70 | zip_name = ""
71 |
72 | if len(args) == 0:
73 | zip_name = "%s.zip" % prop.get_prop('Info', 'version-string')
74 |
75 | else:
76 | zip_name = args.pop()
77 |
78 | log.i(self.name, "Archiving to '%s'..." % zip_name)
79 |
80 | rtn = self.make_zip(zip_name)
81 |
82 | if rtn != 0:
83 | log.e(self.name, "Unable to archive project!")
84 |
85 | return rtn
86 |
87 | def execute(self, args):
88 |
89 | """Main module executor"""
90 |
91 | self.name = self.__self__
92 |
93 | rtn = 0
94 |
95 | if len(args) < 1:
96 | return self.usage()
97 |
98 | sub_cmd = args.pop(0)
99 |
100 | if sub_cmd == 'create':
101 | rtn = self.do_create(args)
102 |
103 | else:
104 | print("Sub-command '%s' not found!" % sub_cmd)
105 | rtn = self.usage()
106 |
107 | return rtn
108 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/binding.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Built-in module for getting a binding path"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 | from dtf.globals import get_all_bindings, get_binding, GlobalPropertyError
21 | from dtf.module import Module
22 | import dtf.logging as log
23 |
24 | TAG = "binding"
25 |
26 |
27 | class binding(Module): # pylint: disable=invalid-name
28 |
29 | """Module class for listing local modules"""
30 |
31 | @classmethod
32 | def do_print_all(cls):
33 |
34 | """Print all bindings"""
35 |
36 | try:
37 | for bind_key, value in get_all_bindings():
38 | if bind_key.startswith('dtf_'):
39 | print("%s : %s" % (bind_key, value))
40 | except GlobalPropertyError:
41 | log.e(TAG, "Unable to list bindings!")
42 | return -1
43 |
44 | return 0
45 |
46 | @classmethod
47 | def do_print_binding(cls, bind_key):
48 |
49 | """Print a single binding"""
50 |
51 | try:
52 | print(get_binding(bind_key))
53 | except GlobalPropertyError:
54 | log.e(TAG, "Unable to find binding: %s" % bind_key)
55 | return -1
56 |
57 | return 0
58 |
59 | def execute(self, args):
60 |
61 | """Main module executor"""
62 |
63 | if len(args) == 0:
64 | return self.do_print_all()
65 | else:
66 | return self.do_print_binding(args[0])
67 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/local.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Built-in module for listing local modules"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 | from os import listdir
21 | from os.path import isfile, join
22 |
23 | import dtf.core.utils as utils
24 | from dtf.module import Module
25 |
26 |
27 | class local(Module): # pylint: disable=invalid-name
28 |
29 | """Module class for listing local modules"""
30 |
31 | @classmethod
32 | def get_locals(cls):
33 |
34 | """List local modules directory"""
35 |
36 | local_path = "%s/%s" % (utils.get_project_root(),
37 | utils.LOCAL_MODULES_DIRECTORY)
38 |
39 | return [f for f in listdir(local_path) if isfile(join(local_path, f))]
40 |
41 | def execute(self, args): # pylint: disable=unused-argument
42 |
43 | """Main module executor"""
44 |
45 | print('Local Modules:')
46 |
47 | for l_module in self.get_locals():
48 |
49 | print(" %s" % l_module)
50 |
51 | return 0
52 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/prop.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Built-in module for handling project properties"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 |
21 | import configparser
22 |
23 | from dtf.module import Module
24 | import dtf.logging as log
25 | import dtf.core.utils as utils
26 |
27 | from dtf.properties import (get_prop, set_prop, del_prop,
28 | test_prop, PropertyError)
29 |
30 |
31 | class prop(Module): # pylint: disable=invalid-name
32 |
33 | """Module class for property management"""
34 |
35 | @classmethod
36 | def usage(cls):
37 |
38 | """Display module usage"""
39 |
40 | print('dtf Property Manager')
41 | print('Subcommands:')
42 | print(' get [sec] [prop] Get a property.')
43 | print(' set [sec] [prop] [val] Set a property.')
44 | print(' del [sec] [prop] Delete a property.')
45 | print(' dump Dump current properties.')
46 | print(' test [sec] [prop] Test if a value is set.')
47 | print('')
48 |
49 | return 0
50 |
51 | def do_get(self, args):
52 |
53 | """Get a property"""
54 |
55 | rtn = 0
56 | value = ""
57 |
58 | if len(args) != 2:
59 | log.e(self.name, "A section and property must be specified.")
60 | rtn = self.usage()
61 |
62 | else:
63 | section = args[0]
64 | prop_name = args[1]
65 |
66 | try:
67 | value = get_prop(section, prop_name)
68 |
69 | except PropertyError:
70 | rtn = -1
71 |
72 | print(value)
73 |
74 | return rtn
75 |
76 | def do_set(self, args):
77 |
78 | """Set a property"""
79 |
80 | rtn = 0
81 |
82 | if len(args) < 3:
83 | log.e(self.name, "A section, prop, and value must be specified.")
84 | rtn = self.usage()
85 |
86 | else:
87 | section = args[0]
88 | prop_name = args[1]
89 | value = " ".join(args[2:])
90 |
91 | rtn = set_prop(section, prop_name, value)
92 |
93 | return rtn
94 |
95 | def do_del(self, args):
96 |
97 | """Delete a property"""
98 |
99 | rtn = 0
100 |
101 | if len(args) != 2:
102 | log.e(self.name, "A section and property must be specified.")
103 | rtn = self.usage()
104 |
105 | else:
106 | section = args[0]
107 | prop_name = args[1]
108 |
109 | rtn = del_prop(section, prop_name)
110 |
111 | return rtn
112 |
113 | @classmethod
114 | def do_dump(cls):
115 |
116 | """Dump entire configuration"""
117 |
118 | config = configparser.ConfigParser()
119 | config.read(utils.CONFIG_FILE_NAME)
120 |
121 | for section in config.sections():
122 | print("[%s]" % section)
123 | for name, value in config.items(section):
124 | print("%s = %s" % (name, value))
125 |
126 | print('')
127 |
128 | return 0
129 |
130 | def do_test(self, args):
131 |
132 | """Test if a value is set or not"""
133 |
134 | rtn = 0
135 |
136 | if len(args) != 2:
137 | log.e(self.name, "A section and property must be specified.")
138 | rtn = self.usage()
139 |
140 | else:
141 | section = args[0]
142 | prop_name = args[1]
143 |
144 | rtn = test_prop(section, prop_name)
145 |
146 | return rtn
147 |
148 | def execute(self, args):
149 |
150 | """Main module executor"""
151 |
152 | self.name = self.__self__
153 |
154 | rtn = 0
155 |
156 | if len(args) < 1:
157 | return self.usage()
158 |
159 | sub_cmd = args.pop(0)
160 |
161 | if sub_cmd == 'get':
162 | rtn = self.do_get(args)
163 |
164 | elif sub_cmd == 'set':
165 | rtn = self.do_set(args)
166 |
167 | elif sub_cmd == 'del':
168 | rtn = self.do_del(args)
169 |
170 | elif sub_cmd == 'dump':
171 | rtn = self.do_dump()
172 |
173 | elif sub_cmd == 'test':
174 | rtn = self.do_test(args)
175 |
176 | else:
177 | print("Sub-command '%s' not found!" % sub_cmd)
178 | rtn = self.usage()
179 |
180 | return rtn
181 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/reset.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Built-in module for reseting a project"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 | import os
21 |
22 | import dtf.core.compat as compat
23 | import dtf.core.utils as utils
24 | import dtf.logging as log
25 |
26 | from dtf.module import Module
27 |
28 | TAG = 'reset'
29 |
30 |
31 | class reset(Module): # pylint: disable=invalid-name
32 |
33 | """Module class for reseting a project"""
34 |
35 | def execute(self, args): # pylint: disable=unused-argument,no-self-use
36 |
37 | """Main module executor"""
38 |
39 | print('Are you sure you want to delete the dtf project in this '
40 | 'directory? This cannot be reversed! [y/N]', end=" ")
41 |
42 | inp = compat.raw_input()
43 |
44 | if inp.lower() == 'y':
45 | os.remove(utils.CONFIG_FILE_NAME)
46 | log.i(TAG, "Reset complete!")
47 | return 0
48 | else:
49 | log.w(TAG, "Reset aborted.")
50 | return -1
51 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/status.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Built-in module for getting the status of a project"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 |
21 | from dtf.module import Module
22 | import dtf.adb as DtfAdb
23 |
24 |
25 | class status(Module): # pylint: disable=invalid-name
26 |
27 | """Module class for getting the status of a device"""
28 |
29 | adb = DtfAdb.DtfAdb()
30 |
31 | def execute(self, args): # pylint: disable=unused-argument
32 |
33 | """Main module executor"""
34 |
35 | found = False
36 |
37 | serial = DtfAdb.get_mode_serial()
38 | devices = self.adb.get_devices()
39 |
40 | for device in devices:
41 | if device['serial'] == serial:
42 | found = True
43 | break
44 |
45 | print("Status:", end=" ")
46 |
47 | if found:
48 | print('Connected')
49 | else:
50 | print('Not Connected')
51 |
52 | print("Serial Number: %s" % serial)
53 |
54 | return 0
55 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/cmds/upgrade.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2017 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Built-in module for archiving a project"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 |
21 | import tempfile
22 | from argparse import ArgumentParser
23 |
24 | import requests
25 |
26 | import dtf.core.autoconfig as autoconfig
27 | import dtf.module as module
28 | import dtf.logging as log
29 |
30 | BRANCH_DEFAULT = 'master'
31 | UPGRADE_SCRIPT_TEMPLATE = ("https://raw.githubusercontent.com/android-dtf/"
32 | "dtf/%s/installscript/install.sh")
33 |
34 | UPGRADE_TAR_TEMPLATE = ("https://raw.githubusercontent.com/android-dtf/"
35 | "dtf/%s/dtf-included/build/included.tar")
36 |
37 |
38 | class upgrade(module.Module): # pylint: disable=invalid-name
39 |
40 | """Module class for performing updates"""
41 |
42 | @classmethod
43 | def usage(cls):
44 |
45 | """Display module usage"""
46 |
47 | print('dtf Client Manager')
48 | print('Subcommands:')
49 | print(' core Update dtf framework.')
50 | print(' included Update just the bundled TAR.')
51 | print('')
52 |
53 | return 0
54 |
55 | def __download_file(self, url, file_name):
56 |
57 | """Download a file from URL to tempfile"""
58 |
59 | try:
60 | req = requests.get(url, verify=True, stream=True,
61 | allow_redirects=True)
62 |
63 | except requests.exceptions.RequestException as excpt:
64 |
65 | log.e(self.name, "Error pulling update script!")
66 | print(excpt)
67 | return None
68 |
69 | if not req.ok:
70 | return None
71 |
72 | temp_file_name = "%s/%s" % (tempfile.gettempdir(), file_name)
73 |
74 | temp_f = open(temp_file_name, "wb")
75 |
76 | for chunk in req.iter_content(chunk_size=1024):
77 | if chunk:
78 | temp_f.write(chunk)
79 |
80 | # Reset the seek
81 | temp_f.close()
82 |
83 | return temp_file_name
84 |
85 | def do_core_upgrade(self, args):
86 |
87 | """Perform upgrade of dtf"""
88 |
89 | parser = ArgumentParser(prog='upgrade core',
90 | description='Update dtf framework.')
91 | parser.add_argument('--reconfigure', action='store_true',
92 | help="Just reconfig (post upgrade).")
93 | parser.add_argument('--branch', dest='branch',
94 | default=BRANCH_DEFAULT,
95 | help="Specify the branch to pull from.")
96 | parsed_args = parser.parse_args(args)
97 |
98 | # First, is this just a reconfig?
99 | if parsed_args.reconfigure:
100 | log.i(self.name, "Performing reconfiguration...")
101 | return autoconfig.initialize_from_local(is_full=True)
102 |
103 | log.i(self.name, "Downloading update script...")
104 |
105 | upgrade_script_url = UPGRADE_SCRIPT_TEMPLATE % parsed_args.branch
106 |
107 | upgrade_script_name = self.__download_file(upgrade_script_url,
108 | 'dtf_upgrade.sh')
109 | if upgrade_script_name is None:
110 | log.e(self.name, "Unable to download: %s" % upgrade_script_url)
111 | return -1
112 |
113 | log.i(self.name, "Update script downloaded. To complete install run:")
114 | log.i(self.name, " chmod u+x %s" % upgrade_script_name)
115 | log.i(self.name, " %s" % upgrade_script_name)
116 |
117 | return 0
118 |
119 | def do_included_upgrade(self, args):
120 |
121 | """Perform upgrade of only included"""
122 |
123 | parser = ArgumentParser(prog='upgrade included',
124 | description='Update the bundled TAR.')
125 | parser.add_argument('--branch', dest='branch',
126 | default=BRANCH_DEFAULT,
127 | help="Specify the branch to pull from.")
128 |
129 | parsed_args = parser.parse_args(args)
130 |
131 | log.i(self.name, "Performing included upgrade...")
132 |
133 | upgrade_tar_url = UPGRADE_TAR_TEMPLATE % parsed_args.branch
134 |
135 | # First pull
136 | tar_name = self.__download_file(upgrade_tar_url, 'dtf_included.tar')
137 | if tar_name is None:
138 | log.e(self.name, "Unable to download: %s" % upgrade_tar_url)
139 | return -1
140 |
141 | # Now we perform the reconfiguration
142 | return autoconfig.initialize_from_tar(tar_name, is_full=False,
143 | clean_up=True)
144 |
145 | def execute(self, args):
146 |
147 | """Main module executor"""
148 |
149 | self.name = self.__self__
150 |
151 | rtn = 0
152 |
153 | if len(args) < 1:
154 | return self.usage()
155 |
156 | sub_cmd = args.pop(0)
157 |
158 | if sub_cmd == 'core':
159 | rtn = self.do_core_upgrade(args)
160 |
161 | elif sub_cmd == 'included':
162 | rtn = self.do_included_upgrade(args)
163 |
164 | else:
165 | print("Sub-command '%s' not found!" % sub_cmd)
166 | rtn = self.usage()
167 |
168 | return rtn
169 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/compat.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2017 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Compatibility helpers"""
17 |
18 | # pylint: disable=invalid-name,input-builtin,raw_input-builtin
19 | # pylint: disable=wrong-import-position
20 |
21 | from __future__ import absolute_import
22 |
23 | try:
24 | raw_input = raw_input # pylint: disable=redefined-builtin
25 | except NameError:
26 | raw_input = input
27 |
28 | try:
29 | from io import StringIO
30 | except ImportError:
31 | from cStringIO import StringIO
32 |
33 | StringIO = StringIO
34 |
35 | try:
36 | import urlparse
37 | except ImportError:
38 | # pylint: disable=no-name-in-module,import-error
39 | import urllib.parse as urlparse
40 |
41 | urlparse = urlparse
42 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/item.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2017 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Item class"""
17 |
18 | # Eventually this will be changed
19 | # pylint: disable=too-many-instance-attributes
20 |
21 | from __future__ import absolute_import
22 | import semantic_version
23 |
24 | TYPE_MODULE = 'module'
25 | TYPE_LIBRARY = 'library'
26 | TYPE_BINARY = 'binary'
27 | TYPE_PACKAGE = 'package'
28 |
29 | VALID_TYPES = [TYPE_BINARY, TYPE_LIBRARY,
30 | TYPE_MODULE, TYPE_PACKAGE]
31 |
32 |
33 | def is_valid_version(version_string):
34 |
35 | """Check if version string is correct"""
36 |
37 | try:
38 | semantic_version.Version(version_string)
39 | except ValueError:
40 | return False
41 |
42 | return True
43 |
44 |
45 | def item_is_newer(installed_item, item):
46 |
47 | """Determine if an item is newer"""
48 |
49 | return bool(semantic_version.Version(installed_item.version) <
50 | semantic_version.Version(item.version))
51 |
52 |
53 | class Item(object): # pylint: disable=too-few-public-methods
54 |
55 | """Class for working with content"""
56 |
57 | install_name = None
58 | local_name = None
59 | name = None
60 | type = type
61 | author = None
62 | about = None
63 | version = None
64 |
65 | def __init__(self):
66 |
67 | """Initialize new object"""
68 |
69 | self.install_name = None
70 | self.local_name = None
71 | self.name = None
72 | self.type = None
73 | self.author = None
74 | self.about = None
75 | self.version = None
76 |
77 | def __repr__(self):
78 |
79 | """Tostring for item"""
80 |
81 | temp = "Name: %s (%s)\n" % (self.name, self.type)
82 | if self.type == TYPE_MODULE:
83 | temp += " About: %s\n" % self.about
84 | temp += " Installs as: %s\n" % self.install_name
85 | temp += " Author: %s\n" % self.author
86 | temp += " Version: %s\n" % self.version
87 | return temp
88 |
--------------------------------------------------------------------------------
/python-dtf/dtf/core/utils.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """ dtf Utilities """
17 |
18 | from __future__ import absolute_import
19 | from hashlib import md5
20 | import errno
21 | import os
22 | import os.path
23 | import shutil
24 | import stat
25 |
26 | import dtf.core.compat as compat
27 |
28 | CONFIG_FILE_NAME = '.dtfini'
29 | LOG_FILE_NAME = '.dtflog'
30 |
31 | REPORTS_DIRECTORY = 'reports'
32 | DBS_DIRECTORY = '.dbs'
33 | LOCAL_MODULES_DIRECTORY = 'local_modules'
34 |
35 | TAG = 'dtf-utils'
36 |
37 |
38 | def __upsearch(file_name, dir_name):
39 |
40 | """Recursively find a file, searching up."""
41 |
42 | if os.path.isfile("%s/%s" % (dir_name, file_name)):
43 | return dir_name
44 | else:
45 | new_dir = os.path.abspath(os.path.join(dir_name, os.pardir))
46 | if dir_name == new_dir:
47 | return None
48 | return __upsearch(file_name, new_dir)
49 |
50 |
51 | def get_project_root():
52 |
53 | """Search for and return the dtf project root."""
54 |
55 | return __upsearch(CONFIG_FILE_NAME, os.getcwd())
56 |
57 |
58 | def get_pydtf_dir():
59 |
60 | """Return the location of the dtf dist-packages directory."""
61 |
62 | return os.path.dirname(os.path.split(os.path.abspath(__file__))[0])
63 |
64 |
65 | def get_dtf_data_dir():
66 |
67 | """Return the location of the dtf data directory."""
68 |
69 | return os.path.expanduser('~') + '/.dtf'
70 |
71 |
72 | def get_dtf_lib_dir():
73 |
74 | """Return the location of the dtf lib dir."""
75 |
76 | return "/usr/local/lib/android-dtf"
77 |
78 |
79 | def md5_local(file_path):
80 |
81 | """MD5 a local file"""
82 |
83 | file_f = open(file_path, 'rb')
84 |
85 | local_m = md5()
86 | while True:
87 | data = file_f.read(128)
88 | if not data:
89 | break
90 | local_m.update(data)
91 |
92 | return local_m.hexdigest()
93 |
94 |
95 | def is_exe(fpath):
96 |
97 | """ Check if file is an executable"""
98 |
99 | # stackoverflow.com/questions/377017/test-if-executable-exists-in-python
100 | return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
101 |
102 |
103 | def which(program):
104 |
105 | """Test if program is pathed."""
106 |
107 | # stackoverflow.com/questions/377017/test-if-executable-exists-in-python
108 |
109 | fpath = os.path.split(program)[0]
110 |
111 | if fpath:
112 | if is_exe(program):
113 | return program
114 | else:
115 | for path in os.environ["PATH"].split(os.pathsep):
116 | path = path.strip('"')
117 | exe_file = os.path.join(path, program)
118 | if is_exe(exe_file):
119 | return exe_file
120 |
121 | return None
122 |
123 |
124 | def is_executable(file_name):
125 |
126 | """Check if a file can be executed"""
127 |
128 | return bool(stat.S_IXUSR & os.stat(file_name)[stat.ST_MODE])
129 |
130 |
131 | def mkdir_recursive(path):
132 |
133 | """Recursively create a directory"""
134 |
135 | try:
136 | os.makedirs(path)
137 | except OSError as exc: # Python >2.5
138 | if exc.errno == errno.EEXIST and os.path.isdir(path):
139 | pass
140 | else:
141 | raise
142 |
143 |
144 | # http://stackoverflow.com/questions/1158076/implement-touch-using-python
145 | def touch(file_name, times=None):
146 |
147 | """Touch a file"""
148 |
149 | with open(file_name, 'a'):
150 | os.utime(file_name, times)
151 |
152 |
153 | def delete_file(file_name):
154 |
155 | """Delete a file (show errors optional)"""
156 |
157 | try:
158 | os.remove(file_name)
159 | except OSError:
160 | pass
161 |
162 | return 0
163 |
164 |
165 | def delete_tree(directory_name):
166 |
167 | """Delete a directory recursively"""
168 |
169 | try:
170 | shutil.rmtree(directory_name)
171 | except OSError:
172 | pass
173 |
174 | return 0
175 |
176 |
177 | def file_in_zip(zip_f, file_name):
178 |
179 | """Determine if a file exists in a ZIP"""
180 |
181 | try:
182 | zip_f.read(file_name)
183 | return True
184 | except KeyError:
185 | return False
186 |
187 |
188 | def directory_in_zip(zip_f, directory_name):
189 |
190 | """Determine if a directory exists in a ZIP"""
191 |
192 | return any(x.startswith("%s/" % directory_name.rstrip("/"))
193 | for x in zip_f.namelist())
194 |
195 |
196 | def is_valid_url(url_string):
197 |
198 | """Test and return valid URL"""
199 |
200 | parsed_url = compat.urlparse.urlparse(url_string)
201 |
202 | return bool(parsed_url.scheme)
203 |
204 |
205 | def is_http_url(url_string):
206 |
207 | """Check scheme of a URL"""
208 |
209 | return bool(compat.urlparse.urlparse(url_string).scheme == 'http')
210 |
--------------------------------------------------------------------------------
/python-dtf/dtf/exceptions.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2017 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """dtf Exceptions"""
17 |
18 | from __future__ import absolute_import
19 |
20 |
21 | class DtfException(Exception): # pylint: disable=too-few-public-methods
22 |
23 | """Generic dtf Exceptions"""
24 |
25 | def __init__(self, message):
26 |
27 | """Raise new exception"""
28 |
29 | # Call the base class constructor with the parameters it needs
30 | Exception.__init__(self, message)
31 |
--------------------------------------------------------------------------------
/python-dtf/dtf/globals.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Global dtf locations"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 | import os.path
21 | import configparser
22 |
23 | import dtf.core.utils as utils
24 |
25 | DTF_DATA_DIR = utils.get_dtf_data_dir()
26 | DTF_BINARIES_DIR = DTF_DATA_DIR + "/binaries/"
27 | DTF_LIBRARIES_DIR = DTF_DATA_DIR + "/libraries/"
28 | DTF_MODULES_DIR = DTF_DATA_DIR + "/modules/"
29 | DTF_PACKAGES_DIR = DTF_DATA_DIR + "/packages/"
30 | DTF_DB = DTF_DATA_DIR + "/main.db"
31 |
32 | DTF_INCLUDED_DIR = DTF_DATA_DIR + "/included"
33 | DTF_GLOBAL_CONFIG = DTF_DATA_DIR + "/globals.ini"
34 |
35 | CONFIG_SECTION_BINDINGS = 'Bindings'
36 | CONFIG_SECTION_CLIENT = 'Client'
37 | CONFIG_SECTION_CONFIG = 'Config'
38 |
39 |
40 | class GlobalPropertyError(Exception):
41 |
42 | """General exception for global properties"""
43 | pass
44 |
45 |
46 | def get_binding(dtf_binding):
47 |
48 | """Read binding from global config"""
49 |
50 | return os.path.expanduser(get_generic_global(CONFIG_SECTION_BINDINGS,
51 | dtf_binding))
52 |
53 |
54 | def get_all_bindings():
55 |
56 | """Get all bindings"""
57 |
58 | return __get_section(CONFIG_SECTION_BINDINGS)
59 |
60 |
61 | def get_generic_global(section, prop):
62 |
63 | """Generic getter for getting a property"""
64 |
65 | if section is None:
66 | raise GlobalPropertyError("Section cannot be null!")
67 | elif prop is None:
68 | raise GlobalPropertyError("Property cannot be null!")
69 |
70 | global_conf = configparser.ConfigParser()
71 | global_conf.read(DTF_GLOBAL_CONFIG)
72 |
73 | try:
74 | return global_conf.get(section, prop)
75 | except configparser.NoSectionError:
76 | raise GlobalPropertyError("Section not found: %s" % section)
77 | except configparser.NoOptionError:
78 | raise GlobalPropertyError("Property not found: %s" % prop)
79 |
80 |
81 | def get_copy():
82 |
83 | """Return a memory-resident copy"""
84 |
85 | global_conf = configparser.ConfigParser()
86 | global_conf.read(DTF_GLOBAL_CONFIG)
87 |
88 | return global_conf
89 |
90 |
91 | def __get_section(section):
92 |
93 | """Private helper to get all section values"""
94 |
95 | if section is None:
96 | raise GlobalPropertyError("Section cannot be null!")
97 |
98 | global_conf = configparser.ConfigParser()
99 | global_conf.read(DTF_GLOBAL_CONFIG)
100 |
101 | if not global_conf.has_section(section):
102 | raise GlobalPropertyError("Section not found: %s" % section)
103 |
104 | return global_conf.items(section)
105 |
--------------------------------------------------------------------------------
/python-dtf/dtf/included.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Python wrapper for Android tools"""
17 |
18 | from __future__ import absolute_import
19 | from subprocess import Popen, PIPE
20 | from dtf.globals import get_binding
21 |
22 |
23 | def aapt(cmd):
24 |
25 | """aapt wrapper"""
26 |
27 | aapt_path = get_binding("dtf_aapt")
28 | cmd = ("%s %s" % (aapt_path, cmd)).split(' ')
29 |
30 | proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False)
31 |
32 | stdout, stderr = proc.communicate()
33 |
34 | stdout = stdout.split("\n")
35 | stderr = stderr.split("\n")
36 | rtn = proc.returncode
37 |
38 | return stdout, stderr, rtn
39 |
40 |
41 | def apktool(cmd):
42 |
43 | """apktool wrapper"""
44 |
45 | apktool_path = get_binding("dtf_apktool")
46 | java_args = "java -Xmx512M -jar"
47 |
48 | cmd = ("%s %s %s" % (java_args, apktool_path, cmd)).split(' ')
49 |
50 | proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False)
51 |
52 | stdout, stderr = proc.communicate()
53 |
54 | stdout = stdout.split("\n")
55 | stderr = stderr.split("\n")
56 | rtn = proc.returncode
57 |
58 | return stdout, stderr, rtn
59 |
60 |
61 | def smali(cmd):
62 |
63 | """smali wrapper"""
64 |
65 | smali_path = get_binding("dtf_smali")
66 | java_args = "java -Xmx512M -jar"
67 |
68 | cmd = ("%s %s %s" % (java_args, smali_path, cmd)).split(' ')
69 |
70 | proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False)
71 |
72 | stdout, stderr = proc.communicate()
73 |
74 | stdout = stdout.split("\n")
75 | stderr = stderr.split("\n")
76 | rtn = proc.returncode
77 |
78 | return stdout, stderr, rtn
79 |
80 |
81 | def baksmali(cmd):
82 |
83 | """baksmali wrapper"""
84 |
85 | baksmali_path = get_binding("dtf_baksmali")
86 | java_args = "java -Xmx512M -jar"
87 |
88 | cmd = ("%s %s %s" % (java_args, baksmali_path, cmd)).split(' ')
89 |
90 | proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False)
91 |
92 | stdout, stderr = proc.communicate()
93 |
94 | stdout = stdout.split("\n")
95 | stderr = stderr.split("\n")
96 | rtn = proc.returncode
97 |
98 | return stdout, stderr, rtn
99 |
100 |
101 | def axmlprinter2(manifest_file_name, out_file_name):
102 |
103 | """axmlprinter2 wrapper"""
104 |
105 | axmlprinter2_path = get_binding("dtf_axmlprinter2")
106 | java_args = "java -Xmx256M -jar"
107 |
108 | cmd = ("%s %s %s"
109 | % (java_args, axmlprinter2_path, manifest_file_name)).split(' ')
110 |
111 | proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False)
112 |
113 | stdout = proc.communicate()[0]
114 |
115 | rtn = proc.returncode
116 |
117 | if len(stdout) == 0:
118 | return -1
119 |
120 | out_f = open(out_file_name, 'wb')
121 |
122 | try:
123 | out_f.write(stdout)
124 | finally:
125 | out_f.close()
126 |
127 | return rtn
128 |
--------------------------------------------------------------------------------
/python-dtf/dtf/library.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2017 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """dtf Libraries Template"""
17 |
18 | from __future__ import absolute_import
19 |
20 | import os.path
21 | import sqlite3
22 |
23 | import dtf.core.utils as utils
24 | import dtf.properties as prop
25 |
26 | TAG = "dtf-library"
27 |
28 |
29 | class DtfDbException(Exception): # pylint: disable=too-few-public-methods
30 |
31 | """Base class for DB Exceptions"""
32 |
33 | def __init__(self, message):
34 |
35 | """Raise new exception"""
36 |
37 | # Call the base class constructor with the parameters it needs
38 | Exception.__init__(self, message)
39 |
40 |
41 | class DbLibrary(object):
42 |
43 | """
44 | Base class for creating a python database library with dtf.
45 | """
46 |
47 | # This needs to be set
48 | db_name = ""
49 |
50 | db_path = ""
51 | db_connection = None
52 |
53 | def __init__(self, safe=False, project_dir=None):
54 |
55 | """Initialize new instance"""
56 |
57 | if project_dir is None:
58 | db_path = "%s/%s/%s" % (prop.TOP, utils.DBS_DIRECTORY,
59 | self.db_name)
60 | else:
61 | db_path = "%s/%s/%s" % (project_dir, utils.DBS_DIRECTORY,
62 | self.db_name)
63 |
64 | if safe and not os.path.isfile(db_path):
65 | raise DtfDbException("Database file not found : %s!" % db_path)
66 |
67 | self.db_path = db_path
68 | self.db_connection = sqlite3.connect(db_path)
69 |
70 | # Call post init for anyone needing additional stuff here
71 | self.post_init()
72 |
73 | def post_init(self):
74 |
75 | """Post-init to allow additional processing after __init__"""
76 | pass
77 |
78 | # The following are not meant to be overridden.
79 | def commit(self):
80 |
81 | """Commit DB changes"""
82 |
83 | if self.db_connection is None:
84 | raise DtfDbException("No active DB connection!")
85 |
86 | return self.db_connection.commit()
87 |
88 | def get_cursor(self):
89 |
90 | """Obtain handle to cursor"""
91 |
92 | if self.db_connection is None:
93 | raise DtfDbException("No active DB connection!")
94 |
95 | return self.db_connection.cursor()
96 |
97 | def close(self):
98 |
99 | """Close handle to DB"""
100 |
101 | if self.db_connection is None:
102 | raise DtfDbException("No Active DB connection!")
103 |
104 | self.db_connection.close()
105 |
106 | return
107 |
108 | @classmethod
109 | def exists(cls):
110 |
111 | """Simple check to determine if DB exists"""
112 |
113 | db_path = "%s/%s/%s" % (prop.TOP, utils.DBS_DIRECTORY,
114 | cls.db_name)
115 |
116 | return bool(os.path.isfile(db_path))
117 |
--------------------------------------------------------------------------------
/python-dtf/dtf/logging.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """dtf logging framework"""
17 |
18 | from __future__ import absolute_import
19 | from sys import stdout
20 | from time import localtime, strftime
21 |
22 | from colored import attr
23 |
24 | import dtf.core.utils as utils
25 | import dtf.colors as colors
26 |
27 |
28 | # Can override just like the shell
29 | LOG_LEVEL_FILE = 4 # By default, log E-V
30 | LOG_LEVEL_STDOUT = 4 # By default, log E-V
31 |
32 | # Internals ###########################################################
33 | LOG_FILE = None
34 |
35 | # Open file on module import
36 | TOP = utils.get_project_root()
37 | if TOP is not None:
38 | LOG_FILE = open("%s/%s" % (TOP, utils.LOG_FILE_NAME), 'a')
39 |
40 |
41 | def __get_date():
42 |
43 | """Format current date"""
44 |
45 | return strftime("%a %b %d %H:%M:%S %Z %Y", localtime())
46 |
47 |
48 | def __log(buf, entry):
49 |
50 | """Low level print function"""
51 |
52 | buf.write(entry)
53 |
54 |
55 | # Low level stdout print
56 | def __log_to_stdout(color, date, tag, message):
57 |
58 | """Write entry to stdout"""
59 |
60 | entry = "%s[%s] %s - %s %s\n" % (color, date, tag, message, attr(0))
61 | __log(stdout, entry)
62 |
63 |
64 | # Low level file print
65 | def __log_to_file(date, tag, message):
66 |
67 | """Write entry to stderr"""
68 |
69 | if LOG_FILE is None:
70 | return
71 |
72 | entry = "[%s] %s - %s\n" % (date, tag, message)
73 | __log(LOG_FILE, entry)
74 |
75 | # ######################################################################
76 |
77 |
78 | # Public Calls #########################################################
79 | def e(tag, message): # pylint: disable=invalid-name
80 |
81 | """Print an error message"""
82 |
83 | date = __get_date()
84 | if LOG_LEVEL_STDOUT >= 1:
85 | __log_to_stdout(colors.COLOR_ERR, date, tag+"/E", message)
86 | if LOG_LEVEL_FILE >= 1:
87 | __log_to_file(date, tag+"/E", message)
88 |
89 |
90 | def w(tag, message): # pylint: disable=invalid-name
91 |
92 | """Print a warning message"""
93 |
94 | date = __get_date()
95 | if LOG_LEVEL_STDOUT >= 2:
96 | __log_to_stdout(colors.COLOR_WARN, date, tag+"/W", message)
97 | if LOG_LEVEL_FILE >= 2:
98 | __log_to_file(date, tag+"/W", message)
99 |
100 |
101 | def i(tag, message): # pylint: disable=invalid-name
102 |
103 | """Print an informational message (non-debug)"""
104 |
105 | date = __get_date()
106 | if LOG_LEVEL_STDOUT >= 3:
107 | __log_to_stdout(colors.COLOR_INFO, date, tag+"/I", message)
108 | if LOG_LEVEL_FILE >= 3:
109 | __log_to_file(date, tag+"/I", message)
110 |
111 |
112 | def v(tag, message): # pylint: disable=invalid-name
113 |
114 | """Print a verbose message (non-debug)"""
115 |
116 | date = __get_date()
117 | if LOG_LEVEL_STDOUT >= 4:
118 | __log_to_stdout(colors.COLOR_VERB, date, tag+"/V", message)
119 | if LOG_LEVEL_FILE >= 4:
120 | __log_to_file(date, tag+"/V", message)
121 |
122 |
123 | def d(tag, message): # pylint: disable=invalid-name
124 |
125 | """Print a debugging message"""
126 |
127 | date = __get_date()
128 | if LOG_LEVEL_STDOUT >= 5:
129 | __log_to_stdout(colors.COLOR_DEB, date, tag+"/D", message)
130 | if LOG_LEVEL_FILE >= 5:
131 | __log_to_file(date, tag+"/D", message)
132 |
133 |
134 | # Multi-line Logging
135 | def e_ml(tag, messages):
136 |
137 | """Print a multi-line error message"""
138 |
139 | if not isinstance(messages, list):
140 | raise TypeError
141 |
142 | for message in messages:
143 | if message == "":
144 | continue
145 |
146 | e(tag, message)
147 |
148 |
149 | def w_ml(tag, messages):
150 |
151 | """Print a multi-lne warning message"""
152 |
153 | if not isinstance(messages, list):
154 | raise TypeError
155 |
156 | for message in messages:
157 | if message == "":
158 | continue
159 |
160 | w(tag, message)
161 |
162 |
163 | def i_ml(tag, messages):
164 |
165 | """Print a multi-line informational message"""
166 |
167 | if not isinstance(messages, list):
168 | raise TypeError
169 |
170 | for message in messages:
171 | if message == "":
172 | continue
173 |
174 | i(tag, message)
175 |
176 |
177 | def v_ml(tag, messages):
178 |
179 | """Print a multi-line verbose message"""
180 |
181 | if not isinstance(messages, list):
182 | raise TypeError
183 |
184 | for message in messages:
185 | if message == "":
186 | continue
187 |
188 | v(tag, message)
189 |
190 |
191 | def d_ml(tag, messages):
192 |
193 | """Print a multi-line debugging message"""
194 |
195 | if not isinstance(messages, list):
196 | raise TypeError
197 |
198 | for message in messages:
199 | if message == "":
200 | continue
201 |
202 | d(tag, message)
203 | #########################################################################
204 |
--------------------------------------------------------------------------------
/python-dtf/dtf/module.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """dtf Module Template"""
17 |
18 | from __future__ import absolute_import
19 | import os
20 |
21 | import dtf.logging as log
22 | import dtf.properties as prop
23 | import dtf.core.packagemanager as pm
24 | from dtf.globals import DTF_PACKAGES_DIR
25 | from dtf.exceptions import DtfException
26 |
27 | TAG = "dtf-module"
28 |
29 |
30 | def sub_cmd(name, usage=""):
31 |
32 | """Decorator for routing a sub command"""
33 |
34 | def decorator(func):
35 |
36 | """Save name of the sub command + function"""
37 |
38 | func.sub_cmd_name = name
39 | func.sub_cmd_route = func.__name__
40 | func.sub_cmd_usage = usage
41 |
42 | return func
43 |
44 | return decorator
45 |
46 |
47 | class Module(object):
48 |
49 | """
50 | Base class for creating a python module with dtf. Override the
51 | fields below, and implement an execute(self, args) method.
52 | """
53 |
54 | name = "MyModule"
55 | version = "1.0.0"
56 | license = "N/A"
57 | author = "N/A"
58 | about = "A basic dtf module."
59 |
60 | requires = []
61 | min_sdk = 0
62 |
63 | launch_dir = ""
64 |
65 | __self__ = ''
66 |
67 | def run(self, args):
68 |
69 | """
70 | Internal entry point for starting a module. It basically executes
71 | the 'execute' method if it exists.
72 | """
73 |
74 | # Save module name
75 | self.__self__ = type(self).__name__
76 |
77 | # Determine if we have an execute() method.
78 | if hasattr(self, 'execute'):
79 |
80 | # Do python logging override
81 | try:
82 | log.LOG_LEVEL_STDOUT = int(os.environ['GLOG_LEVEL'])
83 | except KeyError:
84 | pass
85 | except ValueError:
86 | log.w(TAG, "Invalid GLOG_LEVEL value (0-5 is allowed)")
87 |
88 | result = getattr(self, 'execute')(args)
89 |
90 | else:
91 |
92 | log.e(TAG, "Module '%s' does not define a entry point!"
93 | % self.__self__)
94 | result = None
95 |
96 | return result
97 |
98 | @classmethod
99 | def get_diff_dir(cls):
100 |
101 | """Determine which diffing db to use"""
102 |
103 | # First check for a property override.
104 | if prop.test_prop('Local', 'diff-data-dir'):
105 | diff_dir = prop.get_prop('Local', 'diff-data-dir')
106 |
107 | if not os.path.isdir(diff_dir):
108 | raise DtfException("Unable to find diffing directory!")
109 | else:
110 | return diff_dir
111 |
112 | # Not set
113 | else:
114 | sdk = prop.get_prop("Info", "sdk")
115 | if pm.is_package_installed("aosp-data-%s" % sdk):
116 |
117 | diff_dir = ("%s/aosp-data-%s"
118 | % (DTF_PACKAGES_DIR, sdk))
119 |
120 | return diff_dir
121 | else:
122 | raise DtfException("AOSP data not installed for this API!")
123 |
124 | def cd_launch_dir(self):
125 |
126 | """Change to the launch directory"""
127 |
128 | os.chdir(self.launch_dir)
129 |
--------------------------------------------------------------------------------
/python-dtf/dtf/properties.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """dtf property support"""
17 |
18 | from __future__ import absolute_import
19 | from os.path import abspath, join, isfile
20 | from os import getcwd, pardir
21 |
22 | import configparser
23 |
24 | import dtf.core.utils as utils
25 | import dtf.logging as log
26 |
27 | CONFIG_FILE_NAME = utils.CONFIG_FILE_NAME
28 |
29 | TAG = "dtf-properties"
30 |
31 |
32 | class PropertyError(Exception):
33 |
34 | """General exception for properties"""
35 | pass
36 |
37 |
38 | def __upsearch(file_name, dir_name):
39 |
40 | """Search upward for file"""
41 |
42 | if isfile("%s/%s" % (dir_name, file_name)):
43 | return dir_name
44 | else:
45 | new_dir = abspath(join(dir_name, pardir))
46 | if dir_name == new_dir:
47 | return None
48 | return __upsearch(file_name, new_dir)
49 |
50 |
51 | TOP = __upsearch(CONFIG_FILE_NAME, getcwd())
52 |
53 |
54 | def __load_config():
55 |
56 | """Load the current project configuration"""
57 |
58 | config = configparser.ConfigParser()
59 | config.read(CONFIG_FILE_NAME)
60 |
61 | return config
62 |
63 |
64 | def __update_config(config):
65 |
66 | """Update config file"""
67 |
68 | prop_f = open(CONFIG_FILE_NAME, 'w')
69 | config.write(prop_f)
70 | prop_f.close()
71 |
72 |
73 | def get_prop(section, prop):
74 |
75 | """Get a property value"""
76 |
77 | config = __load_config()
78 | section = section.capitalize()
79 |
80 | # Caller needs to check return if he/she cares what the issue was.
81 | try:
82 | rtn = config.get(section, prop)
83 | except configparser.NoSectionError:
84 | err = "Property section not found: %s" % section
85 | raise PropertyError(err)
86 | except configparser.NoOptionError:
87 | err = r"Property not found: %s\%s" % (section, prop)
88 | raise PropertyError(err)
89 |
90 | return rtn
91 |
92 |
93 | def set_prop(section, prop, value):
94 |
95 | """Set a property"""
96 |
97 | config = __load_config()
98 | section = section.capitalize()
99 |
100 | # Add section if it doesnt exist
101 | if not config.has_section(section):
102 | config.add_section(section)
103 |
104 | # Set the new parameter
105 | config.set(section, prop, value)
106 |
107 | __update_config(config)
108 |
109 | return 0
110 |
111 |
112 | def del_prop(section, prop):
113 |
114 | """Delete a property"""
115 |
116 | config = __load_config()
117 | section = section.capitalize()
118 |
119 | rtn = None
120 |
121 | # Remove the parameter
122 | try:
123 | rtn = config.remove_option(section, prop)
124 | except configparser.NoSectionError:
125 | log.w(TAG, "Property not removed (the section did not exist).")
126 | return -1
127 |
128 | if not rtn:
129 | log.w(TAG, "Property not removed (did not exist).")
130 | return -2
131 |
132 | # Let's make sure we don't have an empty section now.
133 | if len(config.items(section)) == 0:
134 | config.remove_section(section)
135 |
136 | __update_config(config)
137 |
138 | return 0
139 |
140 |
141 | def test_prop(section, prop):
142 |
143 | """Test if a property is set or not"""
144 |
145 | config = __load_config()
146 | section = section.capitalize()
147 | rtn = 0
148 |
149 | try:
150 | config.get(section, prop)
151 | rtn = 1
152 | except configparser.NoSectionError:
153 | rtn = 0
154 | except configparser.NoOptionError:
155 | rtn = 0
156 |
157 | return rtn
158 |
--------------------------------------------------------------------------------
/python-dtf/generate_coverage.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Android Device Testing Framework ("dtf")
3 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # Generate coverage information
18 |
19 | # If we are in travis, we don't need to use virtualenv. For now,
20 | # locally we need to activate it.
21 | if [ "$TRAVIS" != "true" ]; then
22 | echo "Activating virtualenv"
23 | . venv/bin/activate
24 | fi
25 |
26 | export COVERAGE_PROCESS_START=.coveragerc
27 |
28 | # Remove old coverage data
29 | coverage erase
30 |
31 | # Just incase, remove any .dtf* stuff.
32 | rm .dtfini .dtflog 2>/dev/null
33 |
34 | # Make sure dtf is installed.
35 | python setup.py develop
36 |
37 | # We need to make sure there is no .dtf, but for local testing,
38 | # I'd rather not have my stuff blown away. Move it, then move back.
39 | if [ -e ~/.dtf ]; then
40 | mv ~/.dtf ~/.dtf_bk
41 | fi
42 |
43 | # ============ Unit Tests ==============
44 | # Mock a ~/.dtf directory for unit tests.
45 | mkdir -p ~/.dtf/binaries/ ~/.dtf/included/ ~/.dtf/libraries/ ~/.dtf/modules/ ~/.dtf/packages/
46 | tar -xC ~/.dtf/included -f dtf/included.tar
47 |
48 | coverage run -m py.test tests/unit
49 |
50 | # Reset the mocked ~/.dtf/
51 | rm -rf ~/.dtf
52 |
53 | # ========= Integration Tests ==========
54 | # First run non-device integration.
55 | coverage run -m py.test tests/integration
56 |
57 | # These tests will require an active emulator/device
58 | # Only run these if we are Travis OR manually request.
59 | if [ "$TRAVIS" = "true" -o "$DO_DEVICE_INTEGRATION" = "1" ]; then
60 | adb install $(ls included/dtfClient/*.apk)
61 | adb shell am startservice -a com.dtf.action.name.INITIALIZE
62 | coverage run -m py.test tests/integration-device
63 | fi
64 |
65 | # Move it back
66 | if [ -e ~/.dtf_bk ]; then
67 | rm -rf ~/.dtf
68 | mv ~/.dtf_bk ~/.dtf
69 | fi
70 |
71 | # Combine and show
72 | coverage combine
73 |
74 | coverage report
75 | coverage html
76 |
77 | python setup.py develop --uninstall
78 |
79 | if [ "$TRAVIS" != "true" ]; then
80 | deactivate
81 | fi
82 |
--------------------------------------------------------------------------------
/python-dtf/setup.cfg:
--------------------------------------------------------------------------------
1 | [install_lib]
2 | compile=0
3 |
--------------------------------------------------------------------------------
/python-dtf/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Android Device Testing Framework ("dtf")
3 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | """dtf Setup Script"""
18 |
19 | from __future__ import absolute_import
20 | from setuptools import setup
21 | import os
22 | import sys
23 |
24 | # Read in the version data.
25 | def generate_version_string():
26 |
27 | """Generate version string based on VERSION"""
28 |
29 | values = open(os.path.join(
30 | os.path.dirname(__file__),
31 | "dtf/VERSION")).read().rstrip().split('-')
32 |
33 | if len(values) < 3:
34 | return "%s.%s" % (values[0], values[1])
35 | else:
36 | return "%s.%s.%s" % (values[0], values[1], values[2])
37 |
38 | requires = ['colored',
39 | 'configparser',
40 | 'lxml',
41 | 'semantic_version',
42 | 'requests']
43 |
44 | if sys.version_info[:2] == (2, 6):
45 | requires.append("configparser")
46 |
47 | setup(
48 | name='dtf',
49 | version=generate_version_string(),
50 | description='Android Device Testing Framework (dtf)',
51 | long_description=open(
52 | os.path.join(os.path.dirname(__file__), "README.rst")).read(),
53 |
54 | url='https://thecobraden.com/projects/dtf',
55 | download_url='https://github.com/jakev/dtf',
56 |
57 | author='Jake Valletta',
58 | author_email='javallet@gmail.com',
59 | license='ASL',
60 |
61 | classifiers=[
62 | 'Development Status :: 4 - Beta',
63 | 'Intended Audience :: Information Technology',
64 | 'Topic :: Security',
65 | 'License :: OSI Approved :: Apache Software License',
66 | 'Operating System :: POSIX :: Linux',
67 | 'Programming Language :: Python :: 2',
68 | 'Programming Language :: Python :: 2.7',
69 | 'Programming Language :: Python :: 3',
70 | 'Programming Language :: Python :: 3.3'],
71 |
72 | keywords='android device security mobile reverse-engineering framework',
73 |
74 | packages=["dtf",
75 | "dtf.core",
76 | "dtf.core.cmds"],
77 |
78 | install_requires=requires,
79 | setup_requires=['pytest-runner'],
80 |
81 | entry_points={
82 | 'console_scripts': [
83 | 'dtf = dtf.launcher:main',
84 | 'dtf_check = dtf.checker:main',
85 | ],
86 | },
87 |
88 | zip_safe=False,
89 | include_package_data=True,
90 | )
91 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/hello-world.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/python-dtf/tests/data-files/hello-world.apk
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_client_upload_data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/python-dtf/tests/data-files/integration_client_upload_data
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_module_invalid_noclass:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import dtf.logging as log
4 |
5 | from dtf.module import Module
6 |
7 | TAG = "TestModule"
8 |
9 |
10 | class test_nope(Module):
11 |
12 | """A Module class"""
13 |
14 | about = 'Integration test'
15 | author = 'Jake Valletta (jakev)'
16 | name = 'test_nope'
17 | version = '1.0.0'
18 |
19 | def execute(self, args):
20 |
21 | """Main class executor"""
22 |
23 | log.i(TAG, "I was launched!")
24 |
25 | return 0
26 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_module_invalid_noexecargs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import dtf.logging as log
4 |
5 | from dtf.module import Module
6 |
7 | TAG = "TestModule"
8 |
9 |
10 | class test_noexecargs(Module):
11 |
12 | """A Module class"""
13 |
14 | about = 'Integration test'
15 | author = 'Jake Valletta (jakev)'
16 | name = 'test_noexecargs'
17 | version = '1.0.0'
18 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_module_valid_kraise:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import dtf.logging as log
4 | import dtf.module as module
5 |
6 | TAG = "TestModule"
7 |
8 |
9 | class test_kraise(module.Module):
10 |
11 | """A Module class"""
12 |
13 | about = 'Integration test'
14 | author = 'Jake Valletta (jakev)'
15 | name = 'test_kraise'
16 | version = '1.0.0'
17 |
18 | @module.sub_cmd("test")
19 | def cmd_test(self, args):
20 |
21 | raise KeyboardInterrupt("On no!")
22 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_module_valid_mod:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import dtf.logging as log
4 |
5 | from dtf.module import Module
6 |
7 | TAG = "TestModule"
8 |
9 |
10 | class test_execute(Module):
11 |
12 | """A Module class"""
13 |
14 | about = 'Integration test'
15 | author = 'Jake Valletta (jakev)'
16 | name = 'test_execute'
17 | version = '1.0.0'
18 |
19 | def execute(self, args):
20 |
21 | """Main class executor"""
22 |
23 | log.i(TAG, "I was launched!")
24 |
25 | return 0
26 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_module_valid_raise:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import dtf.logging as log
4 | import dtf.module as module
5 |
6 | TAG = "TestModule"
7 |
8 |
9 | class test_raise(module.Module):
10 |
11 | """A Module class"""
12 |
13 | about = 'Integration test'
14 | author = 'Jake Valletta (jakev)'
15 | name = 'test_raise'
16 | version = '1.0.0'
17 |
18 | @module.sub_cmd("test")
19 | def cmd_test(self, args):
20 |
21 | raise IOError("On no!")
22 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_module_valid_subs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import dtf.logging as log
4 | import dtf.module as module
5 |
6 | TAG = "TestModule"
7 |
8 |
9 | class test_sub(module.Module):
10 |
11 | """Module class for viewing binary information"""
12 |
13 | about = 'Integration test - valid module'
14 | author = 'Jake Valletta (jakev)'
15 | name = 'test_module'
16 | version = '1.0.0'
17 |
18 | @module.sub_cmd("test")
19 | def cmd_test(self, args):
20 |
21 | log.i(TAG, "test called!")
22 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_pm_binary_install:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/python-dtf/tests/data-files/integration_pm_binary_install
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_pm_install_library.dz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/python-dtf/tests/data-files/integration_pm_install_library.dz
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_pm_install_package.dz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/python-dtf/tests/data-files/integration_pm_install_package.dz
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_pm_module_install_bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # DTF Core Content
3 | # Copyright 2013-2015 Jake Valletta (@jake_valletta)
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | #@About: Get an APK (optionally with DEX) from device.
18 | #@Author: Jake Valletta (jakev)
19 | #@Version: 1.1.0
20 |
21 | . $DTF_CORE
22 | . $DTF_LOG
23 |
24 | usage()
25 | {
26 | echo "Usage apkget OPTIONS "
27 | echo " OPTIONS:"
28 | echo " -o Pull package's ODEX"
29 | echo " -s Search for package"
30 | echo " -p Pull package"
31 | echo " -h Prints this menu"
32 | exit 1
33 | }
34 |
35 | if [ $# -lt 1 ] ; then
36 | usage
37 | fi
38 |
39 | package=""
40 | search=""
41 | odex=""
42 |
43 | #Process the arguments
44 | while getopts hdeo:p:s: opt
45 | do
46 | case "$opt" in
47 | h) usage;;
48 | o) odex=$OPTARG;;
49 | p) package=$OPTARG;;
50 | s) search=$OPTARG;;
51 | \?) usage;;
52 | esac
53 | done
54 |
55 | adb wait-for-device
56 |
57 | cd "${LAUNCH_DIR}"
58 |
59 | if [ $search ]; then
60 | echo "Searching for \"${search}\"..."
61 | adb shell "pm list packages"|grep -i "$search"|awk '{print $1}'
62 | exit 0
63 |
64 | elif [ $package ]; then
65 | log_i "Attempting to pull APK for \"${package}\"..."
66 | package_path=$(adb shell pm path ${package} | tr -d '\r' |awk -F":" '{print $2}')
67 |
68 | if [ -z $package_path ]; then
69 | log_e "No packages match the string \"${package}\""
70 | exit 1
71 | else
72 | log_i "Found match for \"${package}\""
73 | adb pull $package_path > /dev/null 2>&1
74 | exit 0
75 | fi
76 |
77 | elif [ $odex ]; then
78 |
79 | log_i "Attempting to pull ODEX for \"${odex}\"..."
80 | apk_path=$(adb shell pm path ${odex} | tr -d '\r' |awk -F":" '{print $2}')
81 |
82 | if [ $apk_path ]; then
83 | log_i "Found match for \"${odex}\""
84 |
85 | package_path=$(dirname $apk_path)
86 | odex_name=$(basename $apk_path| sed 's/\.apk$/.odex/')
87 |
88 | # Need to act differently depending on Dalvik/ART
89 | vm_type=$(dtf prop get Info vmtype)
90 |
91 | # Device is using ART/ART64
92 | if [[ "$vm_type" == "ART"* ]]; then
93 |
94 | # It's not with checking the bits, as both can exist.
95 | log_i "Attempting to pull 32-bit ODEX..."
96 | adb pull ${package_path}/arm/${odex_name} > /dev/null 2>&1
97 |
98 | log_i "Attempting to pull 64-bit ODEX..."
99 | adb pull ${package_path}/arm64/${odex_name} > /dev/null 2>&1
100 |
101 | # Dalvik, so path is easy.
102 | else
103 | package_path=$(dirname $apk_path)
104 | odex_name=$(basename $apk_path| sed 's/\.apk$/.odex/')
105 | log_i "Attempting to pull 32-bit ODEX..."
106 | adb pull ${package_path}/${odex_name} > /dev/null 2>&1
107 | fi
108 | else
109 | log_e "No packages match the string \"${odex}\""
110 | exit 1
111 | fi
112 | else
113 | echo "[ERROR] You must specify -p or -s!"
114 | usage
115 | fi
116 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/integration_pm_valid_zip.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/python-dtf/tests/data-files/integration_pm_valid_zip.zip
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/nexus_5x:
--------------------------------------------------------------------------------
1 | [Info]
2 | serial = 1234567890123456
3 | kernel = Linux version 3.10.73-g8eaa82a (android-build@vpba27.mtv.corp.google.com) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Sat Mar 26 01:36:22 UTC 2016
4 | sdk = 23
5 | path = /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
6 | bootclasspath-jars = /system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/apache-xml.jar:/system/framework/org.apache.http.legacy.boot.jar
7 | version-string = google-bullhead_MTC19T
8 | cpu-bits = 64
9 | vmtype = ART
10 | seandroid-state = Enforcing
11 | busybox = /data/data/com.dtf.client/files/busybox
12 |
--------------------------------------------------------------------------------
/python-dtf/tests/data-files/valid_android_manifest.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/python-dtf/tests/data-files/valid_android_manifest.xml
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | class ClientTests(testutils.BasicIntegrationDeviceTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_no_args(self):
27 |
28 | """Run with not args"""
29 |
30 | rtn = self.run_cmd("client")
31 |
32 | assert(rtn.return_code == 0)
33 |
34 |
35 | def test_not_subcommand(self):
36 |
37 | """Try to call invalid sub command"""
38 |
39 | rtn = self.run_cmd("client NOT_EXIST")
40 |
41 | assert(rtn.return_code == 0)
42 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client_download.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client download" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 | import dtf.core.utils as utils
21 |
22 | class ClientDownloadTests(testutils.BasicIntegrationDeviceTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_download(self):
27 |
28 | """Do an download"""
29 |
30 | rtn = self.run_cmd("client download /system/etc/hosts")
31 |
32 | utils.delete_file("hosts")
33 |
34 | assert(rtn.return_code == 0)
35 |
36 | def test_download_local_exists(self):
37 |
38 | """Try to download a file that already exists"""
39 |
40 | utils.touch("hosts")
41 | rtn = self.run_cmd("client download /system/etc/hosts")
42 |
43 | utils.delete_file("hosts")
44 |
45 | assert(rtn.return_code == 255)
46 |
47 | def test_download_path(self):
48 |
49 | """Do a download to a path"""
50 |
51 | rtn = self.run_cmd("client download --path ./hosts /system/etc/hosts")
52 |
53 | utils.delete_file("hosts")
54 |
55 | assert(rtn.return_code == 0)
56 |
57 | def test_download_not_installed(self):
58 |
59 | """Attempt to download with non-existent APK"""
60 |
61 | rtn = self.run_cmd("client remove")
62 | assert(rtn.return_code == 0)
63 |
64 | rtn = self.run_cmd("client download /system/etc/hosts")
65 | assert(rtn.return_code == 255)
66 |
67 | rtn = self.run_cmd("client install")
68 | assert(rtn.return_code == 0)
69 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client_execute.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client execute" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | class ClientExecuteTests(testutils.BasicIntegrationDeviceTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_no_args(self):
27 |
28 | """Run execute with no args"""
29 |
30 | rtn = self.run_cmd("client execute")
31 | assert(rtn.return_code == 255)
32 |
33 | def test_run_ls(self):
34 |
35 | """Run ls command"""
36 |
37 | rtn = self.run_cmd("client execute ls")
38 | assert(rtn.return_code == 0)
39 |
40 | def test_not_installed(self):
41 |
42 | """Test but not installed"""
43 |
44 | rtn = self.run_cmd("client remove")
45 | assert(rtn.return_code == 0)
46 |
47 | rtn = self.run_cmd("client execute ls")
48 | assert(rtn.return_code == 255)
49 |
50 | rtn = self.run_cmd("client install")
51 | assert(rtn.return_code == 0)
52 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client_install.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client install" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | class ClientInstallTests(testutils.BasicIntegrationDeviceTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_install(self):
27 |
28 | """Do an install"""
29 |
30 | rtn = self.run_cmd("client install")
31 | assert(rtn.return_code == 0)
32 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client_remove.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client remove" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | class ClientRemoveTests(testutils.BasicIntegrationDeviceTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_uninstall(self):
27 |
28 | """Run ls command"""
29 |
30 | rtn = self.run_cmd("client remove")
31 | assert(rtn.return_code == 0)
32 |
33 | rtn = self.run_cmd("client install")
34 | assert(rtn.return_code == 0)
35 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client_restart.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client restart" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | class ClientRestartTests(testutils.BasicIntegrationDeviceTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_restart(self):
27 |
28 | """Test if is installed"""
29 |
30 | rtn = self.run_cmd("client restart")
31 | assert(rtn.return_code == 0)
32 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client_status.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client status" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | class ClientStatusTests(testutils.BasicIntegrationDeviceTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_status_installed(self):
27 |
28 | """Test if is installed"""
29 |
30 | rtn = self.run_cmd("client status")
31 | assert(rtn.return_code == 0)
32 |
33 | def test_status_not_installed(self):
34 |
35 | """"Test if not installed"""
36 |
37 | rtn = self.run_cmd("client remove")
38 | assert(rtn.return_code == 0)
39 |
40 | rtn = self.run_cmd("client status")
41 | assert(rtn.return_code == 0)
42 |
43 | rtn = self.run_cmd("client install")
44 | assert(rtn.return_code == 0)
45 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration-device/client/test_client_upload.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "client upload" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | PATH_TO_DTF_DATA = '/data/data/com.dtf.client'
23 |
24 | class ClientUploadTests(testutils.BasicIntegrationDeviceTest):
25 |
26 | """Wraper for integration tests"""
27 |
28 | def test_upload(self):
29 |
30 | """Do an upload"""
31 |
32 | data_file = testutils.DataFile("integration_client_upload_data")
33 |
34 | rtn = self.run_cmd("client upload %s" % str(data_file))
35 | assert(rtn.return_code == 0)
36 |
37 | rtn = self.run_cmd("client execute \"rm %s/integration_client_upload_data\""
38 | % PATH_TO_DTF_DATA)
39 | assert(rtn.return_code == 0)
40 |
41 |
42 | def test_upload_no_exist(self):
43 |
44 | """Upload non-existent file"""
45 |
46 | rtn = self.run_cmd("client upload TEST")
47 | assert(rtn.return_code == 255)
48 |
49 | def test_upload_path(self):
50 |
51 | """Do an upload to a path"""
52 |
53 | data_file = testutils.DataFile("integration_client_upload_data")
54 |
55 | rtn = self.run_cmd("client upload --path /data/data/com.dtf.client/test %s"
56 | % str(data_file))
57 | assert(rtn.return_code == 0)
58 |
59 | rtn = self.run_cmd("client execute \"rm %s/integration_client_upload_data\""
60 | % PATH_TO_DTF_DATA)
61 | assert(rtn.return_code == 0)
62 |
63 | def test_upload_not_installed(self):
64 |
65 | """Attempt to upload with non-existent APK"""
66 |
67 | rtn = self.run_cmd("client remove")
68 | assert(rtn.return_code == 0)
69 |
70 | data_file = testutils.DataFile("integration_client_upload_data")
71 |
72 | rtn = self.run_cmd("client upload %s" % str(data_file))
73 | assert(rtn.return_code == 255)
74 |
75 | rtn = self.run_cmd("client install")
76 | assert(rtn.return_code == 0)
77 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/archive/test_archive.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for archiving"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 | import dtf.core.utils as utils
21 |
22 | import os.path
23 |
24 | class ArchiveTests(testutils.BasicIntegrationTest):
25 |
26 | """Wraper for integration tests"""
27 |
28 | def test_no_args(self):
29 |
30 | """Run with not args"""
31 |
32 | rtn = self.run_cmd("archive")
33 |
34 | assert(rtn.return_code == 0)
35 |
36 |
37 | def test_not_subcommand(self):
38 |
39 | """Try to call invalid sub command"""
40 |
41 | rtn = self.run_cmd("archive NOT_EXIST")
42 |
43 | assert(rtn.return_code == 0)
44 |
45 | def test_help(self):
46 |
47 | """Force the usage"""
48 |
49 | rtn = self.run_cmd("archive -h")
50 |
51 | assert(rtn.return_code == 0)
52 |
53 | def test_no_name(self):
54 |
55 | """Attempt create an archive using builtin name"""
56 |
57 | config = testutils.get_default_config()
58 |
59 | version_string = "android-17_XTS"
60 | zip_name = "%s.zip" % version_string
61 | config.set("Info", "version-string", version_string)
62 |
63 | self.update_config(config)
64 |
65 | rtn = self.run_cmd("archive create")
66 |
67 | assert(rtn.return_code == 0)
68 | assert(os.path.isfile(zip_name))
69 |
70 | utils.delete_file(zip_name)
71 |
72 | def test_named(self):
73 |
74 | """Attempt to create an archive using custom name"""
75 |
76 | version_string = "android-17_XTS"
77 | zip_name = "%s.zip" % version_string
78 |
79 | rtn = self.run_cmd("archive create %s" % zip_name)
80 |
81 | assert(rtn.return_code == 0)
82 | assert(os.path.isfile(zip_name))
83 |
84 | utils.delete_file(zip_name)
85 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/binding/test_binding.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the bindings"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_no_args():
23 |
24 | """Attempt to list bindings"""
25 |
26 | rtn = testutils.dtf("binding")
27 | assert(rtn.return_code == 0)
28 |
29 |
30 | def test_doesnt_exist():
31 |
32 | """Attempt to get a binding that doesn't exist"""
33 |
34 | rtn = testutils.dtf("binding NON")
35 | assert(rtn.return_code == 255)
36 |
37 |
38 | def test_valid_bindings():
39 |
40 | """Test all valid bindings"""
41 |
42 | binding_list = ['dtf_aapt', 'dtf_abe', 'dtf_apktool',
43 | 'dtf_axmlprinter2', 'dtf_baksmali',
44 | 'dtf_smali', 'dtf_dex2jar']
45 |
46 | for binding in binding_list:
47 |
48 | rtn = testutils.dtf("binding %s" % binding)
49 | assert(rtn.return_code == 0)
50 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/local/test_local.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for 'local' command"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 | import dtf.core.utils as utils
21 |
22 | def test_no_args():
23 |
24 | """Run with not args"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | example_local = "%s/example" % utils.LOCAL_MODULES_DIRECTORY
29 | utils.touch(example_local)
30 |
31 | rtn = testutils.dtf("local")
32 |
33 | testutils.undeploy()
34 |
35 | assert(rtn.return_code == 0)
36 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/module/test_module.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for launching modules"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 | class ModuleInstallTests(testutils.BasicIntegrationTest):
22 |
23 | """Wraper for integration tests"""
24 |
25 | def test_valid_python_execute(self):
26 |
27 | """Run module with default execute"""
28 |
29 | data_file = testutils.DataFile("integration_module_valid_mod")
30 |
31 | rtn = self.run_cmd("pm install --force --single module --install_name test_execute --name %s --auto" % str(data_file))
32 | assert(rtn.return_code == 0)
33 |
34 | rtn = self.run_cmd("test_execute")
35 |
36 | assert(rtn.return_code == 0)
37 |
38 | def test_valid_python_sub_cmd(self):
39 |
40 | """Run module with valid sub_cmd"""
41 |
42 | data_file = testutils.DataFile("integration_module_valid_subs")
43 |
44 | rtn = self.run_cmd("pm install --force --single module --install_name test_sub --name %s --auto" % str(data_file))
45 | assert(rtn.return_code == 0)
46 |
47 | rtn = self.run_cmd("test_sub test")
48 |
49 | assert(rtn.return_code == 0)
50 |
51 | def test_valid_python_wrong_sub(self):
52 |
53 | """Run module with not existant subcmd"""
54 |
55 | data_file = testutils.DataFile("integration_module_valid_subs")
56 |
57 | rtn = self.run_cmd("pm install --force --single module --install_name test_sub --name %s --auto" % str(data_file))
58 | assert(rtn.return_code == 0)
59 |
60 | rtn = self.run_cmd("test_sub nope")
61 |
62 | assert(rtn.return_code == 241)
63 |
64 | def test_valid_python_raise_exception(self):
65 |
66 | """Run module and immediately raise an exception"""
67 |
68 | data_file = testutils.DataFile("integration_module_valid_raise")
69 |
70 | rtn = self.run_cmd("pm install --force --single module --install_name test_raise --name %s --auto" % str(data_file))
71 | assert(rtn.return_code == 0)
72 |
73 | rtn = self.run_cmd("test_raise test")
74 |
75 | assert(rtn.return_code == 246)
76 |
77 | def test_valid_python_raise_kb_exception(self):
78 |
79 | """Run module and immediately raise a keyboard exception"""
80 |
81 | data_file = testutils.DataFile("integration_module_valid_kraise")
82 |
83 | rtn = self.run_cmd("pm install --force --single module --install_name test_kraise --name %s --auto" % str(data_file))
84 | assert(rtn.return_code == 0)
85 |
86 | rtn = self.run_cmd("test_kraise test")
87 |
88 | assert(rtn.return_code == 245)
89 |
90 | # TODO: this cant be ran until --install_name is parsed correctly.
91 | #def test_invalid_python_missing_class(self):
92 | #
93 | # """Attempt to run module with missing class"""
94 | #
95 | # data_file = testutils.DataFile("integration_module_invalid_noclass")
96 | #
97 | # rtn = self.run_cmd("pm install --force --single module --install_name test_noclass --name %s" % str(data_file))
98 | # assert(rtn.return_code == 0)
99 | #
100 | # rtn = self.run_cmd("test_noclass test")
101 | #
102 | # assert(rtn.return_code == 247)
103 |
104 | def test_invalid_python_no_exec_zero_args(self):
105 |
106 | """Attempt to run module with no args or exec"""
107 |
108 | data_file = testutils.DataFile("integration_module_invalid_noexecargs")
109 |
110 | rtn = self.run_cmd("pm install --force --single module --install_name test_noexecargs --name %s --auto" % str(data_file))
111 | assert(rtn.return_code == 0)
112 |
113 | rtn = self.run_cmd("test_noexecargs test")
114 |
115 | assert(rtn.return_code == 242)
116 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/pm/test_pm.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "pm" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | class PmTests(testutils.BasicIntegrationTest):
23 |
24 | """Wraper for integration tests"""
25 |
26 | def test_no_args(self):
27 |
28 | """Running with no args"""
29 |
30 | rtn = self.run_cmd("pm")
31 | assert(rtn.return_code == 0)
32 |
33 | def test_not_subcommand(self):
34 |
35 | """Call invalid subcommand"""
36 |
37 | rtn = self.run_cmd("pm NOT_EXIST")
38 | assert(rtn.return_code == 0)
39 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/pm/test_pm_delete.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "pm delete" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 | import dtf.core.utils as utils
21 |
22 |
23 | class PmDeletetTests(testutils.BasicIntegrationTest):
24 |
25 | """Wraper for integration tests"""
26 |
27 | def test_no_args(self):
28 |
29 | """Run with no args"""
30 |
31 | rtn = self.run_cmd("pm delete")
32 | assert(rtn.return_code == 255)
33 |
34 | def test_wrong_type(self):
35 |
36 | """Delete wrong type"""
37 |
38 | rtn = self.run_cmd("pm delete --name ye --type WRONG")
39 | assert(rtn.return_code == 254)
40 |
41 | def test_delete_binary(self):
42 |
43 | """Delete a binary"""
44 |
45 | data_file = testutils.DataFile("integration_pm_valid_zip.zip")
46 |
47 | rtn = self.run_cmd("pm install --zip %s" % str(data_file))
48 | assert(rtn.return_code == 0)
49 |
50 | rtn = self.run_cmd("pm delete --name GenerateAIDL-1.0.jar --type binary",
51 | input_data="y\n")
52 | assert(rtn.return_code == 0)
53 |
54 | def test_delete_library(self):
55 |
56 | """Delete a library"""
57 |
58 | data_file = testutils.DataFile("integration_pm_valid_zip.zip")
59 |
60 | rtn = self.run_cmd("pm install --zip %s" % str(data_file))
61 | assert(rtn.return_code == 0)
62 |
63 | rtn = self.run_cmd("pm delete --name Utils --type library",
64 | input_data="y\n")
65 | assert(rtn.return_code == 0)
66 |
67 | def test_delete_module(self):
68 |
69 | """Delete a module"""
70 |
71 | data_file = testutils.DataFile("integration_pm_valid_zip.zip")
72 |
73 | rtn = self.run_cmd("pm install --zip %s" % str(data_file))
74 | assert(rtn.return_code == 0)
75 |
76 | rtn = self.run_cmd("pm delete --name apkget --type module",
77 | input_data="y\n")
78 |
79 | assert(rtn.return_code == 0)
80 |
81 | def test_delete_package(self):
82 |
83 | """Delete a package"""
84 |
85 | data_file = testutils.DataFile("integration_pm_valid_zip.zip")
86 |
87 | rtn = self.run_cmd("pm install --zip %s" % str(data_file))
88 | assert(rtn.return_code == 0)
89 |
90 | rtn = self.run_cmd("pm delete --name HelloWorld_app --type package",
91 | input_data="y\n")
92 | assert(rtn.return_code == 0)
93 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/pm/test_pm_export.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "pm export" utility"""
17 |
18 | from __future__ import absolute_import
19 | import os.path
20 |
21 | import dtf.testutils as testutils
22 | import dtf.core.utils as utils
23 |
24 |
25 | class PmExportTests(testutils.BasicIntegrationTest):
26 |
27 | """Wraper for integration tests"""
28 |
29 | def test_no_content(self):
30 |
31 | """Attempt to export nothing"""
32 |
33 | rtn = self.run_cmd("pm export test.zip")
34 | assert(rtn.return_code == 254)
35 |
36 | def test_existing_file(self):
37 |
38 | """Attempt to export to exisitng file"""
39 |
40 | utils.touch("test.zip")
41 |
42 | rtn = self.run_cmd("pm export test.zip")
43 |
44 | utils.delete_file("test.zip")
45 |
46 | assert(rtn.return_code == 255)
47 |
48 | def test_real_export(self):
49 |
50 | """Perform an export"""
51 |
52 | data_file = testutils.DataFile("integration_pm_valid_zip.zip")
53 |
54 | rtn = self.run_cmd("pm install --zip %s" % str(data_file))
55 | assert(rtn.return_code == 0)
56 |
57 | rtn = self.run_cmd("pm export test.zip")
58 | assert(rtn.return_code == 0)
59 | assert(os.path.isfile("test.zip"))
60 |
61 | utils.delete_file("test.zip")
62 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/pm/test_pm_list.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "pm list" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 | class PmListTests(testutils.BasicIntegrationTest):
22 |
23 | """Wraper for integration tests"""
24 |
25 | def test_no_args(self):
26 |
27 | """Running list with no args"""
28 |
29 | rtn = self.run_cmd("pm list")
30 | assert(rtn.return_code == 0)
31 |
32 | rtn = self.run_cmd("pm list -v")
33 | assert(rtn.return_code == 0)
34 |
35 |
36 | def test_quiet_verbose(self):
37 |
38 | """Try and fail to print verbose + quiet"""
39 |
40 | rtn = self.run_cmd("pm list -vq")
41 | assert(rtn.return_code == 255)
42 |
43 |
44 | def test_all_valid(self):
45 |
46 | """Print all types, with actual installed content"""
47 |
48 | data_file = testutils.DataFile("integration_pm_valid_zip.zip")
49 |
50 | rtn = self.run_cmd("pm install --zip %s" % str(data_file))
51 | assert(rtn.return_code == 0)
52 |
53 | rtn = self.run_cmd("pm list")
54 | assert(rtn.return_code == 0)
55 |
56 | rtn = self.run_cmd("pm list -v")
57 | assert(rtn.return_code == 0)
58 |
59 | rtn = self.run_cmd("pm list -q")
60 | assert(rtn.return_code == 0)
61 |
62 |
63 | def test_binaries(self):
64 |
65 | """List only binaries"""
66 |
67 | rtn = self.run_cmd("pm list binaries")
68 | assert(rtn.return_code == 0)
69 |
70 | rtn = self.run_cmd("pm list binaries -v")
71 | assert(rtn.return_code == 0)
72 |
73 | rtn = self.run_cmd("pm list binaries -q")
74 | assert(rtn.return_code == 0)
75 |
76 |
77 | def test_libraries(self):
78 |
79 | """List only libraries"""
80 |
81 | rtn = self.run_cmd("pm list libraries")
82 | assert(rtn.return_code == 0)
83 |
84 | rtn = self.run_cmd("pm list libraries -v")
85 | assert(rtn.return_code == 0)
86 |
87 | rtn = self.run_cmd("pm list libraries -q")
88 | assert(rtn.return_code == 0)
89 |
90 |
91 | def test_modules(self):
92 |
93 | """List only modules"""
94 |
95 | rtn = self.run_cmd("pm list modules")
96 | assert(rtn.return_code == 0)
97 |
98 | rtn = self.run_cmd("pm list modules -v")
99 | assert(rtn.return_code == 0)
100 |
101 | rtn = self.run_cmd("pm list modules -q")
102 | assert(rtn.return_code == 0)
103 |
104 |
105 | def test_packages(self):
106 |
107 | """List only packages"""
108 |
109 | rtn = self.run_cmd("pm list packages")
110 | assert(rtn.return_code == 0)
111 |
112 | rtn = self.run_cmd("pm list packages -v")
113 | assert(rtn.return_code == 0)
114 |
115 | rtn = self.run_cmd("pm list packages -q")
116 | assert(rtn.return_code == 0)
117 |
118 | def test_list_invalid(self):
119 |
120 | """List a invalid type"""
121 |
122 | rtn = self.run_cmd("pm list BAD")
123 | assert(rtn.return_code == 253)
124 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/pm/test_pm_purge.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "pm purge" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 | class PmPurgeTests(testutils.BasicIntegrationTest):
22 |
23 | """Wraper for integration tests"""
24 |
25 | def test_purge_cancel(self):
26 |
27 | """Run purge but cancel"""
28 |
29 | rtn = self.run_cmd("pm purge", input_data="n\n")
30 | assert(rtn.return_code == 0)
31 |
32 | def test_purge_go(self):
33 |
34 | """Run purge"""
35 |
36 | rtn = self.run_cmd("pm purge", input_data="y\n")
37 | assert(rtn.return_code == 0)
38 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/pm/test_pm_repo.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2017 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "pm repo" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 | class PmRepoTests(testutils.BasicIntegrationTest):
22 |
23 | """Wraper for integration tests"""
24 |
25 | def test_no_args(self):
26 |
27 | """Running repo with no args"""
28 |
29 | rtn = self.run_cmd("pm repo")
30 | assert(rtn.return_code == 0)
31 |
32 | def test_invalid_cmd(self):
33 |
34 | """Run repo with invalid cmd"""
35 |
36 | rtn = self.run_cmd("pm repo NOTHING")
37 | assert(rtn.return_code == 255)
38 |
39 | def test_repo_add_valid(self):
40 |
41 | """Try to readd a repo with same name"""
42 |
43 | rtn = self.run_cmd("pm repo add core-mods https://somethingsilly.com")
44 | assert(rtn.return_code == 0)
45 |
46 |
47 | def test_repo_add_wrong_args(self):
48 |
49 | """Run add with incorrect args"""
50 |
51 | rtn = self.run_cmd("pm repo add")
52 | assert(rtn.return_code == 255)
53 |
54 | def test_repo_add_invalid_url(self):
55 |
56 | """Try to add invalid repo URL"""
57 |
58 | rtn = self.run_cmd("pm repo add core-mods somethingsilly.com")
59 | assert(rtn.return_code == 254)
60 |
61 | def test_repo_add_already_exists(self):
62 |
63 | """Try to re-add a repo with same name"""
64 |
65 | rtn = self.run_cmd("pm repo add core-mods https://somethingsilly.com")
66 | assert(rtn.return_code == 0)
67 |
68 | rtn = self.run_cmd("pm repo add core-mods https://somethingsilly.com")
69 | assert(rtn.return_code == 253)
70 |
71 | def test_repo_remove_valid(self):
72 |
73 | """Add then remove a repo"""
74 |
75 | rtn = self.run_cmd("pm repo add core-mods https://somethingsilly.com")
76 | assert(rtn.return_code == 0)
77 |
78 | rtn = self.run_cmd("pm repo remove core-mods")
79 | assert(rtn.return_code == 0)
80 |
81 | def test_repo_remove_wrong_args(self):
82 |
83 | """Run remove with incorrect args"""
84 |
85 | rtn = self.run_cmd("pm repo remove")
86 | assert(rtn.return_code == 255)
87 |
88 | def test_repo_remove_nonexist(self):
89 |
90 | """Attempt to remove not exist repo"""
91 |
92 | rtn = self.run_cmd("pm repo remove silly")
93 | assert(rtn.return_code == 253)
94 |
95 | def test_repo_list_empty(self):
96 |
97 | """List no repos"""
98 |
99 | rtn = self.run_cmd("pm repo list")
100 | assert(rtn.return_code == 0)
101 |
102 | def test_repo_list_valid(self):
103 |
104 | """List no repos"""
105 |
106 | rtn = self.run_cmd("pm repo add mods-core https://silly.com")
107 | assert(rtn.return_code == 0)
108 |
109 | rtn = self.run_cmd("pm repo list")
110 | assert(rtn.return_code == 0)
111 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/prop/test_prop.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "prop" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_no_args():
23 |
24 | """Running with no args"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | rtn = testutils.dtf("prop")
29 |
30 | testutils.undeploy()
31 |
32 | assert(rtn.return_code == 0)
33 |
34 |
35 | def test_not_subcommand():
36 |
37 | """Call invalid subcommand"""
38 |
39 | testutils.deploy_config(testutils.get_default_config())
40 |
41 | rtn = testutils.dtf("prop NON_EXIST")
42 |
43 | testutils.undeploy()
44 |
45 | assert(rtn.return_code == 0)
46 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/prop/test_prop_del.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "prop del" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_no_args():
23 |
24 | """Running del with no args"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | rtn = testutils.dtf("prop del")
29 |
30 | testutils.undeploy()
31 |
32 | assert(rtn.return_code == 0)
33 |
34 |
35 | def test_del_valid_prop():
36 |
37 | """Delete a valid property"""
38 |
39 | config = testutils.get_default_config()
40 | config.set("Info", "magic", "AbraKadabra")
41 |
42 | testutils.deploy_config(config)
43 |
44 | rtn = testutils.dtf("prop del Info magic")
45 |
46 | testutils.undeploy()
47 |
48 | assert(rtn.return_code == 0)
49 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/prop/test_prop_dump.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "prop dump" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_no_args():
23 |
24 | """Running dump with no args"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | rtn = testutils.dtf("prop dump")
29 |
30 | testutils.undeploy()
31 |
32 | assert(rtn.return_code == 0)
33 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/prop/test_prop_get.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "prop get" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_no_args():
23 |
24 | """Running get with no args"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | rtn = testutils.dtf("prop get")
29 |
30 | testutils.undeploy()
31 |
32 | assert(rtn.return_code == 0)
33 |
34 |
35 | def test_get_valid_prop():
36 |
37 | """Get an existing property"""
38 |
39 | testutils.deploy_config(testutils.get_default_config())
40 |
41 | rtn = testutils.dtf("prop get Info sdk")
42 |
43 | testutils.undeploy()
44 |
45 | assert(rtn.return_code == 0)
46 |
47 |
48 | def test_get_invalid_prop():
49 |
50 | """Get a non-existing property"""
51 |
52 | testutils.deploy_config(testutils.get_default_config())
53 |
54 | rtn = testutils.dtf("prop get Info magic")
55 |
56 | testutils.undeploy()
57 |
58 | assert(rtn.return_code == 255)
59 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/prop/test_prop_set.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "prop set" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_no_args():
23 |
24 | """Running set with no args"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | rtn = testutils.dtf("prop set")
29 |
30 | testutils.undeploy()
31 |
32 | assert(rtn.return_code == 0)
33 |
34 |
35 | def test_set_a_prop():
36 |
37 | """Set an arbitrary property"""
38 |
39 | testutils.deploy_config(testutils.get_default_config())
40 |
41 | rtn = testutils.dtf("prop set Info magic AbraKadabra")
42 |
43 | testutils.undeploy()
44 |
45 | assert(rtn.return_code == 0)
46 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/prop/test_prop_test.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the "prop test" utility"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_no_args():
23 |
24 | """Running test with no args"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | rtn = testutils.dtf("prop test")
29 |
30 | testutils.undeploy()
31 |
32 | assert(rtn.return_code == 0)
33 |
34 |
35 | def test_test_valid_prop():
36 |
37 | """Test a valid property"""
38 |
39 | testutils.deploy_config(testutils.get_default_config())
40 |
41 | rtn = testutils.dtf("prop test Info sdk")
42 |
43 | testutils.undeploy()
44 |
45 | assert(rtn.return_code == 1)
46 |
47 | def test_test_invalid_prop():
48 |
49 | """Test an invalid property"""
50 |
51 | testutils.deploy_config(testutils.get_default_config())
52 |
53 | rtn = testutils.dtf("prop test Info magic")
54 |
55 | testutils.undeploy()
56 |
57 | assert(rtn.return_code == 0)
58 |
59 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/reset/test_reset.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for "reset" command"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_reset_bail():
23 |
24 | """Attempt a reset but decline"""
25 |
26 | testutils.deploy_config(testutils.get_default_config())
27 |
28 | rtn = testutils.dtf("reset", input_data="n\n")
29 |
30 | testutils.undeploy()
31 |
32 | assert(rtn.return_code == 255)
33 |
34 |
35 | def test_reset_real():
36 |
37 | """Perform a reset"""
38 |
39 | testutils.deploy_config(testutils.get_default_config())
40 |
41 | rtn = testutils.dtf("reset", input_data="y\n")
42 |
43 | testutils.undeploy()
44 |
45 | assert(rtn.return_code == 0)
46 |
--------------------------------------------------------------------------------
/python-dtf/tests/integration/test_dtf.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Integration tests for the general launcher"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.testutils as testutils
20 |
21 |
22 | def test_dtf():
23 |
24 | """Just attempt to run dtf"""
25 |
26 | rtn = testutils.dtf("")
27 | assert(rtn.return_code == 255)
28 |
29 |
30 | def test_version():
31 |
32 | """Attempt to obtain version"""
33 |
34 | rtn = testutils.dtf("--version")
35 | assert(rtn.return_code == 0)
36 |
37 | rtn = testutils.dtf("-v")
38 | assert(rtn.return_code == 0)
39 |
40 | rtn = testutils.dtf("version")
41 | assert(rtn.return_code == 0)
42 |
43 |
44 | def test_help():
45 |
46 | """Attempt to print help/useage"""
47 |
48 | rtn = testutils.dtf("--help")
49 | assert(rtn.return_code == 0)
50 |
51 | rtn = testutils.dtf("-h")
52 | assert(rtn.return_code == 0)
53 |
54 | rtn = testutils.dtf("help")
55 | assert(rtn.return_code == 0)
56 |
57 | def test_non_project():
58 |
59 | """Attempt to run a built-in without a .dtfini"""
60 |
61 | rtn = testutils.dtf("archive")
62 | assert(rtn.return_code == 253)
63 |
64 |
65 | def test_python_precheck_sdk_missing():
66 |
67 | """Attempt to run python module with missing SDK"""
68 |
69 | testutils.deploy_config_raw("")
70 |
71 | rtn = testutils.dtf("archive")
72 |
73 | testutils.undeploy()
74 |
75 | assert(rtn.return_code == 248)
76 |
77 |
78 | def test_python_load_imp_exception():
79 |
80 | """Attempt to run builtin and fail to parse load_imp"""
81 |
82 | testutils.deploy_config_raw("")
83 |
84 | rtn = testutils.dtf("status")
85 |
86 | testutils.undeploy()
87 |
88 | assert(rtn.return_code == 247)
89 |
--------------------------------------------------------------------------------
/python-dtf/tests/unit/test_colors.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """pytest for using dtf coloring"""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import print_function
20 | import dtf.colors as colors
21 | import dtf.testutils as testutils
22 |
23 | TAG = 'test_colors'
24 |
25 |
26 | def test_error():
27 |
28 | """Log an error message"""
29 |
30 | print("This message is an %s" % colors.error("error."))
31 |
32 |
33 | def test_warning():
34 |
35 | """Log an warning message"""
36 |
37 | print("This message is a %s" % colors.warning("warning."))
38 |
39 |
40 | def test_info():
41 |
42 | """Log an info message"""
43 |
44 | print("This message is a %s" % colors.info("info message."))
45 |
46 |
47 | def test_verbose():
48 |
49 | """Log an verbose message"""
50 |
51 | print("This message is a %s" % colors.verbose("verbose message."))
52 |
53 |
54 | def test_debug():
55 |
56 | """Log an debug message"""
57 |
58 | print("This message is a %s" % colors.debug("debug message."))
59 |
60 | def test_bold():
61 |
62 | """Log a bolded message"""
63 |
64 | print("This message is %s" % colors.bold("important!"))
65 |
--------------------------------------------------------------------------------
/python-dtf/tests/unit/test_included.py:
--------------------------------------------------------------------------------
1 | # Android Device Testing Framework ("dtf")
2 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | """Unit tests for testing included wrappers"""
17 |
18 | from __future__ import absolute_import
19 | import dtf.included as included
20 | import dtf.core.utils as utils
21 | import dtf.testutils as testutils
22 |
23 |
24 | def test_aapt():
25 |
26 | """Run test aapt command"""
27 | data_file = testutils.DataFile("hello-world.apk")
28 |
29 | stdout, stderr, rtn = included.aapt("d badging %s" % str(data_file))
30 |
31 | assert rtn == 0
32 |
33 | def test_apktool():
34 |
35 | """Run test apktool command"""
36 |
37 | data_file = testutils.DataFile("hello-world.apk")
38 |
39 | stdout, stderr, rtn = included.apktool("d %s" % str(data_file))
40 |
41 | utils.delete_tree("hello-world")
42 |
43 | assert rtn == 0
44 |
45 | def test_smali():
46 |
47 | """Run test smali/baksmali command"""
48 |
49 | data_file = testutils.DataFile("hello-world.apk")
50 |
51 | stdout, stderr, rtn_bak = included.baksmali("-o out %s" % str(data_file))
52 | stdout, stderr, rtn_smali = included.smali("-o classes.dex out")
53 |
54 | utils.delete_tree("out")
55 | utils.delete_file("classes.dex")
56 |
57 | assert rtn_bak == 0
58 | assert rtn_smali == 0
59 |
60 |
61 | def test_axmlprinter2():
62 |
63 | """Run test axmlprinter2 command"""
64 |
65 | data_file = testutils.DataFile("valid_android_manifest.xml")
66 | out_file = "out.xml"
67 |
68 | rtn = included.axmlprinter2(str(data_file), out_file)
69 |
70 | utils.delete_file(out_file)
71 |
72 | assert rtn == 0
73 |
--------------------------------------------------------------------------------
/release/android-dtf_all.deb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/android-dtf/dtf/a761ace77cea051bfb88d56df65ae6b83f664480/release/android-dtf_all.deb
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | colored==1.3.5
2 | cov-core==1.15.0
3 | coverage==4.2
4 | flake8==3.5.0
5 | lxml==4.1.0
6 | pylint==1.7.4
7 | py==1.4.34
8 | pytest==3.2.3
9 | pytest-runner==3.0
10 | wheel==0.29.0
11 | semantic_version==2.6.0
12 | requests==2.20.0
13 | configparser==3.5.0
14 |
--------------------------------------------------------------------------------
/uninstall_1_3.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Android Device Testing Framework ("dtf")
3 | # Copyright 2013-2016 Jake Valletta (@jake_valletta)
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Uninstaller script to remove dtf 1.3.0
18 | # Usage: sudo ./uninstall_1_3.sh
19 |
20 | # Delete the bash completion
21 | echo "Removing bash completion..."
22 | rm /etc/bash_completion.d/dtf_bash_completion.sh
23 |
24 |
25 | echo "Removing launcher..."
26 | # Delete the launcher
27 | rm /usr/local/bin/dtf
28 |
29 |
30 | echo "Removing Python library..."
31 | # Delete the library
32 | sudo pip uninstall dtf
33 | rm -rf /usr/local/lib/python2.7/dist-packages/dtf
34 |
35 | echo "Uninstall complete!"
36 |
--------------------------------------------------------------------------------
/wait_for_emulator:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Waits for emulator to completely boot to lock screen
4 | # Used to run tests on Travis CI (#137)
5 | # Originally written by Ralf Kistner , but placed in the public domain
6 | # Recommended by Travis docs - http://docs.travis-ci.com/user/languages/android/#How-to-Create-and-Start-an-Emulator
7 | # Source (under Apache 2.0) - https://github.com/andrewhr/rxjava-android-example/blob/master/ci/wait_for_emulator
8 |
9 | set +e
10 |
11 | bootanim=""
12 | failcounter=0
13 | timeout_in_sec=360
14 |
15 | echo "Using adb: $(which adb)"
16 |
17 | until [[ "$bootanim" =~ "stopped" ]]; do
18 | bootanim=`adb -e shell getprop init.svc.bootanim 2>&1 &`
19 | if [[ "$bootanim" =~ "device not found" || "$bootanim" =~ "device offline"
20 | || "$bootanim" =~ "running" ]]; then
21 | let "failcounter += 1"
22 | echo "Waiting for emulator to start"
23 | if [[ $failcounter -gt timeout_in_sec ]]; then
24 | echo "Timeout ($timeout_in_sec seconds) reached; failed to start emulator"
25 | exit 1
26 | fi
27 | fi
28 | sleep 1
29 | done
30 |
31 | echo "Emulator is ready"
32 |
--------------------------------------------------------------------------------