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

Mixed ObjC and Swift Project - Can not add the same measure twice on org.sonar.api.resources.Project #50

Closed
leddo opened this issue Nov 11, 2016 · 11 comments

Comments

@leddo
Copy link

leddo commented Nov 11, 2016

I am getting an error when trying to run a project through it that has both swift and objective-c files in it.

16:40:59 ERROR: Error during Sonar runner execution
16:40:59 org.sonar.runner.impl.RunnerException: Unable to execute Sonar
16:40:59 at org.sonar.runner.impl.BatchLauncher$1.delegateExecution(BatchLauncher.java:91)
16:40:59 at org.sonar.runner.impl.BatchLauncher$1.run(BatchLauncher.java:75)
16:40:59 at java.security.AccessController.doPrivileged(Native Method)
16:40:59 at org.sonar.runner.impl.BatchLauncher.doExecute(BatchLauncher.java:69)
16:40:59 at org.sonar.runner.impl.BatchLauncher.execute(BatchLauncher.java:50)
16:40:59 at org.sonar.runner.api.EmbeddedRunner.doExecute(EmbeddedRunner.java:102)
16:40:59 at org.sonar.runner.api.Runner.execute(Runner.java:100)
16:40:59 at org.sonar.runner.Main.executeTask(Main.java:70)
16:40:59 at org.sonar.runner.Main.execute(Main.java:59)
16:40:59 at org.sonar.runner.Main.main(Main.java:53)
16:40:59 Caused by: org.sonar.api.utils.SonarException: Can not add the same measure twice on org.sonar.api.resources.Project@278cbf5a[id=,key=com.blahblahblah:Mobile-iOS-blah,qualifier=TRK]: org.sonar.api.measures.Measure@7bd0e2e9[metricKey=tests,metric=Metric[id=,key=tests,description=Number of unit tests,type=INT,direction=-1,domain=Coverage,name=Unit tests,qualitative=false,userManaged=false,enabled=true,worstValue=,bestValue=,optimizedBestValue=false,hidden=false,deleteHistoricalData=false,decimalScale=],value=0.0,data=,description=,alertStatus=,alertText=,date=,variation1=,variation2=,variation3=,variation4=,variation5=,url=,personId=,persistenceMode=FULL,fromCore=false]

If I add sonar.language=objc to the sonar-project.properties file, then it all works (the app is predominantly ObjC. but with that removed (the comment in the default properties file says to remove it for a mixed app), then the error happens above.

Also, this project has no unit tests in it, so could that be contributing to the problem?

Any ideas ?

@pbernery
Copy link
Contributor

Hello. This may indeed happen for several reasons.

  1. your sonar-project.properties references files two times. Check swift.classes.
  2. it may happen in some situation when the project includes both Objective-C and Swift. In this case, the solution is to not specify any language with sonar.language. Just comment this line and this should work.

@leddo
Copy link
Author

leddo commented Nov 14, 2016

Thanks for the response. I have done #2, and actually that is the reason it fails. If I specify a language, then it seems to work ok for that language.
in regards to #1, can you explain what you mean by checking swift.classes ? Is this a setting in the sonar-project.properties file that I need to set or something ?
Thanks for your help.

@pbernery
Copy link
Contributor

For #1, I meant sonar.sources in the sonar-project.properties file, sorry. Make sure to specify a directory and not use ..

I have a project here with both Swift and Objective-C, for which I did not specify the language and it passes through the plugin. If it doesn't work for you when specifying the sonar.sources, I'll ask if we have a particular configuration on SonarQube which I am not aware of.

@leddo
Copy link
Author

leddo commented Nov 14, 2016

Just for some more info: the complete error messages is:
11:33:59 Caused by: org.sonar.api.utils.SonarException: Can not add the same measure twice on org.sonar.api.resources.Project@278cbf5a[id=<null>,key=com.xxxx:Mobile-iOS-xxxx,qualifier=TRK]: org.sonar.api.measures.Measure@4a65ce06[metricKey=tests,metric=Metric[id=<null>,key=tests,description=Number of unit tests,type=INT,direction=-1,domain=Coverage,name=Unit tests,qualitative=false,userManaged=false,enabled=true,worstValue=<null>,bestValue=<null>,optimizedBestValue=false,hidden=false,deleteHistoricalData=false,decimalScale=<null>],value=0.0,data=<null>,description=<null>,alertStatus=<null>,alertText=<null>,date=<null>,variation1=<null>,variation2=<null>,variation3=<null>,variation4=<null>,variation5=<null>,url=<null>,personId=<null>,persistenceMode=FULL,fromCore=false]

Could this be because our mixed project does not have any unit tests at all? It seems like the duplicate measure is related to tests.

We are using both backelite Objc & Swift scanners.

@zippy1978
Copy link
Contributor

Hi @leddo,

Can not add the same measure twice usually happens when the same source file is scanned twice (it tries to record the same mesure for the same file twice).

It is often caused by unit tests files being in the sonar.sources dirs : test files must be separated (in a different path) from the app source code.

Gilles

@haynzz
Copy link

haynzz commented Feb 13, 2017

Hey, we also encountered this issue and we have been able to hunt it down to the following:
Since we started migrating our project from Objective-C to Swift we have started writing all new tests in Swift. But with the same filename.

  • TVBookmarksListViewModelSpec.swift
  • TVBookmarksListViewModelSpec.m

They create following JUNIT report:

...
<testsuite name='TVBookmarksListViewModelSpec' tests='39' failures='0'>
    <testcase classname='TVBookmarksListViewModelSpec' name='TVBookmarksListViewModel___searchForBookmarkAtIndexPathCommand__tracks_the_triggered_search' time='0.082'/>
</testsuite>
...
 <testsuite name='HotelSearchTests.TVHotelSearchParametersSpec' tests='43' failures='0'>
    <testcase classname='HotelSearchTests.TVHotelSearchParametersSpec' name='TVHotelSearchParameters___searchParametersChangedSignal__when_the_location_changes__sends_a_RACUnit' time='0.033'/>
</testsuite>
...

For me it is interesting if this is a sonarQube issue or if it is the Plugin?
Do you have a workaround except renaming the test files (there are a lot)?

@leddo
Copy link
Author

leddo commented Feb 14, 2017

Yeah this is still a problem for me.

I have a mixed objc-swift project. Only way I can get it to work, is by setting a language property in sonar-project.properties.

I have a handful of unit tests, all written in swift, but in the sonar debug output, is see messages like
Unable to locate test source file xxxTests/xxxViewControllerTestCase.m (but the actual test case file is in Swift)

I think the coverage file is being processed twice - once for objective-c scanner, and once for the swift scanner.

Any help, or example properties files from people with working systems that have mixed code base, and unit tests and coverage and linting actually working?

@fabb
Copy link

fabb commented May 16, 2017

Any help, or example properties files from people with working systems that have mixed code base, and unit tests and coverage and linting actually working?

That would be very helpful for us too

@Branlute
Copy link

Hi, I have the same problem.

@leddo , you'r right, its the coverage file which processed twice.

In SwiftCobertunaSensor.java (sonar-swift) and CobertunaSensor.java (sonar-objc) have the same pattern : DEFAULT_REPORT_PATTERN = "sonar-reports/coverage-*.xml";

I have tested with pattern sonar-reports/coverage-objc*.xml for objc and sonar-reports/coverage-swift*.xml for swift plugin, and adjust run-sonar-swift.sh for export coverage into sonar-reports/coverage-swift.xml. It works.

I will make two Pull Request today (one for objc, and one for swift).

@zippy1978
Copy link
Contributor

Hi,
I merged the PR.
Thanks again @Branlute !

@gronico
Copy link

gronico commented Jun 30, 2017

Hi, with the 2 fixes, I still have the same error (but not on the same file):

INFO: parsing sonar-reports/TEST-report.xml
INFO: ------------------------------------------------------------------------
INFO: EXECUTION FAILURE
INFO: ------------------------------------------------------------------------
INFO: Total time: 6.987s
INFO: Final Memory: 49M/458M
INFO: ------------------------------------------------------------------------
ERROR: Error during SonarQube Scanner execution
org.sonar.api.utils.SonarException: Can not add the same measure twice on org.sonar.api.resources.Project@21aa6d6c[id=<null>,key=***_develop,qualifier=TRK]: org.sonar.api.measures.Measure@984169e[metricKey=tests,metric=Metric[id=<null>,key=tests,description=Number of unit tests,type=INT,direction=-1,domain=Coverage,name=Unit Tests,qualitative=false,userManaged=false,enabled=true,worstValue=<null>,bestValue=<null>,optimizedBestValue=false,hidden=false,deleteHistoricalData=false,decimalScale=<null>],value=0.0,data=<null>,description=<null>,alertStatus=<null>,alertText=<null>,date=<null>,variation1=<null>,variation2=<null>,variation3=<null>,variation4=<null>,variation5=<null>,url=<null>,personId=<null>,persistenceMode=FULL,fromCore=false]
	at org.sonar.batch.sensor.DefaultSensorStorage.saveMeasure(DefaultSensorStorage.java:148)
	at org.sonar.batch.index.DefaultIndex.addMeasure(DefaultIndex.java:173)
	at org.sonar.batch.deprecated.DeprecatedSensorContext.saveMeasure(DeprecatedSensorContext.java:129)
	at org.sonar.plugins.swift.tests.SwiftSurefireParser.insertZeroWhenNoReports(SwiftSurefireParser.java:94)
	at org.sonar.plugins.swift.tests.SwiftSurefireParser.collect(SwiftSurefireParser.java:72)
	at org.sonar.plugins.swift.tests.SwiftSurefireSensor.collect(SwiftSurefireSensor.java:87)
	at org.sonar.plugins.swift.tests.SwiftSurefireSensor.analyse(SwiftSurefireSensor.java:81)

In the code:
org.sonar.plugins.swift.tests.SwiftSurefireParser.collect has the reportsDir provided by sonar.junit.reportsPath=sonar-reports/TEST-report.xml which is a file and not a dir as expected.
-> org.sonar.plugins.swift.tests.SwiftSurefireParser.getReports returns new File[0];

I've made a quick fix in org.sonar.plugins.swift.tests.SwiftSurefireParser.getReports :

    private File[] getReports(File dir) {

      if (dir == null || !dir.exists()) {
          return new File[0];
      }
      if (!dir.isDirectory()) {
          File[] tabFile = {dir};
          return tabFile;
    }

Maybe it's not perfect, but it works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants