-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TRUNK-4870 Add Unit tests for ModuleUtil.expandJar(File, File, Stri… #1866
Conversation
@mjanuchowski, thanks for your PR! By analyzing the history of the files in this pull request, we identified @bmamlin, @teleivo and @dkayiwa to be potential reviewers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest tests should
- follow the new style of unit tests, use
https://wiki.openmrs.org/display/docs/Generate+Test+Case+Plugin - make tests cleaner (use javas File type without doing all the string concatenation with File.separator and string replace); added a sample of how I would rewrite one of the written tests
I think the change in the implementation shouldnt have the separator hard coded
*/ | ||
@Test | ||
@Verifies(value = "expand entire jar if name is null", method = "expandJar(File,File,String,boolean)") | ||
public void expandJar_shouldExpandEntireJarIfNameIsNull() throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please use the openmrs generate test case plugin, see https://wiki.openmrs.org/display/docs/Generate+Test+Case+Plugin
You used the old test style and the generator will easily create the scaffold for you in the new style :)
@@ -554,6 +554,11 @@ public static URL file2url(final File file) throws MalformedURLException { | |||
* @param keepFullPath if true, will recreate entire directory structure in tmpModuleDir | |||
* relating to <code>name</code>. if false will start directory structure at | |||
* <code>name</code> | |||
* @should expand entire jar if name is null | |||
* @should expand directory with parent tree if name is directory and keepFullPath is true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please add a test for when name
is an empty string. wonder what happens :)
@Test | ||
@Verifies(value = "expand entire jar if name is null", method = "expandJar(File,File,String,boolean)") | ||
public void expandJar_shouldExpandEntireJarIfNameIsNull() throws IOException { | ||
// Arrange |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comments like arrange, act, assert, clean up. are not used in openmrs tests, as far as i know. can you just replace them with newlines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find them helpful to keep tests clean, but no problem, I will apply to rules that are used in a project :)
// Act | ||
ModuleUtil.expandJar(getJarFile(), destinationFolder, directoryPath, true); | ||
// Assert | ||
Object[] filesList = FileUtils.listFiles(destinationFolder, null, true).toArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about using type File
instead of Object
you then dont need to cast multiple times later on.
or maybe use a list:
List filesList = (List) FileUtils.listFiles(destinationFolder, null, true);
String ActualPath = ((File)filesList[0]).getPath().replace(((File)filesList[0]).getName(), ""); | ||
Assert.assertEquals(expectedPath, ActualPath); | ||
// Clean up | ||
FileUtils.deleteDirectory(destinationFolder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think you can simplify your tests by leveraging the java File
you dont need to use/add/replace file separators.
I think you can do something like
public void expandJar_shouldExpandDirectoryWithoutParentTreeIfNameIsDirectoryAndKeepFullPathIsFalse() throws IOException {
final int numberOfFilesInSpecifiedDirectory = 2;
String directoryPath = "META-INF/maven/org.openmrs.module/test1-api";
File destinationFolder = this.getEmptyJarDestinationFolder();
ModuleUtil.expandJar(getJarFile(), destinationFolder, directoryPath, false);
List<File> actualExpandedFiles = (List<File>) FileUtils.listFiles(destinationFolder, null, true);
Assert.assertEquals(numberOfFilesInSpecifiedDirectory, actualExpandedFiles.size());
Assert.assertEquals(destinationFolder.toString(), actualExpandedFiles.get(0).getParent());
FileUtils.deleteDirectory(destinationFolder);
}
@@ -571,7 +576,15 @@ public static void expandJar(File fileToExpand, File tmpModuleDir, String name, | |||
String entryName = jarEntry.getName(); | |||
// trim out the name path from the name of the new file | |||
if (!keepFullPath && name != null) { | |||
entryName = entryName.replaceFirst(name, ""); | |||
if (name.equals(entryName)) { | |||
int lastSlash = name.lastIndexOf('/'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you use File.separator in your tests but hard code the separator here, why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since JarEntry
uses slash as a separator I would expect that name
parameter will also use them. This is in line with rest of the code in this function, which also uses hard coded slash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you saying jarEntry uses forward slash on other systems like windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I ran unit tests also on Windows and they do not fail, which proves that paths in JarEntry
do not use File.Separator but always forward slash.
2803f67
to
5b039ef
Compare
@mjanuchowski thanks for the making the changes 👍 |
if (name.equals(entryName)) { | ||
int lastSlash = name.lastIndexOf('/'); | ||
if (lastSlash >= 0) { | ||
entryName = entryName.replaceFirst(name.substring(0, lastSlash + 1), ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please add a comment here to explain what you're trying to solve?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wluyima what about extracting it into a private method with a descriptive name instead of a comment? A lot of methods are already bloated and hard to read since they do so many things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which ever way he does it, as long as it's clear to the reader I'd be okay with it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually if
block in which this code is nested has already a pretty good description:
// trim out the name path from the name of the new file
I'm just making sure that we trim only a path, without the file name itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That comment made sense for the old changes though, it was trimming out just the name, yours seems to have an extra uncommented inner if clause that's not clear what it does when one glances at the code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is still valid - the whole block trims out the name path from the name of the new file. Code added in inner if statement makes sure that it happens no matter if name
parameter is file or directory. But of course I can add comments to make that clear :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I've been trying to ask for :), i.e to add the comment to say why you have that inner clause and logic, thanks!
5b039ef
to
3ae01a7
Compare
Thank you for all the suggestions! Is there any extra work on this ticket? |
if (name.equals(entryName)) { | ||
int lastSlash = name.lastIndexOf('/'); | ||
if (lastSlash >= 0) { | ||
entryName = entryName.replaceFirst(name.substring(0, lastSlash + 1), ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still a little confused by this change, which test fails when you remove this? The old logic trims out the filename from the entry so that you remain with the path but it appears to me like you're doing the opposite here i.e you are stripping out the path and remaining with the filename
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The failing test was expanding file without full path: expandJar_shouldExpandFileWithoutParentTreeIfNameIsFileAndKeepFullPathIsFalse()
. In this case name
provides filename with path e.g. FOLDER1/FOLDER2/FILE. Original function was stripping this whole string from jar filename which was leaving it empty. As a result nothing was getting extracted. What I did is to make sure in that specific case that only path part of name
gets trimmed out, so that jar filename still stays and gets extracted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand it when you say that but do we actually ever call this method with a path and not a filename?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, in openmrs-core this function is always called with name
parameter as filename, but at the same time it is always called with keepFullPath == true
, so the case causing an error never occured.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess what am saying is that it was intentional to exclude this, right now it just seems to me like a contrived case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I understand. Do you mean that keepFullPath
parameter is obsolete and full path should be always recreated? But isn't it possible that this function gets called from outside of openmrs-core or gets used in future with keepFullPath == false
?
What I did is, since it has keepFullPath
and name
parameters, make sure that it works with every combination of those two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What am saying is this code is intended to be called by the module framework in core only and if it always calls the method with keepFullPath set to true and name as a filename, then we don't need this change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I can revert the change and get rid of failing test.
Still I would prefer such function to work properly with all parameter combinations and not only with those that we can observe in a present code. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to go by this saying don't try to fix it if ain't broke, until something fails because this code is missing then we will fix it at that point, as long as all reference to it in core set the parameters to true and the filename respectively and it works, it's all good otherwise you risk introducing other obscure bugs, we don't expect external code to be calling this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any extra work on this ticket?
Check out Apache FilenameUtils, it contains a lot of handy methods to deal with file names (maybe you won't need any of it) |
3ae01a7
to
1fc2dbc
Compare
* @return <code>File</code> containing folder for Jar tests. | ||
*/ | ||
protected File getEmptyJarDestinationFolder() throws IOException { | ||
File destinationFolder = new File("/tmp/expandedJar"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the path above work on windows? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it does :) I've ran test on both Linux and Windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would need another windows user to run and confirm it. :)
Why don't you use System.getProperty("java.io.tmpdir")?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! I will use it.
1fc2dbc
to
d589443
Compare
Description
Related Issue
https://issues.openmrs.org/browse/TRUNK-4870
Checklist:
git pull --rebase upstream master
.mvn clean package
right before creating this pull request andadded all formatting changes to my commit.