Python unit tests #13
19 changed files with 546 additions and 41 deletions
|
@ -36,7 +36,7 @@ version = 0.1
|
|||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = openssl, sqlite3, hostpython2, pycrypto==2.6.1, android, pyjnius, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pycrypto==2.6.1, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, txrequests==0.9.5, seccure==0.3.1.3, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbryum.git#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbry
|
||||
requirements = openssl, sqlite3, hostpython2, pycrypto==2.6.1, android, pyjnius, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pycrypto==2.6.1, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, txrequests==0.9.5, seccure==0.3.1.3, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, git+https://github.com/lbryio/lbryschema.git@v0.0.12rc1#egg=lbryschema, git+https://github.com/lbryio/lbryum.git@v3.1.9rc2#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbrynet, asn1crypto, cryptography==2.0.3, funcsigs, mock, pbr, unqlite
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
|
|
@ -36,7 +36,7 @@ version = 0.1
|
|||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = openssl, sqlite3, hostpython2, pycrypto==2.6.1, android, pyjnius, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pycrypto==2.6.1, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, txrequests==0.9.5, seccure==0.3.1.3, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbryum.git#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbry
|
||||
requirements = openssl, sqlite3, hostpython2, pycrypto==2.6.1, android, pyjnius, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pycrypto==2.6.1, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, txrequests==0.9.5, seccure==0.3.1.3, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, git+https://github.com/lbryio/lbryschema.git@v0.0.12rc1#egg=lbryschema, git+https://github.com/lbryio/lbryum.git@v3.1.9rc2#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbrynet, asn1crypto, cryptography==2.0.3, funcsigs, mock, pbr, unqlite
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*.egg-info
|
||||
|
||||
# unit test
|
||||
unittest/*
|
||||
#unittest/*
|
||||
|
||||
# python config
|
||||
config/makesetup
|
||||
|
|
|
@ -118,6 +118,8 @@
|
|||
{% endfor %}
|
||||
<service android:name="{{ args.package }}.LbrynetService"
|
||||
android:process=":service_lbrynet" />
|
||||
<service android:name="{{ args.package }}.LbrynetTestRunnerService"
|
||||
android:process=":service_lbrynet_testrunner" />
|
||||
|
||||
{% if args.billing_pubkey %}
|
||||
<service android:name="org.kivy.android.billing.BillingReceiver"
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_start_stop"
|
||||
android:layout_width="120dp"
|
||||
|
@ -42,4 +41,47 @@
|
|||
android:layout_marginTop="12dp"
|
||||
android:text="@string/start"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="24dp"
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3">
|
||||
<TextView
|
||||
android:layout_weight="2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/unit_tests"
|
||||
/>
|
||||
<Button
|
||||
android:id="@+id/btn_run_tests"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:text="@string/run_tests"/>
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_marginTop="12dp"
|
||||
android:padding="6dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/test_runner_output"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
/>
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -10,4 +10,7 @@
|
|||
<string name="stopped">Stopped</string>
|
||||
<string name="start">START</string>
|
||||
<string name="stop">STOP</string>
|
||||
|
||||
<string name="unit_tests">Unit tests</string>
|
||||
<string name="run_tests">RUN</string>
|
||||
</resources>
|
||||
|
|
36
recipes/cffi/__init__.py
Normal file
36
recipes/cffi/__init__.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from pythonforandroid.recipe import CompiledComponentsPythonRecipe, Recipe
|
||||
from os.path import join
|
||||
|
||||
|
||||
class CffiRecipe(CompiledComponentsPythonRecipe):
|
||||
name = 'cffi'
|
||||
version = '1.11.0'
|
||||
#url = 'https://pypi.python.org/packages/source/c/cffi/cffi-{version}.tar.gz'
|
||||
url = 'https://pypi.python.org/packages/4e/32/4070bdf32812c89eb635c80880a5caa2e0189aa7999994c265577e5154f3/cffi-{version}.tar.gz'
|
||||
|
||||
depends = [('python2', 'python3crystax'), 'setuptools', 'pycparser', 'libffi']
|
||||
|
||||
patches = ['disable-pkg-config.patch']
|
||||
|
||||
# call_hostpython_via_targetpython = False
|
||||
install_in_hostpython = True
|
||||
|
||||
def get_recipe_env(self, arch=None):
|
||||
env = super(CffiRecipe, self).get_recipe_env(arch)
|
||||
libffi = self.get_recipe('libffi', self.ctx)
|
||||
includes = libffi.get_include_dirs(arch)
|
||||
env['CFLAGS'] = ' -I'.join([env.get('CFLAGS', '')] + includes)
|
||||
env['LDFLAGS'] = (env.get('CFLAGS', '') + ' -L' +
|
||||
self.ctx.get_libs_dir(arch.arch))
|
||||
env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
|
||||
env['PYTHONPATH'] = ':'.join([self.ctx.get_site_packages_dir(), env['BUILDLIB_PATH']])
|
||||
|
||||
target_python = Recipe.get_recipe('python2', self.ctx).get_build_dir(arch.arch)
|
||||
env['PYTHON_ROOT'] = join(target_python, 'python-install')
|
||||
env['CFLAGS'] += ' -I' + env['PYTHON_ROOT'] + '/include/python2.7'
|
||||
env['LDFLAGS'] += ' -L' + env['PYTHON_ROOT'] + '/lib' + ' -lpython2.7'
|
||||
|
||||
return env
|
||||
|
||||
|
||||
recipe = CffiRecipe()
|
29
recipes/cffi/disable-pkg-config.patch
Normal file
29
recipes/cffi/disable-pkg-config.patch
Normal file
|
@ -0,0 +1,29 @@
|
|||
diff -Naur cffi-1.4.2/setup.py b/setup.py
|
||||
--- cffi-1.4.2/setup.py 2015-12-21 12:09:47.000000000 -0600
|
||||
+++ b/setup.py 2015-12-23 10:20:40.590622524 -0600
|
||||
@@ -5,8 +5,7 @@
|
||||
|
||||
sources = ['c/_cffi_backend.c']
|
||||
libraries = ['ffi']
|
||||
-include_dirs = ['/usr/include/ffi',
|
||||
- '/usr/include/libffi'] # may be changed by pkg-config
|
||||
+include_dirs = []
|
||||
define_macros = []
|
||||
library_dirs = []
|
||||
extra_compile_args = []
|
||||
@@ -67,14 +66,7 @@
|
||||
sys.stderr.write("The above error message can be safely ignored\n")
|
||||
|
||||
def use_pkg_config():
|
||||
- if sys.platform == 'darwin' and os.path.exists('/usr/local/bin/brew'):
|
||||
- use_homebrew_for_libffi()
|
||||
-
|
||||
- _ask_pkg_config(include_dirs, '--cflags-only-I', '-I', sysroot=True)
|
||||
- _ask_pkg_config(extra_compile_args, '--cflags-only-other')
|
||||
- _ask_pkg_config(library_dirs, '--libs-only-L', '-L', sysroot=True)
|
||||
- _ask_pkg_config(extra_link_args, '--libs-only-other')
|
||||
- _ask_pkg_config(libraries, '--libs-only-l', '-l')
|
||||
+ pass
|
||||
|
||||
def use_homebrew_for_libffi():
|
||||
# We can build by setting:
|
30
recipes/cryptography/__init__.py
Normal file
30
recipes/cryptography/__init__.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from pythonforandroid.recipe import CompiledComponentsPythonRecipe, Recipe
|
||||
from os.path import dirname, join
|
||||
|
||||
class CryptographyRecipe(CompiledComponentsPythonRecipe):
|
||||
name = 'cryptography'
|
||||
version = '2.0.3'
|
||||
url = 'https://github.com/pyca/cryptography/archive/{version}.tar.gz'
|
||||
depends = [('python2', 'python3crystax'), 'openssl', 'idna', 'pyasn1', 'six', 'setuptools', 'enum34', 'ipaddress', 'cffi']
|
||||
call_hostpython_via_targetpython = False
|
||||
|
||||
def get_recipe_env(self, arch):
|
||||
env = super(CryptographyRecipe, self).get_recipe_env(arch)
|
||||
r = self.get_recipe('openssl', self.ctx)
|
||||
openssl_dir = r.get_build_dir(arch.arch)
|
||||
target_python = Recipe.get_recipe('python2', self.ctx).get_build_dir(arch.arch)
|
||||
env['PYTHON_ROOT'] = self.ctx.get_python_install_dir()
|
||||
env['CFLAGS'] += ' -I' + env['PYTHON_ROOT'] + '/include/python2.7' + \
|
||||
' -I' + join(openssl_dir, 'include') + \
|
||||
' -I' + join(target_python, 'Modules/_ctypes/libffi_arm_wince')
|
||||
# Set linker to use the correct gcc
|
||||
env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
|
||||
env['LDFLAGS'] += ' -L' + env['PYTHON_ROOT'] + '/lib' + \
|
||||
' -L' + openssl_dir + \
|
||||
' -lpython2.7' + \
|
||||
' -lssl' + r.version + \
|
||||
' -lcrypto' + r.version
|
||||
|
||||
return env
|
||||
|
||||
recipe = CryptographyRecipe()
|
14
recipes/ipaddress/__init__.py
Normal file
14
recipes/ipaddress/__init__.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from pythonforandroid.recipe import PythonRecipe
|
||||
|
||||
|
||||
class IpaddressRecipe(PythonRecipe):
|
||||
name = 'ipaddress'
|
||||
version = '1.0.16'
|
||||
url = 'https://pypi.python.org/packages/source/i/ipaddress/ipaddress-{version}.tar.gz'
|
||||
|
||||
depends = ['python2']
|
||||
|
||||
call_hostpython_via_targetpython = False
|
||||
|
||||
|
||||
recipe = IpaddressRecipe()
|
11
recipes/pyasn1/__init__.py
Normal file
11
recipes/pyasn1/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
from pythonforandroid.toolchain import PythonRecipe
|
||||
|
||||
|
||||
class PyASN1Recipe(PythonRecipe):
|
||||
version = '0.1.8'
|
||||
url = 'https://pypi.python.org/packages/source/p/pyasn1/pyasn1-{version}.tar.gz'
|
||||
depends = ['python2']
|
||||
call_hostpython_via_targetpython = False
|
||||
|
||||
recipe = PyASN1Recipe()
|
32
recipes/unqlite/__init__.py
Normal file
32
recipes/unqlite/__init__.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import glob
|
||||
from pythonforandroid.toolchain import (
|
||||
CythonRecipe,
|
||||
Recipe,
|
||||
current_directory,
|
||||
info,
|
||||
shprint,
|
||||
)
|
||||
from os.path import join
|
||||
import sh
|
||||
|
||||
|
||||
class UnqliteRecipe(CythonRecipe):
|
||||
version = '0.6.0'
|
||||
url = 'https://pypi.python.org/packages/cb/4e/e1f64a3d0f6462167805940b4c72f47bafc1129e363fc4c0f79a1cdc5dd1/unqlite-{version}.tar.gz'
|
||||
depends = ['python2', 'setuptools']
|
||||
call_hostpython_via_targetpython = False
|
||||
|
||||
patches = ['setup.patch']
|
||||
|
||||
def get_recipe_env(self, arch):
|
||||
env = super(UnqliteRecipe, self).get_recipe_env(arch)
|
||||
|
||||
target_python = Recipe.get_recipe('python2', self.ctx).get_build_dir(arch.arch)
|
||||
env['PYTHON_ROOT'] = join(target_python, 'python-install')
|
||||
env['CFLAGS'] += ' -I' + env['PYTHON_ROOT'] + '/include/python2.7'
|
||||
env['LDFLAGS'] += ' -L' + env['PYTHON_ROOT'] + '/lib' + ' -lpython2.7'
|
||||
|
||||
return env
|
||||
|
||||
|
||||
recipe = UnqliteRecipe()
|
26
recipes/unqlite/setup.patch
Normal file
26
recipes/unqlite/setup.patch
Normal file
|
@ -0,0 +1,26 @@
|
|||
--- a/setup.py 2016-08-22 19:45:52.000000000 +0100
|
||||
+++ b/setup.py 2017-09-16 01:35:36.675202502 +0100
|
||||
@@ -1,11 +1,7 @@
|
||||
import glob
|
||||
-from distutils.core import setup, Extension
|
||||
-
|
||||
-try:
|
||||
- from Cython.Build import cythonize
|
||||
-except ImportError:
|
||||
- raise RuntimeError('Cython must be installed to build unqlite-python.')
|
||||
-
|
||||
+from setuptools import setup
|
||||
+from setuptools.extension import Extension
|
||||
+from setuptools.command.build_ext import build_ext
|
||||
|
||||
python_source = 'unqlite.pyx'
|
||||
library_source = glob.glob('src/*.c')
|
||||
@@ -45,5 +41,7 @@
|
||||
'Topic :: Database :: Database Engines/Servers',
|
||||
'Topic :: Software Development :: Embedded Systems',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules'],
|
||||
- ext_modules=cythonize(unqlite_extension)
|
||||
+ cmdclass = {'build_ext': build_ext},
|
||||
+ ext_modules=[unqlite_extension]
|
||||
)
|
||||
+
|
|
@ -1,19 +1,20 @@
|
|||
package io.lbry.lbrynet;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.File;
|
||||
import android.os.Bundle;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.kivy.android.PythonService;
|
||||
import org.kivy.android.PythonActivity;
|
||||
import org.renpy.android.AssetExtract;
|
||||
import org.renpy.android.ResourceManager;
|
||||
|
||||
|
@ -51,7 +52,8 @@ public class LbrynetService extends PythonService {
|
|||
unpackData("private", app_root_file);
|
||||
|
||||
if (intent == null) {
|
||||
intent = buildIntent(getApplicationContext(), "");
|
||||
intent = ServiceHelper.buildIntent(
|
||||
getApplicationContext(), "", LbrynetService.class, "lbrynetservice");
|
||||
}
|
||||
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
|
@ -134,28 +136,4 @@ public class LbrynetService extends PythonService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Intent buildIntent(Context ctx, String pythonServiceArgument) {
|
||||
Intent intent = new Intent(ctx, LbrynetService.class);
|
||||
String argument = ctx.getFilesDir().getAbsolutePath() + "/app";
|
||||
intent.putExtra("androidPrivate", ctx.getFilesDir().getAbsolutePath());
|
||||
intent.putExtra("androidArgument", argument);
|
||||
intent.putExtra("serviceEntrypoint", "./lbrynetservice.py");
|
||||
intent.putExtra("pythonName", "lbrynetservice");
|
||||
intent.putExtra("pythonHome", argument);
|
||||
intent.putExtra("pythonPath", argument + ":" + argument + "/lib");
|
||||
intent.putExtra("pythonServiceArgument", pythonServiceArgument);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static void start(Context ctx, String pythonServiceArgument) {
|
||||
Intent intent = buildIntent(ctx, pythonServiceArgument);
|
||||
ctx.startService(intent);
|
||||
}
|
||||
|
||||
public static void stop(Context ctx) {
|
||||
Intent intent = new Intent(ctx, LbrynetService.class);
|
||||
ctx.stopService(intent);
|
||||
}
|
||||
}
|
||||
|
|
126
src/main/java/io/lbry/lbrynet/LbrynetTestRunnerService.java
Normal file
126
src/main/java/io/lbry/lbrynet/LbrynetTestRunnerService.java
Normal file
|
@ -0,0 +1,126 @@
|
|||
package io.lbry.lbrynet;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.kivy.android.PythonService;
|
||||
import org.renpy.android.AssetExtract;
|
||||
import org.renpy.android.ResourceManager;
|
||||
|
||||
public class LbrynetTestRunnerService extends PythonService {
|
||||
|
||||
public static String TAG = "LbrynetTestRunnerService";
|
||||
|
||||
public static LbrynetTestRunnerService serviceInstance;
|
||||
|
||||
@Override
|
||||
public boolean canDisplayNotification() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// Extract files
|
||||
File app_root_file = new File(getAppRoot());
|
||||
unpackData("private", app_root_file);
|
||||
|
||||
if (intent == null) {
|
||||
intent = ServiceHelper.buildIntent(
|
||||
getApplicationContext(), "", LbrynetTestRunnerService.class, "testrunnerservice");
|
||||
}
|
||||
|
||||
serviceInstance = this;
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
serviceInstance = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public void broadcastTestRunnerOutput(String output) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ServiceControlActivity.TEST_RUNNER_OUTPUT);
|
||||
intent.putExtra("output", output);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
public void unpackData(final String resource, File target) {
|
||||
Log.v(TAG, "UNPACKING!!! " + resource + " " + target.getName());
|
||||
|
||||
// The version of data in memory and on disk.
|
||||
ResourceManager resourceManager = new ResourceManager(getApplicationContext());
|
||||
String data_version = resourceManager.getString(resource + "_version");
|
||||
String disk_version = null;
|
||||
|
||||
Log.v(TAG, "Data version is " + data_version);
|
||||
|
||||
// If no version, no unpacking is necessary.
|
||||
if (data_version == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the current disk version, if any.
|
||||
String filesDir = target.getAbsolutePath();
|
||||
String disk_version_fn = filesDir + "/" + resource + ".version";
|
||||
|
||||
try {
|
||||
byte buf[] = new byte[64];
|
||||
InputStream is = new FileInputStream(disk_version_fn);
|
||||
int len = is.read(buf);
|
||||
disk_version = new String(buf, 0, len);
|
||||
is.close();
|
||||
} catch (Exception e) {
|
||||
disk_version = "";
|
||||
}
|
||||
|
||||
// If the disk data is out of date, extract it and write the
|
||||
// version file.
|
||||
// if (! data_version.equals(disk_version)) {
|
||||
if (! data_version.equals(disk_version)) {
|
||||
Log.v(TAG, "Extracting " + resource + " assets.");
|
||||
|
||||
recursiveDelete(target);
|
||||
target.mkdirs();
|
||||
|
||||
AssetExtract ae = new AssetExtract(getApplicationContext());
|
||||
if (!ae.extractTar(resource + ".mp3", target.getAbsolutePath())) {
|
||||
//toastError("Could not extract " + resource + " data.");
|
||||
Log.e(TAG, "Could not extract " + resource + " data.");
|
||||
}
|
||||
|
||||
try {
|
||||
// Write .nomedia.
|
||||
new File(target, ".nomedia").createNewFile();
|
||||
|
||||
// Write version file.
|
||||
FileOutputStream os = new FileOutputStream(disk_version_fn);
|
||||
os.write(data_version.getBytes());
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
Log.w("python", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void recursiveDelete(File f) {
|
||||
if (f.isDirectory()) {
|
||||
for (File r : f.listFiles()) {
|
||||
recursiveDelete(r);
|
||||
}
|
||||
}
|
||||
f.delete();
|
||||
}
|
||||
|
||||
public String getAppRoot() {
|
||||
String app_root = getApplicationContext().getFilesDir().getAbsolutePath() + "/app";
|
||||
return app_root;
|
||||
}
|
||||
}
|
|
@ -1,18 +1,34 @@
|
|||
package io.lbry.lbrynet;
|
||||
|
||||
import org.kivy.android.PythonActivity;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
//import android.support.v7.app.AppCompatActivity;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class ServiceControlActivity extends Activity {
|
||||
|
||||
public static ServiceControlActivity activityInstance;
|
||||
|
||||
private IntentFilter intentFilter;
|
||||
|
||||
public static String TEST_RUNNER_OUTPUT = "io.lbry.lbrynet.TEST_RUNNER_OUTPUT";
|
||||
|
||||
/**
|
||||
* Flag which indicates whether or not the service is running. Will be updated in the
|
||||
* onResume method.
|
||||
|
@ -24,6 +40,10 @@ public class ServiceControlActivity extends Activity {
|
|||
*/
|
||||
private Button startStopButton;
|
||||
|
||||
private Button runTestsButton;
|
||||
|
||||
private TextView testRunnerOutput;
|
||||
|
||||
/**
|
||||
* Service status text.
|
||||
*/
|
||||
|
@ -33,32 +53,69 @@ public class ServiceControlActivity extends Activity {
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_service_control);
|
||||
intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(TEST_RUNNER_OUTPUT);
|
||||
|
||||
startStopButton = (Button) findViewById(R.id.btn_start_stop);
|
||||
runTestsButton = (Button) findViewById(R.id.btn_run_tests);
|
||||
serviceStatusText = (TextView) findViewById(R.id.text_service_status);
|
||||
testRunnerOutput = (TextView) findViewById(R.id.test_runner_output);
|
||||
|
||||
startStopButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (serviceRunning) {
|
||||
LbrynetService.stop(ServiceControlActivity.this);
|
||||
ServiceHelper.stop(ServiceControlActivity.this, LbrynetService.class);
|
||||
} else {
|
||||
LbrynetService.start(ServiceControlActivity.this, "");
|
||||
ServiceHelper.start(ServiceControlActivity.this, "", LbrynetService.class, "lbrynetservice");
|
||||
}
|
||||
|
||||
serviceRunning = isServiceRunning(LbrynetService.class);
|
||||
updateServiceStatus();
|
||||
}
|
||||
});
|
||||
|
||||
runTestsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
boolean testsRunning = isServiceRunning(LbrynetTestRunnerService.class);
|
||||
if (!testsRunning) {
|
||||
ServiceHelper.start(
|
||||
ServiceControlActivity.this, "", LbrynetTestRunnerService.class, "testrunnerservice");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
registerReceiver(testRunnerOutputReceiver, intentFilter);
|
||||
|
||||
activityInstance = this;
|
||||
serviceRunning = isServiceRunning(LbrynetService.class);
|
||||
updateServiceStatus();
|
||||
}
|
||||
|
||||
private BroadcastReceiver testRunnerOutputReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (TEST_RUNNER_OUTPUT.equals(intent.getAction())) {
|
||||
String output = intent.getStringExtra("output");
|
||||
updateTestRunnerOutput(output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
unregisterReceiver(testRunnerOutputReceiver);
|
||||
// set the activity instance to null on pause in order to prevent NullPointerException
|
||||
// if the activity shuts down prematurely, for example
|
||||
activityInstance = null;
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
public void updateServiceStatus() {
|
||||
new Handler().post(new Runnable() {
|
||||
@Override
|
||||
|
@ -76,6 +133,10 @@ public class ServiceControlActivity extends Activity {
|
|||
});
|
||||
}
|
||||
|
||||
public void updateTestRunnerOutput(String output) {
|
||||
testRunnerOutput.setText(formatTestRunnerOutput(output));
|
||||
}
|
||||
|
||||
private boolean isServiceRunning(Class<?> serviceClass) {
|
||||
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
for (ActivityManager.RunningServiceInfo serviceInfo : manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
|
@ -86,4 +147,12 @@ public class ServiceControlActivity extends Activity {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Spanned formatTestRunnerOutput(String output) {
|
||||
output = output.replace("[OK]", "<font color=\"#008000\">[OK]</font>");
|
||||
output = output.replace("[ERROR]", "<font color=\"#ff0000\">[ERROR]</font>");
|
||||
output = output.replace("[FAILURE]", "<font color=\"#cc0000\">[FAILURE]</font>");
|
||||
|
||||
return Html.fromHtml(output);
|
||||
}
|
||||
}
|
||||
|
|
30
src/main/java/io/lbry/lbrynet/ServiceHelper.java
Normal file
30
src/main/java/io/lbry/lbrynet/ServiceHelper.java
Normal file
|
@ -0,0 +1,30 @@
|
|||
package io.lbry.lbrynet;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
|
||||
public class ServiceHelper {
|
||||
public static Intent buildIntent(Context ctx, String pythonServiceArgument, Class serviceClass, String pythonName) {
|
||||
Intent intent = new Intent(ctx, serviceClass);
|
||||
String argument = ctx.getFilesDir().getAbsolutePath() + "/app";
|
||||
intent.putExtra("androidPrivate", ctx.getFilesDir().getAbsolutePath());
|
||||
intent.putExtra("androidArgument", argument);
|
||||
intent.putExtra("serviceEntrypoint", "./" + pythonName + ".py");
|
||||
intent.putExtra("pythonName", pythonName);
|
||||
intent.putExtra("pythonHome", argument);
|
||||
intent.putExtra("pythonPath", argument + ":" + argument + "/lib");
|
||||
intent.putExtra("pythonServiceArgument", pythonServiceArgument);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static void start(Context ctx, String pythonServiceArgument, Class serviceClass, String pythonName) {
|
||||
Intent intent = buildIntent(ctx, pythonServiceArgument, serviceClass, pythonName);
|
||||
ctx.startService(intent);
|
||||
}
|
||||
|
||||
public static void stop(Context ctx, Class serviceClass) {
|
||||
Intent intent = new Intent(ctx, serviceClass);
|
||||
ctx.stopService(intent);
|
||||
}
|
||||
}
|
|
@ -54,7 +54,8 @@ lbrynet.daemon.auth.util.save_api_keys = save_api_keys
|
|||
lbrynet.daemon.auth.util.initialize_api_key_file = initialize_api_key_file
|
||||
|
||||
import logging.handlers
|
||||
|
||||
if __name__ == '__main__':
|
||||
ServiceApp().run()
|
||||
from lbrynet.core import log_support
|
||||
from twisted.internet import defer, reactor
|
||||
from jsonrpc.proxy import JSONRPCProxy
|
||||
|
|
76
src/main/python/testrunnerservice.py
Normal file
76
src/main/python/testrunnerservice.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
import sys
|
||||
import StringIO
|
||||
|
||||
from twisted.trial.runner import (
|
||||
TestLoader,
|
||||
TrialRunner
|
||||
)
|
||||
from twisted.trial.reporter import TreeReporter
|
||||
from twisted.plugin import getPlugins, IPlugin
|
||||
from jnius import autoclass
|
||||
import lbrynet.tests
|
||||
from os import listdir
|
||||
|
||||
str_stream = StringIO.StringIO()
|
||||
|
||||
serviceClass = autoclass('io.lbry.lbrynet.LbrynetTestRunnerService')
|
||||
|
||||
def update_output_in_activity(str):
|
||||
service = serviceClass.serviceInstance
|
||||
if service is not None:
|
||||
service.broadcastTestRunnerOutput(str)
|
||||
|
||||
class AndroidTestReporter(TreeReporter):
|
||||
def addSuccess(self, test):
|
||||
super(TreeReporter, self).addSuccess(test)
|
||||
self.endLine('[OK]', self.SUCCESS)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def addError(self, *args):
|
||||
super(TreeReporter, self).addError(*args)
|
||||
self.endLine('[ERROR]', self.ERROR)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def addFailure(self, *args):
|
||||
super(TreeReporter, self).addFailure(*args)
|
||||
self.endLine('[FAIL]', self.FAILURE)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def addSkip(self, *args):
|
||||
super(TreeReporter, self).addSkip(*args)
|
||||
self.endLine('[SKIPPED]', self.SKIP)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def addExpectedFailure(self, *args):
|
||||
super(TreeReporter, self).addExpectedFailure(*args)
|
||||
self.endLine('[TODO]', self.TODO)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def addUnexpectedSuccess(self, *args):
|
||||
super(TreeReporter, self).addUnexpectedSuccess(*args)
|
||||
self.endLine('[SUCCESS!?!]', self.TODONE)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def startTest(self, test):
|
||||
super(AndroidTestReporter, self).startTest(test)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def endLine(self, message, color):
|
||||
super(AndroidTestReporter, self).endLine(message, color)
|
||||
update_output_in_activity(str_to_basic_html(self._stream.getvalue()))
|
||||
|
||||
def str_to_basic_html(value):
|
||||
return value.replace("\n", "<br>").replace(" ", ' ')
|
||||
|
||||
def run():
|
||||
loader = TestLoader();
|
||||
suite = loader.loadPackage(lbrynet.tests, True)
|
||||
runner = TrialRunner(AndroidTestReporter)
|
||||
runner.stream = str_stream
|
||||
passFail = not runner.run(suite).wasSuccessful()
|
||||
|
||||
print str_stream.getvalue()
|
||||
sys.exit(passFail)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
Loading…
Reference in a new issue