My app reads files in /proc. I am trying to test this with Robolectric 2.3.
I can create a test file in the "external storage" without problems:
ShadowEnvironment.setExternalStorageState(Environment.MEDIA_MOUNTED);
PrintWriter out;
out = new PrintWriter("myFile");
out.println(contents);
However if I try to write to a file in /proc it blows up with java.io.FileNotFoundException: \proc\net\netstat (Access is denied).
ShadowEnvironment.setExternalStorageState(Environment.MEDIA_MOUNTED);
boolean a = new File( "/proc" ).mkdirs(); //Fails
PrintWriter out;
out = new PrintWriter("/proc/myFile");
out.println(contents);
Is there any way I can cause a (specific) file to exist in /proc, for testing?
I've already answered similar questions today. Looks like today is day about promoting single class responsibility and dependency injections.
I would change your code to next first:
Write a class that will be responsible for opening (closing, other operations, keep an eye that it should be simple) file connections
Make a class that reads information from stream/file to some internal data structure
Process this data in your original class
Next I would write tests:
Check file operations class
Check that reader is passing correct file location to file operations class instance (mock in tests)
Check that original class correctly process information that is provided by reader class (reader is mocked in tests)
Hope it helps!
Related
I have a Realm DB file, with name "abc.realm". How to change this name to something else? Should I just replace the file name using IO operations or can I do it with migrations? Not able to find any satisfactory answer neither on the web nor on StackOverflow.
Realm stores 2 files, the realm itself and a .lock file. So if you call your realm "abc.realm", then next to this file there is also "abc.realm.lock".
The way to go about renaming your realm file is,
Make sure you find the location of both files
Rename both files with the same name but keeping the ".lock" extension on the lock file
Modify the path to the realm that you pass to the RealmConfigurationBase inheritor
Clearly before doing any of this, make sure to backup your database, just in case.
I don't know what programming language you're writing your android application in, so I'll go with a skeleton in pseudocode
private void BackupRealmFile(string realmLocation, string saveLocation)
{
// make a copy of the file and store it somewhere
}
void YourMainMethod()
{
BackupRealmFile("some/path", "your/backup/path");
IOLib.RenameFile("some/path/abc.realm", "some/path/newName.realm");
IOLib.RenameFile("some/path/abc.realm.lock", "some/path/newName.realm.lock");
var config = new RealmConfiguration("some/path/newName.realm");
// maybe some more settings on your conf
var realm = Realm.GetInstance(config);
}
I hope this helps.
I try to understand the process of ART when using reflection. As it can be seen in the simple example below, the DexClassLoader is used to load a class from the DEX-file. The question now is what is ART doing internally when loading a class?
From other sources, I found out that the previously used dalvikVM loads the bytecode of the class into memory and initializes static content during loading. The bytecode can then be interpreted by the dalvikVM (e.g. creating an instance of that class).
The Android documentation states that ART uses Ahead-of-time (AOT) compilation, which converts the bytecode in a DEX-file into some optimized code that is then executed on the device.
So, if I load a class via reflection is it compiled again and then executed? Or does it work the same way it did with the dalvikVM by loading and interpreting the bytecode?
Example:
ClassLoader cl = Thread.currentThread().getContextClassLoader();
DexClassLoader dexClassLoader = new DexClassLoader("path/to/dex", null, ".", cl);
Class<?> loadedClass = dexClassLoader.loadClass("com.package.MyClass");
Object instance = loadedClass.newInstance();
Method method = loadedClass.getDeclaredMethod("myMethodName", String.class);
Object result = method.invoke(instance, "my method input");
I would appreciate any additional information on this topic. Thanks!
Edit:
I found out that using the above example creates a .prof file for my DEX-file in a folder called 'oat' located in the same directory as the original DEX-file.
From this I know that the process of running an app is that the DEX-file is simply loaded and interpreted if there are no OAT-files. During execution profiles are created and the app is compiled with dex2oat. So I assume that with my example the content of the DEX-file is simply interpreted, which then creates the .prof-files that could be used when executing the code again.
Currently, I'm storing the same resources in
/test/resources/sample.txt //for unit tests
/main/asssets/sample.txt //for espresso tests
can I store them in one place?
If yes, how can I read them in my tests?
Preferably, I would like to open them as the File object, not InputStream.
So, I finally decided that the best solution, in this case, is to store everything in assets folder (in mock flavor).
You can open them from instrumentation test:
activityRule.activity.assets.open("sample.txt")
from unit tests:
private val ASSET_BASE_PATH = "../app/src/mock/assets/"
fun openAsset(filename: String): InputStream {
return FileInputStream(ASSET_BASE_PATH + filename)
I'm struggling with storing a realm db on the sd card. The point is that I have to use DocumentFile instead of simple File object to have write access. Another words:
Uri uri = getUriInstanceToSaveDB(); // my inner method
new File(uri.getPath()).canWrite() == false
DocumentFile.fromTreeUri(getActivity(), uri).canWrite() == true
Therefore I can't just store data using RealmConfiguration.Builder() (cause it uses File object as storing mechanism). Of course, I've also tried to use simple String there instead of File object - no result.
Real doesn't support DocumentFile at this point in time, so I'm afraid you are currently out of luck unless you can find a way to map a DocumentFile to a local File reference.
Also one of the problems with DocumentFile is that it might reference a file that doesn't exist locally, which would prevent Realm from using it. So it is unclear if Realm could ever support this.
I am currently refactoring some old app and I am trying to migrate from SQLite to Realm. I have used Realm before and I have never encountered problem like this. When I start my app for first time (after installation), I get this exception:
E/AndroidRuntime: FATAL EXCEPTION:
Process: xx.xxx.xxx.beta.realm, PID: 25947
java.lang.IllegalArgumentException: A RealmObject with no #PrimaryKey cannot be updated: class xx.xxx.xxx.realm.Vod
at io.realm.Realm.checkHasPrimaryKey(Realm.java:1184)
at io.realm.Realm.copyToRealmOrUpdate(Realm.java:713)
at xx.xxx.xxx.services.VodService$4.run(VodService.java:232)
at java.lang.Thread.run(Thread.java:818)
My Vod class looks like this and object is properly created, i.e. has value for PrimaryKey and all other fields:
public class Vod extends RealmObject {
#PrimaryKey
private String uuid;
private String name;
private Integer lengthMin;
private Boolean hasTrailer;
private String description;
private String originalName;
//etc...
//getters & setters
This will crash the app. But after that first time (and every next time) everything works fine - with same code and same data. But when I uninstall and reinstall app again, I will also encounter this exception again.
The part of code in question runs on background thread. If I move it to UI thread, everything works fine even for first time. But I want to parse network responses on background thread and not on UI. Also it isn't specific to Vod class, if I skip data for Vod and start with, for example, User class, then I get "no #PrimaryKey" exception for User class.
Sometimes it also throws this exception:
D/REALM: jni: ThrowingException 5, , .
D/REALM: Exception has been throw: File not found: .
E/AndroidRuntime: FATAL EXCEPTION:
Process: xx.xxx.xxx.beta.realm, PID: 28555
io.realm.exceptions.RealmIOException: File not found: .
at io.realm.internal.SharedGroup.createNativeWithImplicitTransactions(Native Method)
at io.realm.internal.SharedGroup.<init>(SharedGroup.java:67)
at io.realm.internal.SharedGroupManager.<init>(SharedGroupManager.java:47)
at io.realm.BaseRealm.<init>(BaseRealm.java:76)
at io.realm.Realm.<init>(Realm.java:126)
at io.realm.Realm.createAndValidate(Realm.java:246)
at io.realm.Realm.createInstance(Realm.java:231)
at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:114)
at io.realm.Realm.getDefaultInstance(Realm.java:181)
at xx.xxx.xx.services.RecordingService$9.run(RecordingService.java:317)
at java.lang.Thread.run(Thread.java:818)
which leads me to think, that there will be some problem with initialization of Realm file? I create it like this:
public class MainApplication extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
mRealmConfig = new RealmConfiguration.Builder(mContext).build();
Realm.setDefaultConfiguration(mRealmConfig);
}
}
and then use this to get instance in thread:
Realm localRealm = Realm.getDefaultInstance();
Am I doing something wrong? Has anyone has this type of problem before? I tried to search web for answer, but found nothing useful. Thanks for any help.
(I'm using io.realm:realm-android:0.87.4)
EDIT: I have confirmed (via ADB), that internal storage folder for my app package is removed after uninstall. While checking that, I found out that my files folder in path /data/data//files is empty during first app run. Is that correct behavior? Also, I cannot see anything inside Realm via Stetho.
Steps:
1. I uninstall app
ADB says cd: /data/data/xx.xxx.xxx.beta.realm: No such file or directory
I install and run app again
ADB run-as xx.xxx.xxx.beta.realm -> cd files -> ls -> empty
Inspect via Stetho, shows no data
Wait for minute or so (to give Realm time to create whatever needs)
Start network requests and app crashes ("no #PrimaryKey" exception) with first data to parse outside UI thread (parsing on UI works fine)
ADB -> files folder -> ls -> I can see everything, default.realm, default.realm.lock, default.realm.log, default.realm.log_a, default.realm.log_b
Start app again, everything works fine, I can even see realm data via
Stetho.
I really hope that I am making some stupid mistake and that everything will be fine at last. Also one more thing, on app start I see this log few times:
Rejecting re-init on previously-failed class java.lang.Class<io.realm.rx.RealmObservableFactory$4>
I have read this: https://github.com/realm/realm-java/issues/1990 and I don't think, that it is related to my problem, but just to be sure.
It's possible that your imports are messed up. Be sure to be importing io.realm.annotations.PrimaryKey, and not androidx.room.PrimaryKey, which might be a common issue.