001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 the ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.engine.sourcecode.coverage; 018 019import java.io.Serializable; 020import java.util.Comparator; 021import java.util.HashMap; 022import java.util.Map; 023import java.util.Map.Entry; 024import java.util.Set; 025import java.util.stream.Collectors; 026 027import org.conqat.lib.commons.collections.IntList; 028 029import com.fasterxml.jackson.annotation.JsonCreator; 030import com.fasterxml.jackson.annotation.JsonProperty; 031 032/** 033 * Holds line range coverage information for a test covering multiple files. 034 */ 035public class MultiFileRangeCoverageInfo implements Serializable { 036 037 private static final long serialVersionUID = 1L; 038 039 /** 040 * Mapping from normalized uniform path to a list of line numbers. The list may 041 * contain duplicates and may be unsorted. 042 */ 043 @JsonProperty("uniformPathToRanges") 044 private final Map<String, IntList> uniformPathToRanges = new HashMap<>(); 045 046 /** 047 * The timestamp of the code this coverage data refers to. May be -1 if unknown. 048 */ 049 @JsonProperty("timestamp") 050 private long timestamp; 051 052 /** Constructor with a default timestamp. */ 053 @JsonCreator 054 public MultiFileRangeCoverageInfo() { 055 this(-1); 056 } 057 058 public MultiFileRangeCoverageInfo(long timestamp) { 059 this.timestamp = timestamp; 060 } 061 062 /** 063 * Merges all coverage contained in newCoverage into this coverage. Coverage 064 * from the same test case replaces existing coverage. 065 */ 066 public void addLineCoverage(MultiFileRangeCoverageInfo newCoverage) { 067 Set<Entry<String, IntList>> newTestCoverage = newCoverage.uniformPathToRanges.entrySet(); 068 for (Entry<String, IntList> testCoverage : newTestCoverage) { 069 uniformPathToRanges.put(testCoverage.getKey(), testCoverage.getValue()); 070 } 071 } 072 073 /** Adds the coverage information for the given lines. */ 074 public void addLineCoverage(String uniformPath, IntList lines) { 075 uniformPathToRanges.computeIfAbsent(uniformPath, k -> new IntList()).addAll(lines); 076 } 077 078 /** @see #timestamp */ 079 public long getTimestamp() { 080 return timestamp; 081 } 082 083 /** @see #timestamp */ 084 public void setTimestamp(long timestamp) { 085 this.timestamp = timestamp; 086 } 087 088 /** Returns the coverage represented by this object in raw form. */ 089 public Map<String, IntList> getCoverage() { 090 return uniformPathToRanges; 091 } 092 093 /** 094 * {@inheritDoc} 095 */ 096 @Override 097 public String toString() { 098 return "Covered: " 099 + uniformPathToRanges.entrySet().stream().sorted(Comparator.comparing(Entry::getKey)) 100 .map((pair) -> pair.getKey() + " " + pair.getValue()).collect(Collectors.joining(", ")) 101 + "; timestamp: " + timestamp; 102 } 103 104 /** 105 * If the test contains coverage from the given file, the uniform path is 106 * adjusted to match the path used inside Teamscale. 107 */ 108 public void changeFilePath(String reportPath, String pathInTeamscale) { 109 if (uniformPathToRanges.containsKey(reportPath) && !reportPath.equals(pathInTeamscale)) { 110 IntList ranges = uniformPathToRanges.remove(reportPath); 111 uniformPathToRanges.put(pathInTeamscale, ranges); 112 } 113 } 114}