From 32478332830697ef36a6bc6bcc0ef3b914a86e6d Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Mon, 25 Apr 2016 11:23:42 +0300 Subject: Implement custom marschal/unmarschal for LogItem, hopefully this will fix the problems. --- .../de/blinkt/openvpn/core/LogFileHandler.java | 25 +- .../main/java/de/blinkt/openvpn/core/LogItem.java | 375 +++++++++++++++++++++ .../java/de/blinkt/openvpn/core/OpenVPNThread.java | 4 +- .../java/de/blinkt/openvpn/core/VpnStatus.java | 228 +------------ .../de/blinkt/openvpn/fragments/LogFragment.java | 3 +- .../de/blinkt/openvpn/core/TestLogFileHandler.java | 54 ++- 6 files changed, 437 insertions(+), 252 deletions(-) create mode 100644 main/src/main/java/de/blinkt/openvpn/core/LogItem.java (limited to 'main/src') diff --git a/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java b/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java index dfa6c5fa..7bb9d134 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java +++ b/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java @@ -8,7 +8,6 @@ package de.blinkt.openvpn.core; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.os.Parcel; import java.io.BufferedInputStream; import java.io.File; @@ -18,6 +17,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.Locale; @@ -50,14 +50,14 @@ class LogFileHandler extends Handler { throw new RuntimeException("mLogFile not null"); readLogCache((File) msg.obj); openLogFile((File) msg.obj); - } else if (msg.what == LOG_MESSAGE && msg.obj instanceof VpnStatus.LogItem) { + } else if (msg.what == LOG_MESSAGE && msg.obj instanceof LogItem) { // Ignore log messages if not yet initialized if (mLogFile == null) return; - writeLogItemToDisk((VpnStatus.LogItem) msg.obj); + writeLogItemToDisk((LogItem) msg.obj); } else if (msg.what == TRIM_LOG_FILE) { trimLogFile(); - for (VpnStatus.LogItem li : VpnStatus.getlogbuffer()) + for (LogItem li : VpnStatus.getlogbuffer()) writeLogItemToDisk(li); } else if (msg.what == FLUSH_TO_DISK) { flushToDisk(); @@ -84,15 +84,13 @@ class LogFileHandler extends Handler { } } - private void writeLogItemToDisk(VpnStatus.LogItem li) throws IOException { - Parcel p = Parcel.obtain(); - li.writeToParcel(p, 0); + private void writeLogItemToDisk(LogItem li) throws IOException { + // We do not really care if the log cache breaks between Android upgrades, // write binary format to disc - byte[] liBytes = p.marshall(); + byte[] liBytes = li.getMarschaledBytes(); writeEscapedBytes(liBytes); - p.recycle(); } public void writeEscapedBytes(byte[] bytes) throws IOException { @@ -211,11 +209,9 @@ class LogFileHandler extends Handler { } - protected void restoreLogItem(byte[] buf, int len) { - Parcel p = Parcel.obtain(); - p.unmarshall(buf, 0, len); - p.setDataPosition(0); - VpnStatus.LogItem li = VpnStatus.LogItem.CREATOR.createFromParcel(p); + protected void restoreLogItem(byte[] buf, int len) throws UnsupportedEncodingException { + + LogItem li = new LogItem(buf, len); if (li.verify()) { VpnStatus.newLogItem(li, true); } else { @@ -223,7 +219,6 @@ class LogFileHandler extends Handler { "Could not read log item from file: %d: %s", len, bytesToHex(buf, Math.max(len, 80)))); } - p.recycle(); } final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); diff --git a/main/src/main/java/de/blinkt/openvpn/core/LogItem.java b/main/src/main/java/de/blinkt/openvpn/core/LogItem.java new file mode 100644 index 00000000..57bc3e1e --- /dev/null +++ b/main/src/main/java/de/blinkt/openvpn/core/LogItem.java @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2012-2016 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.core; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.Signature; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; +import android.util.Log; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.FormatFlagsConversionMismatchException; +import java.util.Locale; +import java.util.UnknownFormatConversionException; + +import de.blinkt.openvpn.R; + +/** + * Created by arne on 24.04.16. + */ +public class LogItem implements Parcelable { + private Object[] mArgs = null; + private String mMessage = null; + private int mRessourceId; + // Default log priority + VpnStatus.LogLevel mLevel = VpnStatus.LogLevel.INFO; + private long logtime = System.currentTimeMillis(); + private int mVerbosityLevel = -1; + + private LogItem(int ressourceId, Object[] args) { + mRessourceId = ressourceId; + mArgs = args; + } + + public LogItem(VpnStatus.LogLevel level, int verblevel, String message) { + mMessage = message; + mLevel = level; + mVerbosityLevel = verblevel; + } + + @Override + public int describeContents() { + return 0; + } + + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeArray(mArgs); + dest.writeString(mMessage); + dest.writeInt(mRessourceId); + dest.writeInt(mLevel.getInt()); + dest.writeInt(mVerbosityLevel); + + dest.writeLong(logtime); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LogItem)) + return obj.equals(this); + LogItem other = (LogItem) obj; + + return Arrays.equals(mArgs, other.mArgs) && + ((other.mMessage == null && mMessage == other.mMessage) || + mMessage.equals(other.mMessage)) && + mRessourceId == other.mRessourceId && + ((mLevel == null && other.mLevel == mLevel) || + other.mLevel.equals(mLevel)) && + mVerbosityLevel == other.mVerbosityLevel && + logtime == other.logtime; + + + } + + public byte[] getMarschaledBytes() throws UnsupportedEncodingException { + ByteBuffer bb = ByteBuffer.allocate(16384); + + + bb.put((byte) 0x0); //version + bb.putLong(logtime); //8 + bb.putInt(mVerbosityLevel); //4 + bb.putInt(mLevel.getInt()); + bb.putInt(mRessourceId); + if (mMessage == null || mMessage.length() == 0) { + bb.putInt(0); + } else { + marschalString(mMessage, bb); + } + if (mArgs == null || mArgs.length == 0) { + bb.putInt(0); + } else { + bb.putInt(mArgs.length); + for (Object o : mArgs) { + if (o instanceof String) { + bb.putChar('s'); + marschalString((String) o, bb); + } else if (o instanceof Integer) { + bb.putChar('i'); + bb.putInt((Integer) o); + } else if (o instanceof Float) { + bb.putChar('f'); + bb.putFloat((Float) o); + } else if (o instanceof Double) { + bb.putChar('d'); + bb.putDouble((Double) o); + } else if (o instanceof Long) { + bb.putChar('l'); + bb.putLong((Long) o); + } else if (o == null) { + bb.putChar('0'); + } else { + VpnStatus.logDebug("Unknown object for LogItem marschaling " + o); + bb.putChar('s'); + marschalString(o.toString(), bb); + } + + } + } + + int pos = bb.position(); + bb.rewind(); + return Arrays.copyOf(bb.array(), pos); + + } + + public LogItem(byte[] in, int length) throws UnsupportedEncodingException { + ByteBuffer bb = ByteBuffer.wrap(in, 0, length); + bb.get(); // ignore version + logtime = bb.getLong(); + mVerbosityLevel = bb.getInt(); + mLevel = VpnStatus.LogLevel.getEnumByValue(bb.getInt()); + mRessourceId = bb.getInt(); + int len = bb.getInt(); + if (len == 0) { + mMessage = null; + } else { + byte[] utf8bytes = new byte[len]; + bb.get(utf8bytes); + mMessage = new String(utf8bytes, "UTF-8"); + } + int numArgs = bb.getInt(); + if (numArgs > 30) { + throw new IndexOutOfBoundsException("Too many arguments for Logitem to unmarschal"); + } + if (numArgs == 0) { + mArgs = null; + } else { + mArgs = new Object[numArgs]; + for (int i = 0; i < numArgs; i++) { + char type = bb.getChar(); + switch (type) { + case 's': + mArgs[i] = unmarschalString(bb); + break; + case 'i': + mArgs[i] = bb.getInt(); + break; + case 'd': + mArgs[i] = bb.getDouble(); + break; + case 'f': + mArgs[i] = bb.getFloat(); + break; + case 'l': + mArgs[i] = bb.getLong(); + break; + case '0': + mArgs[i] = null; + break; + default: + throw new UnsupportedEncodingException("Unknown format type: " + type); + } + } + } + if (bb.hasRemaining()) + throw new UnsupportedEncodingException(bb.remaining() + " bytes left after unmarshaling everything"); + } + + private void marschalString(String str, ByteBuffer bb) throws UnsupportedEncodingException { + byte[] utf8bytes = str.getBytes("UTF-8"); + bb.putInt(utf8bytes.length); + bb.put(utf8bytes); + } + + private String unmarschalString(ByteBuffer bb) throws UnsupportedEncodingException { + int len = bb.getInt(); + byte[] utf8bytes = new byte[len]; + bb.get(utf8bytes); + return new String(utf8bytes, "UTF-8"); + } + + + public LogItem(Parcel in) { + mArgs = in.readArray(Object.class.getClassLoader()); + mMessage = in.readString(); + mRessourceId = in.readInt(); + mLevel = VpnStatus.LogLevel.getEnumByValue(in.readInt()); + mVerbosityLevel = in.readInt(); + logtime = in.readLong(); + } + + public static final Creator CREATOR + = new Creator() { + public LogItem createFromParcel(Parcel in) { + return new LogItem(in); + } + + public LogItem[] newArray(int size) { + return new LogItem[size]; + } + }; + + public LogItem(VpnStatus.LogLevel loglevel, int ressourceId, Object... args) { + mRessourceId = ressourceId; + mArgs = args; + mLevel = loglevel; + } + + + public LogItem(VpnStatus.LogLevel loglevel, String msg) { + mLevel = loglevel; + mMessage = msg; + } + + + public LogItem(VpnStatus.LogLevel loglevel, int ressourceId) { + mRessourceId = ressourceId; + mLevel = loglevel; + } + + public String getString(Context c) { + try { + if (mMessage != null) { + return mMessage; + } else { + if (c != null) { + if (mRessourceId == R.string.mobile_info) + return getMobileInfoString(c); + if (mArgs == null) + return c.getString(mRessourceId); + else + return c.getString(mRessourceId, mArgs); + } else { + String str = String.format(Locale.ENGLISH, "Log (no context) resid %d", mRessourceId); + if (mArgs != null) + str += join("|", mArgs); + + return str; + } + } + } catch (UnknownFormatConversionException e) { + if (c != null) + throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null)); + else + throw e; + } catch (java.util.FormatFlagsConversionMismatchException e) { + if (c != null) + throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion()); + else + throw e; + } + + } + + + // TextUtils.join will cause not macked exeception in tests .... + public static String join(CharSequence delimiter, Object[] tokens) { + StringBuilder sb = new StringBuilder(); + boolean firstTime = true; + for (Object token : tokens) { + if (firstTime) { + firstTime = false; + } else { + sb.append(delimiter); + } + sb.append(token); + } + return sb.toString(); + } + + + public VpnStatus.LogLevel getLogLevel() { + return mLevel; + } + + + @Override + public String toString() { + return getString(null); + } + + // The lint is wrong here + @SuppressLint("StringFormatMatches") + private String getMobileInfoString(Context c) { + c.getPackageManager(); + String apksign = "error getting package signature"; + + String version = "error getting version"; + try { + @SuppressLint("PackageManagerGetSignatures") + Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] der = cert.getEncoded(); + md.update(der); + byte[] digest = md.digest(); + + if (Arrays.equals(digest, VpnStatus.officalkey)) + apksign = c.getString(R.string.official_build); + else if (Arrays.equals(digest, VpnStatus.officaldebugkey)) + apksign = c.getString(R.string.debug_build); + else if (Arrays.equals(digest, VpnStatus.amazonkey)) + apksign = "amazon version"; + else if (Arrays.equals(digest, VpnStatus.fdroidkey)) + apksign = "F-Droid built and signed version"; + else + apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName()); + + PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0); + version = packageinfo.versionName; + + } catch (PackageManager.NameNotFoundException | CertificateException | + NoSuchAlgorithmException ignored) { + } + + Object[] argsext = Arrays.copyOf(mArgs, mArgs.length); + argsext[argsext.length - 1] = apksign; + argsext[argsext.length - 2] = version; + + return c.getString(R.string.mobile_info, argsext); + + } + + public long getLogtime() { + return logtime; + } + + + public int getVerbosityLevel() { + if (mVerbosityLevel == -1) { + // Hack: + // For message not from OpenVPN, report the status level as log level + return mLevel.getInt(); + } + return mVerbosityLevel; + } + + public boolean verify() { + if (mLevel == null) + return false; + + if (mMessage == null && mRessourceId == 0) + return false; + + return true; + } +} diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java index 7fd43906..4f743a19 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java @@ -25,9 +25,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import de.blinkt.openvpn.R; -import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.LogItem; public class OpenVPNThread implements Runnable { private static final String DUMP_PATH_STRING = "Dump path: "; @@ -69,7 +67,7 @@ public class OpenVPNThread implements Runnable { try { Log.i(TAG, "Starting openvpn"); startOpenVPNThreadArgs(mArgv, mProcessEnv); - Log.i(TAG, "OpenVPN process exited"); + Log.i(TAG, "OpenVPN process exited"); } catch (Exception e) { VpnStatus.logException("Starting OpenVPN Thread", e); Log.e(TAG, "OpenVPNThread Got " + e.toString()); diff --git a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index 92ab5900..d23f0013 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -5,39 +5,18 @@ package de.blinkt.openvpn.core; -import android.annotation.SuppressLint; import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.Signature; import android.os.Build; import android.os.HandlerThread; import android.os.Message; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Log; -import java.io.ByteArrayInputStream; -import java.io.DataOutputStream; import java.io.File; -import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.FormatFlagsConversionMismatchException; import java.util.LinkedList; import java.util.Locale; -import java.util.UnknownFormatConversionException; import java.util.Vector; -import de.blinkt.openvpn.BuildConfig; import de.blinkt.openvpn.R; public class VpnStatus { @@ -206,205 +185,6 @@ public class VpnStatus { } - public static class LogItem implements Parcelable { - private Object[] mArgs = null; - private String mMessage = null; - private int mRessourceId; - // Default log priority - LogLevel mLevel = LogLevel.INFO; - private long logtime = System.currentTimeMillis(); - private int mVerbosityLevel = -1; - - private LogItem(int ressourceId, Object[] args) { - mRessourceId = ressourceId; - mArgs = args; - } - - public LogItem(LogLevel level, int verblevel, String message) { - mMessage = message; - mLevel = level; - mVerbosityLevel = verblevel; - } - - @Override - public int describeContents() { - return 0; - } - - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeArray(mArgs); - dest.writeString(mMessage); - dest.writeInt(mRessourceId); - dest.writeInt(mLevel.getInt()); - dest.writeInt(mVerbosityLevel); - - dest.writeLong(logtime); - } - - public LogItem(Parcel in) { - mArgs = in.readArray(Object.class.getClassLoader()); - mMessage = in.readString(); - mRessourceId = in.readInt(); - mLevel = LogLevel.getEnumByValue(in.readInt()); - mVerbosityLevel = in.readInt(); - logtime = in.readLong(); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public LogItem createFromParcel(Parcel in) { - return new LogItem(in); - } - - public LogItem[] newArray(int size) { - return new LogItem[size]; - } - }; - - public LogItem(LogLevel loglevel, int ressourceId, Object... args) { - mRessourceId = ressourceId; - mArgs = args; - mLevel = loglevel; - } - - - public LogItem(LogLevel loglevel, String msg) { - mLevel = loglevel; - mMessage = msg; - } - - - public LogItem(LogLevel loglevel, int ressourceId) { - mRessourceId = ressourceId; - mLevel = loglevel; - } - - public String getString(Context c) { - try { - if (mMessage != null) { - return mMessage; - } else { - if (c != null) { - if (mRessourceId == R.string.mobile_info) - return getMobileInfoString(c); - if (mArgs == null) - return c.getString(mRessourceId); - else - return c.getString(mRessourceId, mArgs); - } else { - String str = String.format(Locale.ENGLISH, "Log (no context) resid %d", mRessourceId); - if (mArgs != null) - str += join("|", mArgs); - - return str; - } - } - } catch (UnknownFormatConversionException e) { - if (c != null) - throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null)); - else - throw e; - } catch (java.util.FormatFlagsConversionMismatchException e) { - if (c != null) - throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion()); - else - throw e; - } - - } - - - // TextUtils.join will cause not macked exeception in tests .... - public static String join(CharSequence delimiter, Object[] tokens) { - StringBuilder sb = new StringBuilder(); - boolean firstTime = true; - for (Object token: tokens) { - if (firstTime) { - firstTime = false; - } else { - sb.append(delimiter); - } - sb.append(token); - } - return sb.toString(); - } - - - - public LogLevel getLogLevel() { - return mLevel; - } - - // The lint is wrong here - @SuppressLint("StringFormatMatches") - private String getMobileInfoString(Context c) { - c.getPackageManager(); - String apksign = "error getting package signature"; - - String version = "error getting version"; - try { - @SuppressLint("PackageManagerGetSignatures") - Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] der = cert.getEncoded(); - md.update(der); - byte[] digest = md.digest(); - - if (Arrays.equals(digest, officalkey)) - apksign = c.getString(R.string.official_build); - else if (Arrays.equals(digest, officaldebugkey)) - apksign = c.getString(R.string.debug_build); - else if (Arrays.equals(digest, amazonkey)) - apksign = "amazon version"; - else if (Arrays.equals(digest, fdroidkey)) - apksign = "F-Droid built and signed version"; - else - apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName()); - - PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0); - version = packageinfo.versionName; - - } catch (NameNotFoundException | CertificateException | - NoSuchAlgorithmException ignored) { - } - - Object[] argsext = Arrays.copyOf(mArgs, mArgs.length); - argsext[argsext.length - 1] = apksign; - argsext[argsext.length - 2] = version; - - return c.getString(R.string.mobile_info, argsext); - - } - - public long getLogtime() { - return logtime; - } - - - public int getVerbosityLevel() { - if (mVerbosityLevel == -1) { - // Hack: - // For message not from OpenVPN, report the status level as log level - return mLevel.getInt(); - } - return mVerbosityLevel; - } - - public boolean verify() { - if (mLevel == null) - return false; - - if (mMessage == null && mRessourceId == 0) - return false; - - return true; - } - } - public interface LogListener { void newLog(LogItem logItem); } @@ -425,7 +205,7 @@ public class VpnStatus { public synchronized static void clearLog() { logbuffer.clear(); logInformation(); - if (mLogFileHandler!=null) + if (mLogFileHandler != null) mLogFileHandler.sendEmptyMessage(LogFileHandler.TRIM_LOG_FILE); } @@ -438,7 +218,7 @@ public class VpnStatus { } logInfo(R.string.mobile_info, Build.MODEL, Build.BOARD, Build.BRAND, Build.VERSION.SDK_INT, - nativeAPI , Build.VERSION.RELEASE, Build.ID, Build.FINGERPRINT, "", ""); + nativeAPI, Build.VERSION.RELEASE, Build.ID, Build.FINGERPRINT, "", ""); } public synchronized static void addLogListener(LogListener ll) { @@ -607,7 +387,7 @@ public class VpnStatus { logbuffer.addFirst(logItem); } else { logbuffer.addLast(logItem); - if (mLogFileHandler!=null) { + if (mLogFileHandler != null) { Message m = mLogFileHandler.obtainMessage(LogFileHandler.LOG_MESSAGE, logItem); mLogFileHandler.sendMessage(m); } @@ -616,7 +396,7 @@ public class VpnStatus { if (logbuffer.size() > MAXLOGENTRIES + MAXLOGENTRIES / 2) { while (logbuffer.size() > MAXLOGENTRIES) logbuffer.removeFirst(); - if (mLogFileHandler!=null) + if (mLogFileHandler != null) mLogFileHandler.sendMessage(mLogFileHandler.obtainMessage(LogFileHandler.TRIM_LOG_FILE)); } diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java index a620beb4..d3381bcb 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java @@ -22,7 +22,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; -import android.preference.Preference; import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.text.SpannableString; @@ -63,7 +62,7 @@ import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.LogItem; +import de.blinkt.openvpn.core.LogItem; import de.blinkt.openvpn.core.VpnStatus.LogListener; import de.blinkt.openvpn.core.VpnStatus.StateListener; diff --git a/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java b/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java index f86dbcdc..c35df598 100644 --- a/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java +++ b/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java @@ -1,9 +1,6 @@ package de.blinkt.openvpn.core; import android.annotation.SuppressLint; -import android.os.Looper; -import android.os.Message; -import android.util.Log; import junit.framework.Assert; @@ -15,19 +12,18 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.StringBufferInputStream; +import java.io.UnsupportedEncodingException; import java.util.Arrays; public class TestLogFileHandler { - byte[] testUnescaped = new byte[] {0x00, 0x55, -27, 0x00, 0x56, 0x10, -128, 0x55, 0x54}; - byte[] expectedEscaped = new byte[] {0x55, 0x00, 0x00, 0x00, 0x09, 0x00, 0x56, 0x00, -27, 0x00, 0x56, 0x01, 0x10, -128, 0x56, 0x00, 0x54}; + byte[] testUnescaped = new byte[]{0x00, 0x55, -27, 0x00, 0x56, 0x10, -128, 0x55, 0x54}; + byte[] expectedEscaped = new byte[]{0x55, 0x00, 0x00, 0x00, 0x09, 0x00, 0x56, 0x00, -27, 0x00, 0x56, 0x01, 0x10, -128, 0x56, 0x00, 0x54}; private TestingLogFileHandler lfh; @Before - public void setup() - { + public void setup() { lfh = new TestingLogFileHandler(); } @@ -55,6 +51,46 @@ public class TestLogFileHandler { } + @Test + public void testMarschal() throws UnsupportedEncodingException { + LogItem li = new LogItem(VpnStatus.LogLevel.DEBUG, 72, "foobar"); + LogItem li2 = marschalAndBack(li); + testEquals(li, li2); + Assert.assertEquals(li, li2); + } + + @Test + public void testMarschalArgs() throws UnsupportedEncodingException { + LogItem li = new LogItem(VpnStatus.LogLevel.DEBUG, 72, 772, "sinnloser Text", 7723, 723.2f, 7.2); + LogItem li2 = marschalAndBack(li); + testEquals(li, li2); + Assert.assertEquals(li, li2); + } + + @Test + public void testMarschalString() throws UnsupportedEncodingException { + LogItem li = new LogItem(VpnStatus.LogLevel.DEBUG, "Nutzlose Nachricht"); + LogItem li2 = marschalAndBack(li); + testEquals(li, li2); + Assert.assertEquals(li, li2); + } + + + private void testEquals(LogItem li, LogItem li2) { + Assert.assertEquals(li.getLogLevel(), li2.getLogLevel()); + Assert.assertEquals(li.getLogtime(), li2.getLogtime()); + Assert.assertEquals(li.getVerbosityLevel(), li2.getVerbosityLevel()); + Assert.assertEquals(li.toString(), li2.toString()); + + } + + private LogItem marschalAndBack(LogItem li) throws UnsupportedEncodingException { + byte[] bytes = li.getMarschaledBytes(); + + return new LogItem(bytes, bytes.length); + } + + @SuppressLint("HandlerLeak") static class TestingLogFileHandler extends LogFileHandler { @@ -78,4 +114,6 @@ public class TestLogFileHandler { mRestoredByteArray = Arrays.copyOf(buf, len); } } + + } \ No newline at end of file -- cgit v1.2.3