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

Enum constructors should not be mutated #556

Open
hcoles opened this issue Jan 27, 2019 · 9 comments
Open

Enum constructors should not be mutated #556

hcoles opened this issue Jan 27, 2019 · 9 comments

Comments

@hcoles
Copy link
Owner

hcoles commented Jan 27, 2019

Code in enum constructors should be treated as static initializer code as it will only be run once per JVM, effecting both mutant insertion and code coverage.

@rnveach
Copy link
Contributor

rnveach commented Jan 27, 2019

in enum constructors should be treated as static initializer code as it will only be run once per JVM

Unless I am mis-understanding what you mean by constructor, I think you are wrong here as constructors are just when the instance is created. Each enum definition is an instance and calls the enum constructor. If there are multiple definitions then there are multiple constructor calls.

Take the Java code:


public enum EnumExample {
	A(0), // this is the enum definition
	B(1),
	C(2);
	
	int field;
	
	EnumExample(int i) { // this is the constructor
		field = i;
	}
}

The class file creates the following code when decompiled:

// Decompiled by DJ v3.12.12.98 Copyright 2014 Atanas Neshkov  Date: 1/27/2019 11:52:25 AM
// Home Page:  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   EnumExample.java


public final class EnumExample extends Enum
{

    private EnumExample(String s, int j, int i) // this is still the constructor
    {
        super(s, j);
        field = i;
    }

....

    public static final EnumExample A;
    public static final EnumExample B;
    public static final EnumExample C;
    int field;
    private static final EnumExample ENUM$VALUES[];

    static // this is the static block
    {
        A = new EnumExample("A", 0, 0); // these are calling the constructors
        B = new EnumExample("B", 1, 1);
        C = new EnumExample("C", 2, 2);
        ENUM$VALUES = (new EnumExample[] {
            A, B, C
        });
    }
}

As you can see the constructor is called multiple times in 1 JVM. The only static part of the enumeration is the enum definitions.

@hcoles
Copy link
Owner Author

hcoles commented Jan 27, 2019

Yes the constructor is called once per enum instance and will not (barring some horrific trickery) be called again. It is effectively static initializer code.

@JavaJimFl
Copy link

I was just about to create an issue for this very situation. I am unable to kill any mutation related to member variable assignments in an enum constructor, though unit tests fail when manually setting the member variables to their default values.

@christianhujer
Copy link

christianhujer commented Jan 2, 2020

This may be related, I'm getting weird results for enums. Methods in enums are covered normally, but the constants and the constructor are reported uncovered, even though I have extensive tests.

@hcoles
Copy link
Owner Author

hcoles commented Jan 4, 2020

@christianhujer That is a little strange. It could relate to the recent changes made to the coverage system. Are you seeing this across Java versions?

@christianhujer
Copy link

I haven't checked different versions yet. I am observing this using:

  • Linux (Kubuntu 18.04.3 LTS)
  • OpenJDK 13.0.1
  • Maven 3.6.3
  • pitest 1.4.10

I will create a small isolated test case covering all situations where I'm observing this, which is:

  • enums for utility classes
  • enums for singletons
  • enums with constructors and fields

And I'll run this through different JDK versions. Once I'm done, I'll share the results here.

@christianhujer
Copy link

To help with understanding the issue and where it comes from, I've created a small git repository to demonstrate the issue. Here it is: https://github.com/christianhujer/pitest-bug-556

In any case, the coverage reports of Pitest report a reduced line coverage for enums.
The effective result is:

Java PiTest Singleton Utility
8 1.4.9 17% 50%
8 1.4.10 17% 50%
8 1.4.11 17% 50%
11 1.4.9 17% 50%
11 1.4.10 17% 50%
11 1.4.11 17% 50%
13 1.4.9 17% 50%
13 1.4.10 17% 50%
13 1.4.11 17% 50%
14 1.4.9
14 1.4.10
14 1.4.11 17% 50%

@christianhujer
Copy link

I could not observe the original issue that enum constructors should not be mutated. Should I create a new ticket like "enum constructors and constants should not be reported as 'not covered' by line coverage"?

@hcoles
Copy link
Owner Author

hcoles commented Jan 15, 2020

@christianhujer The active mutators would not be triggered by the code in these enums - if you put a sysout call in there you should see it mutated by the void calls mutator.

Thanks for the example project. I'd assumed this was an issue with the new coverage implementation introduced in 1.4.6, but I tried it with 1.4.5 an and saw the same behaviour.

Not sure what's causing this, but yes please do raise a separate ticket as this is a different issue than the one in the title.

hcoles added a commit that referenced this issue Jan 23, 2020
adds filter for enum constructors for #556
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

No branches or pull requests

4 participants