Skip to content
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

Merged
merged 1 commit into from
Nov 21, 2016

Conversation

mjanuchowski
Copy link
Contributor

Description

  • created 5 unit tests for expandJar function
  • added 1 simplified test jar file used by unit tests
  • created 5 @should annotations in expandJar header
  • one of the test cases was failing (name parameter is a file, keepFullPath is false), had to do change to expandJar function to fix a bug

Related Issue

https://issues.openmrs.org/browse/TRUNK-4870

Checklist:

  • My pull request only contains one single commit.
  • My pull request is based on the latest master branch
    git pull --rebase upstream master.
  • I ran mvn clean package right before creating this pull request and
    added all formatting changes to my commit.
  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@mention-bot
Copy link

@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.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 55.722% when pulling 2803f67 on mjanuchowski:TRUNK-4870 into ef0d944 on openmrs:master.

Copy link
Member

@teleivo teleivo left a 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

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 {
Copy link
Member

@teleivo teleivo Nov 4, 2016

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
Copy link
Member

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
Copy link
Member

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.

Copy link
Contributor Author

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();
Copy link
Member

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);
Copy link
Member

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('/');
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

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.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) to 55.632% when pulling 5b039ef on mjanuchowski:TRUNK-4870 into 17c22ce on openmrs:master.

@teleivo
Copy link
Member

teleivo commented Nov 7, 2016

@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), "");
Copy link
Member

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?

Copy link
Member

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

Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor Author

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 :)

Copy link
Member

@wluyima wluyima Nov 7, 2016

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!

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 55.623% when pulling 3ae01a7 on mjanuchowski:TRUNK-4870 into 17c22ce on openmrs:master.

@mjanuchowski
Copy link
Contributor Author

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), "");
Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor Author

@mjanuchowski mjanuchowski Nov 14, 2016

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. :)

Copy link
Member

@wluyima wluyima Nov 14, 2016

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.

Copy link
Contributor Author

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?

@lluismf
Copy link
Contributor

lluismf commented Nov 11, 2016

Check out Apache FilenameUtils, it contains a lot of handy methods to deal with file names (maybe you won't need any of it)

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 55.74% when pulling 1fc2dbc on mjanuchowski:TRUNK-4870 into de99ca9 on openmrs:master.

* @return <code>File</code> containing folder for Jar tests.
*/
protected File getEmptyJarDestinationFolder() throws IOException {
File destinationFolder = new File("/tmp/expandedJar");
Copy link
Member

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? :)

Copy link
Contributor Author

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.

Copy link
Member

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")?

Copy link
Contributor Author

@mjanuchowski mjanuchowski Nov 21, 2016

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.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.03%) to 55.736% when pulling d589443 on mjanuchowski:TRUNK-4870 into 7ce4dfa on openmrs:master.

@dkayiwa dkayiwa merged commit e4d2ea9 into openmrs:master Nov 21, 2016
@mjanuchowski mjanuchowski deleted the TRUNK-4870 branch November 30, 2016 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants