From patchwork Wed Jul 22 20:08:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Ripple X-Patchwork-Id: 93274 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46DB1C4453A for ; Wed, 22 Jul 2026 20:08:53 +0000 (UTC) Received: from mx0a-003cac01.pphosted.com (mx0a-003cac01.pphosted.com [205.220.161.93]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.9028.1784750926088834542 for ; Wed, 22 Jul 2026 13:08:46 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@keysight.com header.s=ppfeb2020 header.b=nRRhOA7+; dkim=fail reason="dkim: body hash did not verify" header.i=@keysight.com header.s=selector1 header.b=NkZBVenN; spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: keysight.com, ip: 205.220.161.93, mailfrom: john.ripple@keysight.com) Received: from pps.filterd (m0187213.ppops.net [127.0.0.1]) by mx0b-003cac01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 66MIwB1j148581 for ; Wed, 22 Jul 2026 13:08:45 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=keysight.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=ppfeb2020; bh= 5fZBbFO+J+lFgfPhIIwo8YgL+7f3WlxCYDS6oKCksMM=; b=nRRhOA7+RnD2jgBr xxfc0NbzdlNgg0OpvnOlo3TvndrkJqMOKF2J/ADpldM/CzigxaBFG1i3eeefHQvy m7DF9yq3GsktAkbsU+G8Ov/kXtErR78JKy07rqMgajpzRetFyBHVc9GlMDsVYneY 7nawGru7Km9who2TRxee6GkCT6ids8WGEhjV6hms21fVNdQNeCFTu77pkbebacx0 9YeoeT4M7DPVenTwxh3dEiZzS/Ca4L6VdSz8BkYzN3iYqvTkQcMzTtSD6qA9T1+0 L4mNwoPysVAQiC43OMddzq7gcqNzOPTUoHlPgawYU3tfueEqbTFmaEXJxX2Ok/rQ TGD3zQ== Received: from bn8pr05cu002.outbound.protection.outlook.com (mail-eastus2azon11011053.outbound.protection.outlook.com [52.101.57.53]) by mx0b-003cac01.pphosted.com (PPS) with ESMTPS id 4fjme53bm8-2 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT) for ; Wed, 22 Jul 2026 13:08:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=gtq4bhm+8jfoUUZNPuUvEeSLm14mBadIm722msDi1PZiqkVEjyFZVnswBQ9QvRfsK7A2ZwucHm+U1S0QFWFo/rZiCc7sfTpCzWf8reA1GaMVPdHxeBFsEqTOtf+Zjb14TGuI8esQYcJB8rkgGdX4vS9Cf4makeHNcrlRe1Ss4PUP9QUkmHOg/YzgeQCggZ7MT+0juxY8iO0LwZtLpBoF6T+LXMWBWjMO14bGWCC/gtsmIlvzXavB9qxbLVQRsKYGNhuaMx3NO3rQJ/yPeqtr2RtZ1Mqc31rYDLUtNl2zP+pRGym96xa/qQoiQS3MB0FTCnmaJVhMN8Lk/shntH8gfw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=5fZBbFO+J+lFgfPhIIwo8YgL+7f3WlxCYDS6oKCksMM=; b=BwcgwzHNvQICL6SFHNxj5KsVYl7/fRmG9gQRj/xoji9fjfNYYT5UW1rGkmdNTjBUOdg9UCeQEdlIqlmkDYMvn4SNB5LdyEej0hzTpo/K15MmCvCF5uXs3uD3S3uK8OBr8+g2AgCQ8znMaL80Hs9NhMA0tcFmFL50vSi1OG90VyFxbPCnddy++/C3t9D36ToNS7FODutFWainbkd0gqa6nr8jhaYF25e8b8T2sW7GabrjxOmYu6QRNlwtUck+8LPRjoHj8oXYiLIArLB5SvI46pLagtLS//2xQjGnq10fywOn1N8opCeTb/7uodiYa6iT/YVMrL7CAOkNhltJ7tGLlg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=keysight.com; dmarc=pass action=none header.from=keysight.com; dkim=pass header.d=keysight.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=keysight.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=5fZBbFO+J+lFgfPhIIwo8YgL+7f3WlxCYDS6oKCksMM=; b=NkZBVenNSeEOpS29hh7tuNdNwBlWYz4SVkiCdgs7iEVif0V/iL6YRNH9sJz3B9+WpRQuWRNeMrsH8Su9oDvgLySP6bNGeZP0V2IM6ojNK6AGLcc2Rz3i+lhdeC+mTzyWY9ZLkzZWsav2zp/hBSt5xCDSx+PIGp18WLkv07PIFTA= Received: from PH7PR17MB6130.namprd17.prod.outlook.com (2603:10b6:510:1f5::17) by DS0PR17MB6981.namprd17.prod.outlook.com (2603:10b6:8:162::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.245.10; Wed, 22 Jul 2026 20:08:41 +0000 Received: from PH7PR17MB6130.namprd17.prod.outlook.com ([fe80::7052:ef05:ccc9:d9c2]) by PH7PR17MB6130.namprd17.prod.outlook.com ([fe80::7052:ef05:ccc9:d9c2%3]) with mapi id 15.21.0245.009; Wed, 22 Jul 2026 20:08:41 +0000 From: John Ripple To: openembedded-core@lists.openembedded.org Cc: John Ripple Subject: [meta][PATCH v4 2/3] oeqa/selftest: Add go-vendor.bbclass selftest suite Date: Wed, 22 Jul 2026 14:08:28 -0600 Message-ID: <20260722200830.2917254-3-john.ripple@keysight.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260722200830.2917254-1-john.ripple@keysight.com> References: <20260722200830.2917254-1-john.ripple@keysight.com> X-ClientProxiedBy: CY5PR15CA0224.namprd15.prod.outlook.com (2603:10b6:930:88::19) To PH7PR17MB6130.namprd17.prod.outlook.com (2603:10b6:510:1f5::17) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH7PR17MB6130:EE_|DS0PR17MB6981:EE_ X-MS-Office365-Filtering-Correlation-Id: 300d0d66-238e-4990-99ee-08dee82d0598 X-MS-Exchange-AtpMessageProperties: SA X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|376014|23010399003|22082099003|18002099003|55112099003|3023799007|13003099007|10067099003|11063799006|56012099006; X-Microsoft-Antispam-Message-Info: HsJeS5+k0xeMLYpnUFMaoaEmHFtE/B7D55+wBYuWSBomOu/1uwyyXJ76c/+m/xBsSiCuQMQIZ2cN2oqChn8vzr24gY1YiBWXx2i7Z1OczgGSdSWWZAyH2Sf7dEECCwLnhgs4qOwJGq2eZdpXo3Vw+TeIuzto7hT2KtfaBCaEBRMXLRCEW+QSR8CTR+vA5kGa9iM5bmzCs7Ht19BDRZGgkq60fQx3f3jaYjExb8ACKkz3GUveqaX6povFAnfmMP/EeulJ0SClbPbgo0Q6le1ZbJm6/Tp2LYjhem87/R8XT8fvv8rM6FW+DWi1kcQbBFDknSZd4ZAqvlEb/n5pkN3ZlaJRCRtlGMuYVQHebBoKblT2PVM+fYh/w/Zss635DFWW2+V8EmR4gYyfRwQeFUa4d0kDzq6FHO+icTuiuFnN3QM5biOTtuyzac/RT0TVmS/UfkbLsQyGO5xHGaMeHJ30O2WSYC1M/Nonthitwv7dghkrEoeNFuo0hzt0K1Y+e06Yu0glGg2nmpkDHWFNcTezYx9EROBZMCETcTSFQVWSUKtVnphsK3RswDqihGgmPSOlw6pK8PLEjpZyemG9i6ecC/W++TSjXdb5/bczbWRIJDA= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH7PR17MB6130.namprd17.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014)(23010399003)(22082099003)(18002099003)(55112099003)(3023799007)(13003099007)(10067099003)(11063799006)(56012099006);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?bMjM2tNU4bg/f+3RYw1Mt7nE0pCs?= =?utf-8?q?DXlBqm19N6EodTAiWpPdNZlJ2e/9jTehxQcSU957iP4X6bMuzxKmNqLwkWLSBQK0O?= =?utf-8?q?STRQ3W+UtaLbubNchjTd59h0KIIvQITyHIQQpuSpUc8JE0zoNU5NsxPxg2QF4c6zg?= =?utf-8?q?m2/x8Oh88p4hn6r7TQGFRxd5eJGZsSe8IPm1yVlH6PPNlVc2aWWiKeUxMoS+vBX3G?= =?utf-8?q?5foGeOXcfeQLDxzifthCsrXxaio1HOlOZiLM1/Lnhu37Rn/BlQx7l/7LDh2x5Is5n?= =?utf-8?q?qLg40SJibsLPdERk74Lqilt1f3xdTauEIfZOHeJNL7DR8Y4HMtbZCDnacp3/m+yJG?= =?utf-8?q?5+tOHZkeSiSA4PuUf6lm59sNPMZBAxiEXmft4AJBci3s5RBsvZnNe1vdNyXjJUe77?= =?utf-8?q?vA7xf1p8v6cgLj0Oyp4U1dymFoihk/+eaJHdWR6SuUJJALIBx2PRdDW3J0sF79ekj?= =?utf-8?q?wiqbE0qP7JQU3dF5g21LRGIOMkR7kp5uHXbrdfniZ9rijt4DIT9ErQhmtZMNl9+OA?= =?utf-8?q?zJEoG/Lb3J9qiagByEu9UPSxjRPtXmAmTiWwev4qLPC28an9iQBXyiUvAPKHcG1AM?= =?utf-8?q?D69CFymyCfu1ON+48Z8TKC22noR2gfl76ixwsxADsxaZSB1Fk969Avl68AAMDTOGS?= =?utf-8?q?QtlJ68Q3clv/y9TJDY46WFExs70I4kYwJhiJQvwYS+Epek/9p3KvZEuR+TuKAPSR1?= =?utf-8?q?Qi+h7pOGMudzidenmFb3vPCK+2U9s1Lr2d4idho394Ek7Pw93MUEouyWXyqze30Ua?= =?utf-8?q?NARxijLWoQO272WoXJfrV2b6bLj+i5P1k47s45jTnUw08JX4ebdbzVu06kyT14LGk?= =?utf-8?q?Dm9Fnn+FL89EGcbAG7ErHLasze9QDQhMGv+W7U3XdJOHwyCLcQSFcWf4JW9JBPZbj?= =?utf-8?q?4P+azTO+bzaUYSNIFgo9Gv8QX91vfvgVF3iw+THojBMrYZAk9dqf4yg0NUmZHoiYZ?= =?utf-8?q?HbgDm8u+bkEAQXVRHQ780VGkRhEGV0iGi92i5uCpukGE3jH0YhMsgzJ9Azjgw1UDE?= =?utf-8?q?jq5UcMxcCDlpLY9EwQHWuLyNjT9Tf2/6g4c+IXMcDYyRcP550io0HJOi97K32XNYn?= =?utf-8?q?shAVTuZwTaUy5pMTBMZsjIVfRbDyOpWP0/9g0y+/jeSo1s2oLVb1RhIRnVYs3o6Be?= =?utf-8?q?3TFRN0xCeOY83tyKoYzyO9jxWES87v6v3BdsH9bY3nAfDuedhxE9HBu4khqNiBgzv?= =?utf-8?q?9a2E0tPi7GkzC+HUVNE/RgLtYspakz6PItWSHm/T2zteI1n07lw9aLh1SqQF91KFP?= =?utf-8?q?UuhIYlGWBtZchRU/e18vFnbgl68Yhno9YFDOK57G1xlIVYrtQQrQpUlHEklkfTL7i?= =?utf-8?q?s/8PREfltbM66q8/Iq5XA+deHNNkcrWfoTlizBAu+G6rrxtqQFekCK3xhKWkxkEYl?= =?utf-8?q?4I/BErmiZ11FtC06wBmkuRfGMeUEmKtiyFJVRoXR2Orr6A+zBF7HDPNbYpt1FAEIw?= =?utf-8?q?8gGQn70XfykfkE35dgMxymQRWter7BdP8phf+nzVXA+HdtXNUyqTYv0wF+WJSvu+U?= =?utf-8?q?0qvnlkJR/aTtTgHw9VHCl0mIEyHGpWfyylKG90w5dbUfR3/J8Ik4mhErVOQjMZ1+6?= =?utf-8?q?nVIpX0JxC76rz/UKx6QO6ldxBe6RfCkj+YfKwduMOwP4DaTFXkuewSZGag/2zVPgF?= =?utf-8?q?RlUNMsKAG4tg3CYAYl0geH2/0berUkiw=3D=3D?= X-Exchange-RoutingPolicyChecked: kslj+IAHZyUz5AsOp6v/puTKMBy8Chi3+rljOHf4LSFcLybXm1p60tC7xEEJkWZ3HKZVIF9L25bZXG32lZehH5yf0rJxkX7lHR0zBEqaTh3snGUErVNxrlYN2IYa6jRdcU+jhC0F0rbs8qN1rY/gSvT8nRIg9wbJhUbC9cgdfvLLlPqYdYbOMqmdrtcdoJFIRihD5/IWP44XgJmZ1rt6b/h8Ca4Z4oC/ehDNHpXJPw5Uj8TonTyLxcrFkV3Ji6Bgs5psgogBxFr6B1Ac6zZUiHlv3ruhO+CK8NfTfDg1xogCO7fsRV3Ze9JFFwTClTORzP2CX7NH6vPGUfsIPWnSgA== X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: ybSgAlnyexwMujPZcY41sdPCrdzd+ttLiqLaM6WhT38U/Nr4v+EQuNpcyJuuU4wrUFMZcrkvZMeex0HRECbLUwat1pLPVp4yx0tAP7Av1zNXxSUBpvd+IosAfMrUUw0eoUoC1a6h5Xzh+9/gZ+DiSbIL7MKn+lvpAHwS8PP+mEJ+odY0wRDs0gz/l7WaZLGdJTjiCquX2XsGKF1+edMewI4dIwl/FzhCakooGS7sFjpPydJU9wI/b+dI65Z8vE6KRgWjhuSDprdBtjQuD3m20Sz2f7cjQriPfKo+Kcipnx9/qYPzYm4i4WRwYmPIjV/AFtsAIWfPS2DJy/3sFaoQOocQjfY5QVBdpIgTjqvJbcl0Bh6oLeNAgOTeh3/XMsVgLkMHG3Z0//PRSGhOx+PJwGkztumCY8vO+XrNGFl5kMXevaOxR4l0p4rbpofgl4pPG0EoURT6l5N2EQLkn7e8RqiMDXO/q6HXn3/AImWv1SXGKjvhri6m1DwSe0SL1ajXce+ojvWwCCIW6nSeVt4/hqcqGn7KLahwD7nxDgS4FkYq7ETbZYtgulpBzm5lg9yER1YeS0rfVqNE172tYKyxzVuF+tR5BBJadBc28L4PXs5YOXiGra+FE9U0CF77q1jt X-OriginatorOrg: keysight.com X-MS-Exchange-CrossTenant-Network-Message-Id: 300d0d66-238e-4990-99ee-08dee82d0598 X-MS-Exchange-CrossTenant-AuthSource: PH7PR17MB6130.namprd17.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jul 2026 20:08:40.0184 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 63545f27-3232-4d74-a44d-cdd457063402 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: LADnPo7eiKSM4Co2BU3RvqMrsmHJrIU7f4fHDd15u/mVnQzBV5ewJ2R+gPNfNXaFQG9f1EHjkzyEY+ieES0aW5N7fRrg7UG5iDtBbtzOirU= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR17MB6981 X-Proofpoint-Spam-Info: AW1haW4tMjYwNzIyMDE5OCBTYWx0ZWRfX75TyX0KWHvd5 3GGTsQC+GXgZEmSE6brxYx5dfkjnOSYXTADaci4+8jORE8ZVynM/prxi6gvhVhku2xkte2SEPyp hJkW7YtT0DG1jVIf3Nch6rl/s+10CsY3X6Em7BfMbU3U17GmhJk5 X-Proofpoint-GUID: mWMMZEfLg0auIFmluzpVuHshLtxVb2As X-Authority-Analysis: v=2.4 cv=PdPPQChd c=1 sm=1 tr=0 ts=6a61234d cx=c_pps a=7AIX19wKKSH4vG2a64CeWA==:117 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=lCpzRmAYbLLaTzLvsPZ7Mbvzbb8=:19 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=RAioF0-LDSMA:10 a=vu2TTH8h0NUA:10 a=VkNPw1HP01LnGYTKEx00:22 a=FLoIbiw2ZNY34kqd41oa:22 a=BswK4llZXKt4Tvt69P-b:22 a=F6MVbVVLAAAA:8 a=NEAV23lmAAAA:8 a=A1X0JdhQAAAA:8 a=iGHA9ds3AAAA:8 a=5cgIs88SztoUVwLlgL4A:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=6mxfPxaA-CAxv1z-Kq-J:22 a=nM-MV4yxpKKO9kiQg6Ot:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzIyMDE5OCBTYWx0ZWRfX/mVt5BnbYciH rrdWIbtZ4KCag9fbnfUx0tpweX+YF/wXB18LuMmy+2LGzXgzt2nmv2TfcpthNpTGr1E6JdL8IVo xt2U4pUwUsOX6v8uo3e7iXiDrEmLh9h6EpH++8FQ+v/uBVHBlgXOGxSqzRbpN5qWZHZZjRv7fRE FpzqSpSzeLopT/qtyr9mlZNoX6L20mIpUpS01Qi9asOzUkSUS4KBfihg18hpvatiKx2gQiwNByo gzVB+UxdNqvLOzEFuSkB8gfxPB30bqPLXCs2WjmHp6dvCI9eGhGXROSRQb/Z2U+01/cYLvqqM4k fUexmkVt4kb6Xz96UAme4w1mOdisQuvFdlrwSA1UAeHmV4W3NQ9RpvjipC/m27+o3Uh8jFRU1ij MhtHxCtq4JzMgx83pDQU5oLPSptjSH/7UBUsw4UpYRm0anXjX+javn8cvfNYxuQ5LbZBfMNN3yY +q8mHSZnuVfDV4tOeyA== X-Proofpoint-ORIG-GUID: mWMMZEfLg0auIFmluzpVuHshLtxVb2As X-Proofpoint-Virus-Version: vendor=nai engine=6900 definitions=11854 signatures=596817 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 impostorscore=0 spamscore=0 malwarescore=0 bulkscore=0 adultscore=0 clxscore=1015 priorityscore=1501 lowpriorityscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607220198 X-MIME-Autoconverted: from 8bit to quoted-printable by mx0b-003cac01.pphosted.com id 66MIwB1j148581 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 22 Jul 2026 20:08:53 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/241743 Add govendor.py with two test classes that cover the behaviors fixed and defined in go-vendor.bbclass: GoVendorSrcUriTests (offline, ~10 s): unit tests for go_src_uri() parsed via bb.tinfoil; verifies the basic URI shape, path/pathmajor/subdir/replaces encoding, and that non-git VCS omits the git-specific nobranch/protocol flags. GoVendorTaskTests: runs do_go_vendor once against the real recipetool-go-test project and checks that external deps land in vendor/, *_test.go files are excluded, pathmajor=/v5 falls back to the repo root when no v5/ subdir exists, modules.txt is reproduced in vendor/, a local replacement (./is) appears as a symlink, and the S/src/GO_IMPORT/vendor -> S/src/import/vendor symlink is created. Exclude the govendor test recipes from world builds since they are only meant to be built directly by the govendor test suite. Signed-off-by: John Ripple --- .../recipes-test/govendor/files/modules.txt | 7 + .../govendor/go-vendor-src-uri_1.0.bb | 18 ++ .../govendor/govendor-real-test_1.0.bb | 29 +++ meta/lib/oeqa/selftest/cases/govendor.py | 179 ++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 meta-selftest/recipes-test/govendor/files/modules.txt create mode 100644 meta-selftest/recipes-test/govendor/go-vendor-src-uri_1.0.bb create mode 100644 meta-selftest/recipes-test/govendor/govendor-real-test_1.0.bb create mode 100644 meta/lib/oeqa/selftest/cases/govendor.py diff --git a/meta-selftest/recipes-test/govendor/files/modules.txt b/meta-selftest/recipes-test/govendor/files/modules.txt new file mode 100644 index 0000000000..f64f5245b5 --- /dev/null +++ b/meta-selftest/recipes-test/govendor/files/modules.txt @@ -0,0 +1,7 @@ +# github.com/godbus/dbus/v5 v5.1.0 +## explicit; go 1.12 +github.com/godbus/dbus/v5 +# github.com/matryer/is v1.4.1 => ./is +## explicit; go 1.14 +github.com/matryer/is +# github.com/matryer/is => ./is \ No newline at end of file diff --git a/meta-selftest/recipes-test/govendor/go-vendor-src-uri_1.0.bb b/meta-selftest/recipes-test/govendor/go-vendor-src-uri_1.0.bb new file mode 100644 index 0000000000..6f0364b7da --- /dev/null +++ b/meta-selftest/recipes-test/govendor/go-vendor-src-uri_1.0.bb @@ -0,0 +1,18 @@ +SUMMARY = "Selftest fixture: go_src_uri parameter variants" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +# Parsed via tinfoil for its GO_SRC_URI_* variables only; never actually built +# (it has no real SRC_URI, so do_go_vendor would fail). +EXCLUDE_FROM_WORLD = "1" + +inherit go-vendor + +GO_IMPORT = "example.com/testpkg" + +GO_SRC_URI_BASIC = "${@go_src_uri('github.com/foo/bar', 'v1.0.0')}" +GO_SRC_URI_PATH = "${@go_src_uri('github.com/foo/bar', 'v2.1.0', path='github.com/foo/bar/v2')}" +GO_SRC_URI_PATHMAJOR = "${@go_src_uri('github.com/foo/bar', 'v2.0.0', pathmajor='/v2')}" +GO_SRC_URI_SUBDIR = "${@go_src_uri('github.com/foo/bar', 'v1.0.0', subdir='sub/pkg')}" +GO_SRC_URI_REPLACES = "${@go_src_uri('github.com/baz/qux', 'v1.0.0', replaces='../local/baz')}" +GO_SRC_URI_SVN = "${@go_src_uri('example.com/svnmod', 'r42', vcs='svn')}" diff --git a/meta-selftest/recipes-test/govendor/govendor-real-test_1.0.bb b/meta-selftest/recipes-test/govendor/govendor-real-test_1.0.bb new file mode 100644 index 0000000000..8086922e10 --- /dev/null +++ b/meta-selftest/recipes-test/govendor/govendor-real-test_1.0.bb @@ -0,0 +1,29 @@ +SUMMARY = "go-vendor integration test: recipetool-go-test" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://src/${GO_IMPORT}/LICENSE;md5=4e3933dd47afbf115e484d11385fb3bd" + +# Only meant to be built directly by GoVendorTaskTests (bitbake('%s -c go_vendor')), +# not as part of a general world build. +EXCLUDE_FROM_WORLD = "1" + +# Native variant lets GoVendorTaskTests.test_do_compile_succeeds exercise the +# real go toolchain without requiring a full target Go cross-toolchain. +BBCLASSEXTEND = "native" + +inherit go-vendor + +GO_IMPORT = "git.yoctoproject.org/recipetool-go-test" + +# modules.txt for recipetool-go-test at SRCREV: +# - github.com/godbus/dbus/v5 v5.1.0 (external, fetched via go_src_uri) +# - github.com/matryer/is v1.4.1 (local replacement => ./is) +# Use go mod vendor to generate the modules.txt +SRC_URI = "\ + git://${GO_IMPORT};name=recipetool-go-test;branch=main;protocol=https;nobranch=1;destsuffix=${GO_SRCURI_DESTSUFFIX} \ + ${@go_src_uri('github.com/godbus/dbus', 'v5.1.0', path='github.com/godbus/dbus/v5', pathmajor='/v5')} \ + file://modules.txt \ + " +SRCREV_FORMAT = "recipetool-go-test" +# git.yoctoproject.org/recipetool-go-test main branch HEAD +SRCREV_recipetool-go-test = "c3e213c01b6c1406b430df03ef0d1ae77de5d2f7" +SRCREV_github.com.godbus.dbus.v5 = "e523abc905595cf17fb0001a7d77eaaddfaa216d" diff --git a/meta/lib/oeqa/selftest/cases/govendor.py b/meta/lib/oeqa/selftest/cases/govendor.py new file mode 100644 index 0000000000..8be2712060 --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/govendor.py @@ -0,0 +1,179 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# +# Comprehensive tests for go-vendor.bbclass: +# GoVendorSrcUriTests -- unit tests for the go_src_uri() helper (offline, ~10 s) +# GoVendorTaskTests -- integration tests using the real recipetool-go-test project +# (network fetch of git.yoctoproject.org + github.com/godbus/dbus) + +import os + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake, get_bb_var + +# --------------------------------------------------------------------------- +# Class 1: go_src_uri() helper function +# --------------------------------------------------------------------------- + +class GoVendorSrcUriTests(OESelftestTestCase): + """Tests for the go_src_uri() Python helper in go-vendor.bbclass. + + Parses the go-vendor-src-uri fixture recipe (meta-selftest/recipes-test/ + govendor/go-vendor-src-uri_1.0.bb) via bb.tinfoil (config_only=True) once + per class so the function runs inside the real BitBake class-loading + machinery. All tests are offline and complete in ~10 s total. + """ + + @classmethod + def setUpClass(cls): + import bb.tinfoil + super().setUpClass() + + recipe_path = os.path.join(cls.testlayer_path, 'recipes-test', + 'govendor', 'go-vendor-src-uri_1.0.bb') + + with bb.tinfoil.Tinfoil() as tinfoil: + tinfoil.prepare(config_only=True, quiet=2) + rd = tinfoil.parse_recipe_file(recipe_path) + cls.bp = rd.getVar('BP') + cls.uris = {k: rd.getVar('GO_SRC_URI_' + k) + for k in ('BASIC', 'PATH', 'PATHMAJOR', 'SUBDIR', + 'REPLACES', 'SVN')} + + # --- individual test methods ------------------------------------------- + + def test_basic(self): + """destsuffix uses expanded BP""" + uri = self.uris['BASIC'] + expected_ds = 'destsuffix=%s/src/import/vendor.fetch/github.com/foo/bar@v1.0.0' % self.bp + self.assertIn(expected_ds, uri) + self.assertIn('go_module_path=github.com/foo/bar', uri) + self.assertIn('nobranch=1', uri) + self.assertIn('protocol=https', uri) + self.assertIn('is_go_dependency=1', uri) + + def test_path_override(self): + """Explicit path= sets go_module_path independently of the repo URL.""" + uri = self.uris['PATH'] + self.assertIn('go_module_path=github.com/foo/bar/v2', uri) + expected_ds = 'destsuffix=%s/src/import/vendor.fetch/github.com/foo/bar@v2.1.0' % self.bp + self.assertIn(expected_ds, uri) + + def test_pathmajor(self): + """pathmajor is encoded as go_pathmajor in the URI.""" + self.assertIn('go_pathmajor=/v2', self.uris['PATHMAJOR']) + + def test_subdir(self): + """subdir is encoded as go_subdir in the URI.""" + self.assertIn('go_subdir=sub/pkg', self.uris['SUBDIR']) + + def test_replaces(self): + """replaces is encoded as go_module_replacement in the URI.""" + self.assertIn('go_module_replacement=../local/baz', self.uris['REPLACES']) + + def test_non_git_vcs(self): + """Non-git VCS omits the git-specific nobranch and protocol=https flags.""" + uri = self.uris['SVN'] + self.assertIn('svn://example.com/svnmod', uri) + self.assertNotIn('nobranch', uri) + self.assertNotIn('protocol=https', uri) + self.assertIn('is_go_dependency=1', uri) + + +# --------------------------------------------------------------------------- +# Class 2: do_go_vendor task integration — real project +# --------------------------------------------------------------------------- + +class GoVendorTaskTests(OESelftestTestCase): + """Integration tests for do_go_vendor using the real recipetool-go-test project. + + The govendor-real-test recipe (meta-selftest/recipes-test/govendor/ + govendor-real-test_1.0.bb) fetches git.yoctoproject.org/recipetool-go-test + (commit c3e213c) as its main source and github.com/godbus/dbus/v5 v5.1.0 + as an external vendor dependency. The project also has a local module + replacement (github.com/matryer/is => ./is) that lives inside the main + source tree. + + do_go_vendor runs ONCE in setUpClass; individual test methods inspect the + resulting vendor directory without re-running bitbake. + + Verified behaviors: + - External dependency files are copied to vendor/ + - *_test.go files are excluded from the vendor copy + - pathmajor fallback: when the /v5 subdir is absent, repo root is used + - modules.txt is reproduced inside vendor/ + - Local module replacement creates a relative symlink in vendor/ + - S/src/GO_IMPORT/vendor symlink is created pointing at S/src/import/vendor + """ + + GO_IMPORT = 'git.yoctoproject.org/recipetool-go-test' + RECIPE_NAME = 'govendor-real-test' + + @classmethod + def setUpClass(cls): + super().setUpClass() + + bitbake('%s -c go_vendor' % cls.RECIPE_NAME) + cls.s_dir = get_bb_var('S', cls.RECIPE_NAME) + cls.vendor_dir = os.path.join(cls.s_dir, 'src', 'import', 'vendor') + + # --- test methods (all inspect cls.vendor_dir, no bitbake) --------------- + + def test_external_dep_copied_to_vendor(self): + """godbus/dbus/v5 source files are copied into vendor/.""" + dbus_dir = os.path.join(self.vendor_dir, 'github.com', 'godbus', 'dbus', 'v5') + self.assertTrue(os.path.isdir(dbus_dir), + 'vendor/github.com/godbus/dbus/v5/ not created') + self.assertTrue(os.path.isfile(os.path.join(dbus_dir, 'conn.go')), + 'conn.go not found in vendor/github.com/godbus/dbus/v5/') + + def test_test_files_excluded_from_vendor(self): + """*_test.go files from godbus/dbus are not copied into vendor/.""" + dbus_dir = os.path.join(self.vendor_dir, 'github.com', 'godbus', 'dbus', 'v5') + self.assertFalse( + os.path.isfile(os.path.join(dbus_dir, 'conn_test.go')), + 'conn_test.go should have been excluded from vendor by *_test.go pattern') + + def test_pathmajor_falls_back_to_root(self): + """godbus/dbus v5.1.0 has no v5/ subdir; pathmajor=/v5 falls back to root.""" + dbus_dir = os.path.join(self.vendor_dir, 'github.com', 'godbus', 'dbus', 'v5') + # auth.go is at the repo root of godbus/dbus, not inside a v5/ subdir. + self.assertTrue(os.path.isfile(os.path.join(dbus_dir, 'auth.go')), + 'auth.go not found; pathmajor=/v5 fallback to repo root did not work') + + def test_modules_txt_in_vendor(self): + """modules.txt is reproduced inside vendor/ and lists the external dep.""" + modules_txt = os.path.join(self.vendor_dir, 'modules.txt') + self.assertTrue(os.path.isfile(modules_txt)) + with open(modules_txt) as fh: + content = fh.read() + self.assertIn('github.com/godbus/dbus/v5 v5.1.0', content) + + def test_local_replacement_symlink(self): + """go.mod local replacement (./is) creates a symlink in vendor/ to S/src/GO_IMPORT/is.""" + symlink = os.path.join(self.vendor_dir, 'github.com', 'matryer', 'is') + self.assertTrue(os.path.islink(symlink), + 'vendor/github.com/matryer/is should be a symlink for the ./is local replacement') + expected_target = os.path.join(self.s_dir, 'src', self.GO_IMPORT, 'is') + self.assertEqual(os.path.realpath(symlink), os.path.realpath(expected_target), + 'Local replacement symlink does not point to S/src/GO_IMPORT/is') + + def test_go_import_vendor_symlink(self): + """do_go_vendor creates S/src/GO_IMPORT/vendor -> S/src/import/vendor.""" + link = os.path.join(self.s_dir, 'src', self.GO_IMPORT, 'vendor') + self.assertTrue(os.path.islink(link), + 'S/src/GO_IMPORT/vendor symlink not created') + self.assertEqual(os.path.realpath(link), os.path.realpath(self.vendor_dir), + 'S/src/GO_IMPORT/vendor does not point to S/src/import/vendor') + + def test_do_compile_succeeds(self): + """The vendored tree is valid Go: the toolchain can actually build it. + + Runs against the -native variant so this only depends on go-native, + not a full target Go cross-toolchain. The SRC_URI fetch is already + cached in DL_DIR from setUpClass, so this mainly re-runs + unpack/go_vendor/compile for the native variant. + """ + bitbake('%s-native -c compile' % self.RECIPE_NAME)