diff --git a/packages/canyon-backend/prisma/schema.prisma b/packages/canyon-backend/prisma/schema.prisma index f892b649..d7e7f7b2 100755 --- a/packages/canyon-backend/prisma/schema.prisma +++ b/packages/canyon-backend/prisma/schema.prisma @@ -73,11 +73,12 @@ model CovMap { } model CovMapTest { - id String @id - mapJsonStr String @map("map_json_str") - projectID String @map("project_id") - sha String - path String + id String @id + mapJsonStr String @map("map_json_str") + mapJsonStatementMapStartLine String @map("map_json_statement_map_start_line") + projectID String @map("project_id") + sha String + path String } model CovHit { diff --git a/packages/canyon-backend/src/coverage/services/core/consumer-coverage.service.ts b/packages/canyon-backend/src/coverage/services/core/consumer-coverage.service.ts index 4566817f..f8e53560 100644 --- a/packages/canyon-backend/src/coverage/services/core/consumer-coverage.service.ts +++ b/packages/canyon-backend/src/coverage/services/core/consumer-coverage.service.ts @@ -117,9 +117,42 @@ export class ConsumerCoverageService { }) .then((res) => JSON.parse(res.mapJsonStr)); - // const newcoverage = JSON.parse(merge_coverage_json_str(JSON.stringify(queueDataToBeConsumed.coverage), JSON.stringify(cov))); const newcoverage = mergeCoverageMap(queueDataToBeConsumed.coverage, cov); + const map = await this.prisma.covMapTest + .findMany({ + where: { + projectID: queueDataToBeConsumed.projectID, + sha: queueDataToBeConsumed.sha, + }, + select: { + path: true, + mapJsonStatementMapStartLine: true, + }, + }) + .then((res) => { + return res.reduce((acc, cur) => { + if (cur.mapJsonStatementMapStartLine) { + acc[cur.path] = { + statementMap: JSON.parse(cur.mapJsonStatementMapStartLine), + }; + } + return acc; + }, {}); + }); + + const obj = {}; + + Object.entries(newcoverage).forEach(([key, value]: any) => { + if (map[key]) { + obj[key] = { + path: key, + ...value, + ...map[key], + }; + } + }); + await this.prisma.coverage.update({ where: { id: coverage.id, @@ -130,7 +163,7 @@ export class ConsumerCoverageService { genSummaryMapByCoverageMap( await this.testExcludeService.invoke( queueDataToBeConsumed.projectID, - newcoverage, + obj, ), codechanges, ), @@ -149,6 +182,44 @@ export class ConsumerCoverageService { }); } else { // 创建新的agg + + // TODO: 这里需要修改,每次都拉取map,成本很大,这里只需要拉取语句map来计算行覆盖率 + const map = await this.prisma.covMapTest + .findMany({ + where: { + projectID: queueDataToBeConsumed.projectID, + sha: queueDataToBeConsumed.sha, + }, + select: { + path: true, + mapJsonStatementMapStartLine: true, + }, + }) + .then((res) => { + return res.reduce((acc, cur) => { + if (cur.mapJsonStatementMapStartLine) { + acc[cur.path] = { + statementMap: JSON.parse(cur.mapJsonStatementMapStartLine), + }; + } + return acc; + }, {}); + }); + + const obj = {}; + + Object.entries(queueDataToBeConsumed.coverage).forEach( + ([key, value]: any) => { + if (map[key]) { + obj[key] = { + path: key, + ...value, + ...map[key], + }; + } + }, + ); + const newAgg = await this.prisma.coverage.create({ data: { covType: covType, @@ -158,7 +229,7 @@ export class ConsumerCoverageService { genSummaryMapByCoverageMap( await this.testExcludeService.invoke( queueDataToBeConsumed.projectID, - queueDataToBeConsumed.coverage, + obj, ), codechanges, ), diff --git a/packages/canyon-backend/src/coverage/services/coverage-client.service.ts b/packages/canyon-backend/src/coverage/services/coverage-client.service.ts index 082cdb26..091cb9e8 100755 --- a/packages/canyon-backend/src/coverage/services/coverage-client.service.ts +++ b/packages/canyon-backend/src/coverage/services/coverage-client.service.ts @@ -3,7 +3,7 @@ import { PrismaService } from '../../prisma/prisma.service'; import { CoverageClientDto } from '../dto/coverage-client.dto'; import { Coverage } from '@prisma/client'; import { CoveragediskService } from './core/coveragedisk.service'; -import { formatReportObject } from '../../utils/coverage'; +import { filterStatementMap, formatReportObject } from '../../utils/coverage'; /** * 上传覆盖率,十分重要的服务 */ @@ -127,16 +127,15 @@ export class CoverageClientService { }, ); - await this.coveragediskService.pushQueue({ - ...dataFormatAndCheckQueueDataToBeConsumed, - coverage: objHit, - }); await this.prisma.covMapTest.createMany({ - data: Object.entries(objMap).map(([path, value]) => { + data: Object.entries(objMap).map(([path, value]: any) => { const { projectID, sha } = dataFormatAndCheckQueueDataToBeConsumed; return { id: `__${projectID}__${sha}__${path}__`, mapJsonStr: JSON.stringify(value), //???没删除bfs + mapJsonStatementMapStartLine: JSON.stringify( + filterStatementMap(value.statementMap), + ), projectID: projectID, sha: sha, path: path, @@ -144,6 +143,10 @@ export class CoverageClientService { }), skipDuplicates: true, }); + await this.coveragediskService.pushQueue({ + ...dataFormatAndCheckQueueDataToBeConsumed, + coverage: objHit, + }); return { msg: 'ok', coverageId: '', diff --git a/packages/canyon-backend/src/coverage/services/coverage.service.ts b/packages/canyon-backend/src/coverage/services/coverage.service.ts index 172adc11..ef880626 100755 --- a/packages/canyon-backend/src/coverage/services/coverage.service.ts +++ b/packages/canyon-backend/src/coverage/services/coverage.service.ts @@ -1,9 +1,9 @@ -import { Injectable } from "@nestjs/common"; -import { PrismaService } from "src/prisma/prisma.service"; -import { CoverageSummary } from "../models/coverage-summary"; -import { genSummaryMapByCoverageMap } from "@canyon/data"; -import { TestExcludeService } from "./common/test-exclude.service"; -import { removeNullKeys } from "../../utils/utils"; +import { Injectable } from '@nestjs/common'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { CoverageSummary } from '../models/coverage-summary'; +import { genSummaryMapByCoverageMap } from '@canyon/data'; +import { TestExcludeService } from './common/test-exclude.service'; +import { removeNullKeys } from '../../utils/utils'; @Injectable() export class CoverageService { @@ -21,15 +21,15 @@ export class CoverageService { where: { sha: sha, projectID, - covType: "agg", + covType: 'agg', NOT: { projectID: { - contains: "-ut", + contains: '-ut', }, }, }, orderBy: { - updatedAt: "desc", + updatedAt: 'desc', }, }); if (coverages.length === 0) { @@ -78,8 +78,8 @@ export class CoverageService { where: { projectID, sha: sha, - covType: reportID === "" ? "all" : "agg", - reportID: reportID === "" ? undefined : reportID, + covType: reportID === '' ? 'all' : 'agg', + reportID: reportID === '' ? undefined : reportID, }, }); const maps = [ @@ -108,8 +108,6 @@ export class CoverageService { }), ]; - // this.prisma.covMap - const time = Date.now(); const [hit, map] = await Promise.all(maps); const obj = {}; diff --git a/packages/canyon-backend/src/utils/coverage.ts b/packages/canyon-backend/src/utils/coverage.ts index acf1ccdf..65ae3757 100755 --- a/packages/canyon-backend/src/utils/coverage.ts +++ b/packages/canyon-backend/src/utils/coverage.ts @@ -1,7 +1,7 @@ import * as libCoverage from 'istanbul-lib-coverage'; import * as libSourceMaps from 'istanbul-lib-source-maps'; -import {mergeCoverageMap as mergeCoverageMapOfCanyonData} from "@canyon/data"; -import {merge_coverage_json_str} from "canyon-data"; +import { mergeCoverageMap as mergeCoverageMapOfCanyonData } from '@canyon/data'; +import { merge_coverage_json_str } from 'canyon-data'; function parseInstrumentCwd(instrumentCwd) { if (instrumentCwd.includes('=>')) { const instrumentCwdSplit = instrumentCwd.split('=>'); @@ -80,17 +80,30 @@ function getJsonSize(jsonObj) { const encodedJson = encoder.encode(jsonString); // 返回字节数组的长度 - return encodedJson.length/1024/1024; + return encodedJson.length / 1024 / 1024; } - export const mergeCoverageMap = (cov1: any, cov2: any) => { // 超过2M的数据用js合并 const size = getJsonSize(cov1); - if (size > 0){ + if (size > 0) { // console.log(`size of cov1: ${size}M`); - return mergeCoverageMapOfCanyonData(cov1, cov2) + return mergeCoverageMapOfCanyonData(cov1, cov2); } else { - return JSON.parse(merge_coverage_json_str(JSON.stringify(cov1), JSON.stringify(cov2))); + return JSON.parse( + merge_coverage_json_str(JSON.stringify(cov1), JSON.stringify(cov2)), + ); } -} +}; + +export const filterStatementMap = (statementMap: any) => { + const obj = {}; + Object.entries(statementMap).forEach(([key, value]: any) => { + obj[key] = { + start: { + line: value.start.line, + }, + }; + }); + return obj; +};